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.c145
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
4073static int cx_auto_init(struct hda_codec *codec) 4059static int cx_auto_init(struct hda_codec *codec)
@@ -4084,9 +4070,9 @@ static int cx_auto_init(struct hda_codec *codec)
4084 4070
4085static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename, 4071static 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. */
4177static 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
4188static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, 4204static 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
4385static void apply_pin_fixup(struct hda_codec *codec, 4422enum {
4423 CXT_PINCFG_LENOVO_X200,
4424 CXT_PINCFG_LENOVO_TP410,
4425 CXT_FIXUP_STEREO_DMIC,
4426};
4427
4428static 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
4397enum {
4398 CXT_PINCFG_LENOVO_X200,
4399 CXT_PINCFG_LENOVO_TP410,
4400};
4401
4402/* ThinkPad X200 & co with cxt5051 */ 4449/* ThinkPad X200 & co with cxt5051 */
4403static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = { 4450static 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[] = {
4419static const struct cxt_pincfg *cxt_pincfg_tbl[] = { 4466static 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
4424static const struct snd_pci_quirk cxt5051_fixups[] = { 4472static 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