ens1370.c

来自「linux 内核源代码」· C语言 代码 · 共 1,967 行 · 第 1/5 页

C
1,967
字号
}static int snd_ensoniq_playback2_close(struct snd_pcm_substream *substream){	struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);	ensoniq->playback2_substream = NULL;	spin_lock_irq(&ensoniq->reg_lock);#ifdef CHIP1370	ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_PLAY2;#endif	ensoniq->mode &= ~ES_MODE_PLAY2;	spin_unlock_irq(&ensoniq->reg_lock);	return 0;}static int snd_ensoniq_capture_close(struct snd_pcm_substream *substream){	struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);	ensoniq->capture_substream = NULL;	spin_lock_irq(&ensoniq->reg_lock);#ifdef CHIP1370	ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_CAPTURE;#endif	ensoniq->mode &= ~ES_MODE_CAPTURE;	spin_unlock_irq(&ensoniq->reg_lock);	return 0;}static struct snd_pcm_ops snd_ensoniq_playback1_ops = {	.open =		snd_ensoniq_playback1_open,	.close =	snd_ensoniq_playback1_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_ensoniq_hw_params,	.hw_free =	snd_ensoniq_hw_free,	.prepare =	snd_ensoniq_playback1_prepare,	.trigger =	snd_ensoniq_trigger,	.pointer =	snd_ensoniq_playback1_pointer,};static struct snd_pcm_ops snd_ensoniq_playback2_ops = {	.open =		snd_ensoniq_playback2_open,	.close =	snd_ensoniq_playback2_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_ensoniq_hw_params,	.hw_free =	snd_ensoniq_hw_free,	.prepare =	snd_ensoniq_playback2_prepare,	.trigger =	snd_ensoniq_trigger,	.pointer =	snd_ensoniq_playback2_pointer,};static struct snd_pcm_ops snd_ensoniq_capture_ops = {	.open =		snd_ensoniq_capture_open,	.close =	snd_ensoniq_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_ensoniq_hw_params,	.hw_free =	snd_ensoniq_hw_free,	.prepare =	snd_ensoniq_capture_prepare,	.trigger =	snd_ensoniq_trigger,	.pointer =	snd_ensoniq_capture_pointer,};static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device,				     struct snd_pcm ** rpcm){	struct snd_pcm *pcm;	int err;	if (rpcm)		*rpcm = NULL;#ifdef CHIP1370	err = snd_pcm_new(ensoniq->card, "ES1370/1", device, 1, 1, &pcm);#else	err = snd_pcm_new(ensoniq->card, "ES1371/1", device, 1, 1, &pcm);#endif	if (err < 0)		return err;#ifdef CHIP1370	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ensoniq_playback2_ops);#else	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ensoniq_playback1_ops);#endif	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ensoniq_capture_ops);	pcm->private_data = ensoniq;	pcm->info_flags = 0;#ifdef CHIP1370	strcpy(pcm->name, "ES1370 DAC2/ADC");#else	strcpy(pcm->name, "ES1371 DAC2/ADC");#endif	ensoniq->pcm1 = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024);	if (rpcm)		*rpcm = pcm;	return 0;}static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device,				      struct snd_pcm ** rpcm){	struct snd_pcm *pcm;	int err;	if (rpcm)		*rpcm = NULL;#ifdef CHIP1370	err = snd_pcm_new(ensoniq->card, "ES1370/2", device, 1, 0, &pcm);#else	err = snd_pcm_new(ensoniq->card, "ES1371/2", device, 1, 0, &pcm);#endif	if (err < 0)		return err;#ifdef CHIP1370	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ensoniq_playback1_ops);#else	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ensoniq_playback2_ops);#endif	pcm->private_data = ensoniq;	pcm->info_flags = 0;#ifdef CHIP1370	strcpy(pcm->name, "ES1370 DAC1");#else	strcpy(pcm->name, "ES1371 DAC1");#endif	ensoniq->pcm2 = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024);	if (rpcm)		*rpcm = pcm;	return 0;}/* *  Mixer section *//* * ENS1371 mixer (including SPDIF interface) */#ifdef CHIP1371static int snd_ens1373_spdif_info(struct snd_kcontrol *kcontrol,				  struct snd_ctl_elem_info *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;	uinfo->count = 1;	return 0;}static int snd_ens1373_spdif_default_get(struct snd_kcontrol *kcontrol,                                         struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);	spin_lock_irq(&ensoniq->reg_lock);	ucontrol->value.iec958.status[0] = (ensoniq->spdif_default >> 0) & 0xff;	ucontrol->value.iec958.status[1] = (ensoniq->spdif_default >> 8) & 0xff;	ucontrol->value.iec958.status[2] = (ensoniq->spdif_default >> 16) & 0xff;	ucontrol->value.iec958.status[3] = (ensoniq->spdif_default >> 24) & 0xff;	spin_unlock_irq(&ensoniq->reg_lock);	return 0;}static int snd_ens1373_spdif_default_put(struct snd_kcontrol *kcontrol,                                         struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);	unsigned int val;	int change;	val = ((u32)ucontrol->value.iec958.status[0] << 0) |	      ((u32)ucontrol->value.iec958.status[1] << 8) |	      ((u32)ucontrol->value.iec958.status[2] << 16) |	      ((u32)ucontrol->value.iec958.status[3] << 24);	spin_lock_irq(&ensoniq->reg_lock);	change = ensoniq->spdif_default != val;	ensoniq->spdif_default = val;	if (change && ensoniq->playback1_substream == NULL &&	    ensoniq->playback2_substream == NULL)		outl(val, ES_REG(ensoniq, CHANNEL_STATUS));	spin_unlock_irq(&ensoniq->reg_lock);	return change;}static int snd_ens1373_spdif_mask_get(struct snd_kcontrol *kcontrol,				      struct snd_ctl_elem_value *ucontrol){	ucontrol->value.iec958.status[0] = 0xff;	ucontrol->value.iec958.status[1] = 0xff;	ucontrol->value.iec958.status[2] = 0xff;	ucontrol->value.iec958.status[3] = 0xff;	return 0;}static int snd_ens1373_spdif_stream_get(struct snd_kcontrol *kcontrol,					struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);	spin_lock_irq(&ensoniq->reg_lock);	ucontrol->value.iec958.status[0] = (ensoniq->spdif_stream >> 0) & 0xff;	ucontrol->value.iec958.status[1] = (ensoniq->spdif_stream >> 8) & 0xff;	ucontrol->value.iec958.status[2] = (ensoniq->spdif_stream >> 16) & 0xff;	ucontrol->value.iec958.status[3] = (ensoniq->spdif_stream >> 24) & 0xff;	spin_unlock_irq(&ensoniq->reg_lock);	return 0;}static int snd_ens1373_spdif_stream_put(struct snd_kcontrol *kcontrol,                                        struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);	unsigned int val;	int change;	val = ((u32)ucontrol->value.iec958.status[0] << 0) |	      ((u32)ucontrol->value.iec958.status[1] << 8) |	      ((u32)ucontrol->value.iec958.status[2] << 16) |	      ((u32)ucontrol->value.iec958.status[3] << 24);	spin_lock_irq(&ensoniq->reg_lock);	change = ensoniq->spdif_stream != val;	ensoniq->spdif_stream = val;	if (change && (ensoniq->playback1_substream != NULL ||		       ensoniq->playback2_substream != NULL))		outl(val, ES_REG(ensoniq, CHANNEL_STATUS));	spin_unlock_irq(&ensoniq->reg_lock);	return change;}#define ES1371_SPDIF(xname) \{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_es1371_spdif_info, \  .get = snd_es1371_spdif_get, .put = snd_es1371_spdif_put }#define snd_es1371_spdif_info		snd_ctl_boolean_mono_infostatic int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol,				struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);		spin_lock_irq(&ensoniq->reg_lock);	ucontrol->value.integer.value[0] = ensoniq->ctrl & ES_1373_SPDIF_THRU ? 1 : 0;	spin_unlock_irq(&ensoniq->reg_lock);	return 0;}static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol,				struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);	unsigned int nval1, nval2;	int change;		nval1 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_THRU : 0;	nval2 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_EN : 0;	spin_lock_irq(&ensoniq->reg_lock);	change = (ensoniq->ctrl & ES_1373_SPDIF_THRU) != nval1;	ensoniq->ctrl &= ~ES_1373_SPDIF_THRU;	ensoniq->ctrl |= nval1;	ensoniq->cssr &= ~ES_1373_SPDIF_EN;	ensoniq->cssr |= nval2;	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));	outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));	spin_unlock_irq(&ensoniq->reg_lock);	return change;}/* spdif controls */static struct snd_kcontrol_new snd_es1371_mixer_spdif[] __devinitdata = {	ES1371_SPDIF(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH)),	{		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),		.info =		snd_ens1373_spdif_info,		.get =		snd_ens1373_spdif_default_get,		.put =		snd_ens1373_spdif_default_put,	},	{		.access =	SNDRV_CTL_ELEM_ACCESS_READ,		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),		.info =		snd_ens1373_spdif_info,		.get =		snd_ens1373_spdif_mask_get	},	{		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),		.info =		snd_ens1373_spdif_info,		.get =		snd_ens1373_spdif_stream_get,		.put =		snd_ens1373_spdif_stream_put	},};#define snd_es1373_rear_info		snd_ctl_boolean_mono_infostatic int snd_es1373_rear_get(struct snd_kcontrol *kcontrol,			       struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);	int val = 0;		spin_lock_irq(&ensoniq->reg_lock);	if ((ensoniq->cssr & (ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|			      ES_1373_REAR_BIT24)) == ES_1373_REAR_BIT26)	    	val = 1;	ucontrol->value.integer.value[0] = val;	spin_unlock_irq(&ensoniq->reg_lock);	return 0;}static int snd_es1373_rear_put(struct snd_kcontrol *kcontrol,			       struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);	unsigned int nval1;	int change;		nval1 = ucontrol->value.integer.value[0] ?		ES_1373_REAR_BIT26 : (ES_1373_REAR_BIT27|ES_1373_REAR_BIT24);	spin_lock_irq(&ensoniq->reg_lock);	change = (ensoniq->cssr & (ES_1373_REAR_BIT27|				   ES_1373_REAR_BIT26|ES_1373_REAR_BIT24)) != nval1;	ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|ES_1373_REAR_BIT24);	ensoniq->cssr |= nval1;	outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));	spin_unlock_irq(&ensoniq->reg_lock);	return change;}static struct snd_kcontrol_new snd_ens1373_rear __devinitdata ={	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,	.name =		"AC97 2ch->4ch Copy Switch",	.info =		snd_es1373_rear_info,	.get =		snd_es1373_rear_get,	.put =		snd_es1373_rear_put,};#define snd_es1373_line_info		snd_ctl_boolean_mono_infostatic int snd_es1373_line_get(struct snd_kcontrol *kcontrol,			       struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);	int val = 0;		spin_lock_irq(&ensoniq->reg_lock);	if ((ensoniq->ctrl & ES_1371_GPIO_OUTM) >= 4)	    	val = 1;	ucontrol->value.integer.value[0] = val;	spin_unlock_irq(&ensoniq->reg_lock);	return 0;}static int snd_es1373_line_put(struct snd_kcontrol *kcontrol,			       struct snd_ctl_elem_value *ucontrol){	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);	int changed;	unsigned int ctrl;		spin_lock_irq(&ensoniq->reg_lock);	ctrl = ensoniq->ctrl;	if (ucontrol->value.integer.value[0])		ensoniq->ctrl |= ES_1371_GPIO_OUT(4);	/* switch line-in -> rear out */	else		ensoniq->ctrl &= ~ES_1371_GPIO_OUT(4);	changed = (ctrl != ensoniq->ctrl);	if (changed)		outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));	spin_unlock_irq(&ensoniq->reg_lock);	return changed;}static struct snd_kcontrol_new snd_ens1373_line __devinitdata ={	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,	.name =		"Line In->Rear Out Switch",	.info =		snd_es1373_line_info,	.get =		snd_es1373_line_get,	.put =		snd_es1373_line_put,};static void snd_ensoniq_mixer_free_ac97(struct snd_ac97 *ac97){	struct ensoniq *ensoniq = ac97->private_data;

⌨️ 快捷键说明

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