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

📄 cardwo.c

📁 linux-2.6.15.6
💻 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) {		/* currently only one waveout instance may use pass-through */		if (woinst->state != WAVE_STATE_CLOSED || 		    card->pt.state != PT_STATE_INACTIVE ||		    (wave_fmt->samplingrate != 48000 && !is_ac3)) {			DPF(2, "unable to set pass-through mode\n");		} else if (USE_PT_METHOD1) {			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);			if (i < 0 || j < 0)				DPF(2, "unable to set pass-through mode\n");			else {				wave_fmt->samplingrate = 48000;				wave_fmt->channels = 2;				card->pt.pos_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,									    card->pt.pos_gpr_name);				wave_fmt->passthrough = 1;				card->pt.intr_gpr = i;				card->pt.enable_gpr = j;				card->pt.state = PT_STATE_INACTIVE;							DPD(2, "is_ac3 is %d\n", is_ac3);				card->pt.ac3data = is_ac3;				wave_fmt->bitsperchannel = 16;			}		}else{			DPF(2, "Using Passthrough Method 2\n");			card->pt.enable_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name,								       card->pt.enable_gpr_name);			wave_fmt->passthrough = 2;			wave_fmt->bitsperchannel = 16;		}	}	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;	if (wave_fmt->channels == 2)		wave_fmt->bytespervoicesample = wave_fmt->channels * wave_fmt->bytesperchannel;	else		wave_fmt->bytespervoicesample = wave_fmt->bytesperchannel;}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. */	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 = (voice->mem.emupageindex << 12) /	 woinst->format.bytespervoicesample;	voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample;	voice->start = voice->startloop;		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;		if (voice->flags & VOICE_FLAGS_STEREO) {		if (woinst->format.passthrough == 2) {			voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PT];			voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PT];			voice->params[0].send_dcba = 0xff;			voice->params[1].send_dcba = 0xff00;			voice->params[0].send_hgfe = voice->params[1].send_hgfe=0;		} else {			voice->params[0].send_dcba = card->waveout.send_dcba[SEND_LEFT];			voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_LEFT];			voice->params[1].send_dcba = card->waveout.send_dcba[SEND_RIGHT];			voice->params[1].send_hgfe = card->waveout.send_hgfe[SEND_RIGHT];			if (woinst->device) {				// /dev/dps1				voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PCM1];				voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];			} else {				voice->params[0].send_routing  = voice->params[1].send_routing  = card->waveout.send_routing[ROUTE_PCM];				voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];			}		}				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) {			// Multichannel pcm			voice->params[0].send_dcba=0xff;			voice->params[0].send_hgfe=0;			if (card->is_audigy) {				voice->params[0].send_routing = 0x3f3f3f00 + card->mchannel_fx + voicenum;				voice->params[0].send_routing2 = 0x3f3f3f3f;			} else {				voice->params[0].send_routing = 0xfff0 + card->mchannel_fx + voicenum;			}					} else {			voice->params[0].send_dcba = card->waveout.send_dcba[SEND_MONO];			voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_MONO];			if (woinst->device) {				voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM1];				voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1];			} else {				voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM];				voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM];			}		}	}	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;	u16 delay;	DPF(2, "emu10k1_waveout_open()\n");	for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) {		if (emu10k1_voice_alloc_buffer(card, &woinst->voice[voicenum].mem, woinst->buffer.pages) < 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);	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]);		emu10k1_voice_free_buffer(card, &woinst->voice[voicenum].mem);	}	woinst->state = WAVE_STATE_CLOSED;}void emu10k1_waveout_start(struct emu10k1_wavedevice *wave_dev){	struct emu10k1_card *card = wave_dev->card;	struct woinst *woinst = wave_dev->woinst;	struct pt_data *pt = &card->pt;	DPF(2, "emu10k1_waveout_start()\n");	if (woinst->format.passthrough == 2) {		emu10k1_pt_setup(wave_dev);		sblive_writeptr(card, (card->is_audigy ? A_GPR_BASE : GPR_BASE) + pt->enable_gpr, 0, 1);		pt->state = PT_STATE_PLAYING;	}	/* Actual start */	emu10k1_voices_start(woinst->voice, woinst->num_voices, woinst->total_played);	emu10k1_timer_enable(card, &woinst->timer);	woinst->state |= WAVE_STATE_STARTED;}int emu10k1_waveout_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format){	struct emu10k1_card *card = wave_dev->card;	struct woinst *woinst = wave_dev->woinst;	unsigned int voicenum;	u16 delay;	DPF(2, "emu10k1_waveout_setformat()\n");

⌨️ 快捷键说明

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