⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cardwo.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ********************************************************************** *     cardwo.c - PCM output HAL for emu10k1 driver *     Copyright 1999, 2000 Creative Labs, Inc. * ********************************************************************** * *     Date                 Author          Summary of changes *     ----                 ------          ------------------ *     October 20, 1999     Bertrand Lee    base code release * ********************************************************************** * *     This program is free software; you can redistribute it and/or *     modify it under the terms of the GNU General Public License as *     published by the Free Software Foundation; either version 2 of *     the License, or (at your option) any later version. * *     This program is distributed in the hope that it will be useful, *     but WITHOUT ANY WARRANTY; without even the implied warranty of *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *     GNU General Public License for more details. * *     You should have received a copy of the GNU General Public *     License along with this program; if not, write to the Free *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, *     USA. * ********************************************************************** */#include <linux/poll.h>#include "hwaccess.h"#include "8010.h"#include "voicemgr.h"#include "cardwo.h"#include "audio.h"static u32 samplerate_to_linearpitch(u32 samplingrate){	samplingrate = (samplingrate << 8) / 375;	return (samplingrate >> 1) + (samplingrate & 1);}static void query_format(struct emu10k1_wavedevice *wave_dev, struct wave_format *wave_fmt){	int i, j, do_passthrough = 0, is_ac3 = 0;	struct emu10k1_card *card = wave_dev->card;	struct woinst *woinst = wave_dev->woinst;	if ((wave_fmt->channels > 2) && (wave_fmt->id != AFMT_S16_LE) && (wave_fmt->id != AFMT_U8))		wave_fmt->channels = 2;	if ((wave_fmt->channels < 1) || (wave_fmt->channels > WAVEOUT_MAXVOICES))		wave_fmt->channels = 2;	if (wave_fmt->channels == 2)		woinst->num_voices = 1;	else		woinst->num_voices = wave_fmt->channels;	if (wave_fmt->samplingrate >= 0x2ee00)		wave_fmt->samplingrate = 0x2ee00;	wave_fmt->passthrough = 0;	do_passthrough = is_ac3 = 0;	if (card->pt.selected)		do_passthrough = 1;	switch (wave_fmt->id) {	case AFMT_S16_LE:		wave_fmt->bitsperchannel = 16;		break;	case AFMT_U8:		wave_fmt->bitsperchannel = 8;		break;	case AFMT_AC3:		do_passthrough = 1;		is_ac3 = 1;		break;	default:		wave_fmt->id = AFMT_S16_LE;		wave_fmt->bitsperchannel = 16;		break;	}		if (do_passthrough) {		i = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.intr_gpr_name);		j = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.enable_gpr_name);		/* currently only one waveout instance may use pass-through */		if (i < 0 || j < 0 || woinst->state != WAVE_STATE_CLOSED || 		    card->pt.state != PT_STATE_INACTIVE ||		    (wave_fmt->samplingrate != 48000 && !is_ac3) ||		    (wave_fmt->samplingrate != 48000 && !is_ac3)) {			DPF(2, "unable to set pass-through mode\n");		} else {			wave_fmt->samplingrate = 48000;			wave_fmt->channels = 2;			wave_fmt->passthrough = 1;			card->pt.intr_gpr = i;			card->pt.enable_gpr = j;			card->pt.state = PT_STATE_INACTIVE;			card->pt.pos_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.pos_gpr_name);			DPD(2, "is_ac3 is %d\n", is_ac3);			card->pt.ac3data = is_ac3;	                wave_fmt->bitsperchannel = 16;		}	}	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;	if (wave_fmt->channels == 2)		wave_fmt->bytespervoicesample = wave_fmt->channels * wave_fmt->bytesperchannel;	else		wave_fmt->bytespervoicesample = wave_fmt->bytesperchannel;	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;}/** * alloc_buffer - * * allocates the memory buffer for a voice. Two page tables are kept for each buffer. * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable) * is passed to the device so that it can do DMA to host memory.  * */static int alloc_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum){	u32 pageindex, pagecount;	unsigned long busaddx;	int i;	DPD(2, "requested pages is: %d\n", buffer->pages);	if ((buffer->mem[voicenum].emupageindex =	 emu10k1_addxmgr_alloc(buffer->pages * PAGE_SIZE, card)) < 0)		return -1;	/* Fill in virtual memory table */	for (pagecount = 0; pagecount < buffer->pages; pagecount++) {		if ((buffer->mem[voicenum].addr[pagecount] =		 pci_alloc_consistent(card->pci_dev, PAGE_SIZE,		 &buffer->mem[voicenum].dma_handle[pagecount])) == NULL) {			buffer->pages = pagecount;			return -1;		}		DPD(2, "Virtual Addx: %p\n", buffer->mem[voicenum].addr[pagecount]);		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {			busaddx = buffer->mem[voicenum].dma_handle[pagecount] + i * EMUPAGESIZE;			DPD(3, "Bus Addx: %#lx\n", busaddx);			pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;			((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex);		}	}	return 0;}/** * free_buffer - * * frees the memory buffer for a voice. */static void free_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum){	u32 pagecount, pageindex;	int i;	if (buffer->mem[voicenum].emupageindex < 0)		return;	for (pagecount = 0; pagecount < buffer->pages; pagecount++) {		pci_free_consistent(card->pci_dev, PAGE_SIZE,		 buffer->mem[voicenum].addr[pagecount],		 buffer->mem[voicenum].dma_handle[pagecount]);		for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {			pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;			((u32 *) card->virtualpagetable.addr)[pageindex] =			 cpu_to_le32((card->silentpage.dma_handle * 2) | pageindex);		}	}	emu10k1_addxmgr_free(card, buffer->mem[voicenum].emupageindex);	buffer->mem[voicenum].emupageindex = -1;}static int get_voice(struct emu10k1_card *card, struct woinst *woinst, unsigned int voicenum){	struct emu_voice *voice = &woinst->voice[voicenum];	/* Allocate voices here, if no voices available, return error.	 * Init voice_allocdesc first.*/	voice->usage = VOICE_USAGE_PLAYBACK;	voice->flags = 0;	if (woinst->format.channels == 2)		voice->flags |= VOICE_FLAGS_STEREO;	if (woinst->format.bitsperchannel == 16)		voice->flags |= VOICE_FLAGS_16BIT;	if (emu10k1_voice_alloc(card, voice) < 0) {		voice->usage = VOICE_USAGE_FREE;		return -1;	}	/* Calculate pitch */	voice->initial_pitch = (u16) (srToPitch(woinst->format.samplingrate) >> 8);	voice->pitch_target = samplerate_to_linearpitch(woinst->format.samplingrate);	DPD(2, "Initial pitch --> %#x\n", voice->initial_pitch);	voice->startloop = (woinst->buffer.mem[voicenum].emupageindex << 12) /	 woinst->format.bytespervoicesample;	voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample;	voice->start = voice->startloop;	if (voice->flags & VOICE_FLAGS_STEREO) {		voice->params[0].send_a = card->waveout.send_a[1];		voice->params[0].send_b = card->waveout.send_b[1];		voice->params[0].send_c = card->waveout.send_c[1];		voice->params[0].send_d = card->waveout.send_d[1];		if (woinst->device)			voice->params[0].send_routing = 0x7654;		else			voice->params[0].send_routing = card->waveout.send_routing[1];		voice->params[0].volume_target = 0xffff;		voice->params[0].initial_fc = 0xff;		voice->params[0].initial_attn = 0x00;		voice->params[0].byampl_env_sustain = 0x7f;		voice->params[0].byampl_env_decay = 0x7f;		voice->params[1].send_a = card->waveout.send_a[2];		voice->params[1].send_b = card->waveout.send_b[2];		voice->params[1].send_c = card->waveout.send_c[2];		voice->params[1].send_d = card->waveout.send_d[2];		if (woinst->device)			voice->params[1].send_routing = 0x7654;		else			voice->params[1].send_routing = card->waveout.send_routing[2];		voice->params[1].volume_target = 0xffff;		voice->params[1].initial_fc = 0xff;		voice->params[1].initial_attn = 0x00;		voice->params[1].byampl_env_sustain = 0x7f;		voice->params[1].byampl_env_decay = 0x7f;	} else {		if (woinst->num_voices > 1) {			voice->params[0].send_a = 0xff;			voice->params[0].send_b = 0;			voice->params[0].send_c = 0;			voice->params[0].send_d = 0;			voice->params[0].send_routing =			 0xfff0 + card->mchannel_fx + voicenum;		} else {			voice->params[0].send_a = card->waveout.send_a[0];			voice->params[0].send_b = card->waveout.send_b[0];			voice->params[0].send_c = card->waveout.send_c[0];			voice->params[0].send_d = card->waveout.send_d[0];			if (woinst->device)				voice->params[0].send_routing = 0x7654;			else				voice->params[0].send_routing = card->waveout.send_routing[0];		}			voice->params[0].volume_target = 0xffff;		voice->params[0].initial_fc = 0xff;		voice->params[0].initial_attn = 0x00;		voice->params[0].byampl_env_sustain = 0x7f;		voice->params[0].byampl_env_decay = 0x7f;	}	DPD(2, "voice: startloop=%#x, endloop=%#x\n", voice->startloop, voice->endloop);	emu10k1_voice_playback_setup(voice);	return 0;}int emu10k1_waveout_open(struct emu10k1_wavedevice *wave_dev){	struct emu10k1_card *card = wave_dev->card;	struct woinst *woinst = wave_dev->woinst;	struct waveout_buffer *buffer = &woinst->buffer;	unsigned int voicenum;	u32 delay;	DPF(2, "emu10k1_waveout_open()\n");	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {		if (alloc_buffer(card, buffer, voicenum) < 0) {			ERROR();			emu10k1_waveout_close(wave_dev);			return -1;		}		if (get_voice(card, woinst, voicenum) < 0) {			ERROR();			emu10k1_waveout_close(wave_dev);			return -1;		}	}	buffer->fill_silence = 0;	buffer->silence_bytes = 0;	buffer->silence_pos = 0;	buffer->hw_pos = 0;	buffer->free_bytes = woinst->buffer.size;	delay = (48000 * woinst->buffer.fragment_size) /		 (woinst->format.samplingrate * woinst->format.bytespervoicesample);	emu10k1_timer_install(card, &woinst->timer, delay / 2);	woinst->state = WAVE_STATE_OPEN;	return 0;}void emu10k1_waveout_close(struct emu10k1_wavedevice *wave_dev){	struct emu10k1_card *card = wave_dev->card;	struct woinst *woinst = wave_dev->woinst;	unsigned int voicenum;	DPF(2, "emu10k1_waveout_close()\n");	emu10k1_waveout_stop(wave_dev);	emu10k1_timer_uninstall(card, &woinst->timer);	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {		emu10k1_voice_free(&woinst->voice[voicenum]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -