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.c72
1 files changed, 49 insertions, 23 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 686ec6d75c64..0c8b5a1993ed 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -136,6 +136,8 @@ struct conexant_spec {
136 unsigned int thinkpad:1; 136 unsigned int thinkpad:1;
137 unsigned int hp_laptop:1; 137 unsigned int hp_laptop:1;
138 unsigned int asus:1; 138 unsigned int asus:1;
139 unsigned int pin_eapd_ctrls:1;
140 unsigned int single_adc_amp:1;
139 141
140 unsigned int adc_switching:1; 142 unsigned int adc_switching:1;
141 143
@@ -3430,12 +3432,14 @@ static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins,
3430static void do_automute(struct hda_codec *codec, int num_pins, 3432static void do_automute(struct hda_codec *codec, int num_pins,
3431 hda_nid_t *pins, bool on) 3433 hda_nid_t *pins, bool on)
3432{ 3434{
3435 struct conexant_spec *spec = codec->spec;
3433 int i; 3436 int i;
3434 for (i = 0; i < num_pins; i++) 3437 for (i = 0; i < num_pins; i++)
3435 snd_hda_codec_write(codec, pins[i], 0, 3438 snd_hda_codec_write(codec, pins[i], 0,
3436 AC_VERB_SET_PIN_WIDGET_CONTROL, 3439 AC_VERB_SET_PIN_WIDGET_CONTROL,
3437 on ? PIN_OUT : 0); 3440 on ? PIN_OUT : 0);
3438 cx_auto_turn_eapd(codec, num_pins, pins, on); 3441 if (spec->pin_eapd_ctrls)
3442 cx_auto_turn_eapd(codec, num_pins, pins, on);
3439} 3443}
3440 3444
3441static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins) 3445static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
@@ -3460,9 +3464,12 @@ static void cx_auto_update_speakers(struct hda_codec *codec)
3460 int on = 1; 3464 int on = 1;
3461 3465
3462 /* turn on HP EAPD when HP jacks are present */ 3466 /* turn on HP EAPD when HP jacks are present */
3463 if (spec->auto_mute) 3467 if (spec->pin_eapd_ctrls) {
3464 on = spec->hp_present; 3468 if (spec->auto_mute)
3465 cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on); 3469 on = spec->hp_present;
3470 cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
3471 }
3472
3466 /* mute speakers in auto-mode if HP or LO jacks are plugged */ 3473 /* mute speakers in auto-mode if HP or LO jacks are plugged */
3467 if (spec->auto_mute) 3474 if (spec->auto_mute)
3468 on = !(spec->hp_present || 3475 on = !(spec->hp_present ||
@@ -3889,20 +3896,10 @@ static void cx_auto_parse_beep(struct hda_codec *codec)
3889#define cx_auto_parse_beep(codec) 3896#define cx_auto_parse_beep(codec)
3890#endif 3897#endif
3891 3898
3892static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) 3899/* parse EAPDs */
3893{
3894 int i;
3895 for (i = 0; i < nums; i++)
3896 if (list[i] == nid)
3897 return true;
3898 return false;
3899}
3900
3901/* parse extra-EAPD that aren't assigned to any pins */
3902static void cx_auto_parse_eapd(struct hda_codec *codec) 3900static void cx_auto_parse_eapd(struct hda_codec *codec)
3903{ 3901{
3904 struct conexant_spec *spec = codec->spec; 3902 struct conexant_spec *spec = codec->spec;
3905 struct auto_pin_cfg *cfg = &spec->autocfg;
3906 hda_nid_t nid, end_nid; 3903 hda_nid_t nid, end_nid;
3907 3904
3908 end_nid = codec->start_nid + codec->num_nodes; 3905 end_nid = codec->start_nid + codec->num_nodes;
@@ -3911,14 +3908,18 @@ static void cx_auto_parse_eapd(struct hda_codec *codec)
3911 continue; 3908 continue;
3912 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) 3909 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD))
3913 continue; 3910 continue;
3914 if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) ||
3915 found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) ||
3916 found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs))
3917 continue;
3918 spec->eapds[spec->num_eapds++] = nid; 3911 spec->eapds[spec->num_eapds++] = nid;
3919 if (spec->num_eapds >= ARRAY_SIZE(spec->eapds)) 3912 if (spec->num_eapds >= ARRAY_SIZE(spec->eapds))
3920 break; 3913 break;
3921 } 3914 }
3915
3916 /* NOTE: below is a wild guess; if we have more than two EAPDs,
3917 * it's a new chip, where EAPDs are supposed to be associated to
3918 * pins, and we can control EAPD per pin.
3919 * OTOH, if only one or two EAPDs are found, it's an old chip,
3920 * thus it might control over all pins.
3921 */
3922 spec->pin_eapd_ctrls = spec->num_eapds > 2;
3922} 3923}
3923 3924
3924static int cx_auto_parse_auto_config(struct hda_codec *codec) 3925static int cx_auto_parse_auto_config(struct hda_codec *codec)
@@ -4024,8 +4025,9 @@ static void cx_auto_init_output(struct hda_codec *codec)
4024 } 4025 }
4025 } 4026 }
4026 cx_auto_update_speakers(codec); 4027 cx_auto_update_speakers(codec);
4027 /* turn on/off extra EAPDs, too */ 4028 /* turn on all EAPDs if no individual EAPD control is available */
4028 cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); 4029 if (!spec->pin_eapd_ctrls)
4030 cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
4029} 4031}
4030 4032
4031static void cx_auto_init_input(struct hda_codec *codec) 4033static void cx_auto_init_input(struct hda_codec *codec)
@@ -4212,6 +4214,8 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
4212 int idx = get_input_connection(codec, adc_nid, nid); 4214 int idx = get_input_connection(codec, adc_nid, nid);
4213 if (idx < 0) 4215 if (idx < 0)
4214 continue; 4216 continue;
4217 if (spec->single_adc_amp)
4218 idx = 0;
4215 return cx_auto_add_volume_idx(codec, label, pfx, 4219 return cx_auto_add_volume_idx(codec, label, pfx,
4216 cidx, adc_nid, HDA_INPUT, idx); 4220 cidx, adc_nid, HDA_INPUT, idx);
4217 } 4221 }
@@ -4252,14 +4256,21 @@ static int cx_auto_build_input_controls(struct hda_codec *codec)
4252 struct hda_input_mux *imux = &spec->private_imux; 4256 struct hda_input_mux *imux = &spec->private_imux;
4253 const char *prev_label; 4257 const char *prev_label;
4254 int input_conn[HDA_MAX_NUM_INPUTS]; 4258 int input_conn[HDA_MAX_NUM_INPUTS];
4255 int i, err, cidx; 4259 int i, j, err, cidx;
4256 int multi_connection; 4260 int multi_connection;
4257 4261
4262 if (!imux->num_items)
4263 return 0;
4264
4258 multi_connection = 0; 4265 multi_connection = 0;
4259 for (i = 0; i < imux->num_items; i++) { 4266 for (i = 0; i < imux->num_items; i++) {
4260 cidx = get_input_connection(codec, spec->imux_info[i].adc, 4267 cidx = get_input_connection(codec, spec->imux_info[i].adc,
4261 spec->imux_info[i].pin); 4268 spec->imux_info[i].pin);
4262 input_conn[i] = (spec->imux_info[i].adc << 8) | cidx; 4269 if (cidx < 0)
4270 continue;
4271 input_conn[i] = spec->imux_info[i].adc;
4272 if (!spec->single_adc_amp)
4273 input_conn[i] |= cidx << 8;
4263 if (i > 0 && input_conn[i] != input_conn[0]) 4274 if (i > 0 && input_conn[i] != input_conn[0])
4264 multi_connection = 1; 4275 multi_connection = 1;
4265 } 4276 }
@@ -4288,6 +4299,15 @@ static int cx_auto_build_input_controls(struct hda_codec *codec)
4288 err = cx_auto_add_capture_volume(codec, nid, 4299 err = cx_auto_add_capture_volume(codec, nid,
4289 "Capture", "", cidx); 4300 "Capture", "", cidx);
4290 } else { 4301 } else {
4302 bool dup_found = false;
4303 for (j = 0; j < i; j++) {
4304 if (input_conn[j] == input_conn[i]) {
4305 dup_found = true;
4306 break;
4307 }
4308 }
4309 if (dup_found)
4310 continue;
4291 err = cx_auto_add_capture_volume(codec, nid, 4311 err = cx_auto_add_capture_volume(codec, nid,
4292 label, " Capture", cidx); 4312 label, " Capture", cidx);
4293 } 4313 }
@@ -4412,6 +4432,12 @@ static int patch_conexant_auto(struct hda_codec *codec)
4412 codec->spec = spec; 4432 codec->spec = spec;
4413 codec->pin_amp_workaround = 1; 4433 codec->pin_amp_workaround = 1;
4414 4434
4435 switch (codec->vendor_id) {
4436 case 0x14f15045:
4437 spec->single_adc_amp = 1;
4438 break;
4439 }
4440
4415 apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); 4441 apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl);
4416 4442
4417 err = cx_auto_search_adcs(codec); 4443 err = cx_auto_search_adcs(codec);