|
@@ -182,7 +182,6 @@ struct alc_spec {
|
|
|
int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
|
|
|
hda_nid_t inv_dmic_pin;
|
|
|
hda_nid_t shared_mic_vref_pin;
|
|
|
- int inv_dmic_split_idx; /* used internally for inv_dmic_split */
|
|
|
|
|
|
/* DAC list */
|
|
|
int num_all_dacs;
|
|
@@ -2552,23 +2551,19 @@ static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
|
|
|
static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs);
|
|
|
|
|
|
static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
|
|
|
- int idx, bool is_switch, unsigned int ctl)
|
|
|
+ int idx, bool is_switch, unsigned int ctl,
|
|
|
+ bool inv_dmic)
|
|
|
{
|
|
|
struct alc_spec *spec = codec->spec;
|
|
|
char tmpname[44];
|
|
|
int type = is_switch ? ALC_CTL_WIDGET_MUTE : ALC_CTL_WIDGET_VOL;
|
|
|
const char *sfx = is_switch ? "Switch" : "Volume";
|
|
|
- unsigned int chs;
|
|
|
+ unsigned int chs = inv_dmic ? 1 : 3;
|
|
|
int err;
|
|
|
|
|
|
if (!ctl)
|
|
|
return 0;
|
|
|
|
|
|
- if (idx == spec->inv_dmic_split_idx)
|
|
|
- chs = 1;
|
|
|
- else
|
|
|
- chs = 3;
|
|
|
-
|
|
|
if (label)
|
|
|
snprintf(tmpname, sizeof(tmpname),
|
|
|
"%s Capture %s", label, sfx);
|
|
@@ -2591,15 +2586,36 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
|
|
|
amp_val_replace_channels(ctl, 2));
|
|
|
}
|
|
|
|
|
|
+static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
|
|
|
+{
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
+ struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
|
+ unsigned int val;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (!spec->inv_dmic_split)
|
|
|
+ return false;
|
|
|
+ for (i = 0; i < cfg->num_inputs; i++) {
|
|
|
+ if (cfg->inputs[i].pin != nid)
|
|
|
+ continue;
|
|
|
+ if (cfg->inputs[i].type != AUTO_PIN_MIC)
|
|
|
+ return false;
|
|
|
+ val = snd_hda_codec_get_pincfg(codec, nid);
|
|
|
+ return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
/* create single (and simple) capture volume and switch controls */
|
|
|
static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
|
|
|
- unsigned int vol_ctl, unsigned int sw_ctl)
|
|
|
+ unsigned int vol_ctl, unsigned int sw_ctl,
|
|
|
+ bool inv_dmic)
|
|
|
{
|
|
|
int err;
|
|
|
- err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl);
|
|
|
+ err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
- err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl);
|
|
|
+ err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
return 0;
|
|
@@ -2665,16 +2681,19 @@ static int create_multi_cap_vol_ctl(struct hda_codec *codec)
|
|
|
|
|
|
for (i = 0; i < imux->num_items; i++) {
|
|
|
const char *label;
|
|
|
+ bool inv_dmic;
|
|
|
label = hda_get_autocfg_input_label(codec, &spec->autocfg, i);
|
|
|
if (prev_label && !strcmp(label, prev_label))
|
|
|
type_idx++;
|
|
|
else
|
|
|
type_idx = 0;
|
|
|
prev_label = label;
|
|
|
+ inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
|
|
|
|
|
|
for (type = 0; type < 2; type++) {
|
|
|
err = add_single_cap_ctl(codec, label, type_idx, type,
|
|
|
- get_first_cap_ctl(codec, i, type));
|
|
|
+ get_first_cap_ctl(codec, i, type),
|
|
|
+ inv_dmic);
|
|
|
if (err < 0)
|
|
|
return err;
|
|
|
}
|
|
@@ -2703,6 +2722,7 @@ static int create_capture_mixers(struct hda_codec *codec)
|
|
|
|
|
|
for (n = 0; n < nums; n++) {
|
|
|
bool multi = false;
|
|
|
+ bool inv_dmic = false;
|
|
|
int vol, sw;
|
|
|
|
|
|
vol = sw = 0;
|
|
@@ -2721,10 +2741,13 @@ static int create_capture_mixers(struct hda_codec *codec)
|
|
|
sw = path->ctls[NID_PATH_MUTE_CTL];
|
|
|
else if (sw != path->ctls[NID_PATH_MUTE_CTL])
|
|
|
multi = true;
|
|
|
+ if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
|
|
|
+ inv_dmic = true;
|
|
|
}
|
|
|
|
|
|
if (!multi)
|
|
|
- err = create_single_cap_vol_ctl(codec, n, vol, sw);
|
|
|
+ err = create_single_cap_vol_ctl(codec, n, vol, sw,
|
|
|
+ inv_dmic);
|
|
|
else if (!spec->multi_cap_vol)
|
|
|
err = create_bind_cap_vol_ctl(codec, n, vol, sw);
|
|
|
else
|
|
@@ -2751,7 +2774,6 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
|
|
|
if (num_adcs < 0)
|
|
|
return 0;
|
|
|
|
|
|
- spec->inv_dmic_split_idx = -1;
|
|
|
for (i = 0; i < cfg->num_inputs; i++) {
|
|
|
hda_nid_t pin;
|
|
|
const char *label;
|
|
@@ -2805,14 +2827,6 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
|
|
|
imux_added = true;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- if (spec->inv_dmic_split) {
|
|
|
- if (cfg->inputs[i].type == AUTO_PIN_MIC) {
|
|
|
- unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
|
|
|
- if (snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT)
|
|
|
- spec->inv_dmic_split_idx = i;
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
return 0;
|