Ack: Re: [12.04 SRU PATCH] ALSA: HDA: Add support for Cirrus Logic 4213

Herton Ronaldo Krzesinski herton.krzesinski at canonical.com
Tue Jun 5 14:18:40 UTC 2012


On Tue, Jun 05, 2012 at 09:50:58AM +0200, David Henningsson wrote:
> The CS4213 chip is similar to the CS4210, but it does not have
> SPDIF capabilities. Also, it has fewer pins, and the vendor specific
> nid is different. With this patch, we have working inputs and outputs
> (and automute/autoswitch). However, we don't know anything about
> the vendor specific processing coefficients, so we don't read or write
> to that node in this patch.
> 
> BugLink: https://bugs.launchpad.net/bugs/910792
> Tested-by: Hsin-Yi Chen <hychen at canonical.com>
> Signed-off-by: David Henningsson <david.henningsson at canonical.com>
> Signed-off-by: Takashi Iwai <tiwai at suse.de>
> 
> (cherry picked from commit 5660ffd06935e564404412997a703279e325fa64)
> Signed-off-by: David Henningsson <david.henningsson at canonical.com>
> ---
>  sound/pci/hda/patch_cirrus.c |  105 ++++++++++++++++++++++++++++--------------
>  1 file changed, 70 insertions(+), 35 deletions(-)
> 
> Anthony Wong asked me to try to SRU this patch in order to be able to certify
> a machine for 12.04.
> The CS4213 shares some code with the CS4210 chip, but the CS4210 chip - which 
> would be the possible regression risk here, was AFAIK never used in production.
> Therefore I believe this should be safe to SRU.

Ack, patch looks ok, code moves etc. all well isolated.

