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

📄 emupcm.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		epcm->capture_bs_val++;	}	if (epcm->type == CAPTURE_AC97ADC) {		epcm->capture_cr_val = emu->audigy ? A_ADCCR_LCHANENABLE : ADCCR_LCHANENABLE;		if (runtime->channels > 1)			epcm->capture_cr_val |= emu->audigy ? A_ADCCR_RCHANENABLE : ADCCR_RCHANENABLE;		epcm->capture_cr_val |= emu->audigy ?			snd_emu10k1_audigy_capture_rate_reg(runtime->rate) :			snd_emu10k1_capture_rate_reg(runtime->rate);	}	return 0;}static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, emu10k1_voice_t *evoice){	snd_pcm_runtime_t *runtime;	unsigned int voice, i, ccis, cra = 64, cs, sample;	if (evoice == NULL)		return;	runtime = evoice->epcm->substream->runtime;	voice = evoice->number;	sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080;	if (runtime->channels > 1) {		ccis = 28;		cs = 4;	} else {		ccis = 30;		cs = 2;	}	if (sample == 0)	/* 16-bit */		ccis *= 2;	for (i = 0; i < cs; i++)		snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample);	// reset cache	snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0);	snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);	if (runtime->channels > 1) {		snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);		snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);	}	// fill cache	snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);}static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra){	snd_pcm_substream_t *substream;	snd_pcm_runtime_t *runtime;	emu10k1_pcm_mixer_t *mix;	unsigned int voice, pitch, pitch_target, tmp;	unsigned int attn;	if (evoice == NULL)	/* skip second voice for mono */		return;	substream = evoice->epcm->substream;	runtime = substream->runtime;	mix = &emu->pcm_mixer[substream->number];	voice = evoice->number;	pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8;	pitch_target = emu10k1_calc_pitch_target(runtime->rate);	attn = extra ? 0 : 0x00ff;	tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0;	snd_emu10k1_ptr_write(emu, IFATN, voice, attn);	snd_emu10k1_ptr_write(emu, VTFT, voice, (mix->attn[tmp] << 16) | 0xffff);	snd_emu10k1_ptr_write(emu, CVCF, voice, (mix->attn[tmp] << 16) | 0xffff);	snd_emu10k1_voice_clear_loop_stop(emu, voice);			if (extra)		snd_emu10k1_voice_intr_enable(emu, voice);	snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f);	snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target);	if (master)		snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target);	snd_emu10k1_ptr_write(emu, IP, voice, pitch);}static void snd_emu10k1_playback_stop_voice(emu10k1_t *emu, emu10k1_voice_t *evoice){	unsigned int voice;	if (evoice == NULL)		return;	voice = evoice->number;	snd_emu10k1_voice_intr_disable(emu, voice);	snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, 0);	snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, 0);	snd_emu10k1_ptr_write(emu, IFATN, voice, 0xffff);	snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff);	snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff);	snd_emu10k1_ptr_write(emu, IP, voice, 0);}static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,				        int cmd){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1_pcm_t *epcm = runtime->private_data;	int result = 0;	// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));	spin_lock(&emu->reg_lock);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		snd_emu10k1_playback_invalidate_cache(emu, epcm->extra);	/* do we need this? */		snd_emu10k1_playback_invalidate_cache(emu, epcm->voices[0]);		/* follow thru */	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:		snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0);		snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0);		snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);		epcm->running = 1;		break;	case SNDRV_PCM_TRIGGER_STOP:	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:		epcm->running = 0;		snd_emu10k1_playback_stop_voice(emu, epcm->voices[0]);		snd_emu10k1_playback_stop_voice(emu, epcm->voices[1]);		snd_emu10k1_playback_stop_voice(emu, epcm->extra);		break;	default:		result = -EINVAL;		break;	}	spin_unlock(&emu->reg_lock);	return result;}static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,				       int cmd){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1_pcm_t *epcm = runtime->private_data;	int result = 0;	// printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream));	spin_lock(&emu->reg_lock);	switch (cmd) {	case SNDRV_PCM_TRIGGER_START:		outl(epcm->capture_ipr, emu->port + IPR);		snd_emu10k1_intr_enable(emu, epcm->capture_inte);		// printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs);		switch (epcm->type) {		case CAPTURE_AC97ADC:			snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);			break;		case CAPTURE_EFX:			if (emu->audigy) {				snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);				snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);			} else				snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);			break;		default:				break;		}		snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, epcm->capture_bs_val);		epcm->running = 1;		epcm->first_ptr = 1;		break;	case SNDRV_PCM_TRIGGER_STOP:		epcm->running = 0;		snd_emu10k1_intr_disable(emu, epcm->capture_inte);		outl(epcm->capture_ipr, emu->port + IPR);		snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);		switch (epcm->type) {		case CAPTURE_AC97ADC:			snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);			break;		case CAPTURE_EFX:			if (emu->audigy) {				snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);				snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);			} else				snd_emu10k1_ptr_write(emu, FXWC, 0, 0);			break;		default:			break;		}		break;	default:		result = -EINVAL;	}	spin_unlock(&emu->reg_lock);	return result;}static snd_pcm_uframes_t snd_emu10k1_playback_pointer(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1_pcm_t *epcm = runtime->private_data;	unsigned int ptr;	if (!epcm->running)		return 0;	ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff;#if 0	/* Perex's code */	ptr += runtime->buffer_size;	ptr -= epcm->ccca_start_addr;	ptr %= runtime->buffer_size;#else	/* EMU10K1 Open Source code from Creative */	if (ptr < epcm->ccca_start_addr)		ptr += runtime->buffer_size - epcm->ccca_start_addr;	else {		ptr -= epcm->ccca_start_addr;		if (ptr >= runtime->buffer_size)			ptr -= runtime->buffer_size;	}#endif	// printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size);	return ptr;}static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1_pcm_t *epcm = runtime->private_data;	unsigned int ptr;	if (!epcm->running)		return 0;	if (epcm->first_ptr) {		udelay(50);	// hack, it takes awhile until capture is started		epcm->first_ptr = 0;	}	ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff;	return bytes_to_frames(runtime, ptr);}/* *  Playback support device description */static snd_pcm_hardware_t snd_emu10k1_playback ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		4000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(128*1024),	.period_bytes_min =	64,	.period_bytes_max =	(128*1024),	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};/* *  Capture support device description */static snd_pcm_hardware_t snd_emu10k1_capture ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =		SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_8000_48000,	.rate_min =		8000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(64*1024),	.period_bytes_min =	384,	.period_bytes_max =	(64*1024),	.periods_min =		2,	.periods_max =		2,	.fifo_size =		0,};/* * */static void snd_emu10k1_pcm_mixer_notify1(emu10k1_t *emu, snd_kcontrol_t *kctl, int idx, int activate){	snd_ctl_elem_id_t id;	snd_runtime_check(kctl != NULL, return);	if (activate)		kctl->vd[idx].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;	else		kctl->vd[idx].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;	snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |		       SNDRV_CTL_EVENT_MASK_INFO,		       snd_ctl_build_ioff(&id, kctl, idx));}static void snd_emu10k1_pcm_mixer_notify(emu10k1_t *emu, int idx, int activate){	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_routing, idx, activate);	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_volume, idx, activate);	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate);}static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime){	emu10k1_pcm_t *epcm = runtime->private_data;	kfree(epcm);}static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	emu10k1_pcm_t *epcm;	emu10k1_pcm_mixer_t *mix;	snd_pcm_runtime_t *runtime = substream->runtime;	int i, err;	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);	if (epcm == NULL)		return -ENOMEM;	epcm->emu = emu;	epcm->type = PLAYBACK_EMUVOICE;	epcm->substream = substream;	runtime->private_data = epcm;	runtime->private_free = snd_emu10k1_pcm_free_substream;	runtime->hw = snd_emu10k1_playback;	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) {		kfree(epcm);		return err;	}	if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) {		kfree(epcm);		return err;	}	mix = &emu->pcm_mixer[substream->number];	for (i = 0; i < 4; i++)		mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i;	memset(&mix->send_volume, 0, sizeof(mix->send_volume));	mix->send_volume[0][0] = mix->send_volume[0][1] =	mix->send_volume[1][0] = mix->send_volume[2][1] = 255;	mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;	mix->epcm = epcm;	snd_emu10k1_pcm_mixer_notify(emu, substream->number, 1);	return 0;}static int snd_emu10k1_playback_close(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number];	mix->epcm = NULL;	snd_emu10k1_pcm_mixer_notify(emu, substream->number, 0);	return 0;}static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	emu10k1_pcm_t *epcm;	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);	if (epcm == NULL)		return -ENOMEM;	epcm->emu = emu;	epcm->type = CAPTURE_AC97ADC;	epcm->substream = substream;	epcm->capture_ipr = IPR_ADCBUFFULL|IPR_ADCBUFHALFFULL;	epcm->capture_inte = INTE_ADCBUFENABLE;	epcm->capture_ba_reg = ADCBA;	epcm->capture_bs_reg = ADCBS;	epcm->capture_idx_reg = emu->audigy ? A_ADCIDX : ADCIDX;	runtime->private_data = epcm;	runtime->private_free = snd_emu10k1_pcm_free_substream;	runtime->hw = snd_emu10k1_capture;	emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;	emu->pcm_capture_substream = substream;	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates);	return 0;}static int snd_emu10k1_capture_close(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	emu->capture_interrupt = NULL;	emu->pcm_capture_substream = NULL;	return 0;}static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	emu10k1_pcm_t *epcm;	snd_pcm_runtime_t *runtime = substream->runtime;	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);	if (epcm == NULL)		return -ENOMEM;	epcm->emu = emu;	epcm->type = CAPTURE_AC97MIC;	epcm->substream = substream;	epcm->capture_ipr = IPR_MICBUFFULL|IPR_MICBUFHALFFULL;	epcm->capture_inte = INTE_MICBUFENABLE;	epcm->capture_ba_reg = MICBA;	epcm->capture_bs_reg = MICBS;	epcm->capture_idx_reg = emu->audigy ? A_MICIDX : MICIDX;	substream->runtime->private_data = epcm;	substream->runtime->private_free = snd_emu10k1_pcm_free_substream;	runtime->hw = snd_emu10k1_capture;	runtime->hw.rates = SNDRV_PCM_RATE_8000;	runtime->hw.rate_min = runtime->hw.rate_max = 8000;	runtime->hw.channels_min = 1;	emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt;	emu->pcm_capture_mic_substream = substream;	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);	return 0;}static int snd_emu10k1_capture_mic_close(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	emu->capture_interrupt = NULL;	emu->pcm_capture_mic_substream = NULL;	return 0;}static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream){	emu10k1_t *emu = snd_pcm_substream_chip(substream);	emu10k1_pcm_t *epcm;	snd_pcm_runtime_t *runtime = substream->runtime;	int nefx = emu->audigy ? 64 : 32;	int idx;	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);	if (epcm == NULL)		return -ENOMEM;	epcm->emu = emu;	epcm->type = CAPTURE_EFX;	epcm->substream = substream;	epcm->capture_ipr = IPR_EFXBUFFULL|IPR_EFXBUFHALFFULL;	epcm->capture_inte = INTE_EFXBUFENABLE;	epcm->capture_ba_reg = FXBA;	epcm->capture_bs_reg = FXBS;	epcm->capture_idx_reg = FXIDX;	substream->runtime->private_data = epcm;	substream->runtime->private_free = snd_emu10k1_pcm_free_substream;	runtime->hw = snd_emu10k1_capture;	runtime->hw.rates = SNDRV_PCM_RATE_48000;	runtime->hw.rate_min = runtime->hw.rate_max = 48000;	spin_lock_irq(&emu->reg_lock);	runtime->hw.channels_min = runtime->hw.channels_max = 0;	for (idx = 0; idx < nefx; idx++) {		if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {			runtime->hw.channels_min++;			runtime->hw.channels_max++;		}	}	epcm->capture_cr_val = emu->efx_voices_mask[0];	epcm->capture_cr_val2 = emu->efx_voices_mask[1];	spin_unlock_irq(&emu->reg_lock);	emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt;

⌨️ 快捷键说明

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