|
@@ -136,6 +136,8 @@ struct conexant_spec {
|
|
|
unsigned int thinkpad:1;
|
|
|
unsigned int hp_laptop:1;
|
|
|
unsigned int asus:1;
|
|
|
+ unsigned int pin_eapd_ctrls:1;
|
|
|
+ unsigned int single_adc_amp:1;
|
|
|
|
|
|
unsigned int adc_switching:1;
|
|
|
|
|
@@ -3430,12 +3432,14 @@ static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins,
|
|
|
static void do_automute(struct hda_codec *codec, int num_pins,
|
|
|
hda_nid_t *pins, bool on)
|
|
|
{
|
|
|
+ struct conexant_spec *spec = codec->spec;
|
|
|
int i;
|
|
|
for (i = 0; i < num_pins; i++)
|
|
|
snd_hda_codec_write(codec, pins[i], 0,
|
|
|
AC_VERB_SET_PIN_WIDGET_CONTROL,
|
|
|
on ? PIN_OUT : 0);
|
|
|
- cx_auto_turn_eapd(codec, num_pins, pins, on);
|
|
|
+ if (spec->pin_eapd_ctrls)
|
|
|
+ cx_auto_turn_eapd(codec, num_pins, pins, on);
|
|
|
}
|
|
|
|
|
|
static 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)
|
|
|
int on = 1;
|
|
|
|
|
|
/* turn on HP EAPD when HP jacks are present */
|
|
|
- if (spec->auto_mute)
|
|
|
- on = spec->hp_present;
|
|
|
- cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
|
|
|
+ if (spec->pin_eapd_ctrls) {
|
|
|
+ if (spec->auto_mute)
|
|
|
+ on = spec->hp_present;
|
|
|
+ cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
|
|
|
+ }
|
|
|
+
|
|
|
/* mute speakers in auto-mode if HP or LO jacks are plugged */
|
|
|
if (spec->auto_mute)
|
|
|
on = !(spec->hp_present ||
|
|
@@ -3889,20 +3896,10 @@ static void cx_auto_parse_beep(struct hda_codec *codec)
|
|
|
#define cx_auto_parse_beep(codec)
|
|
|
#endif
|
|
|
|
|
|
-static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
|
|
|
-{
|
|
|
- int i;
|
|
|
- for (i = 0; i < nums; i++)
|
|
|
- if (list[i] == nid)
|
|
|
- return true;
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-/* parse extra-EAPD that aren't assigned to any pins */
|
|
|
+/* parse EAPDs */
|
|
|
static void cx_auto_parse_eapd(struct hda_codec *codec)
|
|
|
{
|
|
|
struct conexant_spec *spec = codec->spec;
|
|
|
- struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
|
hda_nid_t nid, end_nid;
|
|
|
|
|
|
end_nid = codec->start_nid + codec->num_nodes;
|
|
@@ -3911,14 +3908,18 @@ static void cx_auto_parse_eapd(struct hda_codec *codec)
|
|
|
continue;
|
|
|
if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD))
|
|
|
continue;
|
|
|
- if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) ||
|
|
|
- found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) ||
|
|
|
- found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs))
|
|
|
- continue;
|
|
|
spec->eapds[spec->num_eapds++] = nid;
|
|
|
if (spec->num_eapds >= ARRAY_SIZE(spec->eapds))
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
+ /* NOTE: below is a wild guess; if we have more than two EAPDs,
|
|
|
+ * it's a new chip, where EAPDs are supposed to be associated to
|
|
|
+ * pins, and we can control EAPD per pin.
|
|
|
+ * OTOH, if only one or two EAPDs are found, it's an old chip,
|
|
|
+ * thus it might control over all pins.
|
|
|
+ */
|
|
|
+ spec->pin_eapd_ctrls = spec->num_eapds > 2;
|
|
|
}
|
|
|
|
|
|
static int cx_auto_parse_auto_config(struct hda_codec *codec)
|
|
@@ -4024,8 +4025,9 @@ static void cx_auto_init_output(struct hda_codec *codec)
|
|
|
}
|
|
|
}
|
|
|
cx_auto_update_speakers(codec);
|
|
|
- /* turn on/off extra EAPDs, too */
|
|
|
- cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
|
|
|
+ /* turn on all EAPDs if no individual EAPD control is available */
|
|
|
+ if (!spec->pin_eapd_ctrls)
|
|
|
+ cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
|
|
|
}
|
|
|
|
|
|
static 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,
|
|
|
int idx = get_input_connection(codec, adc_nid, nid);
|
|
|
if (idx < 0)
|
|
|
continue;
|
|
|
+ if (spec->single_adc_amp)
|
|
|
+ idx = 0;
|
|
|
return cx_auto_add_volume_idx(codec, label, pfx,
|
|
|
cidx, adc_nid, HDA_INPUT, idx);
|
|
|
}
|
|
@@ -4252,14 +4256,21 @@ static int cx_auto_build_input_controls(struct hda_codec *codec)
|
|
|
struct hda_input_mux *imux = &spec->private_imux;
|
|
|
const char *prev_label;
|
|
|
int input_conn[HDA_MAX_NUM_INPUTS];
|
|
|
- int i, err, cidx;
|
|
|
+ int i, j, err, cidx;
|
|
|
int multi_connection;
|
|
|
|
|
|
+ if (!imux->num_items)
|
|
|
+ return 0;
|
|
|
+
|
|
|
multi_connection = 0;
|
|
|
for (i = 0; i < imux->num_items; i++) {
|
|
|
cidx = get_input_connection(codec, spec->imux_info[i].adc,
|
|
|
spec->imux_info[i].pin);
|
|
|
- input_conn[i] = (spec->imux_info[i].adc << 8) | cidx;
|
|
|
+ if (cidx < 0)
|
|
|
+ continue;
|
|
|
+ input_conn[i] = spec->imux_info[i].adc;
|
|
|
+ if (!spec->single_adc_amp)
|
|
|
+ input_conn[i] |= cidx << 8;
|
|
|
if (i > 0 && input_conn[i] != input_conn[0])
|
|
|
multi_connection = 1;
|
|
|
}
|
|
@@ -4288,6 +4299,15 @@ static int cx_auto_build_input_controls(struct hda_codec *codec)
|
|
|
err = cx_auto_add_capture_volume(codec, nid,
|
|
|
"Capture", "", cidx);
|
|
|
} else {
|
|
|
+ bool dup_found = false;
|
|
|
+ for (j = 0; j < i; j++) {
|
|
|
+ if (input_conn[j] == input_conn[i]) {
|
|
|
+ dup_found = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (dup_found)
|
|
|
+ continue;
|
|
|
err = cx_auto_add_capture_volume(codec, nid,
|
|
|
label, " Capture", cidx);
|
|
|
}
|
|
@@ -4412,6 +4432,12 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
|
|
codec->spec = spec;
|
|
|
codec->pin_amp_workaround = 1;
|
|
|
|
|
|
+ switch (codec->vendor_id) {
|
|
|
+ case 0x14f15045:
|
|
|
+ spec->single_adc_amp = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl);
|
|
|
|
|
|
err = cx_auto_search_adcs(codec);
|