> 
> diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
> index ee2c1ed..297f5e2 100644
> --- a/sound/pci/hda/patch_cirrus.c
> +++ b/sound/pci/hda/patch_cirrus.c
> @@ -138,7 +138,7 @@ enum {
>  */
>  #define CS4210_DAC_NID		0x02
>  #define CS4210_ADC_NID		0x03
> -#define CS421X_VENDOR_NID	0x0B
> +#define CS4210_VENDOR_NID	0x0B
>  #define CS421X_DMIC_PIN_NID	0x09 /* Port E */
>  #define CS421X_SPDIF_PIN_NID	0x0A /* Port H */
>  
> @@ -149,6 +149,10 @@ enum {
>  
>  #define SPDIF_EVENT		0x04
>  
> +/* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */
> +#define CS4213_VENDOR_NID	0x09
> +
> +
>  static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
>  {
>  	struct cs_spec *spec = codec->spec;
> @@ -923,8 +927,8 @@ static void cs_automute(struct hda_codec *codec)
>  	/* mute speakers if spdif or hp jack is plugged in */
>  	for (i = 0; i < cfg->speaker_outs; i++) {
>  		int pin_ctl = hp_present ? 0 : PIN_OUT;
> -		/* detect on spdif is specific to CS421x */
> -		if (spdif_present && (spec->vendor_nid == CS421X_VENDOR_NID))
> +		/* detect on spdif is specific to CS4210 */
> +		if (spdif_present && (spec->vendor_nid == CS4210_VENDOR_NID))
>  			pin_ctl = 0;
>  
>  		nid = cfg->speaker_pins[i];
> @@ -938,8 +942,8 @@ static void cs_automute(struct hda_codec *codec)
>  				    AC_VERB_SET_GPIO_DATA, gpio);
>  	}
>  
> -	/* specific to CS421x */
> -	if (spec->vendor_nid == CS421X_VENDOR_NID) {
> +	/* specific to CS4210 */
> +	if (spec->vendor_nid == CS4210_VENDOR_NID) {
>  		/* mute HPs if spdif jack (SENSE_B) is present */
>  		for (i = 0; i < cfg->hp_outs; i++) {
>  			nid = cfg->hp_pins[i];
> @@ -976,7 +980,12 @@ static void cs_automic(struct hda_codec *codec)
>  	present = snd_hda_jack_detect(codec, nid);
>  
>  	/* specific to CS421x, single ADC */
> -	if (spec->vendor_nid == CS421X_VENDOR_NID) {
> +	if (spec->vendor_nid == CS420X_VENDOR_NID) {
> +		if (present)
> +			change_cur_input(codec, spec->automic_idx, 0);
> +		else
> +			change_cur_input(codec, !spec->automic_idx, 0);
> +	} else {
>  		if (present) {
>  			if (spec->cur_input != spec->automic_idx) {
>  				spec->last_input = spec->cur_input;
> @@ -986,11 +995,6 @@ static void cs_automic(struct hda_codec *codec)
>  			spec->cur_input = spec->last_input;
>  		}
>  		cs_update_input_select(codec);
> -	} else {
> -		if (present)
> -			change_cur_input(codec, spec->automic_idx, 0);
> -		else
> -			change_cur_input(codec, !spec->automic_idx, 0);
>  	}
>  }
>  
> @@ -1072,15 +1076,8 @@ static void init_input(struct hda_codec *codec)
>  		if (spec->mic_detect && spec->automic_idx == i)
>  			snd_hda_jack_detect_enable(codec, pin, MIC_EVENT);
>  	}
> -	/* specific to CS421x */
> -	if (spec->vendor_nid == CS421X_VENDOR_NID) {
> -		if (spec->mic_detect)
> -			cs_automic(codec);
> -		else  {
> -			spec->cur_adc = spec->adc_nid[spec->cur_input];
> -			cs_update_input_select(codec);
> -		}
> -	} else {
> +	/* CS420x has multiple ADC, CS421x has single ADC */
> +	if (spec->vendor_nid == CS420X_VENDOR_NID) {
>  		change_cur_input(codec, spec->cur_input, 1);
>  		if (spec->mic_detect)
>  			cs_automic(codec);
> @@ -1094,6 +1091,13 @@ static void init_input(struct hda_codec *codec)
>  					 * selected in IDX_SPDIF_CTL.
>  					*/
>  		cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
> +	} else {
> +		if (spec->mic_detect)
> +			cs_automic(codec);
> +		else  {
> +			spec->cur_adc = spec->adc_nid[spec->cur_input];
> +			cs_update_input_select(codec);
> +		}
>  	}
>  }
>  
> @@ -1567,7 +1571,7 @@ static const struct snd_kcontrol_new cs421x_speaker_bost_ctl = {
>  	.tlv = { .p = cs421x_speaker_boost_db_scale },
>  };
>  
> -static void cs421x_pinmux_init(struct hda_codec *codec)
> +static void cs4210_pinmux_init(struct hda_codec *codec)
>  {
>  	struct cs_spec *spec = codec->spec;
>  	unsigned int def_conf, coef;
> @@ -1622,10 +1626,11 @@ static int cs421x_init(struct hda_codec *codec)
>  {
>  	struct cs_spec *spec = codec->spec;
>  
> -	snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
> -	snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
> -
> -	cs421x_pinmux_init(codec);
> +	if (spec->vendor_nid == CS4210_VENDOR_NID) {
> +		snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
> +		snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
> +		cs4210_pinmux_init(codec);
> +	}
>  
>  	if (spec->gpio_mask) {
>  		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
> @@ -1793,7 +1798,7 @@ static int build_cs421x_output(struct hda_codec *codec)
>  	if (err < 0)
>  		return err;
>  
> -	if (cfg->speaker_outs) {
> +	if (cfg->speaker_outs && (spec->vendor_nid == CS4210_VENDOR_NID)) {
>  		err = snd_hda_ctl_add(codec, 0,
>  			snd_ctl_new1(&cs421x_speaker_bost_ctl, codec));
>  		if (err < 0)
> @@ -1890,6 +1895,7 @@ static int cs421x_parse_auto_config(struct hda_codec *codec)
>  */
>  static int cs421x_suspend(struct hda_codec *codec, pm_message_t state)
>  {
> +	struct cs_spec *spec = codec->spec;
>  	unsigned int coef;
>  
>  	snd_hda_shutup_pins(codec);
> @@ -1899,15 +1905,17 @@ static int cs421x_suspend(struct hda_codec *codec, pm_message_t state)
>  	snd_hda_codec_write(codec, CS4210_ADC_NID, 0,
>  			    AC_VERB_SET_POWER_STATE,  AC_PWRST_D3);
>  
> -	coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
> -	coef |= 0x0004; /* PDREF */
> -	cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
> +	if (spec->vendor_nid == CS4210_VENDOR_NID) {
> +		coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
> +		coef |= 0x0004; /* PDREF */
> +		cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
> +	}
>  
>  	return 0;
>  }
>  #endif
>  
> -static struct hda_codec_ops cs4210_patch_ops = {
> +static struct hda_codec_ops cs421x_patch_ops = {
>  	.build_controls = cs421x_build_controls,
>  	.build_pcms = cs_build_pcms,
>  	.init = cs421x_init,
> @@ -1918,7 +1926,7 @@ static struct hda_codec_ops cs4210_patch_ops = {
>  #endif
>  };
>  
> -static int patch_cs421x(struct hda_codec *codec)
> +static int patch_cs4210(struct hda_codec *codec)
>  {
>  	struct cs_spec *spec;
>  	int err;
> @@ -1928,7 +1936,7 @@ static int patch_cs421x(struct hda_codec *codec)
>  		return -ENOMEM;
>  	codec->spec = spec;
>  
> -	spec->vendor_nid = CS421X_VENDOR_NID;
> +	spec->vendor_nid = CS4210_VENDOR_NID;
>  
>  	spec->board_config =
>  		snd_hda_check_board_config(codec, CS421X_MODELS,
> @@ -1956,14 +1964,39 @@ static int patch_cs421x(struct hda_codec *codec)
>  	    is auto-parsed. If GPIO or SENSE_B is forced, DMIC input
>  	    is disabled.
>  	*/
> -	cs421x_pinmux_init(codec);
> +	cs4210_pinmux_init(codec);
>  
>  	err = cs421x_parse_auto_config(codec);
>  	if (err < 0)
>  		goto error;
>  
> -	codec->patch_ops = cs4210_patch_ops;
> +	codec->patch_ops = cs421x_patch_ops;
> +
> +	return 0;
> +
> + error:
> +	kfree(codec->spec);
> +	codec->spec = NULL;
> +	return err;
> +}
> +
> +static int patch_cs4213(struct hda_codec *codec)
> +{
> +	struct cs_spec *spec;
> +	int err;
> +
> +	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
> +	if (!spec)
> +		return -ENOMEM;
> +	codec->spec = spec;
> +
> +	spec->vendor_nid = CS4213_VENDOR_NID;
> +
> +	err = cs421x_parse_auto_config(codec);
> +	if (err < 0)
> +		goto error;
>  
> +	codec->patch_ops = cs421x_patch_ops;
>  	return 0;
>  
>   error:
> @@ -1979,13 +2012,15 @@ static int patch_cs421x(struct hda_codec *codec)
>  static const struct hda_codec_preset snd_hda_preset_cirrus[] = {
>  	{ .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x },
>  	{ .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x },
> -	{ .id = 0x10134210, .name = "CS4210", .patch = patch_cs421x },
> +	{ .id = 0x10134210, .name = "CS4210", .patch = patch_cs4210 },
> +	{ .id = 0x10134213, .name = "CS4213", .patch = patch_cs4213 },
>  	{} /* terminator */
>  };
>  
>  MODULE_ALIAS("snd-hda-codec-id:10134206");
>  MODULE_ALIAS("snd-hda-codec-id:10134207");
>  MODULE_ALIAS("snd-hda-codec-id:10134210");
> +MODULE_ALIAS("snd-hda-codec-id:10134213");
>  
>  MODULE_LICENSE("GPL");
>  MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");
> -- 
> 1.7.9.5
> 
> 
> -- 
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
> 

-- 
[]'s
Herton




More information about the kernel-team mailing list