[alsa-devel] [PATCH] ALSA: hda/realtek - Support for microphone in Dell's XPS 13 9343 with ALC288.

Takashi Iwai tiwai at suse.de
Sun Apr 5 17:48:23 CEST 2015


At Thu,  2 Apr 2015 12:33:40 +0100,
me at jdiez.me wrote:
> 
> From: Jose Diez <me at jdiez.me>
> 
> Original patch by Kailang Yang did not compile on 4.0-rc5. It was
> referencing a member field `core` in `struct hda_codec` in order to
> access the `vendor_id`. This has always been in the codec structure
> itself.
> 
> This patch fixes the build and is verified to work properly on 4.0-rc5,
> running actual hardware.
> 
> Signed-off-by: Jose Diez <me at jdiez.me>

I prefer splitting the Dell-specific part as its own quirk, as
mentioned in the review of Kailang's patch.  Then it'll be applicable
to both 4.1 and older kernels.


thanks,

Takashi

> ---
>  sound/pci/hda/patch_realtek.c | 122 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 122 insertions(+)
> 
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index 7438213..a8fc2c8 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -3583,6 +3583,14 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
>  		WRITE_COEF(0x32, 0x42a3),
>  		{}
>  	};
> +	static struct coef_fw coef0286[] = {
> +		UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
> +		UPDATE_COEF(0x50, 0x2000, 0x2000),
> +		UPDATE_COEF(0x56, 0x0006, 0x0006),
> +		UPDATE_COEF(0x66, 0x0008, 0),
> +		UPDATE_COEF(0x67, 0x2000, 0),
> +		{}
> +	};
>  	static struct coef_fw coef0292[] = {
>  		WRITE_COEF(0x76, 0x000e),
>  		WRITE_COEF(0x6c, 0x2400),
> @@ -3613,6 +3621,10 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
>  	case 0x10ec0283:
>  		alc_process_coef_fw(codec, coef0233);
>  		break;
> +	case 0x10ec0286:
> +	case 0x10ec0288:
> +		alc_process_coef_fw(codec, coef0286);
> +		break;
>  	case 0x10ec0292:
>  		alc_process_coef_fw(codec, coef0292);
>  		break;
> @@ -3642,6 +3654,14 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
>  		WRITE_COEF(0x26, 0x008c),
>  		{}
>  	};
> +	static struct coef_fw coef0286[] = {
> +		UPDATE_COEF(0x50, 0x2000, 0),
> +		UPDATE_COEF(0x56, 0x0006, 0),
> +		UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
> +		UPDATE_COEF(0x66, 0x0008, 0x0008),
> +		UPDATE_COEF(0x67, 0x2000, 0x2000),
> +		{}
> +	};
>  	static struct coef_fw coef0292[] = {
>  		WRITE_COEF(0x19, 0xa208),
>  		WRITE_COEF(0x2e, 0xacf0),
> @@ -3674,6 +3694,13 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
>  		alc_process_coef_fw(codec, coef0233);
>  		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
>  		break;
> +	case 0x10ec0286:
> +	case 0x10ec0288:
> +		alc_update_coef_idx(codec, 0x4f, 0x000c, 0);
> +		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
> +		alc_process_coef_fw(codec, coef0286);
> +		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
> +		break;
>  	case 0x10ec0292:
>  		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
>  		alc_process_coef_fw(codec, coef0292);
> @@ -3709,6 +3736,14 @@ static void alc_headset_mode_default(struct hda_codec *codec)
>  		WRITE_COEF(0x32, 0x4ea3),
>  		{}
>  	};
> +	static struct coef_fw coef0286[] = {
> +		UPDATE_COEF(0x4f, 0xfcc0, 0xc400), /* Set to TRS type */
> +		UPDATE_COEF(0x50, 0x2000, 0x2000),
> +		UPDATE_COEF(0x56, 0x0006, 0x0006),
> +		UPDATE_COEF(0x66, 0x0008, 0),
> +		UPDATE_COEF(0x67, 0x2000, 0),
> +		{}
> +	};
>  	static struct coef_fw coef0292[] = {
>  		WRITE_COEF(0x76, 0x000e),
>  		WRITE_COEF(0x6c, 0x2400),
> @@ -3737,6 +3772,11 @@ static void alc_headset_mode_default(struct hda_codec *codec)
>  	case 0x10ec0283:
>  		alc_process_coef_fw(codec, coef0233);
>  		break;
> +	case 0x10ec0286:
> +	case 0x10ec0288:
> +		alc_process_coef_fw(codec, coef0286);
> +		break;
> +		break;
>  	case 0x10ec0292:
>  		alc_process_coef_fw(codec, coef0292);
>  		break;
> @@ -3765,6 +3805,13 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
>  		WRITE_COEF(0x32, 0x4ea3),
>  		{}
>  	};
> +	static struct coef_fw coef0286[] = {
> +		UPDATE_COEF(0x50, 0x2000, 0x2000),
> +		UPDATE_COEF(0x56, 0x0006, 0x0006),
> +		UPDATE_COEF(0x66, 0x0008, 0),
> +		UPDATE_COEF(0x67, 0x2000, 0),
> +		{}
> +	};
>  	static struct coef_fw coef0292[] = {
>  		WRITE_COEF(0x6b, 0xd429),
>  		WRITE_COEF(0x76, 0x0008),
> @@ -3791,6 +3838,12 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
>  	case 0x10ec0283:
>  		alc_process_coef_fw(codec, coef0233);
>  		break;
> +	case 0x10ec0286:
> +	case 0x10ec0288:
> +		alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
> +		msleep(300);
> +		alc_process_coef_fw(codec, coef0286);
> +		break;
>  	case 0x10ec0292:
>  		alc_process_coef_fw(codec, coef0292);
>  		break;
> @@ -3819,6 +3872,13 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
>  		WRITE_COEF(0x32, 0x4ea3),
>  		{}
>  	};
> +	static struct coef_fw coef0286[] = {
> +		UPDATE_COEF(0x50, 0x2000, 0x2000),
> +		UPDATE_COEF(0x56, 0x0006, 0x0006),
> +		UPDATE_COEF(0x66, 0x0008, 0),
> +		UPDATE_COEF(0x67, 0x2000, 0),
> +		{}
> +	};
>  	static struct coef_fw coef0292[] = {
>  		WRITE_COEF(0x6b, 0xe429),
>  		WRITE_COEF(0x76, 0x0008),
> @@ -3845,6 +3905,12 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
>  	case 0x10ec0283:
>  		alc_process_coef_fw(codec, coef0233);
>  		break;
> +	case 0x10ec0286:
> +	case 0x10ec0288:
> +		alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400);
> +		msleep(300);
> +		alc_process_coef_fw(codec, coef0286);
> +		break;
>  	case 0x10ec0292:
>  		alc_process_coef_fw(codec, coef0292);
>  		break;
> @@ -3869,6 +3935,11 @@ static void alc_determine_headset_type(struct hda_codec *codec)
>   conteol) */
>  		{}
>  	};
> +	static struct coef_fw coef0286[] = {
> +		//UPDATE_COEF(0x4f, 0xfcc0, 0x5400), /* Combo Jack auto detect */
> +		UPDATE_COEF(0x4f, 0xfcc0, 0xd400),
> +		{}
> +	};
>  	static struct coef_fw coef0293[] = {
>  		UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */
>  		WRITE_COEF(0x45, 0xD429), /* Set to ctia type */
> @@ -3896,6 +3967,13 @@ static void alc_determine_headset_type(struct hda_codec *codec)
>  		val = alc_read_coef_idx(codec, 0x46);
>  		is_ctia = (val & 0x0070) == 0x0070;
>  		break;
> +	case 0x10ec0286:
> +	case 0x10ec0288:
> +		alc_process_coef_fw(codec, coef0286);
> +		msleep(350);
> +		val = alc_read_coef_idx(codec, 0x50);
> +		is_ctia = (val & 0x0070) == 0x0070;
> +		break;
>  	case 0x10ec0292:
>  		alc_write_coef_idx(codec, 0x6b, 0xd429);
>  		msleep(300);
> @@ -3990,8 +4068,15 @@ static void alc_update_headset_jack_cb(struct hda_codec *codec,
>  				       struct hda_jack_callback *jack)
>  {
>  	struct alc_spec *spec = codec->spec;
> +	int present;
>  	spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
>  	snd_hda_gen_hp_automute(codec, jack);
> +	present = spec->gen.hp_jack_present ? 0x40 : 0;
> +	if (codec->bus->pci->subsystem_vendor == 0x1028 &&
> +				codec->vendor_id == 0x10ec0288)
> +		/* Headset Mic enable and disable, ony for Dell Dino */
> +		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
> +					present);
>  }
>  
>  static void alc_probe_headset_mode(struct hda_codec *codec)
> @@ -4418,6 +4503,8 @@ enum {
>  	ALC286_FIXUP_HP_GPIO_LED,
>  	ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY,
>  	ALC280_FIXUP_HP_DOCK_PINS,
> +	ALC286_FIXUP_DELL1_MIC_NO_PRESENCE,
> +	ALC286_FIXUP_DELL_XPS_13_GPIO6,
>  };
>  
>  static const struct hda_fixup alc269_fixups[] = {
> @@ -4906,6 +4993,27 @@ static const struct hda_fixup alc269_fixups[] = {
>  		.chained = true,
>  		.chain_id = ALC280_FIXUP_HP_GPIO4
>  	},
> +	[ALC286_FIXUP_DELL1_MIC_NO_PRESENCE] = {
> +		.type = HDA_FIXUP_PINS,
> +		.v.pins = (const struct hda_pintbl[]) {
> +			{ 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
> +			{ 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
> +			{ }
> +		},
> +		.chained = true,
> +		.chain_id = ALC269_FIXUP_HEADSET_MODE
> +	},
> +	[ALC286_FIXUP_DELL_XPS_13_GPIO6] = {
> +		.type = HDA_FIXUP_VERBS,
> +		.v.verbs = (const struct hda_verb[]) {
> +			{0x01, AC_VERB_SET_GPIO_MASK, 0x40},
> +			{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x40},
> +			{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
> +			{ }
> +		},
> +		.chained = true,
> +		.chain_id = ALC286_FIXUP_DELL1_MIC_NO_PRESENCE
> +	},
>  };
>  
>  static const struct snd_pci_quirk alc269_fixup_tbl[] = {
> @@ -5132,6 +5240,13 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
>  	{0x1b, 0x411111f0}, \
>  	{0x1e, 0x411111f0}
>  
> +#define ALC286_STANDARD_PINS \
> +	{0x17, 0x411111f0}, \
> +	{0x18, 0x411111f0}, \
> +	{0x19, 0x411111f0}, \
> +	{0x1a, 0x411111f0}, \
> +	{0x1e, 0x411111f0}
> +
>  #define ALC290_STANDARD_PINS \
>  	{0x12, 0x99a30130}, \
>  	{0x13, 0x40000000}, \
> @@ -5317,6 +5432,13 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
>  		{0x19, 0x03a11020},
>  		{0x1d, 0x40e00001},
>  		{0x21, 0x0321101f}),
> +	SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC286_FIXUP_DELL_XPS_13_GPIO6,
> +		ALC286_STANDARD_PINS,
> +		{0x12, 0x90a60120},
> +		{0x13, 0x40000000},
> +		{0x14, 0x90170110},
> +		{0x1d, 0x4076832d},
> +		{0x21, 0x0321101f}),
>  	SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
>  		ALC290_STANDARD_PINS,
>  		{0x14, 0x411111f0},
> -- 
> 2.3.5
> 


More information about the Alsa-devel mailing list