aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_conexant.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r--sound/pci/hda/patch_conexant.c186
1 files changed, 116 insertions, 70 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index d906c5b74cf0..3acb5824ad39 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -30,6 +30,7 @@
30 30
31#include "hda_codec.h" 31#include "hda_codec.h"
32#include "hda_local.h" 32#include "hda_local.h"
33#include "hda_auto_parser.h"
33#include "hda_beep.h" 34#include "hda_beep.h"
34#include "hda_jack.h" 35#include "hda_jack.h"
35 36
@@ -66,6 +67,7 @@ struct imux_info {
66}; 67};
67 68
68struct conexant_spec { 69struct conexant_spec {
70 struct hda_gen_spec gen;
69 71
70 const struct snd_kcontrol_new *mixers[5]; 72 const struct snd_kcontrol_new *mixers[5];
71 int num_mixers; 73 int num_mixers;
@@ -141,6 +143,7 @@ struct conexant_spec {
141 unsigned int hp_laptop:1; 143 unsigned int hp_laptop:1;
142 unsigned int asus:1; 144 unsigned int asus:1;
143 unsigned int pin_eapd_ctrls:1; 145 unsigned int pin_eapd_ctrls:1;
146 unsigned int fixup_stereo_dmic:1;
144 147
145 unsigned int adc_switching:1; 148 unsigned int adc_switching:1;
146 149
@@ -1601,17 +1604,13 @@ static void cxt5051_update_speaker(struct hda_codec *codec)
1601 unsigned int pinctl; 1604 unsigned int pinctl;
1602 /* headphone pin */ 1605 /* headphone pin */
1603 pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0; 1606 pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0;
1604 snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 1607 snd_hda_set_pin_ctl(codec, 0x16, pinctl);
1605 pinctl);
1606 /* speaker pin */ 1608 /* speaker pin */
1607 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; 1609 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
1608 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 1610 snd_hda_set_pin_ctl(codec, 0x1a, pinctl);
1609 pinctl);
1610 /* on ideapad there is an additional speaker (subwoofer) to mute */ 1611 /* on ideapad there is an additional speaker (subwoofer) to mute */
1611 if (spec->ideapad) 1612 if (spec->ideapad)
1612 snd_hda_codec_write(codec, 0x1b, 0, 1613 snd_hda_set_pin_ctl(codec, 0x1b, pinctl);
1613 AC_VERB_SET_PIN_WIDGET_CONTROL,
1614 pinctl);
1615} 1614}
1616 1615
1617/* turn on/off EAPD (+ mute HP) as a master switch */ 1616/* turn on/off EAPD (+ mute HP) as a master switch */
@@ -1996,8 +1995,7 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
1996 1995
1997 /* Port A (HP) */ 1996 /* Port A (HP) */
1998 pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0; 1997 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, 1998 snd_hda_set_pin_ctl(codec, 0x19, pinctl);
2000 pinctl);
2001 1999
2002 /* Port D (HP/LO) */ 2000 /* Port D (HP/LO) */
2003 pinctl = spec->cur_eapd ? spec->port_d_mode : 0; 2001 pinctl = spec->cur_eapd ? spec->port_d_mode : 0;
@@ -2010,13 +2008,11 @@ static void cxt5066_update_speaker(struct hda_codec *codec)
2010 if (!hp_port_d_present(spec)) 2008 if (!hp_port_d_present(spec))
2011 pinctl = 0; 2009 pinctl = 0;
2012 } 2010 }
2013 snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2011 snd_hda_set_pin_ctl(codec, 0x1c, pinctl);
2014 pinctl);
2015 2012
2016 /* CLASS_D AMP */ 2013 /* CLASS_D AMP */
2017 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; 2014 pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
2018 snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2015 snd_hda_set_pin_ctl(codec, 0x1f, pinctl);
2019 pinctl);
2020} 2016}
2021 2017
2022/* turn on/off EAPD (+ mute HP) as a master switch */ 2018/* turn on/off EAPD (+ mute HP) as a master switch */
@@ -2047,8 +2043,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. 2043 /* 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 2044 * 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. */ 2045 * just in case that is necessary to make the bias setting take effect. */
2050 return snd_hda_codec_write_cache(codec, 0x1a, 0, 2046 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); 2047 cxt5066_olpc_dc_bias.items[spec->dc_input_bias].index);
2053} 2048}
2054 2049
@@ -2081,14 +2076,14 @@ static void cxt5066_olpc_select_mic(struct hda_codec *codec)
2081 } 2076 }
2082 2077
2083 /* disable DC (port F) */ 2078 /* disable DC (port F) */
2084 snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0); 2079 snd_hda_set_pin_ctl(codec, 0x1e, 0);
2085 2080
2086 /* external mic, port B */ 2081 /* external mic, port B */
2087 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2082 snd_hda_set_pin_ctl(codec, 0x1a,
2088 spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0); 2083 spec->ext_mic_present ? CXT5066_OLPC_EXT_MIC_BIAS : 0);
2089 2084
2090 /* internal mic, port C */ 2085 /* internal mic, port C */
2091 snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 2086 snd_hda_set_pin_ctl(codec, 0x1b,
2092 spec->ext_mic_present ? 0 : PIN_VREF80); 2087 spec->ext_mic_present ? 0 : PIN_VREF80);
2093} 2088}
2094 2089
@@ -3357,9 +3352,7 @@ static void do_automute(struct hda_codec *codec, int num_pins,
3357 struct conexant_spec *spec = codec->spec; 3352 struct conexant_spec *spec = codec->spec;
3358 int i; 3353 int i;
3359 for (i = 0; i < num_pins; i++) 3354 for (i = 0; i < num_pins; i++)
3360 snd_hda_codec_write(codec, pins[i], 0, 3355 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) 3356 if (spec->pin_eapd_ctrls)
3364 cx_auto_turn_eapd(codec, num_pins, pins, on); 3357 cx_auto_turn_eapd(codec, num_pins, pins, on);
3365} 3358}
@@ -3976,8 +3969,7 @@ static void cx_auto_init_output(struct hda_codec *codec)
3976 if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) & 3969 if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) &
3977 AC_PINCAP_HP_DRV) 3970 AC_PINCAP_HP_DRV)
3978 val |= AC_PINCTL_HP_EN; 3971 val |= AC_PINCTL_HP_EN;
3979 snd_hda_codec_write(codec, cfg->hp_pins[i], 0, 3972 snd_hda_set_pin_ctl(codec, cfg->hp_pins[i], val);
3980 AC_VERB_SET_PIN_WIDGET_CONTROL, val);
3981 } 3973 }
3982 mute_outputs(codec, cfg->hp_outs, cfg->hp_pins); 3974 mute_outputs(codec, cfg->hp_outs, cfg->hp_pins);
3983 mute_outputs(codec, cfg->line_outs, cfg->line_out_pins); 3975 mute_outputs(codec, cfg->line_outs, cfg->line_out_pins);
@@ -4030,13 +4022,11 @@ static void cx_auto_init_input(struct hda_codec *codec)
4030 } 4022 }
4031 4023
4032 for (i = 0; i < cfg->num_inputs; i++) { 4024 for (i = 0; i < cfg->num_inputs; i++) {
4033 unsigned int type; 4025 hda_nid_t pin = cfg->inputs[i].pin;
4026 unsigned int type = PIN_IN;
4034 if (cfg->inputs[i].type == AUTO_PIN_MIC) 4027 if (cfg->inputs[i].type == AUTO_PIN_MIC)
4035 type = PIN_VREF80; 4028 type |= snd_hda_get_default_vref(codec, pin);
4036 else 4029 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 } 4030 }
4041 4031
4042 if (spec->auto_mic) { 4032 if (spec->auto_mic) {
@@ -4063,11 +4053,9 @@ static void cx_auto_init_digital(struct hda_codec *codec)
4063 struct auto_pin_cfg *cfg = &spec->autocfg; 4053 struct auto_pin_cfg *cfg = &spec->autocfg;
4064 4054
4065 if (spec->multiout.dig_out_nid) 4055 if (spec->multiout.dig_out_nid)
4066 snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0, 4056 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) 4057 if (spec->dig_in_nid)
4069 snd_hda_codec_write(codec, cfg->dig_in_pin, 0, 4058 snd_hda_set_pin_ctl(codec, cfg->dig_in_pin, PIN_IN);
4070 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
4071} 4059}
4072 4060
4073static int cx_auto_init(struct hda_codec *codec) 4061static int cx_auto_init(struct hda_codec *codec)
@@ -4084,9 +4072,9 @@ static int cx_auto_init(struct hda_codec *codec)
4084 4072
4085static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, 4073static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
4086 const char *dir, int cidx, 4074 const char *dir, int cidx,
4087 hda_nid_t nid, int hda_dir, int amp_idx) 4075 hda_nid_t nid, int hda_dir, int amp_idx, int chs)
4088{ 4076{
4089 static char name[32]; 4077 static char name[44];
4090 static struct snd_kcontrol_new knew[] = { 4078 static struct snd_kcontrol_new knew[] = {
4091 HDA_CODEC_VOLUME(name, 0, 0, 0), 4079 HDA_CODEC_VOLUME(name, 0, 0, 0),
4092 HDA_CODEC_MUTE(name, 0, 0, 0), 4080 HDA_CODEC_MUTE(name, 0, 0, 0),
@@ -4096,7 +4084,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
4096 4084
4097 for (i = 0; i < 2; i++) { 4085 for (i = 0; i < 2; i++) {
4098 struct snd_kcontrol *kctl; 4086 struct snd_kcontrol *kctl;
4099 knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx, 4087 knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, chs, amp_idx,
4100 hda_dir); 4088 hda_dir);
4101 knew[i].subdevice = HDA_SUBDEV_AMP_FLAG; 4089 knew[i].subdevice = HDA_SUBDEV_AMP_FLAG;
4102 knew[i].index = cidx; 4090 knew[i].index = cidx;
@@ -4115,7 +4103,7 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
4115} 4103}
4116 4104
4117#define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \ 4105#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) 4106 cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0, 3)
4119 4107
4120#define cx_auto_add_pb_volume(codec, nid, str, idx) \ 4108#define cx_auto_add_pb_volume(codec, nid, str, idx) \
4121 cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) 4109 cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
@@ -4185,6 +4173,36 @@ static int cx_auto_build_output_controls(struct hda_codec *codec)
4185 return 0; 4173 return 0;
4186} 4174}
4187 4175
4176/* Returns zero if this is a normal stereo channel, and non-zero if it should
4177 be split in two independent channels.
4178 dest_label must be at least 44 characters. */
4179static int cx_auto_get_rightch_label(struct hda_codec *codec, const char *label,
4180 char *dest_label, int nid)
4181{
4182 struct conexant_spec *spec = codec->spec;
4183 int i;
4184
4185 if (!spec->fixup_stereo_dmic)
4186 return 0;
4187
4188 for (i = 0; i < AUTO_CFG_MAX_INS; i++) {
4189 int def_conf;
4190 if (spec->autocfg.inputs[i].pin != nid)
4191 continue;
4192
4193 if (spec->autocfg.inputs[i].type != AUTO_PIN_MIC)
4194 return 0;
4195 def_conf = snd_hda_codec_get_pincfg(codec, nid);
4196 if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT)
4197 return 0;
4198
4199 /* Finally found the inverted internal mic! */
4200 snprintf(dest_label, 44, "Inverted %s", label);
4201 return 1;
4202 }
4203 return 0;
4204}
4205
4188static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, 4206static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
4189 const char *label, const char *pfx, 4207 const char *label, const char *pfx,
4190 int cidx) 4208 int cidx)
@@ -4193,14 +4211,25 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
4193 int i; 4211 int i;
4194 4212
4195 for (i = 0; i < spec->num_adc_nids; i++) { 4213 for (i = 0; i < spec->num_adc_nids; i++) {
4214 char rightch_label[44];
4196 hda_nid_t adc_nid = spec->adc_nids[i]; 4215 hda_nid_t adc_nid = spec->adc_nids[i];
4197 int idx = get_input_connection(codec, adc_nid, nid); 4216 int idx = get_input_connection(codec, adc_nid, nid);
4198 if (idx < 0) 4217 if (idx < 0)
4199 continue; 4218 continue;
4200 if (codec->single_adc_amp) 4219 if (codec->single_adc_amp)
4201 idx = 0; 4220 idx = 0;
4221
4222 if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) {
4223 /* Make two independent kcontrols for left and right */
4224 int err = cx_auto_add_volume_idx(codec, label, pfx,
4225 cidx, adc_nid, HDA_INPUT, idx, 1);
4226 if (err < 0)
4227 return err;
4228 return cx_auto_add_volume_idx(codec, rightch_label, pfx,
4229 cidx, adc_nid, HDA_INPUT, idx, 2);
4230 }
4202 return cx_auto_add_volume_idx(codec, label, pfx, 4231 return cx_auto_add_volume_idx(codec, label, pfx,
4203 cidx, adc_nid, HDA_INPUT, idx); 4232 cidx, adc_nid, HDA_INPUT, idx, 3);
4204 } 4233 }
4205 return 0; 4234 return 0;
4206} 4235}
@@ -4213,9 +4242,19 @@ static int cx_auto_add_boost_volume(struct hda_codec *codec, int idx,
4213 int i, con; 4242 int i, con;
4214 4243
4215 nid = spec->imux_info[idx].pin; 4244 nid = spec->imux_info[idx].pin;
4216 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) 4245 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
4246 char rightch_label[44];
4247 if (cx_auto_get_rightch_label(codec, label, rightch_label, nid)) {
4248 int err = cx_auto_add_volume_idx(codec, label, " Boost",
4249 cidx, nid, HDA_INPUT, 0, 1);
4250 if (err < 0)
4251 return err;
4252 return cx_auto_add_volume_idx(codec, rightch_label, " Boost",
4253 cidx, nid, HDA_INPUT, 0, 2);
4254 }
4217 return cx_auto_add_volume(codec, label, " Boost", cidx, 4255 return cx_auto_add_volume(codec, label, " Boost", cidx,
4218 nid, HDA_INPUT); 4256 nid, HDA_INPUT);
4257 }
4219 con = __select_input_connection(codec, spec->imux_info[idx].adc, nid, 4258 con = __select_input_connection(codec, spec->imux_info[idx].adc, nid,
4220 &mux, false, 0); 4259 &mux, false, 0);
4221 if (con < 0) 4260 if (con < 0)
@@ -4370,37 +4409,21 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
4370/* 4409/*
4371 * pin fix-up 4410 * pin fix-up
4372 */ 4411 */
4373struct cxt_pincfg {
4374 hda_nid_t nid;
4375 u32 val;
4376};
4377
4378static void apply_pincfg(struct hda_codec *codec, const struct cxt_pincfg *cfg)
4379{
4380 for (; cfg->nid; cfg++)
4381 snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
4382
4383}
4384
4385static void apply_pin_fixup(struct hda_codec *codec,
4386 const struct snd_pci_quirk *quirk,
4387 const struct cxt_pincfg **table)
4388{
4389 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
4390 if (quirk) {
4391 snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n",
4392 quirk->name);
4393 apply_pincfg(codec, table[quirk->value]);
4394 }
4395}
4396
4397enum { 4412enum {
4398 CXT_PINCFG_LENOVO_X200, 4413 CXT_PINCFG_LENOVO_X200,
4399 CXT_PINCFG_LENOVO_TP410, 4414 CXT_PINCFG_LENOVO_TP410,
4415 CXT_FIXUP_STEREO_DMIC,
4400}; 4416};
4401 4417
4418static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
4419 const struct hda_fixup *fix, int action)
4420{
4421 struct conexant_spec *spec = codec->spec;
4422 spec->fixup_stereo_dmic = 1;
4423}
4424
4402/* ThinkPad X200 & co with cxt5051 */ 4425/* ThinkPad X200 & co with cxt5051 */
4403static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { 4426static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
4404 { 0x16, 0x042140ff }, /* HP (seq# overridden) */ 4427 { 0x16, 0x042140ff }, /* HP (seq# overridden) */
4405 { 0x17, 0x21a11000 }, /* dock-mic */ 4428 { 0x17, 0x21a11000 }, /* dock-mic */
4406 { 0x19, 0x2121103f }, /* dock-HP */ 4429 { 0x19, 0x2121103f }, /* dock-HP */
@@ -4409,16 +4432,26 @@ static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
4409}; 4432};
4410 4433
4411/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */ 4434/* ThinkPad 410/420/510/520, X201 & co with cxt5066 */
4412static const struct cxt_pincfg cxt_pincfg_lenovo_tp410[] = { 4435static const struct hda_pintbl cxt_pincfg_lenovo_tp410[] = {
4413 { 0x19, 0x042110ff }, /* HP (seq# overridden) */ 4436 { 0x19, 0x042110ff }, /* HP (seq# overridden) */
4414 { 0x1a, 0x21a190f0 }, /* dock-mic */ 4437 { 0x1a, 0x21a190f0 }, /* dock-mic */
4415 { 0x1c, 0x212140ff }, /* dock-HP */ 4438 { 0x1c, 0x212140ff }, /* dock-HP */
4416 {} 4439 {}
4417}; 4440};
4418 4441
4419static const struct cxt_pincfg *cxt_pincfg_tbl[] = { 4442static const struct hda_fixup cxt_fixups[] = {
4420 [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200, 4443 [CXT_PINCFG_LENOVO_X200] = {
4421 [CXT_PINCFG_LENOVO_TP410] = cxt_pincfg_lenovo_tp410, 4444 .type = HDA_FIXUP_PINS,
4445 .v.pins = cxt_pincfg_lenovo_x200,
4446 },
4447 [CXT_PINCFG_LENOVO_TP410] = {
4448 .type = HDA_FIXUP_PINS,
4449 .v.pins = cxt_pincfg_lenovo_tp410,
4450 },
4451 [CXT_FIXUP_STEREO_DMIC] = {
4452 .type = HDA_FIXUP_FUNC,
4453 .v.func = cxt_fixup_stereo_dmic,
4454 },
4422}; 4455};
4423 4456
4424static const struct snd_pci_quirk cxt5051_fixups[] = { 4457static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -4432,6 +4465,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
4432 SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410), 4465 SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
4433 SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), 4466 SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
4434 SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), 4467 SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
4468 SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
4435 {} 4469 {}
4436}; 4470};
4437 4471
@@ -4471,13 +4505,16 @@ static int patch_conexant_auto(struct hda_codec *codec)
4471 case 0x14f15051: 4505 case 0x14f15051:
4472 add_cx5051_fake_mutes(codec); 4506 add_cx5051_fake_mutes(codec);
4473 codec->pin_amp_workaround = 1; 4507 codec->pin_amp_workaround = 1;
4474 apply_pin_fixup(codec, cxt5051_fixups, cxt_pincfg_tbl); 4508 snd_hda_pick_fixup(codec, NULL, cxt5051_fixups, cxt_fixups);
4475 break; 4509 break;
4476 default: 4510 default:
4477 codec->pin_amp_workaround = 1; 4511 codec->pin_amp_workaround = 1;
4478 apply_pin_fixup(codec, cxt5066_fixups, cxt_pincfg_tbl); 4512 snd_hda_pick_fixup(codec, NULL, cxt5066_fixups, cxt_fixups);
4513 break;
4479 } 4514 }
4480 4515
4516 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
4517
4481 /* Show mute-led control only on HP laptops 4518 /* Show mute-led control only on HP laptops
4482 * This is a sort of white-list: on HP laptops, EAPD corresponds 4519 * This is a sort of white-list: on HP laptops, EAPD corresponds
4483 * only to the mute-LED without actualy amp function. Meanwhile, 4520 * only to the mute-LED without actualy amp function. Meanwhile,
@@ -4556,6 +4593,12 @@ static const struct hda_codec_preset snd_hda_preset_conexant[] = {
4556 .patch = patch_conexant_auto }, 4593 .patch = patch_conexant_auto },
4557 { .id = 0x14f150b9, .name = "CX20665", 4594 { .id = 0x14f150b9, .name = "CX20665",
4558 .patch = patch_conexant_auto }, 4595 .patch = patch_conexant_auto },
4596 { .id = 0x14f1510f, .name = "CX20751/2",
4597 .patch = patch_conexant_auto },
4598 { .id = 0x14f15110, .name = "CX20751/2",
4599 .patch = patch_conexant_auto },
4600 { .id = 0x14f15111, .name = "CX20753/4",
4601 .patch = patch_conexant_auto },
4559 {} /* terminator */ 4602 {} /* terminator */
4560}; 4603};
4561 4604
@@ -4576,6 +4619,9 @@ MODULE_ALIAS("snd-hda-codec-id:14f150ab");
4576MODULE_ALIAS("snd-hda-codec-id:14f150ac"); 4619MODULE_ALIAS("snd-hda-codec-id:14f150ac");
4577MODULE_ALIAS("snd-hda-codec-id:14f150b8"); 4620MODULE_ALIAS("snd-hda-codec-id:14f150b8");
4578MODULE_ALIAS("snd-hda-codec-id:14f150b9"); 4621MODULE_ALIAS("snd-hda-codec-id:14f150b9");
4622MODULE_ALIAS("snd-hda-codec-id:14f1510f");
4623MODULE_ALIAS("snd-hda-codec-id:14f15110");
4624MODULE_ALIAS("snd-hda-codec-id:14f15111");
4579 4625
4580MODULE_LICENSE("GPL"); 4626MODULE_LICENSE("GPL");
4581MODULE_DESCRIPTION("Conexant HD-audio codec"); 4627MODULE_DESCRIPTION("Conexant HD-audio codec");