diff options
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 145 |
1 files changed, 97 insertions, 48 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index d906c5b74cf0..aabdb9e9a484 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -141,6 +141,7 @@ struct conexant_spec { | |||
141 | unsigned int hp_laptop:1; | 141 | unsigned int hp_laptop:1; |
142 | unsigned int asus:1; | 142 | unsigned int asus:1; |
143 | unsigned int pin_eapd_ctrls:1; | 143 | unsigned int pin_eapd_ctrls:1; |
144 | unsigned int fixup_stereo_dmic:1; | ||
144 | 145 | ||
145 | unsigned int adc_switching:1; | 146 | unsigned int adc_switching:1; |
146 | 147 | ||
@@ -1601,17 +1602,13 @@ static void cxt5051_update_speaker(struct hda_codec *codec) | |||
1601 | unsigned int pinctl; | 1602 | unsigned int pinctl; |
1602 | /* headphone pin */ | 1603 | /* headphone pin */ |
1603 | pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; | 1604 | pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; |
1604 | snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 1605 | snd_hda_set_pin_ctl(codec, 0x16, pinctl); |
1605 | pinctl); | ||
1606 | /* speaker pin */ | 1606 | /* speaker pin */ |
1607 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | 1607 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; |
1608 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 1608 | snd_hda_set_pin_ctl(codec, 0x1a, pinctl); |
1609 | pinctl); | ||
1610 | /* on ideapad there is an additional speaker (subwoofer) to mute */ | 1609 | /* on ideapad there is an additional speaker (subwoofer) to mute */ |
1611 | if (spec->ideapad) | 1610 | if (spec->ideapad) |
1612 | snd_hda_codec_write(codec, 0x1b, 0, | 1611 | snd_hda_set_pin_ctl(codec, 0x1b, pinctl); |
1613 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
1614 | pinctl); | ||
1615 | } | 1612 | } |
1616 | 1613 | ||
1617 | /* turn on/off EAPD (+ mute HP) as a master switch */ | 1614 | /* turn on/off EAPD (+ mute HP) as a master switch */ |
@@ -1996,8 +1993,7 @@ static void cxt5066_update_speaker(struct hda_codec *codec) | |||
1996 | 1993 | ||
1997 | /* Port A (HP) */ | 1994 | /* Port A (HP) */ |
1998 | pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; | 1995 | pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; |
1999 | snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 1996 | snd_hda_set_pin_ctl(codec, 0x19, pinctl); |
2000 | pinctl); | ||
2001 | 1997 | ||
2002 | /* Port D (HP/LO) */ | 1998 | /* Port D (HP/LO) */ |
2003 | pinctl = spec->cur_eapd ? spec->port_d_mode : 0; | 1999 | pinctl = spec->cur_eapd ? spec->port_d_mode : 0; |
@@ -2010,13 +2006,11 @@ static void cxt5066_update_speaker(struct hda_codec *codec) | |||
2010 | if (!hp_port_d_present(spec)) | 2006 | if (!hp_port_d_present(spec)) |
2011 | pinctl = 0; | 2007 | pinctl = 0; |
2012 | } | 2008 | } |
2013 | snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2009 | snd_hda_set_pin_ctl(codec, 0x1c, pinctl); |
2014 | pinctl); | ||
2015 | 2010 | ||
2016 | /* CLASS_D AMP */ | 2011 | /* CLASS_D AMP */ |
2017 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; | 2012 | pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; |
2018 | snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2013 | snd_hda_set_pin_ctl(codec, 0x1f, pinctl); |
2019 | pinctl); | ||
2020 | } | 2014 | } |
2021 | 2015 | ||
2022 | /* turn on/off EAPD (+ mute HP) as a master switch */ | 2016 | /* turn on/off EAPD (+ mute HP) as a master switch */ |
@@ -2047,8 +2041,7 @@ static int cxt5066_set_olpc_dc_bias(struct hda_codec *codec) | |||
2047 | /* Even though port F is the DC input, the bias is controlled on port B. | 2041 | /* Even though port F is the DC input, the bias is controlled on port B. |
2048 | * we also leave that port as an active input (but unselected) in DC mode | 2042 | * we also leave that port as an active input (but unselected) in DC mode |
2049 | * just in case that is necessary to make the bias setting take effect. */ | 2043 | * just in case that is necessary to make the bias setting take effect. */ |
2050 | return snd_hda_codec_write_cache(codec, 0x1a, 0, | 2044 | return snd_hda_set_pin_ctl_cache(codec, 0x1a, |
2051 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
2052 | cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); | 2045 | cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index); |
2053 | } | 2046 | } |
2054 | 2047 | ||
@@ -2081,14 +2074,14 @@ static void cxt5066_olpc_select_mic(struct hda_codec *codec) | |||
2081 | } | 2074 | } |
2082 | 2075 | ||
2083 | /* disable DC (port F) */ | 2076 | /* disable DC (port F) */ |
2084 | snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | 2077 | snd_hda_set_pin_ctl(codec, 0x1e, 0); |
2085 | 2078 | ||
2086 | /* external mic, port B */ | 2079 | /* external mic, port B */ |
2087 | snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2080 | snd_hda_set_pin_ctl(codec, 0x1a, |
2088 | spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); | 2081 | spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); |
2089 | 2082 | ||
2090 | /* internal mic, port C */ | 2083 | /* internal mic, port C */ |
2091 | snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 2084 | snd_hda_set_pin_ctl(codec, 0x1b, |
2092 | spec->ext_mic_present ? 0 : PIN_VREF80); | 2085 | spec->ext_mic_present ? 0 : PIN_VREF80); |
2093 | } | 2086 | } |
2094 | 2087 | ||
@@ -3357,9 +3350,7 @@ static void do_automute(struct hda_codec *codec, int num_pins, | |||
3357 | struct conexant_spec *spec = codec->spec; | 3350 | struct conexant_spec *spec = codec->spec; |
3358 | int i; | 3351 | int i; |
3359 | for (i = 0; i < num_pins; i++) | 3352 | for (i = 0; i < num_pins; i++) |
3360 | snd_hda_codec_write(codec, pins[i], 0, | 3353 | snd_hda_set_pin_ctl(codec, pins[i], on ? PIN_OUT : 0); |
3361 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
3362 | on ? PIN_OUT : 0); | ||
3363 | if (spec->pin_eapd_ctrls) | 3354 | if (spec->pin_eapd_ctrls) |
3364 | cx_auto_turn_eapd(codec, num_pins, pins, on); | 3355 | cx_auto_turn_eapd(codec, num_pins, pins, on); |
3365 | } | 3356 | } |
@@ -3976,8 +3967,7 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
3976 | if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) & | 3967 | if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) & |
3977 | AC_PINCAP_HP_DRV) | 3968 | AC_PINCAP_HP_DRV) |
3978 | val |= AC_PINCTL_HP_EN; | 3969 | val |= AC_PINCTL_HP_EN; |
3979 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, | 3970 | snd_hda_set_pin_ctl(codec, cfg->hp_pins[i], val); |
3980 | AC_VERB_SET_PIN_WIDGET_CONTROL, val); | ||
3981 | } | 3971 | } |
3982 | mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); | 3972 | mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); |
3983 | mute_outputs(codec, cfg->line_outs, cfg->line_out_pins); | 3973 | mute_outputs(codec, cfg->line_outs, cfg->line_out_pins); |
@@ -4030,13 +4020,11 @@ static void cx_auto_init_input(struct hda_codec *codec) | |||
4030 | } | 4020 | } |
4031 | 4021 | ||
4032 | for (i = 0; i < cfg->num_inputs; i++) { | 4022 | for (i = 0; i < cfg->num_inputs; i++) { |
4033 | unsigned int type; | 4023 | hda_nid_t pin = cfg->inputs[i].pin; |
4024 | unsigned int type = PIN_IN; | ||
4034 | if (cfg->inputs[i].type == AUTO_PIN_MIC) | 4025 | if (cfg->inputs[i].type == AUTO_PIN_MIC) |
4035 | type = PIN_VREF80; | 4026 | type |= snd_hda_get_default_vref(codec, pin); |
4036 | else | 4027 | snd_hda_set_pin_ctl(codec, pin, type); |
4037 | type = PIN_IN; | ||
4038 | snd_hda_codec_write(codec, cfg->inputs[i].pin, 0, | ||
4039 | AC_VERB_SET_PIN_WIDGET_CONTROL, type); | ||
4040 | } | 4028 | } |
4041 | 4029 | ||
4042 | if (spec->auto_mic) { | 4030 | if (spec->auto_mic) { |
@@ -4063,11 +4051,9 @@ static void cx_auto_init_digital(struct hda_codec *codec) | |||
4063 | struct auto_pin_cfg *cfg = &spec->autocfg; | 4051 | struct auto_pin_cfg *cfg = &spec->autocfg; |
4064 | 4052 | ||
4065 | if (spec->multiout.dig_out_nid) | 4053 | if (spec->multiout.dig_out_nid) |
4066 | snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0, | 4054 | snd_hda_set_pin_ctl(codec, cfg->dig_out_pins[0], PIN_OUT); |
4067 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
4068 | if (spec->dig_in_nid) | 4055 | if (spec->dig_in_nid) |
4069 | snd_hda_codec_write(codec, cfg->dig_in_pin, 0, | 4056 | snd_hda_set_pin_ctl(codec, cfg->dig_in_pin, PIN_IN); |
4070 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN); | ||
4071 | } | 4057 | } |
4072 | 4058 | ||
4073 | static int cx_auto_init(struct hda_codec *codec) | 4059 | static int cx_auto_init(struct hda_codec *codec) |
@@ -4084,9 +4070,9 @@ static int cx_auto_init(struct hda_codec *codec) | |||
4084 | 4070 | ||
4085 | static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, | 4071 | static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, |
4086 | const char *dir, int cidx, | 4072 | const char *dir, int cidx, |
4087 | hda_nid_t nid, int hda_dir, int amp_idx) | 4073 | hda_nid_t nid, int hda_dir, int amp_idx, int chs) |
4088 | { | 4074 | { |
4089 | static char name[32]; | 4075 | static char name[44]; |
4090 | static struct snd_kcontrol_new knew[] = { | 4076 | static struct snd_kcontrol_new knew[] = { |
4091 | HDA_CODEC_VOLUME(name, 0, 0, 0), | 4077 | HDA_CODEC_VOLUME(name, 0, 0, 0), |
4092 | HDA_CODEC_MUTE(name, 0, 0, 0), | 4078 | HDA_CODEC_MUTE(name, 0, 0, 0), |
@@ -4096,7 +4082,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, | |||
4096 | 4082 | ||
4097 | for (i = 0; i < 2; i++) { | 4083 | for (i = 0; i < 2; i++) { |
4098 | struct snd_kcontrol *kctl; | 4084 | struct snd_kcontrol *kctl; |
4099 | knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx, | 4085 | knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, chs, amp_idx, |
4100 | hda_dir); | 4086 | hda_dir); |
4101 | knew[i].subdevice = HDA_SUBDEV_AMP_FLAG; | 4087 | knew[i].subdevice = HDA_SUBDEV_AMP_FLAG; |
4102 | knew[i].index = cidx; | 4088 | knew[i].index = cidx; |
@@ -4115,7 +4101,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, | |||
4115 | } | 4101 | } |
4116 | 4102 | ||
4117 | #define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \ | 4103 | #define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \ |
4118 | cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0) | 4104 | cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0, 3) |
4119 | 4105 | ||
4120 | #define cx_auto_add_pb_volume(codec, nid, str, idx) \ | 4106 | #define cx_auto_add_pb_volume(codec, nid, str, idx) \ |
4121 | cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) | 4107 | cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) |
@@ -4185,6 +4171,36 @@ static int cx_auto_build_output_controls(struct hda_codec *codec) | |||
4185 | return 0; | 4171 | return 0; |
4186 | } | 4172 | } |
4187 | 4173 | ||
4174 | /* Returns zero if this is a normal stereo channel, and non-zero if it should | ||
4175 | be split in two independent channels. | ||
4176 | dest_label must be at least 44 characters. */ | ||
4177 | static int cx_auto_get_rightch_label(struct hda_codec *codec, const char *label, | ||
4178 | char *dest_label, int nid) | ||
4179 | { | ||
4180 | struct conexant_spec *spec = codec->spec; | ||
4181 | int i; | ||
4182 | |||
4183 | if (!spec->fixup_stereo_dmic) | ||
4184 | return 0; | ||
4185 | |||
4186 | for (i = 0; i < AUTO_CFG_MAX_INS; i++) { | ||
4187 | int def_conf; | ||
4188 | if (spec->autocfg.inputs[i].pin != nid) | ||
4189 | continue; | ||
4190 | |||
4191 | if (spec->autocfg.inputs[i].type != AUTO_PIN_MIC) | ||
4192 | return 0; | ||
4193 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
4194 | if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) | ||
4195 | return 0; | ||
4196 | |||
4197 | /* Finally found the inverted internal mic! */ | ||
4198 | snprintf(dest_label, 44, "Inverted %s", label); | ||
4199 | return 1; | ||
4200 | } | ||
4201 | return 0; | ||
4202 | } | ||
4203 | |||
4188 | static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, | 4204 | static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, |
4189 | const char *label, const char *pfx, | 4205 | const char *label, const char *pfx, |
4190 | int cidx) | 4206 | int cidx) |
@@ -4193,14 +4209,25 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, | |||
4193 | int i; | 4209 | int i; |
4194 | 4210 | ||
4195 | for (i = 0; i < spec->num_adc_nids; i++) { | 4211 | for (i = 0; i < spec->num_adc_nids; i++) { |
4212 | char rightch_label[44]; | ||
4196 | hda_nid_t adc_nid = spec->adc_nids[i]; | 4213 | hda_nid_t adc_nid = spec->adc_nids[i]; |
4197 | int idx = get_input_connection(codec, adc_nid, nid); | 4214 | int idx = get_input_connection(codec, adc_nid, nid); |
4198 | if (idx < 0) | 4215 | if (idx < 0) |
4199 | continue; | 4216 | continue; |
4200 | if (codec->single_adc_amp) | 4217 | if (codec->single_adc_amp) |
4201 | idx = 0; | 4218 | idx = 0; |
4219 | |||
4220 | if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) { | ||
4221 | /* Make two independent kcontrols for left and right */ | ||
4222 | int err = cx_auto_add_volume_idx(codec, label, pfx, | ||
4223 | cidx, adc_nid, HDA_INPUT, idx, 1); | ||
4224 | if (err < 0) | ||
4225 | return err; | ||
4226 | return cx_auto_add_volume_idx(codec, rightch_label, pfx, | ||
4227 | cidx, adc_nid, HDA_INPUT, idx, 2); | ||
4228 | } | ||
4202 | return cx_auto_add_volume_idx(codec, label, pfx, | 4229 | return cx_auto_add_volume_idx(codec, label, pfx, |
4203 | cidx, adc_nid, HDA_INPUT, idx); | 4230 | cidx, adc_nid, HDA_INPUT, idx, 3); |
4204 | } | 4231 | } |
4205 | return 0; | 4232 | return 0; |
4206 | } | 4233 | } |
@@ -4213,9 +4240,19 @@ static int cx_auto_add_boost_volume(struct hda_codec *codec, int idx, | |||
4213 | int i, con; | 4240 | int i, con; |
4214 | 4241 | ||
4215 | nid = spec->imux_info[idx].pin; | 4242 | nid = spec->imux_info[idx].pin; |
4216 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) | 4243 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { |
4244 | char rightch_label[44]; | ||
4245 | if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) { | ||
4246 | int err = cx_auto_add_volume_idx(codec, label, " Boost", | ||
4247 | cidx, nid, HDA_INPUT, 0, 1); | ||
4248 | if (err < 0) | ||
4249 | return err; | ||
4250 | return cx_auto_add_volume_idx(codec, rightch_label, " Boost", | ||
4251 | cidx, nid, HDA_INPUT, 0, 2); | ||
4252 | } | ||
4217 | return cx_auto_add_volume(codec, label, " Boost", cidx, | 4253 | return cx_auto_add_volume(codec, label, " Boost", cidx, |
4218 | nid, HDA_INPUT); | 4254 | nid, HDA_INPUT); |
4255 | } | ||
4219 | con = __select_input_connection(codec, spec->imux_info[idx].adc, nid, | 4256 | con = __select_input_connection(codec, spec->imux_info[idx].adc, nid, |
4220 | &mux, false, 0); | 4257 | &mux, false, 0); |
4221 | if (con < 0) | 4258 | if (con < 0) |
@@ -4382,23 +4419,33 @@ static void apply_pincfg(struct hda_codec *codec, const struct cxt_pincfg *cfg) | |||
4382 | 4419 | ||
4383 | } | 4420 | } |
4384 | 4421 | ||
4385 | static void apply_pin_fixup(struct hda_codec *codec, | 4422 | enum { |
4423 | CXT_PINCFG_LENOVO_X200, | ||
4424 | CXT_PINCFG_LENOVO_TP410, | ||
4425 | CXT_FIXUP_STEREO_DMIC, | ||
4426 | }; | ||
4427 | |||
4428 | static void apply_fixup(struct hda_codec *codec, | ||
4386 | const struct snd_pci_quirk *quirk, | 4429 | const struct snd_pci_quirk *quirk, |
4387 | const struct cxt_pincfg **table) | 4430 | const struct cxt_pincfg **table) |
4388 | { | 4431 | { |
4432 | struct conexant_spec *spec = codec->spec; | ||
4433 | |||
4389 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); | 4434 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); |
4390 | if (quirk) { | 4435 | if (!quirk) |
4436 | return; | ||
4437 | if (table[quirk->value]) { | ||
4391 | snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n", | 4438 | snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n", |
4392 | quirk->name); | 4439 | quirk->name); |
4393 | apply_pincfg(codec, table[quirk->value]); | 4440 | apply_pincfg(codec, table[quirk->value]); |
4394 | } | 4441 | } |
4442 | if (quirk->value == CXT_FIXUP_STEREO_DMIC) { | ||
4443 | snd_printdd(KERN_INFO "hda_codec: applying internal mic workaround for %s\n", | ||
4444 | quirk->name); | ||
4445 | spec->fixup_stereo_dmic = 1; | ||
4446 | } | ||
4395 | } | 4447 | } |
4396 | 4448 | ||
4397 | enum { | ||
4398 | CXT_PINCFG_LENOVO_X200, | ||
4399 | CXT_PINCFG_LENOVO_TP410, | ||
4400 | }; | ||
4401 | |||
4402 | /* ThinkPad X200 & co with cxt5051 */ | 4449 | /* ThinkPad X200 & co with cxt5051 */ |
4403 | static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { | 4450 | static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { |
4404 | { 0x16, 0x042140ff }, /* HP (seq# overridden) */ | 4451 | { 0x16, 0x042140ff }, /* HP (seq# overridden) */ |
@@ -4419,6 +4466,7 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_tp410[] = { | |||
4419 | static const struct cxt_pincfg *cxt_pincfg_tbl[] = { | 4466 | static const struct cxt_pincfg *cxt_pincfg_tbl[] = { |
4420 | [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200, | 4467 | [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200, |
4421 | [CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410, | 4468 | [CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410, |
4469 | [CXT_FIXUP_STEREO_DMIC] = NULL, | ||
4422 | }; | 4470 | }; |
4423 | 4471 | ||
4424 | static const struct snd_pci_quirk cxt5051_fixups[] = { | 4472 | static const struct snd_pci_quirk cxt5051_fixups[] = { |
@@ -4432,6 +4480,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { | |||
4432 | SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), | 4480 | SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), |
4433 | SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), | 4481 | SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), |
4434 | SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), | 4482 | SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), |
4483 | SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), | ||
4435 | {} | 4484 | {} |
4436 | }; | 4485 | }; |
4437 | 4486 | ||
@@ -4471,11 +4520,11 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
4471 | case 0x14f15051: | 4520 | case 0x14f15051: |
4472 | add_cx5051_fake_mutes(codec); | 4521 | add_cx5051_fake_mutes(codec); |
4473 | codec->pin_amp_workaround = 1; | 4522 | codec->pin_amp_workaround = 1; |
4474 | apply_pin_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); | 4523 | apply_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); |
4475 | break; | 4524 | break; |
4476 | default: | 4525 | default: |
4477 | codec->pin_amp_workaround = 1; | 4526 | codec->pin_amp_workaround = 1; |
4478 | apply_pin_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); | 4527 | apply_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); |
4479 | } | 4528 | } |
4480 | 4529 | ||
4481 | /* Show mute-led control only on HP laptops | 4530 | /* Show mute-led control only on HP laptops |