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

📄 emupcm.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	return result;}static snd_pcm_uframes_t snd_emu10k1_capture_pointer(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_emu10k1_pcm *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 struct snd_pcm_hardware snd_emu10k1_playback ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_RESUME |				 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_96000,	.rate_min =		4000,	.rate_max =		96000,	.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 struct snd_pcm_hardware snd_emu10k1_capture ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_RESUME |				 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 struct snd_pcm_hardware snd_emu10k1_capture_efx ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_RESUME |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =		SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 				 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | 				 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,	.rate_min =		44100,	.rate_max =		192000,	.channels_min =		8,	.channels_max =		8,	.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(struct snd_emu10k1 *emu, struct snd_kcontrol *kctl, int idx, int activate){	struct snd_ctl_elem_id id;	if (! kctl)		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(struct snd_emu10k1 *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_efx_mixer_notify(struct snd_emu10k1 *emu, int idx, int activate){	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_routing, idx, activate);	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_volume, idx, activate);	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_attn, idx, activate);}static void snd_emu10k1_pcm_free_substream(struct snd_pcm_runtime *runtime){	kfree(runtime->private_data);}static int snd_emu10k1_efx_playback_close(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	struct snd_emu10k1_pcm_mixer *mix;	int i;	for (i = 0; i < NUM_EFX_PLAYBACK; i++) {		mix = &emu->efx_pcm_mixer[i];		mix->epcm = NULL;		snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0);	}	return 0;}static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	struct snd_emu10k1_pcm *epcm;	struct snd_emu10k1_pcm_mixer *mix;	struct snd_pcm_runtime *runtime = substream->runtime;	int i;	epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);	if (epcm == NULL)		return -ENOMEM;	epcm->emu = emu;	epcm->type = PLAYBACK_EFX;	epcm->substream = substream;		emu->pcm_playback_efx_substream = substream;	runtime->private_data = epcm;	runtime->private_free = snd_emu10k1_pcm_free_substream;	runtime->hw = snd_emu10k1_efx_playback;		for (i = 0; i < NUM_EFX_PLAYBACK; i++) {		mix = &emu->efx_pcm_mixer[i];		mix->send_routing[0][0] = i;		memset(&mix->send_volume, 0, sizeof(mix->send_volume));		mix->send_volume[0][0] = 255;		mix->attn[0] = 0xffff;		mix->epcm = epcm;		snd_emu10k1_pcm_efx_mixer_notify(emu, i, 1);	}	return 0;}static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	struct snd_emu10k1_pcm *epcm;	struct snd_emu10k1_pcm_mixer *mix;	struct snd_pcm_runtime *runtime = substream->runtime;	int i, err;	epcm = kzalloc(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(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	struct snd_emu10k1_pcm_mixer *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(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	struct snd_pcm_runtime *runtime = substream->runtime;	struct snd_emu10k1_pcm *epcm;	epcm = kzalloc(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(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	emu->capture_interrupt = NULL;	emu->pcm_capture_substream = NULL;	return 0;}static int snd_emu10k1_capture_mic_open(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	struct snd_emu10k1_pcm *epcm;	struct snd_pcm_runtime *runtime = substream->runtime;	epcm = kzalloc(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(struct snd_pcm_substream *substream){	struct snd_emu10k1 *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(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	struct snd_emu10k1_pcm *epcm;	struct snd_pcm_runtime *runtime = substream->runtime;	int nefx = emu->audigy ? 64 : 32;	int idx;	epcm = kzalloc(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_efx;	runtime->hw.rates = SNDRV_PCM_RATE_48000;	runtime->hw.rate_min = runtime->hw.rate_max = 48000;	spin_lock_irq(&emu->reg_lock);	if (emu->card_capabilities->emu1010) {		/*  Nb. of channels has been increased to 16 */		/* TODO		 * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE		 * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |		 * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |		 * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000		 * rate_min = 44100,		 * rate_max = 192000,		 * channels_min = 16,		 * channels_max = 16,		 * Need to add mixer control to fix sample rate		 *                 		 * There are 32 mono channels of 16bits each.		 * 24bit Audio uses 2x channels over 16bit		 * 96kHz uses 2x channels over 48kHz		 * 192kHz uses 4x channels over 48kHz		 * So, for 48kHz 24bit, one has 16 channels		 * for 96kHz 24bit, one has 8 channels		 * for 192kHz 24bit, one has 4 channels		 *		 */#if 1		switch (emu->emu1010.internal_clock) {		case 0:			/* For 44.1kHz */			runtime->hw.rates = SNDRV_PCM_RATE_44100;			runtime->hw.rate_min = runtime->hw.rate_max = 44100;			runtime->hw.channels_min =				runtime->hw.channels_max = 16;			break;		case 1:			/* For 48kHz */			runtime->hw.rates = SNDRV_PCM_RATE_48000;			runtime->hw.rate_min = runtime->hw.rate_max = 48000;			runtime->hw.channels_min =				runtime->hw.channels_max = 16;			break;		};#endif#if 0		/* For 96kHz */		runtime->hw.rates = SNDRV_PCM_RATE_96000;		runtime->hw.rate_min = runtime->hw.rate_max = 96000;		runtime->hw.channels_min = runtime->hw.channels_max = 4;#endif#if 0		/* For 192kHz */		runtime->hw.rates = SNDRV_PCM_RATE_192000;		runtime->hw.rate_min = runtime->hw.rate_max = 192000;		runtime->hw.channels_min = runtime->hw.channels_max = 2;#endif		runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;		/* efx_voices_mask[0] is expected to be zero 		 * efx_voices_mask[1] is expected to have 32bits set		 */	} else {		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;	emu->pcm_capture_efx_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_efx_close(struct snd_pcm_substream *substream){	struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);	emu->capture_interrupt = NULL;	emu->pcm_capture_efx_substream = NULL;	return 0;}static struct snd_pcm_ops snd_emu10k1_playback_ops = {	.open =			snd_emu10k1_playback_open,	.close =		snd_emu10k1_playback_close,	.ioctl =		snd_pcm_lib_ioctl,	.hw_params =		snd_emu10k1_playback_hw_params,	.hw_free =		snd_emu10k1_playback_hw_free,	.prepare =		snd_emu10k1_playback_prepare,	.trigger =		snd_emu10k1_playback_trigger,	.pointer =		snd_emu10k1_playback_pointer,	.page =			snd_pcm_sgbuf_ops_page,};static struct snd_pcm_ops snd_emu10k1_capture_ops = {	.open =			snd_emu10k1_capture_open,	.close =		snd_emu10k1_capture_close,	.ioctl =		snd_pcm_lib_ioctl,	.hw_params =		snd_emu10k1_capture_hw_params,	.hw_free =		snd_emu10k1_capture_hw_free,	.prepare =		snd_emu10k1_capture_prepare,	.trigger =		snd_emu10k1_capture_trigger,	.pointer =		snd_emu10k1_capture_pointer,};/* EFX playback */static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {	.open =			snd_emu10k1_efx_playback_open,	.close =		snd_emu10k1_efx_playback_close,	.ioctl =		snd_pcm_lib_ioctl,	.hw_params =		snd_emu10k1_playback_hw_params,	.hw_free =		snd_emu10k1_efx_playback_hw_free,	.prepare =		snd_emu10k1_efx_playback_prepare,	.trigger =		snd_emu10k1_efx_playback_trigger,	.pointer =		snd_emu10k1_efx_playback_pointer,	.page =			snd_pcm_sgbuf_ops_page,};int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm){	struct snd_pcm *pcm;	struct snd_pcm_substream *substream;	int err;	if (rpcm)		*rpcm = NULL;	if ((err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm)) < 0)		return err;	pcm->private_data = emu;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_playback_ops);

⌨️ 快捷键说明

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