cs46xx_lib.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,248 行 · 第 1/5 页

C
2,248
字号
	pcm->private_data = chip;	pcm->private_free = snd_cs46xx_pcm_iec958_free;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops);	/* global setup */	pcm->info_flags = 0;	strcpy(pcm->name, "CS46xx - IEC958");	chip->pcm_rear = pcm;	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);	if (rpcm)		*rpcm = pcm;	return 0;}#endif/* *  Mixer routines */static void snd_cs46xx_mixer_free_ac97_bus(ac97_bus_t *bus){	cs46xx_t *chip = snd_magic_cast(cs46xx_t, bus->private_data, return);	chip->ac97_bus = NULL;}static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97){	cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);	snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||		    (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),		    return);	if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) {		chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;		chip->eapd_switch = NULL;	}	else		chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;}static int snd_cs46xx_vol_info(snd_kcontrol_t *kcontrol, 			       snd_ctl_elem_info_t *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 0x7fff;	return 0;}static int snd_cs46xx_vol_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value;	unsigned int val = snd_cs46xx_peek(chip, reg);	ucontrol->value.integer.value[0] = 0xffff - (val >> 16);	ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff);	return 0;}static int snd_cs46xx_vol_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value;	unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 | 			    (0xffff - ucontrol->value.integer.value[1]));	unsigned int old = snd_cs46xx_peek(chip, reg);	int change = (old != val);	if (change) {		snd_cs46xx_poke(chip, reg, val);	}	return change;}#ifdef CONFIG_SND_CS46XX_NEW_DSPstatic int snd_cs46xx_vol_dac_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left;	ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right;	return 0;}static int snd_cs46xx_vol_dac_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int change = 0;	if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] ||	    chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) {		cs46xx_dsp_set_dac_volume(chip,					  ucontrol->value.integer.value[0],					  ucontrol->value.integer.value[1]);		change = 1;	}	return change;}#if 0static int snd_cs46xx_vol_iec958_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left;	ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right;	return 0;}static int snd_cs46xx_vol_iec958_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int change = 0;	if (chip->dsp_spos_instance->spdif_input_volume_left  != ucontrol->value.integer.value[0] ||	    chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) {		cs46xx_dsp_set_iec958_volume (chip,					      ucontrol->value.integer.value[0],					      ucontrol->value.integer.value[1]);		change = 1;	}	return change;}#endifstatic int snd_mixer_boolean_info(snd_kcontrol_t *kcontrol, 				  snd_ctl_elem_info_t *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 1;	return 0;}static int snd_cs46xx_iec958_get(snd_kcontrol_t *kcontrol,                                  snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_value;	if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)		ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);	else		ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in;	return 0;}static int snd_cs46xx_iec958_put(snd_kcontrol_t *kcontrol,                                   snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int change, res;	switch (kcontrol->private_value) {	case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT:		down (&chip->spos_mutex);		change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);		if (ucontrol->value.integer.value[0] && !change) 			cs46xx_dsp_enable_spdif_out(chip);		else if (change && !ucontrol->value.integer.value[0])			cs46xx_dsp_disable_spdif_out(chip);		res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED));		up (&chip->spos_mutex);		break;	case CS46XX_MIXER_SPDIF_INPUT_ELEMENT:		change = chip->dsp_spos_instance->spdif_status_in;		if (ucontrol->value.integer.value[0] && !change) {			cs46xx_dsp_enable_spdif_in(chip);			/* restore volume */		}		else if (change && !ucontrol->value.integer.value[0])			cs46xx_dsp_disable_spdif_in(chip);				res = (change != chip->dsp_spos_instance->spdif_status_in);		break;	default:		res = -EINVAL;		snd_assert(0, (void)0);	}	return res;}static int snd_cs46xx_adc_capture_get(snd_kcontrol_t *kcontrol,                                       snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	if (ins->adc_input != NULL) 		ucontrol->value.integer.value[0] = 1;	else 		ucontrol->value.integer.value[0] = 0;		return 0;}static int snd_cs46xx_adc_capture_put(snd_kcontrol_t *kcontrol,                                       snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	int change = 0;	if (ucontrol->value.integer.value[0] && !ins->adc_input) {		cs46xx_dsp_enable_adc_capture(chip);		change = 1;	} else  if (!ucontrol->value.integer.value[0] && ins->adc_input) {		cs46xx_dsp_disable_adc_capture(chip);		change = 1;	}	return change;}static int snd_cs46xx_pcm_capture_get(snd_kcontrol_t *kcontrol,                                       snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	if (ins->pcm_input != NULL) 		ucontrol->value.integer.value[0] = 1;	else 		ucontrol->value.integer.value[0] = 0;	return 0;}static int snd_cs46xx_pcm_capture_put(snd_kcontrol_t *kcontrol,                                       snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	int change = 0;	if (ucontrol->value.integer.value[0] && !ins->pcm_input) {		cs46xx_dsp_enable_pcm_capture(chip);		change = 1;	} else  if (!ucontrol->value.integer.value[0] && ins->pcm_input) {		cs46xx_dsp_disable_pcm_capture(chip);		change = 1;	}	return change;}static int snd_herc_spdif_select_get(snd_kcontrol_t *kcontrol,                                      snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);	if (val1 & EGPIODR_GPOE0)		ucontrol->value.integer.value[0] = 1;	else		ucontrol->value.integer.value[0] = 0;	return 0;}/* *	Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial. */ static int snd_herc_spdif_select_put(snd_kcontrol_t *kcontrol,                                        snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);	int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);	if (ucontrol->value.integer.value[0]) {		/* optical is default */		snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 				   EGPIODR_GPOE0 | val1);  /* enable EGPIO0 output */		snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 				   EGPIOPTR_GPPT0 | val2); /* open-drain on output */	} else {		/* coaxial */		snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,  val1 & ~EGPIODR_GPOE0); /* disable */		snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */	}	/* checking diff from the EGPIO direction register 	   should be enough */	return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR));}static int snd_cs46xx_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;	uinfo->count = 1;	return 0;}static int snd_cs46xx_spdif_default_get(snd_kcontrol_t * kcontrol,					snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	down (&chip->spos_mutex);	ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff);	ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff);	ucontrol->value.iec958.status[2] = 0;	ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff);	up (&chip->spos_mutex);	return 0;}static int snd_cs46xx_spdif_default_put(snd_kcontrol_t * kcontrol,					snd_ctl_elem_value_t * ucontrol){	cs46xx_t * chip = snd_kcontrol_chip(kcontrol);	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	unsigned int val;	int change;	down (&chip->spos_mutex);	val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |		((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) |		((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3]))  |		/* left and right validity bit */		(1 << 13) | (1 << 12);	change = (unsigned int)ins->spdif_csuv_default != val;	ins->spdif_csuv_default = val;	if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) )		cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);	up (&chip->spos_mutex);	return change;}static int snd_cs46xx_spdif_mask_get(snd_kcontrol_t * kcontrol,				     snd_ctl_elem_value_t * ucontrol){	ucontrol->value.iec958.status[0] = 0xff;	ucontrol->value.iec958.status[1] = 0xff;	ucontrol->value.iec958.status[2] = 0x00;	ucontrol->value.iec958.status[3] = 0xff;	return 0;}static int snd_cs46xx_spdif_stream_get(snd_kcontrol_t * kcontrol,                                         snd_ctl_elem_value_t * ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	down (&chip->spos_mutex);	ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff);	ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff);	ucontrol->value.iec958.status[2] = 0;	ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff);	up (&chip->spos_mutex);	return 0;}static int snd_cs46xx_spdif_stream_put(snd_kcontrol_t * kcontrol,                                        snd_ctl_elem_value_t * ucontrol){	cs46xx_t * chip = snd_kcontrol_chip(kcontrol);	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	unsigned int val;	int change;	down (&chip->spos_mutex);	val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |		((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) |		((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |		/* left and right validity bit */		(1 << 13) | (1 << 12);	change = ins->spdif_csuv_stream != val;	ins->spdif_csuv_stream = val;	if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN )		cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);	up (&chip->spos_mutex);	return change;}#endif /* CONFIG_SND_CS46XX_NEW_DSP */#ifdef CONFIG_SND_CS46XX_DEBUG_GPIOstatic int snd_cs46xx_egpio_select_info(snd_kcontrol_t *kcontrol,                                         snd_ctl_elem_info_t *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 1;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = 8;	return 0;}static int snd_cs46xx_egpio_select_get(snd_kcontrol_t *kcontrol,                                        snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	ucontrol->value.integer.value[0] = chip->current_gpio;	return 0;}static int snd_cs46xx_egpio_select_put(snd_kcontrol_t *kcontrol,                                        snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int change = (chip->current_gpio != ucontrol->value.integer.value[0]);	chip->current_gpio = ucontrol->value.integer.value[0];	return change;}static int snd_cs46xx_egpio_get(snd_kcontrol_t *kcontrol,                                        snd_ctl_elem_value_t *ucontrol){	cs46xx_t *chip = snd_kcontrol_chip(kcontrol);	int reg = kcontrol->private_

⌨️ 快捷键说明

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