|
@@ -198,8 +198,11 @@ struct alc_spec {
|
|
|
|
|
|
/* for virtual master */
|
|
/* for virtual master */
|
|
hda_nid_t vmaster_nid;
|
|
hda_nid_t vmaster_nid;
|
|
|
|
+ struct hda_vmaster_mute_hook vmaster_mute;
|
|
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
struct hda_loopback_check loopback;
|
|
struct hda_loopback_check loopback;
|
|
|
|
+ int num_loopbacks;
|
|
|
|
+ struct hda_amp_list loopback_list[8];
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* for PLL fix */
|
|
/* for PLL fix */
|
|
@@ -220,8 +223,6 @@ struct alc_spec {
|
|
struct snd_array bind_ctls;
|
|
struct snd_array bind_ctls;
|
|
};
|
|
};
|
|
|
|
|
|
-#define ALC_MODEL_AUTO 0 /* common for all chips */
|
|
|
|
-
|
|
|
|
static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
|
|
static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
|
|
int dir, unsigned int bits)
|
|
int dir, unsigned int bits)
|
|
{
|
|
{
|
|
@@ -300,6 +301,9 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
|
|
int i, type, num_conns;
|
|
int i, type, num_conns;
|
|
hda_nid_t nid;
|
|
hda_nid_t nid;
|
|
|
|
|
|
|
|
+ if (!spec->input_mux)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
|
|
mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
|
|
imux = &spec->input_mux[mux_idx];
|
|
imux = &spec->input_mux[mux_idx];
|
|
if (!imux->num_items && mux_idx > 0)
|
|
if (!imux->num_items && mux_idx > 0)
|
|
@@ -651,15 +655,51 @@ static void alc_exec_unsol_event(struct hda_codec *codec, int action)
|
|
snd_hda_jack_report_sync(codec);
|
|
snd_hda_jack_report_sync(codec);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* update the master volume per volume-knob's unsol event */
|
|
|
|
+static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid)
|
|
|
|
+{
|
|
|
|
+ unsigned int val;
|
|
|
|
+ struct snd_kcontrol *kctl;
|
|
|
|
+ struct snd_ctl_elem_value *uctl;
|
|
|
|
+
|
|
|
|
+ kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
|
|
|
|
+ if (!kctl)
|
|
|
|
+ return;
|
|
|
|
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
|
|
|
|
+ if (!uctl)
|
|
|
|
+ return;
|
|
|
|
+ val = snd_hda_codec_read(codec, nid, 0,
|
|
|
|
+ AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
|
|
|
|
+ val &= HDA_AMP_VOLMASK;
|
|
|
|
+ uctl->value.integer.value[0] = val;
|
|
|
|
+ uctl->value.integer.value[1] = val;
|
|
|
|
+ kctl->put(kctl, uctl);
|
|
|
|
+ kfree(uctl);
|
|
|
|
+}
|
|
|
|
+
|
|
/* unsolicited event for HP jack sensing */
|
|
/* unsolicited event for HP jack sensing */
|
|
static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
|
|
static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
|
|
{
|
|
{
|
|
|
|
+ int action;
|
|
|
|
+
|
|
if (codec->vendor_id == 0x10ec0880)
|
|
if (codec->vendor_id == 0x10ec0880)
|
|
res >>= 28;
|
|
res >>= 28;
|
|
else
|
|
else
|
|
res >>= 26;
|
|
res >>= 26;
|
|
- res = snd_hda_jack_get_action(codec, res);
|
|
|
|
- alc_exec_unsol_event(codec, res);
|
|
|
|
|
|
+ action = snd_hda_jack_get_action(codec, res);
|
|
|
|
+ if (action == ALC_DCVOL_EVENT) {
|
|
|
|
+ /* Execute the dc-vol event here as it requires the NID
|
|
|
|
+ * but we don't pass NID to alc_exec_unsol_event().
|
|
|
|
+ * Once when we convert all static quirks to the auto-parser,
|
|
|
|
+ * this can be integerated into there.
|
|
|
|
+ */
|
|
|
|
+ struct hda_jack_tbl *jack;
|
|
|
|
+ jack = snd_hda_jack_tbl_get_from_tag(codec, res);
|
|
|
|
+ if (jack)
|
|
|
|
+ alc_update_knob_master(codec, jack->nid);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ alc_exec_unsol_event(codec, action);
|
|
}
|
|
}
|
|
|
|
|
|
/* call init functions of standard auto-mute helpers */
|
|
/* call init functions of standard auto-mute helpers */
|
|
@@ -1033,45 +1073,6 @@ static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-/* rebuild imux for matching with the given auto-mic pins (if not yet) */
|
|
|
|
-static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
|
|
|
|
-{
|
|
|
|
- struct alc_spec *spec = codec->spec;
|
|
|
|
- struct hda_input_mux *imux;
|
|
|
|
- static char * const texts[3] = {
|
|
|
|
- "Mic", "Internal Mic", "Dock Mic"
|
|
|
|
- };
|
|
|
|
- int i;
|
|
|
|
-
|
|
|
|
- if (!spec->auto_mic)
|
|
|
|
- return false;
|
|
|
|
- imux = &spec->private_imux[0];
|
|
|
|
- if (spec->input_mux == imux)
|
|
|
|
- return true;
|
|
|
|
- spec->imux_pins[0] = spec->ext_mic_pin;
|
|
|
|
- spec->imux_pins[1] = spec->int_mic_pin;
|
|
|
|
- spec->imux_pins[2] = spec->dock_mic_pin;
|
|
|
|
- for (i = 0; i < 3; i++) {
|
|
|
|
- strcpy(imux->items[i].label, texts[i]);
|
|
|
|
- if (spec->imux_pins[i]) {
|
|
|
|
- hda_nid_t pin = spec->imux_pins[i];
|
|
|
|
- int c;
|
|
|
|
- for (c = 0; c < spec->num_adc_nids; c++) {
|
|
|
|
- hda_nid_t cap = get_capsrc(spec, c);
|
|
|
|
- int idx = get_connection_index(codec, cap, pin);
|
|
|
|
- if (idx >= 0) {
|
|
|
|
- imux->items[i].index = idx;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- imux->num_items = i + 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- spec->num_mux_defs = 1;
|
|
|
|
- spec->input_mux = imux;
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/* check whether all auto-mic pins are valid; setup indices if OK */
|
|
/* check whether all auto-mic pins are valid; setup indices if OK */
|
|
static bool alc_auto_mic_check_imux(struct hda_codec *codec)
|
|
static bool alc_auto_mic_check_imux(struct hda_codec *codec)
|
|
{
|
|
{
|
|
@@ -1441,6 +1442,7 @@ enum {
|
|
ALC_FIXUP_ACT_PRE_PROBE,
|
|
ALC_FIXUP_ACT_PRE_PROBE,
|
|
ALC_FIXUP_ACT_PROBE,
|
|
ALC_FIXUP_ACT_PROBE,
|
|
ALC_FIXUP_ACT_INIT,
|
|
ALC_FIXUP_ACT_INIT,
|
|
|
|
+ ALC_FIXUP_ACT_BUILD,
|
|
};
|
|
};
|
|
|
|
|
|
static void alc_apply_fixup(struct hda_codec *codec, int action)
|
|
static void alc_apply_fixup(struct hda_codec *codec, int action)
|
|
@@ -1520,6 +1522,13 @@ static void alc_pick_fixup(struct hda_codec *codec,
|
|
int id = -1;
|
|
int id = -1;
|
|
const char *name = NULL;
|
|
const char *name = NULL;
|
|
|
|
|
|
|
|
+ /* when model=nofixup is given, don't pick up any fixups */
|
|
|
|
+ if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
|
|
|
|
+ spec->fixup_list = NULL;
|
|
|
|
+ spec->fixup_id = -1;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (codec->modelname && models) {
|
|
if (codec->modelname && models) {
|
|
while (models->name) {
|
|
while (models->name) {
|
|
if (!strcmp(codec->modelname, models->name)) {
|
|
if (!strcmp(codec->modelname, models->name)) {
|
|
@@ -1847,36 +1856,10 @@ DEFINE_CAPMIX_NOSRC(3);
|
|
/*
|
|
/*
|
|
* slave controls for virtual master
|
|
* slave controls for virtual master
|
|
*/
|
|
*/
|
|
-static const char * const alc_slave_vols[] = {
|
|
|
|
- "Front Playback Volume",
|
|
|
|
- "Surround Playback Volume",
|
|
|
|
- "Center Playback Volume",
|
|
|
|
- "LFE Playback Volume",
|
|
|
|
- "Side Playback Volume",
|
|
|
|
- "Headphone Playback Volume",
|
|
|
|
- "Speaker Playback Volume",
|
|
|
|
- "Mono Playback Volume",
|
|
|
|
- "Line Out Playback Volume",
|
|
|
|
- "CLFE Playback Volume",
|
|
|
|
- "Bass Speaker Playback Volume",
|
|
|
|
- "PCM Playback Volume",
|
|
|
|
- NULL,
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-static const char * const alc_slave_sws[] = {
|
|
|
|
- "Front Playback Switch",
|
|
|
|
- "Surround Playback Switch",
|
|
|
|
- "Center Playback Switch",
|
|
|
|
- "LFE Playback Switch",
|
|
|
|
- "Side Playback Switch",
|
|
|
|
- "Headphone Playback Switch",
|
|
|
|
- "Speaker Playback Switch",
|
|
|
|
- "Mono Playback Switch",
|
|
|
|
- "IEC958 Playback Switch",
|
|
|
|
- "Line Out Playback Switch",
|
|
|
|
- "CLFE Playback Switch",
|
|
|
|
- "Bass Speaker Playback Switch",
|
|
|
|
- "PCM Playback Switch",
|
|
|
|
|
|
+static const char * const alc_slave_pfxs[] = {
|
|
|
|
+ "Front", "Surround", "Center", "LFE", "Side",
|
|
|
|
+ "Headphone", "Speaker", "Mono", "Line Out",
|
|
|
|
+ "CLFE", "Bass Speaker", "PCM",
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
|
|
@@ -1967,14 +1950,17 @@ static int __alc_build_controls(struct hda_codec *codec)
|
|
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
|
|
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
|
|
HDA_OUTPUT, vmaster_tlv);
|
|
HDA_OUTPUT, vmaster_tlv);
|
|
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
|
|
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
|
|
- vmaster_tlv, alc_slave_vols);
|
|
|
|
|
|
+ vmaster_tlv, alc_slave_pfxs,
|
|
|
|
+ "Playback Volume");
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
if (!spec->no_analog &&
|
|
if (!spec->no_analog &&
|
|
!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
|
|
!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
|
|
- err = snd_hda_add_vmaster(codec, "Master Playback Switch",
|
|
|
|
- NULL, alc_slave_sws);
|
|
|
|
|
|
+ err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
|
|
|
|
+ NULL, alc_slave_pfxs,
|
|
|
|
+ "Playback Switch",
|
|
|
|
+ true, &spec->vmaster_mute.sw_kctl);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
@@ -2059,7 +2045,11 @@ static int alc_build_controls(struct hda_codec *codec)
|
|
int err = __alc_build_controls(codec);
|
|
int err = __alc_build_controls(codec);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
- return snd_hda_jack_add_kctls(codec, &spec->autocfg);
|
|
|
|
|
|
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ return err;
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD);
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2068,15 +2058,15 @@ static int alc_build_controls(struct hda_codec *codec)
|
|
*/
|
|
*/
|
|
|
|
|
|
static void alc_init_special_input_src(struct hda_codec *codec);
|
|
static void alc_init_special_input_src(struct hda_codec *codec);
|
|
-static int alc269_fill_coef(struct hda_codec *codec);
|
|
|
|
|
|
+static void alc_auto_init_std(struct hda_codec *codec);
|
|
|
|
|
|
static int alc_init(struct hda_codec *codec)
|
|
static int alc_init(struct hda_codec *codec)
|
|
{
|
|
{
|
|
struct alc_spec *spec = codec->spec;
|
|
struct alc_spec *spec = codec->spec;
|
|
unsigned int i;
|
|
unsigned int i;
|
|
|
|
|
|
- if (codec->vendor_id == 0x10ec0269)
|
|
|
|
- alc269_fill_coef(codec);
|
|
|
|
|
|
+ if (spec->init_hook)
|
|
|
|
+ spec->init_hook(codec);
|
|
|
|
|
|
alc_fix_pll(codec);
|
|
alc_fix_pll(codec);
|
|
alc_auto_init_amp(codec, spec->init_amp);
|
|
alc_auto_init_amp(codec, spec->init_amp);
|
|
@@ -2084,9 +2074,7 @@ static int alc_init(struct hda_codec *codec)
|
|
for (i = 0; i < spec->num_init_verbs; i++)
|
|
for (i = 0; i < spec->num_init_verbs; i++)
|
|
snd_hda_sequence_write(codec, spec->init_verbs[i]);
|
|
snd_hda_sequence_write(codec, spec->init_verbs[i]);
|
|
alc_init_special_input_src(codec);
|
|
alc_init_special_input_src(codec);
|
|
-
|
|
|
|
- if (spec->init_hook)
|
|
|
|
- spec->init_hook(codec);
|
|
|
|
|
|
+ alc_auto_init_std(codec);
|
|
|
|
|
|
alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
|
|
alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
|
|
|
|
|
|
@@ -2675,6 +2663,25 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
|
|
return channel_name[ch];
|
|
return channel_name[ch];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
+/* add the powersave loopback-list entry */
|
|
|
|
+static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx)
|
|
|
|
+{
|
|
|
|
+ struct hda_amp_list *list;
|
|
|
|
+
|
|
|
|
+ if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
|
|
|
|
+ return;
|
|
|
|
+ list = spec->loopback_list + spec->num_loopbacks;
|
|
|
|
+ list->nid = mix;
|
|
|
|
+ list->dir = HDA_INPUT;
|
|
|
|
+ list->idx = idx;
|
|
|
|
+ spec->num_loopbacks++;
|
|
|
|
+ spec->loopback.amplist = spec->loopback_list;
|
|
|
|
+}
|
|
|
|
+#else
|
|
|
|
+#define add_loopback_list(spec, mix, idx) /* NOP */
|
|
|
|
+#endif
|
|
|
|
+
|
|
/* create input playback/capture controls for the given pin */
|
|
/* create input playback/capture controls for the given pin */
|
|
static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
|
|
static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
|
|
const char *ctlname, int ctlidx,
|
|
const char *ctlname, int ctlidx,
|
|
@@ -2690,6 +2697,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
|
|
HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
|
|
HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
|
|
+ add_loopback_list(spec, mix_nid, idx);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2954,10 +2962,27 @@ static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ int i;
|
|
|
|
+ if (found_in_nid_list(nid, spec->multiout.dac_nids,
|
|
|
|
+ ARRAY_SIZE(spec->private_dac_nids)) ||
|
|
|
|
+ found_in_nid_list(nid, spec->multiout.hp_out_nid,
|
|
|
|
+ ARRAY_SIZE(spec->multiout.hp_out_nid)) ||
|
|
|
|
+ found_in_nid_list(nid, spec->multiout.extra_out_nid,
|
|
|
|
+ ARRAY_SIZE(spec->multiout.extra_out_nid)))
|
|
|
|
+ return true;
|
|
|
|
+ for (i = 0; i < spec->multi_ios; i++) {
|
|
|
|
+ if (spec->multi_io[i].dac == nid)
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
/* look for an empty DAC slot */
|
|
/* look for an empty DAC slot */
|
|
static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
|
|
static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
|
|
{
|
|
{
|
|
- struct alc_spec *spec = codec->spec;
|
|
|
|
hda_nid_t srcs[5];
|
|
hda_nid_t srcs[5];
|
|
int i, num;
|
|
int i, num;
|
|
|
|
|
|
@@ -2967,16 +2992,8 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
|
|
hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
|
|
hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
|
|
if (!nid)
|
|
if (!nid)
|
|
continue;
|
|
continue;
|
|
- if (found_in_nid_list(nid, spec->multiout.dac_nids,
|
|
|
|
- ARRAY_SIZE(spec->private_dac_nids)))
|
|
|
|
- continue;
|
|
|
|
- if (found_in_nid_list(nid, spec->multiout.hp_out_nid,
|
|
|
|
- ARRAY_SIZE(spec->multiout.hp_out_nid)))
|
|
|
|
- continue;
|
|
|
|
- if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
|
|
|
|
- ARRAY_SIZE(spec->multiout.extra_out_nid)))
|
|
|
|
- continue;
|
|
|
|
- return nid;
|
|
|
|
|
|
+ if (!alc_is_dac_already_used(codec, nid))
|
|
|
|
+ return nid;
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -2988,6 +3005,8 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
|
|
hda_nid_t srcs[5];
|
|
hda_nid_t srcs[5];
|
|
int i, num;
|
|
int i, num;
|
|
|
|
|
|
|
|
+ if (!pin || !dac)
|
|
|
|
+ return false;
|
|
pin = alc_go_down_to_selector(codec, pin);
|
|
pin = alc_go_down_to_selector(codec, pin);
|
|
num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
|
|
num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
|
|
for (i = 0; i < num; i++) {
|
|
for (i = 0; i < num; i++) {
|
|
@@ -3000,83 +3019,260 @@ static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
|
|
|
|
|
|
static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
|
|
static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
|
|
{
|
|
{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
hda_nid_t sel = alc_go_down_to_selector(codec, pin);
|
|
hda_nid_t sel = alc_go_down_to_selector(codec, pin);
|
|
- if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
|
|
|
|
|
|
+ hda_nid_t nid, nid_found, srcs[5];
|
|
|
|
+ int i, num = snd_hda_get_connections(codec, sel, srcs,
|
|
|
|
+ ARRAY_SIZE(srcs));
|
|
|
|
+ if (num == 1)
|
|
return alc_auto_look_for_dac(codec, pin);
|
|
return alc_auto_look_for_dac(codec, pin);
|
|
- return 0;
|
|
|
|
|
|
+ nid_found = 0;
|
|
|
|
+ for (i = 0; i < num; i++) {
|
|
|
|
+ if (srcs[i] == spec->mixer_nid)
|
|
|
|
+ continue;
|
|
|
|
+ nid = alc_auto_mix_to_dac(codec, srcs[i]);
|
|
|
|
+ if (nid && !alc_is_dac_already_used(codec, nid)) {
|
|
|
|
+ if (nid_found)
|
|
|
|
+ return 0;
|
|
|
|
+ nid_found = nid;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nid_found;
|
|
}
|
|
}
|
|
|
|
|
|
-/* return 0 if no possible DAC is found, 1 if one or more found */
|
|
|
|
-static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs,
|
|
|
|
- const hda_nid_t *pins, hda_nid_t *dacs)
|
|
|
|
|
|
+/* mark up volume and mute control NIDs: used during badness parsing and
|
|
|
|
+ * at creating actual controls
|
|
|
|
+ */
|
|
|
|
+static inline unsigned int get_ctl_pos(unsigned int data)
|
|
{
|
|
{
|
|
- int i;
|
|
|
|
|
|
+ hda_nid_t nid = get_amp_nid_(data);
|
|
|
|
+ unsigned int dir;
|
|
|
|
+ if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
|
|
|
|
+ return 0;
|
|
|
|
+ dir = get_amp_direction_(data);
|
|
|
|
+ return (nid << 1) | dir;
|
|
|
|
+}
|
|
|
|
|
|
- if (num_outs && !dacs[0]) {
|
|
|
|
- dacs[0] = alc_auto_look_for_dac(codec, pins[0]);
|
|
|
|
- if (!dacs[0])
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+#define is_ctl_used(bits, data) \
|
|
|
|
+ test_bit(get_ctl_pos(data), bits)
|
|
|
|
+#define mark_ctl_usage(bits, data) \
|
|
|
|
+ set_bit(get_ctl_pos(data), bits)
|
|
|
|
|
|
- for (i = 1; i < num_outs; i++)
|
|
|
|
- dacs[i] = get_dac_if_single(codec, pins[i]);
|
|
|
|
- for (i = 1; i < num_outs; i++) {
|
|
|
|
|
|
+static void clear_vol_marks(struct hda_codec *codec)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls));
|
|
|
|
+ memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* badness definition */
|
|
|
|
+enum {
|
|
|
|
+ /* No primary DAC is found for the main output */
|
|
|
|
+ BAD_NO_PRIMARY_DAC = 0x10000,
|
|
|
|
+ /* No DAC is found for the extra output */
|
|
|
|
+ BAD_NO_DAC = 0x4000,
|
|
|
|
+ /* No possible multi-ios */
|
|
|
|
+ BAD_MULTI_IO = 0x103,
|
|
|
|
+ /* No individual DAC for extra output */
|
|
|
|
+ BAD_NO_EXTRA_DAC = 0x102,
|
|
|
|
+ /* No individual DAC for extra surrounds */
|
|
|
|
+ BAD_NO_EXTRA_SURR_DAC = 0x101,
|
|
|
|
+ /* Primary DAC shared with main surrounds */
|
|
|
|
+ BAD_SHARED_SURROUND = 0x100,
|
|
|
|
+ /* Primary DAC shared with main CLFE */
|
|
|
|
+ BAD_SHARED_CLFE = 0x10,
|
|
|
|
+ /* Primary DAC shared with extra surrounds */
|
|
|
|
+ BAD_SHARED_EXTRA_SURROUND = 0x10,
|
|
|
|
+ /* Volume widget is shared */
|
|
|
|
+ BAD_SHARED_VOL = 0x10,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
|
|
|
|
+ hda_nid_t pin, hda_nid_t dac);
|
|
|
|
+static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
|
|
|
|
+ hda_nid_t pin, hda_nid_t dac);
|
|
|
|
+
|
|
|
|
+static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin,
|
|
|
|
+ hda_nid_t dac)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ hda_nid_t nid;
|
|
|
|
+ unsigned int val;
|
|
|
|
+ int badness = 0;
|
|
|
|
+
|
|
|
|
+ nid = alc_look_for_out_vol_nid(codec, pin, dac);
|
|
|
|
+ if (nid) {
|
|
|
|
+ val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
|
|
|
|
+ if (is_ctl_used(spec->vol_ctls, nid))
|
|
|
|
+ badness += BAD_SHARED_VOL;
|
|
|
|
+ else
|
|
|
|
+ mark_ctl_usage(spec->vol_ctls, val);
|
|
|
|
+ } else
|
|
|
|
+ badness += BAD_SHARED_VOL;
|
|
|
|
+ nid = alc_look_for_out_mute_nid(codec, pin, dac);
|
|
|
|
+ if (nid) {
|
|
|
|
+ unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
|
|
|
|
+ if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT)
|
|
|
|
+ val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
|
|
|
|
+ else
|
|
|
|
+ val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
|
|
|
|
+ if (is_ctl_used(spec->sw_ctls, val))
|
|
|
|
+ badness += BAD_SHARED_VOL;
|
|
|
|
+ else
|
|
|
|
+ mark_ctl_usage(spec->sw_ctls, val);
|
|
|
|
+ } else
|
|
|
|
+ badness += BAD_SHARED_VOL;
|
|
|
|
+ return badness;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct badness_table {
|
|
|
|
+ int no_primary_dac; /* no primary DAC */
|
|
|
|
+ int no_dac; /* no secondary DACs */
|
|
|
|
+ int shared_primary; /* primary DAC is shared with main output */
|
|
|
|
+ int shared_surr; /* secondary DAC shared with main or primary */
|
|
|
|
+ int shared_clfe; /* third DAC shared with main or primary */
|
|
|
|
+ int shared_surr_main; /* secondary DAC sahred with main/DAC0 */
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct badness_table main_out_badness = {
|
|
|
|
+ .no_primary_dac = BAD_NO_PRIMARY_DAC,
|
|
|
|
+ .no_dac = BAD_NO_DAC,
|
|
|
|
+ .shared_primary = BAD_NO_PRIMARY_DAC,
|
|
|
|
+ .shared_surr = BAD_SHARED_SURROUND,
|
|
|
|
+ .shared_clfe = BAD_SHARED_CLFE,
|
|
|
|
+ .shared_surr_main = BAD_SHARED_SURROUND,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct badness_table extra_out_badness = {
|
|
|
|
+ .no_primary_dac = BAD_NO_DAC,
|
|
|
|
+ .no_dac = BAD_NO_DAC,
|
|
|
|
+ .shared_primary = BAD_NO_EXTRA_DAC,
|
|
|
|
+ .shared_surr = BAD_SHARED_EXTRA_SURROUND,
|
|
|
|
+ .shared_clfe = BAD_SHARED_EXTRA_SURROUND,
|
|
|
|
+ .shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/* try to assign DACs to pins and return the resultant badness */
|
|
|
|
+static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs,
|
|
|
|
+ const hda_nid_t *pins, hda_nid_t *dacs,
|
|
|
|
+ const struct badness_table *bad)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
|
|
+ int i, j;
|
|
|
|
+ int badness = 0;
|
|
|
|
+ hda_nid_t dac;
|
|
|
|
+
|
|
|
|
+ if (!num_outs)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < num_outs; i++) {
|
|
|
|
+ hda_nid_t pin = pins[i];
|
|
if (!dacs[i])
|
|
if (!dacs[i])
|
|
- dacs[i] = alc_auto_look_for_dac(codec, pins[i]);
|
|
|
|
|
|
+ dacs[i] = alc_auto_look_for_dac(codec, pin);
|
|
|
|
+ if (!dacs[i] && !i) {
|
|
|
|
+ for (j = 1; j < num_outs; j++) {
|
|
|
|
+ if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) {
|
|
|
|
+ dacs[0] = dacs[j];
|
|
|
|
+ dacs[j] = 0;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ dac = dacs[i];
|
|
|
|
+ if (!dac) {
|
|
|
|
+ if (alc_auto_is_dac_reachable(codec, pin, dacs[0]))
|
|
|
|
+ dac = dacs[0];
|
|
|
|
+ else if (cfg->line_outs > i &&
|
|
|
|
+ alc_auto_is_dac_reachable(codec, pin,
|
|
|
|
+ spec->private_dac_nids[i]))
|
|
|
|
+ dac = spec->private_dac_nids[i];
|
|
|
|
+ if (dac) {
|
|
|
|
+ if (!i)
|
|
|
|
+ badness += bad->shared_primary;
|
|
|
|
+ else if (i == 1)
|
|
|
|
+ badness += bad->shared_surr;
|
|
|
|
+ else
|
|
|
|
+ badness += bad->shared_clfe;
|
|
|
|
+ } else if (alc_auto_is_dac_reachable(codec, pin,
|
|
|
|
+ spec->private_dac_nids[0])) {
|
|
|
|
+ dac = spec->private_dac_nids[0];
|
|
|
|
+ badness += bad->shared_surr_main;
|
|
|
|
+ } else if (!i)
|
|
|
|
+ badness += bad->no_primary_dac;
|
|
|
|
+ else
|
|
|
|
+ badness += bad->no_dac;
|
|
|
|
+ }
|
|
|
|
+ if (dac)
|
|
|
|
+ badness += eval_shared_vol_badness(codec, pin, dac);
|
|
}
|
|
}
|
|
- return 1;
|
|
|
|
|
|
+
|
|
|
|
+ return badness;
|
|
}
|
|
}
|
|
|
|
|
|
static int alc_auto_fill_multi_ios(struct hda_codec *codec,
|
|
static int alc_auto_fill_multi_ios(struct hda_codec *codec,
|
|
- unsigned int location, int offset);
|
|
|
|
-static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
|
|
|
|
- hda_nid_t pin, hda_nid_t dac);
|
|
|
|
|
|
+ hda_nid_t reference_pin,
|
|
|
|
+ bool hardwired, int offset);
|
|
|
|
+
|
|
|
|
+static bool alc_map_singles(struct hda_codec *codec, int outs,
|
|
|
|
+ const hda_nid_t *pins, hda_nid_t *dacs)
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+ bool found = false;
|
|
|
|
+ for (i = 0; i < outs; i++) {
|
|
|
|
+ if (dacs[i])
|
|
|
|
+ continue;
|
|
|
|
+ dacs[i] = get_dac_if_single(codec, pins[i]);
|
|
|
|
+ if (dacs[i])
|
|
|
|
+ found = true;
|
|
|
|
+ }
|
|
|
|
+ return found;
|
|
|
|
+}
|
|
|
|
|
|
/* fill in the dac_nids table from the parsed pin configuration */
|
|
/* fill in the dac_nids table from the parsed pin configuration */
|
|
-static int alc_auto_fill_dac_nids(struct hda_codec *codec)
|
|
|
|
|
|
+static int fill_and_eval_dacs(struct hda_codec *codec,
|
|
|
|
+ bool fill_hardwired,
|
|
|
|
+ bool fill_mio_first)
|
|
{
|
|
{
|
|
struct alc_spec *spec = codec->spec;
|
|
struct alc_spec *spec = codec->spec;
|
|
struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
- unsigned int location, defcfg;
|
|
|
|
- int num_pins;
|
|
|
|
- bool redone = false;
|
|
|
|
- int i;
|
|
|
|
|
|
+ int i, err, badness;
|
|
|
|
|
|
- again:
|
|
|
|
/* set num_dacs once to full for alc_auto_look_for_dac() */
|
|
/* set num_dacs once to full for alc_auto_look_for_dac() */
|
|
spec->multiout.num_dacs = cfg->line_outs;
|
|
spec->multiout.num_dacs = cfg->line_outs;
|
|
- spec->multiout.hp_out_nid[0] = 0;
|
|
|
|
- spec->multiout.extra_out_nid[0] = 0;
|
|
|
|
- memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
|
|
|
|
spec->multiout.dac_nids = spec->private_dac_nids;
|
|
spec->multiout.dac_nids = spec->private_dac_nids;
|
|
|
|
+ memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
|
|
|
|
+ memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
|
|
|
|
+ memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
|
|
spec->multi_ios = 0;
|
|
spec->multi_ios = 0;
|
|
|
|
+ clear_vol_marks(codec);
|
|
|
|
+ badness = 0;
|
|
|
|
|
|
/* fill hard-wired DACs first */
|
|
/* fill hard-wired DACs first */
|
|
- if (!redone) {
|
|
|
|
- for (i = 0; i < cfg->line_outs; i++)
|
|
|
|
- spec->private_dac_nids[i] =
|
|
|
|
- get_dac_if_single(codec, cfg->line_out_pins[i]);
|
|
|
|
- if (cfg->hp_outs)
|
|
|
|
- spec->multiout.hp_out_nid[0] =
|
|
|
|
- get_dac_if_single(codec, cfg->hp_pins[0]);
|
|
|
|
- if (cfg->speaker_outs)
|
|
|
|
- spec->multiout.extra_out_nid[0] =
|
|
|
|
- get_dac_if_single(codec, cfg->speaker_pins[0]);
|
|
|
|
|
|
+ if (fill_hardwired) {
|
|
|
|
+ bool mapped;
|
|
|
|
+ do {
|
|
|
|
+ mapped = alc_map_singles(codec, cfg->line_outs,
|
|
|
|
+ cfg->line_out_pins,
|
|
|
|
+ spec->private_dac_nids);
|
|
|
|
+ mapped |= alc_map_singles(codec, cfg->hp_outs,
|
|
|
|
+ cfg->hp_pins,
|
|
|
|
+ spec->multiout.hp_out_nid);
|
|
|
|
+ mapped |= alc_map_singles(codec, cfg->speaker_outs,
|
|
|
|
+ cfg->speaker_pins,
|
|
|
|
+ spec->multiout.extra_out_nid);
|
|
|
|
+ if (fill_mio_first && cfg->line_outs == 1 &&
|
|
|
|
+ cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
|
|
|
+ err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], true, 0);
|
|
|
|
+ if (!err)
|
|
|
|
+ mapped = true;
|
|
|
|
+ }
|
|
|
|
+ } while (mapped);
|
|
}
|
|
}
|
|
|
|
|
|
- for (i = 0; i < cfg->line_outs; i++) {
|
|
|
|
- hda_nid_t pin = cfg->line_out_pins[i];
|
|
|
|
- if (spec->private_dac_nids[i])
|
|
|
|
- continue;
|
|
|
|
- spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
|
|
|
|
- if (!spec->private_dac_nids[i] && !redone) {
|
|
|
|
- /* if we can't find primary DACs, re-probe without
|
|
|
|
- * checking the hard-wired DACs
|
|
|
|
- */
|
|
|
|
- redone = true;
|
|
|
|
- goto again;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins,
|
|
|
|
+ spec->private_dac_nids,
|
|
|
|
+ &main_out_badness);
|
|
|
|
|
|
/* re-count num_dacs and squash invalid entries */
|
|
/* re-count num_dacs and squash invalid entries */
|
|
spec->multiout.num_dacs = 0;
|
|
spec->multiout.num_dacs = 0;
|
|
@@ -3091,30 +3287,144 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
|
|
|
|
|
+ if (fill_mio_first &&
|
|
|
|
+ cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
|
/* try to fill multi-io first */
|
|
/* try to fill multi-io first */
|
|
- defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
|
|
|
|
- location = get_defcfg_location(defcfg);
|
|
|
|
-
|
|
|
|
- num_pins = alc_auto_fill_multi_ios(codec, location, 0);
|
|
|
|
- if (num_pins > 0) {
|
|
|
|
- spec->multi_ios = num_pins;
|
|
|
|
- spec->ext_channel_count = 2;
|
|
|
|
- spec->multiout.num_dacs = num_pins + 1;
|
|
|
|
- }
|
|
|
|
|
|
+ err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ return err;
|
|
|
|
+ /* we don't count badness at this stage yet */
|
|
}
|
|
}
|
|
|
|
|
|
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
|
|
|
|
- alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins,
|
|
|
|
- spec->multiout.hp_out_nid);
|
|
|
|
|
|
+ if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
|
|
|
|
+ err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins,
|
|
|
|
+ spec->multiout.hp_out_nid,
|
|
|
|
+ &extra_out_badness);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ return err;
|
|
|
|
+ badness += err;
|
|
|
|
+ }
|
|
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
|
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
|
- int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs,
|
|
|
|
- cfg->speaker_pins,
|
|
|
|
- spec->multiout.extra_out_nid);
|
|
|
|
- /* if no speaker volume is assigned, try again as the primary
|
|
|
|
- * output
|
|
|
|
- */
|
|
|
|
- if (!err && cfg->speaker_outs > 0 &&
|
|
|
|
|
|
+ err = alc_auto_fill_dacs(codec, cfg->speaker_outs,
|
|
|
|
+ cfg->speaker_pins,
|
|
|
|
+ spec->multiout.extra_out_nid,
|
|
|
|
+ &extra_out_badness);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ return err;
|
|
|
|
+ badness += err;
|
|
|
|
+ }
|
|
|
|
+ if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
|
|
|
|
+ err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ return err;
|
|
|
|
+ badness += err;
|
|
|
|
+ }
|
|
|
|
+ if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
|
|
|
|
+ /* try multi-ios with HP + inputs */
|
|
|
|
+ int offset = 0;
|
|
|
|
+ if (cfg->line_outs >= 3)
|
|
|
|
+ offset = 1;
|
|
|
|
+ err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false,
|
|
|
|
+ offset);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ return err;
|
|
|
|
+ badness += err;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (spec->multi_ios == 2) {
|
|
|
|
+ for (i = 0; i < 2; i++)
|
|
|
|
+ spec->private_dac_nids[spec->multiout.num_dacs++] =
|
|
|
|
+ spec->multi_io[i].dac;
|
|
|
|
+ spec->ext_channel_count = 2;
|
|
|
|
+ } else if (spec->multi_ios) {
|
|
|
|
+ spec->multi_ios = 0;
|
|
|
|
+ badness += BAD_MULTI_IO;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return badness;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#define DEBUG_BADNESS
|
|
|
|
+
|
|
|
|
+#ifdef DEBUG_BADNESS
|
|
|
|
+#define debug_badness snd_printdd
|
|
|
|
+#else
|
|
|
|
+#define debug_badness(...)
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg)
|
|
|
|
+{
|
|
|
|
+ debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
|
|
|
|
+ cfg->line_out_pins[0], cfg->line_out_pins[1],
|
|
|
|
+ cfg->line_out_pins[2], cfg->line_out_pins[2],
|
|
|
|
+ spec->multiout.dac_nids[0],
|
|
|
|
+ spec->multiout.dac_nids[1],
|
|
|
|
+ spec->multiout.dac_nids[2],
|
|
|
|
+ spec->multiout.dac_nids[3]);
|
|
|
|
+ if (spec->multi_ios > 0)
|
|
|
|
+ debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
|
|
|
|
+ spec->multi_ios,
|
|
|
|
+ spec->multi_io[0].pin, spec->multi_io[1].pin,
|
|
|
|
+ spec->multi_io[0].dac, spec->multi_io[1].dac);
|
|
|
|
+ debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
|
|
|
|
+ cfg->hp_pins[0], cfg->hp_pins[1],
|
|
|
|
+ cfg->hp_pins[2], cfg->hp_pins[2],
|
|
|
|
+ spec->multiout.hp_out_nid[0],
|
|
|
|
+ spec->multiout.hp_out_nid[1],
|
|
|
|
+ spec->multiout.hp_out_nid[2],
|
|
|
|
+ spec->multiout.hp_out_nid[3]);
|
|
|
|
+ debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
|
|
|
|
+ cfg->speaker_pins[0], cfg->speaker_pins[1],
|
|
|
|
+ cfg->speaker_pins[2], cfg->speaker_pins[3],
|
|
|
|
+ spec->multiout.extra_out_nid[0],
|
|
|
|
+ spec->multiout.extra_out_nid[1],
|
|
|
|
+ spec->multiout.extra_out_nid[2],
|
|
|
|
+ spec->multiout.extra_out_nid[3]);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int alc_auto_fill_dac_nids(struct hda_codec *codec)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
|
|
+ struct auto_pin_cfg *best_cfg;
|
|
|
|
+ int best_badness = INT_MAX;
|
|
|
|
+ int badness;
|
|
|
|
+ bool fill_hardwired = true, fill_mio_first = true;
|
|
|
|
+ bool best_wired = true, best_mio = true;
|
|
|
|
+ bool hp_spk_swapped = false;
|
|
|
|
+
|
|
|
|
+ best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
|
|
|
|
+ if (!best_cfg)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ *best_cfg = *cfg;
|
|
|
|
+
|
|
|
|
+ for (;;) {
|
|
|
|
+ badness = fill_and_eval_dacs(codec, fill_hardwired,
|
|
|
|
+ fill_mio_first);
|
|
|
|
+ if (badness < 0)
|
|
|
|
+ return badness;
|
|
|
|
+ debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
|
|
|
|
+ cfg->line_out_type, fill_hardwired, fill_mio_first,
|
|
|
|
+ badness);
|
|
|
|
+ debug_show_configs(spec, cfg);
|
|
|
|
+ if (badness < best_badness) {
|
|
|
|
+ best_badness = badness;
|
|
|
|
+ *best_cfg = *cfg;
|
|
|
|
+ best_wired = fill_hardwired;
|
|
|
|
+ best_mio = fill_mio_first;
|
|
|
|
+ }
|
|
|
|
+ if (!badness)
|
|
|
|
+ break;
|
|
|
|
+ fill_mio_first = !fill_mio_first;
|
|
|
|
+ if (!fill_mio_first)
|
|
|
|
+ continue;
|
|
|
|
+ fill_hardwired = !fill_hardwired;
|
|
|
|
+ if (!fill_hardwired)
|
|
|
|
+ continue;
|
|
|
|
+ if (hp_spk_swapped)
|
|
|
|
+ break;
|
|
|
|
+ hp_spk_swapped = true;
|
|
|
|
+ if (cfg->speaker_outs > 0 &&
|
|
cfg->line_out_type == AUTO_PIN_HP_OUT) {
|
|
cfg->line_out_type == AUTO_PIN_HP_OUT) {
|
|
cfg->hp_outs = cfg->line_outs;
|
|
cfg->hp_outs = cfg->line_outs;
|
|
memcpy(cfg->hp_pins, cfg->line_out_pins,
|
|
memcpy(cfg->hp_pins, cfg->line_out_pins,
|
|
@@ -3125,48 +3435,45 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec)
|
|
cfg->speaker_outs = 0;
|
|
cfg->speaker_outs = 0;
|
|
memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
|
|
memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
|
|
cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
|
|
cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
|
|
- redone = false;
|
|
|
|
- goto again;
|
|
|
|
- }
|
|
|
|
|
|
+ fill_hardwired = true;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if (cfg->hp_outs > 0 &&
|
|
|
|
+ cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
|
|
|
|
+ cfg->speaker_outs = cfg->line_outs;
|
|
|
|
+ memcpy(cfg->speaker_pins, cfg->line_out_pins,
|
|
|
|
+ sizeof(cfg->speaker_pins));
|
|
|
|
+ cfg->line_outs = cfg->hp_outs;
|
|
|
|
+ memcpy(cfg->line_out_pins, cfg->hp_pins,
|
|
|
|
+ sizeof(cfg->hp_pins));
|
|
|
|
+ cfg->hp_outs = 0;
|
|
|
|
+ memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
|
|
|
|
+ cfg->line_out_type = AUTO_PIN_HP_OUT;
|
|
|
|
+ fill_hardwired = true;
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!spec->multi_ios &&
|
|
|
|
- cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
|
|
|
|
- cfg->hp_outs) {
|
|
|
|
- /* try multi-ios with HP + inputs */
|
|
|
|
- defcfg = snd_hda_codec_get_pincfg(codec, cfg->hp_pins[0]);
|
|
|
|
- location = get_defcfg_location(defcfg);
|
|
|
|
-
|
|
|
|
- num_pins = alc_auto_fill_multi_ios(codec, location, 1);
|
|
|
|
- if (num_pins > 0) {
|
|
|
|
- spec->multi_ios = num_pins;
|
|
|
|
- spec->ext_channel_count = 2;
|
|
|
|
- spec->multiout.num_dacs = num_pins + 1;
|
|
|
|
- }
|
|
|
|
|
|
+ if (badness) {
|
|
|
|
+ *cfg = *best_cfg;
|
|
|
|
+ fill_and_eval_dacs(codec, best_wired, best_mio);
|
|
}
|
|
}
|
|
|
|
+ debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
|
|
|
|
+ cfg->line_out_type, best_wired, best_mio);
|
|
|
|
+ debug_show_configs(spec, cfg);
|
|
|
|
|
|
if (cfg->line_out_pins[0])
|
|
if (cfg->line_out_pins[0])
|
|
spec->vmaster_nid =
|
|
spec->vmaster_nid =
|
|
alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0],
|
|
alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0],
|
|
spec->multiout.dac_nids[0]);
|
|
spec->multiout.dac_nids[0]);
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
|
|
|
|
-static inline unsigned int get_ctl_pos(unsigned int data)
|
|
|
|
-{
|
|
|
|
- hda_nid_t nid = get_amp_nid_(data);
|
|
|
|
- unsigned int dir;
|
|
|
|
- if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
|
|
|
|
- return 0;
|
|
|
|
- dir = get_amp_direction_(data);
|
|
|
|
- return (nid << 1) | dir;
|
|
|
|
|
|
+ /* clear the bitmap flags for creating controls */
|
|
|
|
+ clear_vol_marks(codec);
|
|
|
|
+ kfree(best_cfg);
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-#define is_ctl_used(bits, data) \
|
|
|
|
- test_bit(get_ctl_pos(data), bits)
|
|
|
|
-#define mark_ctl_usage(bits, data) \
|
|
|
|
- set_bit(get_ctl_pos(data), bits)
|
|
|
|
-
|
|
|
|
static int alc_auto_add_vol_ctl(struct hda_codec *codec,
|
|
static int alc_auto_add_vol_ctl(struct hda_codec *codec,
|
|
const char *pfx, int cidx,
|
|
const char *pfx, int cidx,
|
|
hda_nid_t nid, unsigned int chs)
|
|
hda_nid_t nid, unsigned int chs)
|
|
@@ -3278,14 +3585,17 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
|
|
dac = spec->multiout.dac_nids[i];
|
|
dac = spec->multiout.dac_nids[i];
|
|
if (!dac)
|
|
if (!dac)
|
|
continue;
|
|
continue;
|
|
- if (i >= cfg->line_outs)
|
|
|
|
|
|
+ if (i >= cfg->line_outs) {
|
|
pin = spec->multi_io[i - 1].pin;
|
|
pin = spec->multi_io[i - 1].pin;
|
|
- else
|
|
|
|
|
|
+ index = 0;
|
|
|
|
+ name = channel_name[i];
|
|
|
|
+ } else {
|
|
pin = cfg->line_out_pins[i];
|
|
pin = cfg->line_out_pins[i];
|
|
|
|
+ name = alc_get_line_out_pfx(spec, i, true, &index);
|
|
|
|
+ }
|
|
|
|
|
|
sw = alc_look_for_out_mute_nid(codec, pin, dac);
|
|
sw = alc_look_for_out_mute_nid(codec, pin, dac);
|
|
vol = alc_look_for_out_vol_nid(codec, pin, dac);
|
|
vol = alc_look_for_out_vol_nid(codec, pin, dac);
|
|
- name = alc_get_line_out_pfx(spec, i, true, &index);
|
|
|
|
if (!name || !strcmp(name, "CLFE")) {
|
|
if (!name || !strcmp(name, "CLFE")) {
|
|
/* Center/LFE */
|
|
/* Center/LFE */
|
|
err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
|
|
err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
|
|
@@ -3382,41 +3692,31 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins,
|
|
return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0);
|
|
return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0);
|
|
}
|
|
}
|
|
|
|
|
|
- if (dacs[num_pins - 1]) {
|
|
|
|
- /* OK, we have a multi-output system with individual volumes */
|
|
|
|
- for (i = 0; i < num_pins; i++) {
|
|
|
|
- if (num_pins >= 3) {
|
|
|
|
- snprintf(name, sizeof(name), "%s %s",
|
|
|
|
- pfx, channel_name[i]);
|
|
|
|
- err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
|
|
|
|
- name, 0);
|
|
|
|
- } else {
|
|
|
|
- err = alc_auto_create_extra_out(codec, pins[i], dacs[i],
|
|
|
|
- pfx, i);
|
|
|
|
- }
|
|
|
|
- if (err < 0)
|
|
|
|
- return err;
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Let's create a bind-controls */
|
|
|
|
- ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_sw);
|
|
|
|
- if (!ctl)
|
|
|
|
- return -ENOMEM;
|
|
|
|
- n = 0;
|
|
|
|
for (i = 0; i < num_pins; i++) {
|
|
for (i = 0; i < num_pins; i++) {
|
|
- if (get_wcaps(codec, pins[i]) & AC_WCAP_OUT_AMP)
|
|
|
|
- ctl->values[n++] =
|
|
|
|
- HDA_COMPOSE_AMP_VAL(pins[i], 3, 0, HDA_OUTPUT);
|
|
|
|
- }
|
|
|
|
- if (n) {
|
|
|
|
- snprintf(name, sizeof(name), "%s Playback Switch", pfx);
|
|
|
|
- err = add_control(spec, ALC_CTL_BIND_SW, name, 0, (long)ctl);
|
|
|
|
|
|
+ hda_nid_t dac;
|
|
|
|
+ if (dacs[num_pins - 1])
|
|
|
|
+ dac = dacs[i]; /* with individual volumes */
|
|
|
|
+ else
|
|
|
|
+ dac = 0;
|
|
|
|
+ if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) {
|
|
|
|
+ err = alc_auto_create_extra_out(codec, pins[i], dac,
|
|
|
|
+ "Bass Speaker", 0);
|
|
|
|
+ } else if (num_pins >= 3) {
|
|
|
|
+ snprintf(name, sizeof(name), "%s %s",
|
|
|
|
+ pfx, channel_name[i]);
|
|
|
|
+ err = alc_auto_create_extra_out(codec, pins[i], dac,
|
|
|
|
+ name, 0);
|
|
|
|
+ } else {
|
|
|
|
+ err = alc_auto_create_extra_out(codec, pins[i], dac,
|
|
|
|
+ pfx, i);
|
|
|
|
+ }
|
|
if (err < 0)
|
|
if (err < 0)
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
+ if (dacs[num_pins - 1])
|
|
|
|
+ return 0;
|
|
|
|
|
|
|
|
+ /* Let's create a bind-controls for volumes */
|
|
ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
|
|
ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
|
|
if (!ctl)
|
|
if (!ctl)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
@@ -3552,58 +3852,111 @@ static void alc_auto_init_extra_out(struct hda_codec *codec)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* check whether the given pin can be a multi-io pin */
|
|
|
|
+static bool can_be_multiio_pin(struct hda_codec *codec,
|
|
|
|
+ unsigned int location, hda_nid_t nid)
|
|
|
|
+{
|
|
|
|
+ unsigned int defcfg, caps;
|
|
|
|
+
|
|
|
|
+ defcfg = snd_hda_codec_get_pincfg(codec, nid);
|
|
|
|
+ if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
|
|
|
|
+ return false;
|
|
|
|
+ if (location && get_defcfg_location(defcfg) != location)
|
|
|
|
+ return false;
|
|
|
|
+ caps = snd_hda_query_pin_caps(codec, nid);
|
|
|
|
+ if (!(caps & AC_PINCAP_OUT))
|
|
|
|
+ return false;
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* multi-io helper
|
|
* multi-io helper
|
|
|
|
+ *
|
|
|
|
+ * When hardwired is set, try to fill ony hardwired pins, and returns
|
|
|
|
+ * zero if any pins are filled, non-zero if nothing found.
|
|
|
|
+ * When hardwired is off, try to fill possible input pins, and returns
|
|
|
|
+ * the badness value.
|
|
*/
|
|
*/
|
|
static int alc_auto_fill_multi_ios(struct hda_codec *codec,
|
|
static int alc_auto_fill_multi_ios(struct hda_codec *codec,
|
|
- unsigned int location,
|
|
|
|
- int offset)
|
|
|
|
|
|
+ hda_nid_t reference_pin,
|
|
|
|
+ bool hardwired, int offset)
|
|
{
|
|
{
|
|
struct alc_spec *spec = codec->spec;
|
|
struct alc_spec *spec = codec->spec;
|
|
struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
- hda_nid_t prime_dac = spec->private_dac_nids[0];
|
|
|
|
- int type, i, dacs, num_pins = 0;
|
|
|
|
|
|
+ int type, i, j, dacs, num_pins, old_pins;
|
|
|
|
+ unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
|
|
|
|
+ unsigned int location = get_defcfg_location(defcfg);
|
|
|
|
+ int badness = 0;
|
|
|
|
|
|
- dacs = spec->multiout.num_dacs;
|
|
|
|
|
|
+ old_pins = spec->multi_ios;
|
|
|
|
+ if (old_pins >= 2)
|
|
|
|
+ goto end_fill;
|
|
|
|
+
|
|
|
|
+ num_pins = 0;
|
|
for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
|
|
for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
|
|
for (i = 0; i < cfg->num_inputs; i++) {
|
|
for (i = 0; i < cfg->num_inputs; i++) {
|
|
- hda_nid_t nid = cfg->inputs[i].pin;
|
|
|
|
- hda_nid_t dac = 0;
|
|
|
|
- unsigned int defcfg, caps;
|
|
|
|
if (cfg->inputs[i].type != type)
|
|
if (cfg->inputs[i].type != type)
|
|
continue;
|
|
continue;
|
|
- defcfg = snd_hda_codec_get_pincfg(codec, nid);
|
|
|
|
- if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
|
|
|
|
|
|
+ if (can_be_multiio_pin(codec, location,
|
|
|
|
+ cfg->inputs[i].pin))
|
|
|
|
+ num_pins++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (num_pins < 2)
|
|
|
|
+ goto end_fill;
|
|
|
|
+
|
|
|
|
+ dacs = spec->multiout.num_dacs;
|
|
|
|
+ for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
|
|
|
|
+ for (i = 0; i < cfg->num_inputs; i++) {
|
|
|
|
+ hda_nid_t nid = cfg->inputs[i].pin;
|
|
|
|
+ hda_nid_t dac = 0;
|
|
|
|
+
|
|
|
|
+ if (cfg->inputs[i].type != type)
|
|
continue;
|
|
continue;
|
|
- if (location && get_defcfg_location(defcfg) != location)
|
|
|
|
|
|
+ if (!can_be_multiio_pin(codec, location, nid))
|
|
continue;
|
|
continue;
|
|
- caps = snd_hda_query_pin_caps(codec, nid);
|
|
|
|
- if (!(caps & AC_PINCAP_OUT))
|
|
|
|
|
|
+ for (j = 0; j < spec->multi_ios; j++) {
|
|
|
|
+ if (nid == spec->multi_io[j].pin)
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if (j < spec->multi_ios)
|
|
continue;
|
|
continue;
|
|
- if (offset && offset + num_pins < dacs) {
|
|
|
|
- dac = spec->private_dac_nids[offset + num_pins];
|
|
|
|
|
|
+
|
|
|
|
+ if (offset && offset + spec->multi_ios < dacs) {
|
|
|
|
+ dac = spec->private_dac_nids[offset + spec->multi_ios];
|
|
if (!alc_auto_is_dac_reachable(codec, nid, dac))
|
|
if (!alc_auto_is_dac_reachable(codec, nid, dac))
|
|
dac = 0;
|
|
dac = 0;
|
|
}
|
|
}
|
|
- if (!dac)
|
|
|
|
|
|
+ if (hardwired)
|
|
|
|
+ dac = get_dac_if_single(codec, nid);
|
|
|
|
+ else if (!dac)
|
|
dac = alc_auto_look_for_dac(codec, nid);
|
|
dac = alc_auto_look_for_dac(codec, nid);
|
|
- if (!dac)
|
|
|
|
|
|
+ if (!dac) {
|
|
|
|
+ badness++;
|
|
continue;
|
|
continue;
|
|
- spec->multi_io[num_pins].pin = nid;
|
|
|
|
- spec->multi_io[num_pins].dac = dac;
|
|
|
|
- num_pins++;
|
|
|
|
- spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
|
|
|
|
|
|
+ }
|
|
|
|
+ spec->multi_io[spec->multi_ios].pin = nid;
|
|
|
|
+ spec->multi_io[spec->multi_ios].dac = dac;
|
|
|
|
+ spec->multi_ios++;
|
|
|
|
+ if (spec->multi_ios >= 2)
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- spec->multiout.num_dacs = dacs;
|
|
|
|
- if (num_pins < 2) {
|
|
|
|
- /* clear up again */
|
|
|
|
- memset(spec->private_dac_nids + dacs, 0,
|
|
|
|
- sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - dacs));
|
|
|
|
- spec->private_dac_nids[0] = prime_dac;
|
|
|
|
- return 0;
|
|
|
|
|
|
+ end_fill:
|
|
|
|
+ if (badness)
|
|
|
|
+ badness = BAD_MULTI_IO;
|
|
|
|
+ if (old_pins == spec->multi_ios) {
|
|
|
|
+ if (hardwired)
|
|
|
|
+ return 1; /* nothing found */
|
|
|
|
+ else
|
|
|
|
+ return badness; /* no badness if nothing found */
|
|
|
|
+ }
|
|
|
|
+ if (!hardwired && spec->multi_ios < 2) {
|
|
|
|
+ spec->multi_ios = old_pins;
|
|
|
|
+ return badness;
|
|
}
|
|
}
|
|
- return num_pins;
|
|
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
|
|
static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
|
|
@@ -3958,6 +4311,7 @@ static const struct snd_pci_quirk beep_white_list[] = {
|
|
SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
|
|
SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
|
|
SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
|
|
SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
|
|
SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
|
|
SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
|
|
|
|
+ SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
|
|
SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
|
|
SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
|
|
{}
|
|
{}
|
|
};
|
|
};
|
|
@@ -4057,6 +4411,9 @@ static int alc_parse_auto_config(struct hda_codec *codec,
|
|
if (spec->kctls.list)
|
|
if (spec->kctls.list)
|
|
add_mixer(spec, spec->kctls.list);
|
|
add_mixer(spec, spec->kctls.list);
|
|
|
|
|
|
|
|
+ if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
+ set_capture_mixer(codec);
|
|
|
|
+
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4067,26 +4424,47 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
|
|
return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
|
|
return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
-static const struct hda_amp_list alc880_loopbacks[] = {
|
|
|
|
- { 0x0b, HDA_INPUT, 0 },
|
|
|
|
- { 0x0b, HDA_INPUT, 1 },
|
|
|
|
- { 0x0b, HDA_INPUT, 2 },
|
|
|
|
- { 0x0b, HDA_INPUT, 3 },
|
|
|
|
- { 0x0b, HDA_INPUT, 4 },
|
|
|
|
- { } /* end */
|
|
|
|
-};
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* ALC880 fix-ups
|
|
* ALC880 fix-ups
|
|
*/
|
|
*/
|
|
enum {
|
|
enum {
|
|
|
|
+ ALC880_FIXUP_GPIO1,
|
|
ALC880_FIXUP_GPIO2,
|
|
ALC880_FIXUP_GPIO2,
|
|
ALC880_FIXUP_MEDION_RIM,
|
|
ALC880_FIXUP_MEDION_RIM,
|
|
|
|
+ ALC880_FIXUP_LG,
|
|
|
|
+ ALC880_FIXUP_W810,
|
|
|
|
+ ALC880_FIXUP_EAPD_COEF,
|
|
|
|
+ ALC880_FIXUP_TCL_S700,
|
|
|
|
+ ALC880_FIXUP_VOL_KNOB,
|
|
|
|
+ ALC880_FIXUP_FUJITSU,
|
|
|
|
+ ALC880_FIXUP_F1734,
|
|
|
|
+ ALC880_FIXUP_UNIWILL,
|
|
|
|
+ ALC880_FIXUP_UNIWILL_DIG,
|
|
|
|
+ ALC880_FIXUP_Z71V,
|
|
|
|
+ ALC880_FIXUP_3ST_BASE,
|
|
|
|
+ ALC880_FIXUP_3ST,
|
|
|
|
+ ALC880_FIXUP_3ST_DIG,
|
|
|
|
+ ALC880_FIXUP_5ST_BASE,
|
|
|
|
+ ALC880_FIXUP_5ST,
|
|
|
|
+ ALC880_FIXUP_5ST_DIG,
|
|
|
|
+ ALC880_FIXUP_6ST_BASE,
|
|
|
|
+ ALC880_FIXUP_6ST,
|
|
|
|
+ ALC880_FIXUP_6ST_DIG,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* enable the volume-knob widget support on NID 0x21 */
|
|
|
|
+static void alc880_fixup_vol_knob(struct hda_codec *codec,
|
|
|
|
+ const struct alc_fixup *fix, int action)
|
|
|
|
+{
|
|
|
|
+ if (action == ALC_FIXUP_ACT_PROBE)
|
|
|
|
+ snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT);
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct alc_fixup alc880_fixups[] = {
|
|
static const struct alc_fixup alc880_fixups[] = {
|
|
|
|
+ [ALC880_FIXUP_GPIO1] = {
|
|
|
|
+ .type = ALC_FIXUP_VERBS,
|
|
|
|
+ .v.verbs = alc_gpio1_init_verbs,
|
|
|
|
+ },
|
|
[ALC880_FIXUP_GPIO2] = {
|
|
[ALC880_FIXUP_GPIO2] = {
|
|
.type = ALC_FIXUP_VERBS,
|
|
.type = ALC_FIXUP_VERBS,
|
|
.v.verbs = alc_gpio2_init_verbs,
|
|
.v.verbs = alc_gpio2_init_verbs,
|
|
@@ -4101,40 +4479,323 @@ static const struct alc_fixup alc880_fixups[] = {
|
|
.chained = true,
|
|
.chained = true,
|
|
.chain_id = ALC880_FIXUP_GPIO2,
|
|
.chain_id = ALC880_FIXUP_GPIO2,
|
|
},
|
|
},
|
|
|
|
+ [ALC880_FIXUP_LG] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ /* disable bogus unused pins */
|
|
|
|
+ { 0x16, 0x411111f0 },
|
|
|
|
+ { 0x18, 0x411111f0 },
|
|
|
|
+ { 0x1a, 0x411111f0 },
|
|
|
|
+ { }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_W810] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ /* disable bogus unused pins */
|
|
|
|
+ { 0x17, 0x411111f0 },
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_GPIO2,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_EAPD_COEF] = {
|
|
|
|
+ .type = ALC_FIXUP_VERBS,
|
|
|
|
+ .v.verbs = (const struct hda_verb[]) {
|
|
|
|
+ /* change to EAPD mode */
|
|
|
|
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
|
|
|
|
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
|
|
|
|
+ {}
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_TCL_S700] = {
|
|
|
|
+ .type = ALC_FIXUP_VERBS,
|
|
|
|
+ .v.verbs = (const struct hda_verb[]) {
|
|
|
|
+ /* change to EAPD mode */
|
|
|
|
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
|
|
|
|
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
|
|
|
|
+ {}
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_GPIO2,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_VOL_KNOB] = {
|
|
|
|
+ .type = ALC_FIXUP_FUNC,
|
|
|
|
+ .v.func = alc880_fixup_vol_knob,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_FUJITSU] = {
|
|
|
|
+ /* override all pins as BIOS on old Amilo is broken */
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x14, 0x0121411f }, /* HP */
|
|
|
|
+ { 0x15, 0x99030120 }, /* speaker */
|
|
|
|
+ { 0x16, 0x99030130 }, /* bass speaker */
|
|
|
|
+ { 0x17, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x18, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x19, 0x01a19950 }, /* mic-in */
|
|
|
|
+ { 0x1a, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1b, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1c, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1d, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1e, 0x01454140 }, /* SPDIF out */
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_VOL_KNOB,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_F1734] = {
|
|
|
|
+ /* almost compatible with FUJITSU, but no bass and SPDIF */
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x14, 0x0121411f }, /* HP */
|
|
|
|
+ { 0x15, 0x99030120 }, /* speaker */
|
|
|
|
+ { 0x16, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x17, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x18, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x19, 0x01a19950 }, /* mic-in */
|
|
|
|
+ { 0x1a, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1b, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1c, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1d, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1e, 0x411111f0 }, /* N/A */
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_VOL_KNOB,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_UNIWILL] = {
|
|
|
|
+ /* need to fix HP and speaker pins to be parsed correctly */
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x14, 0x0121411f }, /* HP */
|
|
|
|
+ { 0x15, 0x99030120 }, /* speaker */
|
|
|
|
+ { 0x16, 0x99030130 }, /* bass speaker */
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_UNIWILL_DIG] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ /* disable bogus unused pins */
|
|
|
|
+ { 0x17, 0x411111f0 },
|
|
|
|
+ { 0x19, 0x411111f0 },
|
|
|
|
+ { 0x1b, 0x411111f0 },
|
|
|
|
+ { 0x1f, 0x411111f0 },
|
|
|
|
+ { }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_Z71V] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ /* set up the whole pins as BIOS is utterly broken */
|
|
|
|
+ { 0x14, 0x99030120 }, /* speaker */
|
|
|
|
+ { 0x15, 0x0121411f }, /* HP */
|
|
|
|
+ { 0x16, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x17, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x18, 0x01a19950 }, /* mic-in */
|
|
|
|
+ { 0x19, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1a, 0x01813031 }, /* line-in */
|
|
|
|
+ { 0x1b, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1c, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1d, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1e, 0x0144111e }, /* SPDIF */
|
|
|
|
+ { }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_3ST_BASE] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x14, 0x01014010 }, /* line-out */
|
|
|
|
+ { 0x15, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x16, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x17, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x18, 0x01a19c30 }, /* mic-in */
|
|
|
|
+ { 0x19, 0x0121411f }, /* HP */
|
|
|
|
+ { 0x1a, 0x01813031 }, /* line-in */
|
|
|
|
+ { 0x1b, 0x02a19c40 }, /* front-mic */
|
|
|
|
+ { 0x1c, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1d, 0x411111f0 }, /* N/A */
|
|
|
|
+ /* 0x1e is filled in below */
|
|
|
|
+ { 0x1f, 0x411111f0 }, /* N/A */
|
|
|
|
+ { }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_3ST] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x1e, 0x411111f0 }, /* N/A */
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_3ST_BASE,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_3ST_DIG] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x1e, 0x0144111e }, /* SPDIF */
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_3ST_BASE,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_5ST_BASE] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x14, 0x01014010 }, /* front */
|
|
|
|
+ { 0x15, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x16, 0x01011411 }, /* CLFE */
|
|
|
|
+ { 0x17, 0x01016412 }, /* surr */
|
|
|
|
+ { 0x18, 0x01a19c30 }, /* mic-in */
|
|
|
|
+ { 0x19, 0x0121411f }, /* HP */
|
|
|
|
+ { 0x1a, 0x01813031 }, /* line-in */
|
|
|
|
+ { 0x1b, 0x02a19c40 }, /* front-mic */
|
|
|
|
+ { 0x1c, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1d, 0x411111f0 }, /* N/A */
|
|
|
|
+ /* 0x1e is filled in below */
|
|
|
|
+ { 0x1f, 0x411111f0 }, /* N/A */
|
|
|
|
+ { }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_5ST] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x1e, 0x411111f0 }, /* N/A */
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_5ST_BASE,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_5ST_DIG] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x1e, 0x0144111e }, /* SPDIF */
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_5ST_BASE,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_6ST_BASE] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x14, 0x01014010 }, /* front */
|
|
|
|
+ { 0x15, 0x01016412 }, /* surr */
|
|
|
|
+ { 0x16, 0x01011411 }, /* CLFE */
|
|
|
|
+ { 0x17, 0x01012414 }, /* side */
|
|
|
|
+ { 0x18, 0x01a19c30 }, /* mic-in */
|
|
|
|
+ { 0x19, 0x02a19c40 }, /* front-mic */
|
|
|
|
+ { 0x1a, 0x01813031 }, /* line-in */
|
|
|
|
+ { 0x1b, 0x0121411f }, /* HP */
|
|
|
|
+ { 0x1c, 0x411111f0 }, /* N/A */
|
|
|
|
+ { 0x1d, 0x411111f0 }, /* N/A */
|
|
|
|
+ /* 0x1e is filled in below */
|
|
|
|
+ { 0x1f, 0x411111f0 }, /* N/A */
|
|
|
|
+ { }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_6ST] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x1e, 0x411111f0 }, /* N/A */
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_6ST_BASE,
|
|
|
|
+ },
|
|
|
|
+ [ALC880_FIXUP_6ST_DIG] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x1e, 0x0144111e }, /* SPDIF */
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC880_FIXUP_6ST_BASE,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
static const struct snd_pci_quirk alc880_fixup_tbl[] = {
|
|
static const struct snd_pci_quirk alc880_fixup_tbl[] = {
|
|
|
|
+ SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
|
|
|
|
+ SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
|
|
|
|
+ SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
|
|
|
|
+ SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
|
|
|
|
+ SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
|
|
|
|
+ SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
|
|
|
|
+ SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
|
|
|
|
+ SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
|
|
|
|
+ SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
|
|
SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
|
|
SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
|
|
|
|
+ SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734),
|
|
|
|
+ SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
|
|
|
|
+ SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
|
|
|
|
+ SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
|
|
|
|
+ SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
|
|
|
|
+ SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
|
|
|
|
+ SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
|
|
|
|
+ SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
|
|
|
|
+
|
|
|
|
+ /* Below is the copied entries from alc880_quirks.c.
|
|
|
|
+ * It's not quite sure whether BIOS sets the correct pin-config table
|
|
|
|
+ * on these machines, thus they are kept to be compatible with
|
|
|
|
+ * the old static quirks. Once when it's confirmed to work without
|
|
|
|
+ * these overrides, it'd be better to remove.
|
|
|
|
+ */
|
|
|
|
+ SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
|
|
|
|
+ SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
|
|
|
|
+ SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
|
|
|
|
+ SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
|
|
|
|
+ SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
|
|
|
|
+ SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
|
|
|
|
+ SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
|
|
|
|
+ SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ /* default Intel */
|
|
|
|
+ SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
|
|
|
|
+ SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
|
|
|
|
+ SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
|
|
{}
|
|
{}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static const struct alc_model_fixup alc880_fixup_models[] = {
|
|
|
|
+ {.id = ALC880_FIXUP_3ST, .name = "3stack"},
|
|
|
|
+ {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
|
|
|
|
+ {.id = ALC880_FIXUP_5ST, .name = "5stack"},
|
|
|
|
+ {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
|
|
|
|
+ {.id = ALC880_FIXUP_6ST, .name = "6stack"},
|
|
|
|
+ {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
|
|
|
|
+ {}
|
|
|
|
+};
|
|
|
|
|
|
-/*
|
|
|
|
- * board setups
|
|
|
|
- */
|
|
|
|
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
|
|
|
|
-#define alc_board_config \
|
|
|
|
- snd_hda_check_board_config
|
|
|
|
-#define alc_board_codec_sid_config \
|
|
|
|
- snd_hda_check_board_codec_sid_config
|
|
|
|
-#include "alc_quirks.c"
|
|
|
|
-#else
|
|
|
|
-#define alc_board_config(codec, nums, models, tbl) -1
|
|
|
|
-#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
|
|
|
|
-#define setup_preset(codec, x) /* NOP */
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
* OK, here we have finally the patch for ALC880
|
|
* OK, here we have finally the patch for ALC880
|
|
*/
|
|
*/
|
|
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
|
|
|
|
-#include "alc880_quirks.c"
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
static int patch_alc880(struct hda_codec *codec)
|
|
static int patch_alc880(struct hda_codec *codec)
|
|
{
|
|
{
|
|
struct alc_spec *spec;
|
|
struct alc_spec *spec;
|
|
- int board_config;
|
|
|
|
int err;
|
|
int err;
|
|
|
|
|
|
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
|
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
|
@@ -4146,47 +4807,14 @@ static int patch_alc880(struct hda_codec *codec)
|
|
spec->mixer_nid = 0x0b;
|
|
spec->mixer_nid = 0x0b;
|
|
spec->need_dac_fix = 1;
|
|
spec->need_dac_fix = 1;
|
|
|
|
|
|
- board_config = alc_board_config(codec, ALC880_MODEL_LAST,
|
|
|
|
- alc880_models, alc880_cfg_tbl);
|
|
|
|
- if (board_config < 0) {
|
|
|
|
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
|
|
|
|
- codec->chip_name);
|
|
|
|
- board_config = ALC_MODEL_AUTO;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (board_config == ALC_MODEL_AUTO) {
|
|
|
|
- alc_pick_fixup(codec, NULL, alc880_fixup_tbl, alc880_fixups);
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (board_config == ALC_MODEL_AUTO) {
|
|
|
|
- /* automatic parse from the BIOS config */
|
|
|
|
- err = alc880_parse_auto_config(codec);
|
|
|
|
- if (err < 0)
|
|
|
|
- goto error;
|
|
|
|
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
|
|
|
|
- else if (!err) {
|
|
|
|
- printk(KERN_INFO
|
|
|
|
- "hda_codec: Cannot set up configuration "
|
|
|
|
- "from BIOS. Using 3-stack mode...\n");
|
|
|
|
- board_config = ALC880_3ST;
|
|
|
|
- }
|
|
|
|
-#endif
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (board_config != ALC_MODEL_AUTO) {
|
|
|
|
- spec->vmaster_nid = 0x0c;
|
|
|
|
- setup_preset(codec, &alc880_presets[board_config]);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->adc_nids) {
|
|
|
|
- alc_auto_fill_adc_caps(codec);
|
|
|
|
- alc_rebuild_imux_for_auto_mic(codec);
|
|
|
|
- alc_remove_invalid_adc_nids(codec);
|
|
|
|
- }
|
|
|
|
|
|
+ alc_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
|
|
|
|
+ alc880_fixups);
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
|
|
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
|
|
+ /* automatic parse from the BIOS config */
|
|
|
|
+ err = alc880_parse_auto_config(codec);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ goto error;
|
|
|
|
|
|
if (!spec->no_analog) {
|
|
if (!spec->no_analog) {
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
@@ -4195,17 +4823,9 @@ static int patch_alc880(struct hda_codec *codec)
|
|
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
|
|
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
|
|
}
|
|
}
|
|
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
- if (board_config == ALC_MODEL_AUTO)
|
|
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
- else
|
|
|
|
- codec->patch_ops.build_controls = __alc_build_controls;
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
- if (!spec->loopback.amplist)
|
|
|
|
- spec->loopback.amplist = alc880_loopbacks;
|
|
|
|
-#endif
|
|
|
|
|
|
+
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -4225,49 +4845,115 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
|
|
return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
|
|
return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
-static const struct hda_amp_list alc260_loopbacks[] = {
|
|
|
|
- { 0x07, HDA_INPUT, 0 },
|
|
|
|
- { 0x07, HDA_INPUT, 1 },
|
|
|
|
- { 0x07, HDA_INPUT, 2 },
|
|
|
|
- { 0x07, HDA_INPUT, 3 },
|
|
|
|
- { 0x07, HDA_INPUT, 4 },
|
|
|
|
- { } /* end */
|
|
|
|
-};
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Pin config fixes
|
|
* Pin config fixes
|
|
*/
|
|
*/
|
|
enum {
|
|
enum {
|
|
- PINFIX_HP_DC5750,
|
|
|
|
|
|
+ ALC260_FIXUP_HP_DC5750,
|
|
|
|
+ ALC260_FIXUP_HP_PIN_0F,
|
|
|
|
+ ALC260_FIXUP_COEF,
|
|
|
|
+ ALC260_FIXUP_GPIO1,
|
|
|
|
+ ALC260_FIXUP_GPIO1_TOGGLE,
|
|
|
|
+ ALC260_FIXUP_REPLACER,
|
|
|
|
+ ALC260_FIXUP_HP_B1900,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static void alc260_gpio1_automute(struct hda_codec *codec)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
|
|
|
|
+ spec->hp_jack_present);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
|
|
|
|
+ const struct alc_fixup *fix, int action)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ if (action == ALC_FIXUP_ACT_PROBE) {
|
|
|
|
+ /* although the machine has only one output pin, we need to
|
|
|
|
+ * toggle GPIO1 according to the jack state
|
|
|
|
+ */
|
|
|
|
+ spec->automute_hook = alc260_gpio1_automute;
|
|
|
|
+ spec->detect_hp = 1;
|
|
|
|
+ spec->automute_speaker = 1;
|
|
|
|
+ spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
|
|
|
|
+ snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
|
|
|
|
+ spec->unsol_event = alc_sku_unsol_event;
|
|
|
|
+ add_verb(codec->spec, alc_gpio1_init_verbs);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct alc_fixup alc260_fixups[] = {
|
|
static const struct alc_fixup alc260_fixups[] = {
|
|
- [PINFIX_HP_DC5750] = {
|
|
|
|
|
|
+ [ALC260_FIXUP_HP_DC5750] = {
|
|
.type = ALC_FIXUP_PINS,
|
|
.type = ALC_FIXUP_PINS,
|
|
.v.pins = (const struct alc_pincfg[]) {
|
|
.v.pins = (const struct alc_pincfg[]) {
|
|
{ 0x11, 0x90130110 }, /* speaker */
|
|
{ 0x11, 0x90130110 }, /* speaker */
|
|
{ }
|
|
{ }
|
|
}
|
|
}
|
|
},
|
|
},
|
|
|
|
+ [ALC260_FIXUP_HP_PIN_0F] = {
|
|
|
|
+ .type = ALC_FIXUP_PINS,
|
|
|
|
+ .v.pins = (const struct alc_pincfg[]) {
|
|
|
|
+ { 0x0f, 0x01214000 }, /* HP */
|
|
|
|
+ { }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ [ALC260_FIXUP_COEF] = {
|
|
|
|
+ .type = ALC_FIXUP_VERBS,
|
|
|
|
+ .v.verbs = (const struct hda_verb[]) {
|
|
|
|
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
|
|
|
|
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 },
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC260_FIXUP_HP_PIN_0F,
|
|
|
|
+ },
|
|
|
|
+ [ALC260_FIXUP_GPIO1] = {
|
|
|
|
+ .type = ALC_FIXUP_VERBS,
|
|
|
|
+ .v.verbs = alc_gpio1_init_verbs,
|
|
|
|
+ },
|
|
|
|
+ [ALC260_FIXUP_GPIO1_TOGGLE] = {
|
|
|
|
+ .type = ALC_FIXUP_FUNC,
|
|
|
|
+ .v.func = alc260_fixup_gpio1_toggle,
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC260_FIXUP_HP_PIN_0F,
|
|
|
|
+ },
|
|
|
|
+ [ALC260_FIXUP_REPLACER] = {
|
|
|
|
+ .type = ALC_FIXUP_VERBS,
|
|
|
|
+ .v.verbs = (const struct hda_verb[]) {
|
|
|
|
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
|
|
|
|
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
|
|
|
|
+ { }
|
|
|
|
+ },
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
|
|
|
|
+ },
|
|
|
|
+ [ALC260_FIXUP_HP_B1900] = {
|
|
|
|
+ .type = ALC_FIXUP_FUNC,
|
|
|
|
+ .v.func = alc260_fixup_gpio1_toggle,
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC260_FIXUP_COEF,
|
|
|
|
+ }
|
|
};
|
|
};
|
|
|
|
|
|
static const struct snd_pci_quirk alc260_fixup_tbl[] = {
|
|
static const struct snd_pci_quirk alc260_fixup_tbl[] = {
|
|
- SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
|
|
|
|
|
|
+ SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
|
|
|
|
+ SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
|
|
|
|
+ SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
|
|
|
|
+ SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
|
|
|
|
+ SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
|
|
|
|
+ SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
|
|
|
|
+ SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
|
|
|
|
+ SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
|
|
{}
|
|
{}
|
|
};
|
|
};
|
|
|
|
|
|
/*
|
|
/*
|
|
*/
|
|
*/
|
|
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
|
|
|
|
-#include "alc260_quirks.c"
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
static int patch_alc260(struct hda_codec *codec)
|
|
static int patch_alc260(struct hda_codec *codec)
|
|
{
|
|
{
|
|
struct alc_spec *spec;
|
|
struct alc_spec *spec;
|
|
- int err, board_config;
|
|
|
|
|
|
+ int err;
|
|
|
|
|
|
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
|
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
|
if (spec == NULL)
|
|
if (spec == NULL)
|
|
@@ -4277,47 +4963,13 @@ static int patch_alc260(struct hda_codec *codec)
|
|
|
|
|
|
spec->mixer_nid = 0x07;
|
|
spec->mixer_nid = 0x07;
|
|
|
|
|
|
- board_config = alc_board_config(codec, ALC260_MODEL_LAST,
|
|
|
|
- alc260_models, alc260_cfg_tbl);
|
|
|
|
- if (board_config < 0) {
|
|
|
|
- snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
|
|
|
|
- codec->chip_name);
|
|
|
|
- board_config = ALC_MODEL_AUTO;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (board_config == ALC_MODEL_AUTO) {
|
|
|
|
- alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (board_config == ALC_MODEL_AUTO) {
|
|
|
|
- /* automatic parse from the BIOS config */
|
|
|
|
- err = alc260_parse_auto_config(codec);
|
|
|
|
- if (err < 0)
|
|
|
|
- goto error;
|
|
|
|
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
|
|
|
|
- else if (!err) {
|
|
|
|
- printk(KERN_INFO
|
|
|
|
- "hda_codec: Cannot set up configuration "
|
|
|
|
- "from BIOS. Using base mode...\n");
|
|
|
|
- board_config = ALC260_BASIC;
|
|
|
|
- }
|
|
|
|
-#endif
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (board_config != ALC_MODEL_AUTO) {
|
|
|
|
- setup_preset(codec, &alc260_presets[board_config]);
|
|
|
|
- spec->vmaster_nid = 0x08;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->adc_nids) {
|
|
|
|
- alc_auto_fill_adc_caps(codec);
|
|
|
|
- alc_rebuild_imux_for_auto_mic(codec);
|
|
|
|
- alc_remove_invalid_adc_nids(codec);
|
|
|
|
- }
|
|
|
|
|
|
+ alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
|
|
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
|
|
+ /* automatic parse from the BIOS config */
|
|
|
|
+ err = alc260_parse_auto_config(codec);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ goto error;
|
|
|
|
|
|
if (!spec->no_analog) {
|
|
if (!spec->no_analog) {
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
@@ -4326,18 +4978,10 @@ static int patch_alc260(struct hda_codec *codec)
|
|
set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
|
|
set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
|
|
}
|
|
}
|
|
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
- if (board_config == ALC_MODEL_AUTO)
|
|
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
- else
|
|
|
|
- codec->patch_ops.build_controls = __alc_build_controls;
|
|
|
|
spec->shutup = alc_eapd_shutup;
|
|
spec->shutup = alc_eapd_shutup;
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
- if (!spec->loopback.amplist)
|
|
|
|
- spec->loopback.amplist = alc260_loopbacks;
|
|
|
|
-#endif
|
|
|
|
|
|
+
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -4358,9 +5002,6 @@ static int patch_alc260(struct hda_codec *codec)
|
|
* In addition, an independent DAC for the multi-playback (not used in this
|
|
* In addition, an independent DAC for the multi-playback (not used in this
|
|
* driver yet).
|
|
* driver yet).
|
|
*/
|
|
*/
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
-#define alc882_loopbacks alc880_loopbacks
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
* Pin config fixes
|
|
* Pin config fixes
|
|
@@ -4377,6 +5018,8 @@ enum {
|
|
ALC882_FIXUP_EAPD,
|
|
ALC882_FIXUP_EAPD,
|
|
ALC883_FIXUP_EAPD,
|
|
ALC883_FIXUP_EAPD,
|
|
ALC883_FIXUP_ACER_EAPD,
|
|
ALC883_FIXUP_ACER_EAPD,
|
|
|
|
+ ALC882_FIXUP_GPIO1,
|
|
|
|
+ ALC882_FIXUP_GPIO2,
|
|
ALC882_FIXUP_GPIO3,
|
|
ALC882_FIXUP_GPIO3,
|
|
ALC889_FIXUP_COEF,
|
|
ALC889_FIXUP_COEF,
|
|
ALC882_FIXUP_ASUS_W2JC,
|
|
ALC882_FIXUP_ASUS_W2JC,
|
|
@@ -4385,6 +5028,8 @@ enum {
|
|
ALC882_FIXUP_ASPIRE_8930G_VERBS,
|
|
ALC882_FIXUP_ASPIRE_8930G_VERBS,
|
|
ALC885_FIXUP_MACPRO_GPIO,
|
|
ALC885_FIXUP_MACPRO_GPIO,
|
|
ALC889_FIXUP_DAC_ROUTE,
|
|
ALC889_FIXUP_DAC_ROUTE,
|
|
|
|
+ ALC889_FIXUP_MBP_VREF,
|
|
|
|
+ ALC889_FIXUP_IMAC91_VREF,
|
|
};
|
|
};
|
|
|
|
|
|
static void alc889_fixup_coef(struct hda_codec *codec,
|
|
static void alc889_fixup_coef(struct hda_codec *codec,
|
|
@@ -4463,6 +5108,51 @@ static void alc889_fixup_dac_route(struct hda_codec *codec,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Set VREF on HP pin */
|
|
|
|
+static void alc889_fixup_mbp_vref(struct hda_codec *codec,
|
|
|
|
+ const struct alc_fixup *fix, int action)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ static hda_nid_t nids[2] = { 0x14, 0x15 };
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (action != ALC_FIXUP_ACT_INIT)
|
|
|
|
+ return;
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(nids); i++) {
|
|
|
|
+ unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
|
|
|
|
+ if (get_defcfg_device(val) != AC_JACK_HP_OUT)
|
|
|
|
+ continue;
|
|
|
|
+ val = snd_hda_codec_read(codec, nids[i], 0,
|
|
|
|
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
|
|
|
|
+ val |= AC_PINCTL_VREF_80;
|
|
|
|
+ snd_hda_codec_write(codec, nids[i], 0,
|
|
|
|
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
|
|
|
|
+ spec->keep_vref_in_automute = 1;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Set VREF on speaker pins on imac91 */
|
|
|
|
+static void alc889_fixup_imac91_vref(struct hda_codec *codec,
|
|
|
|
+ const struct alc_fixup *fix, int action)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ static hda_nid_t nids[2] = { 0x18, 0x1a };
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (action != ALC_FIXUP_ACT_INIT)
|
|
|
|
+ return;
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(nids); i++) {
|
|
|
|
+ unsigned int val;
|
|
|
|
+ val = snd_hda_codec_read(codec, nids[i], 0,
|
|
|
|
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
|
|
|
|
+ val |= AC_PINCTL_VREF_50;
|
|
|
|
+ snd_hda_codec_write(codec, nids[i], 0,
|
|
|
|
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
|
|
|
|
+ }
|
|
|
|
+ spec->keep_vref_in_automute = 1;
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct alc_fixup alc882_fixups[] = {
|
|
static const struct alc_fixup alc882_fixups[] = {
|
|
[ALC882_FIXUP_ABIT_AW9D_MAX] = {
|
|
[ALC882_FIXUP_ABIT_AW9D_MAX] = {
|
|
.type = ALC_FIXUP_PINS,
|
|
.type = ALC_FIXUP_PINS,
|
|
@@ -4548,6 +5238,14 @@ static const struct alc_fixup alc882_fixups[] = {
|
|
{ }
|
|
{ }
|
|
}
|
|
}
|
|
},
|
|
},
|
|
|
|
+ [ALC882_FIXUP_GPIO1] = {
|
|
|
|
+ .type = ALC_FIXUP_VERBS,
|
|
|
|
+ .v.verbs = alc_gpio1_init_verbs,
|
|
|
|
+ },
|
|
|
|
+ [ALC882_FIXUP_GPIO2] = {
|
|
|
|
+ .type = ALC_FIXUP_VERBS,
|
|
|
|
+ .v.verbs = alc_gpio2_init_verbs,
|
|
|
|
+ },
|
|
[ALC882_FIXUP_GPIO3] = {
|
|
[ALC882_FIXUP_GPIO3] = {
|
|
.type = ALC_FIXUP_VERBS,
|
|
.type = ALC_FIXUP_VERBS,
|
|
.v.verbs = alc_gpio3_init_verbs,
|
|
.v.verbs = alc_gpio3_init_verbs,
|
|
@@ -4621,6 +5319,18 @@ static const struct alc_fixup alc882_fixups[] = {
|
|
.type = ALC_FIXUP_FUNC,
|
|
.type = ALC_FIXUP_FUNC,
|
|
.v.func = alc889_fixup_dac_route,
|
|
.v.func = alc889_fixup_dac_route,
|
|
},
|
|
},
|
|
|
|
+ [ALC889_FIXUP_MBP_VREF] = {
|
|
|
|
+ .type = ALC_FIXUP_FUNC,
|
|
|
|
+ .v.func = alc889_fixup_mbp_vref,
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC882_FIXUP_GPIO1,
|
|
|
|
+ },
|
|
|
|
+ [ALC889_FIXUP_IMAC91_VREF] = {
|
|
|
|
+ .type = ALC_FIXUP_FUNC,
|
|
|
|
+ .v.func = alc889_fixup_imac91_vref,
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC882_FIXUP_GPIO1,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
|
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
|
@@ -4654,11 +5364,26 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
|
|
SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
|
|
|
|
|
|
/* All Apple entries are in codec SSIDs */
|
|
/* All Apple entries are in codec SSIDs */
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
|
|
SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
|
|
SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
|
|
SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
|
|
SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
|
|
SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
|
|
SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
|
|
SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
|
|
SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
|
|
SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
|
|
SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
|
|
|
|
+ SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
|
|
|
|
|
|
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
|
|
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
|
|
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
|
|
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
|
|
@@ -4684,14 +5409,10 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
|
|
|
|
|
|
/*
|
|
/*
|
|
*/
|
|
*/
|
|
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
|
|
|
|
-#include "alc882_quirks.c"
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
static int patch_alc882(struct hda_codec *codec)
|
|
static int patch_alc882(struct hda_codec *codec)
|
|
{
|
|
{
|
|
struct alc_spec *spec;
|
|
struct alc_spec *spec;
|
|
- int err, board_config;
|
|
|
|
|
|
+ int err;
|
|
|
|
|
|
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
|
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
|
if (spec == NULL)
|
|
if (spec == NULL)
|
|
@@ -4715,45 +5436,15 @@ static int patch_alc882(struct hda_codec *codec)
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
- board_config = alc_board_config(codec, ALC882_MODEL_LAST,
|
|
|
|
- alc882_models, NULL);
|
|
|
|
- if (board_config < 0)
|
|
|
|
- board_config = alc_board_codec_sid_config(codec,
|
|
|
|
- ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
|
|
|
|
-
|
|
|
|
- if (board_config < 0) {
|
|
|
|
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
|
|
|
|
- codec->chip_name);
|
|
|
|
- board_config = ALC_MODEL_AUTO;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (board_config == ALC_MODEL_AUTO) {
|
|
|
|
- alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
|
|
|
|
- }
|
|
|
|
|
|
+ alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
|
|
|
|
|
|
alc_auto_parse_customize_define(codec);
|
|
alc_auto_parse_customize_define(codec);
|
|
|
|
|
|
- if (board_config == ALC_MODEL_AUTO) {
|
|
|
|
- /* automatic parse from the BIOS config */
|
|
|
|
- err = alc882_parse_auto_config(codec);
|
|
|
|
- if (err < 0)
|
|
|
|
- goto error;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (board_config != ALC_MODEL_AUTO) {
|
|
|
|
- setup_preset(codec, &alc882_presets[board_config]);
|
|
|
|
- spec->vmaster_nid = 0x0c;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->adc_nids) {
|
|
|
|
- alc_auto_fill_adc_caps(codec);
|
|
|
|
- alc_rebuild_imux_for_auto_mic(codec);
|
|
|
|
- alc_remove_invalid_adc_nids(codec);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
|
|
+ /* automatic parse from the BIOS config */
|
|
|
|
+ err = alc882_parse_auto_config(codec);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ goto error;
|
|
|
|
|
|
if (!spec->no_analog && has_cdefine_beep(codec)) {
|
|
if (!spec->no_analog && has_cdefine_beep(codec)) {
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
@@ -4762,18 +5453,9 @@ static int patch_alc882(struct hda_codec *codec)
|
|
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
|
|
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
|
|
}
|
|
}
|
|
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
- if (board_config == ALC_MODEL_AUTO)
|
|
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
- else
|
|
|
|
- codec->patch_ops.build_controls = __alc_build_controls;
|
|
|
|
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
- if (!spec->loopback.amplist)
|
|
|
|
- spec->loopback.amplist = alc882_loopbacks;
|
|
|
|
-#endif
|
|
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -4869,10 +5551,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
-#define alc262_loopbacks alc880_loopbacks
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
*/
|
|
*/
|
|
static int patch_alc262(struct hda_codec *codec)
|
|
static int patch_alc262(struct hda_codec *codec)
|
|
@@ -4912,15 +5590,6 @@ static int patch_alc262(struct hda_codec *codec)
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
- if (!spec->no_analog && !spec->adc_nids) {
|
|
|
|
- alc_auto_fill_adc_caps(codec);
|
|
|
|
- alc_rebuild_imux_for_auto_mic(codec);
|
|
|
|
- alc_remove_invalid_adc_nids(codec);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
-
|
|
|
|
if (!spec->no_analog && has_cdefine_beep(codec)) {
|
|
if (!spec->no_analog && has_cdefine_beep(codec)) {
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
@@ -4928,16 +5597,10 @@ static int patch_alc262(struct hda_codec *codec)
|
|
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
|
|
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
|
|
}
|
|
}
|
|
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
spec->shutup = alc_eapd_shutup;
|
|
spec->shutup = alc_eapd_shutup;
|
|
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
- if (!spec->loopback.amplist)
|
|
|
|
- spec->loopback.amplist = alc262_loopbacks;
|
|
|
|
-#endif
|
|
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -5031,17 +5694,7 @@ static int patch_alc268(struct hda_codec *codec)
|
|
(0 << AC_AMPCAP_MUTE_SHIFT));
|
|
(0 << AC_AMPCAP_MUTE_SHIFT));
|
|
}
|
|
}
|
|
|
|
|
|
- if (!spec->no_analog && !spec->adc_nids) {
|
|
|
|
- alc_auto_fill_adc_caps(codec);
|
|
|
|
- alc_rebuild_imux_for_auto_mic(codec);
|
|
|
|
- alc_remove_invalid_adc_nids(codec);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
spec->shutup = alc_eapd_shutup;
|
|
spec->shutup = alc_eapd_shutup;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -5054,10 +5707,6 @@ static int patch_alc268(struct hda_codec *codec)
|
|
/*
|
|
/*
|
|
* ALC269
|
|
* ALC269
|
|
*/
|
|
*/
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
-#define alc269_loopbacks alc880_loopbacks
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
|
|
static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
|
|
.substreams = 1,
|
|
.substreams = 1,
|
|
.channels_min = 2,
|
|
.channels_min = 2,
|
|
@@ -5079,35 +5728,6 @@ static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
|
|
/* NID is set in alc_build_pcms */
|
|
/* NID is set in alc_build_pcms */
|
|
};
|
|
};
|
|
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
-static int alc269_mic2_for_mute_led(struct hda_codec *codec)
|
|
|
|
-{
|
|
|
|
- switch (codec->subsystem_id) {
|
|
|
|
- case 0x103c1586:
|
|
|
|
- return 1;
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
|
|
|
|
-{
|
|
|
|
- /* update mute-LED according to the speaker mute state */
|
|
|
|
- if (nid == 0x01 || nid == 0x14) {
|
|
|
|
- int pinval;
|
|
|
|
- if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
|
|
|
|
- HDA_AMP_MUTE)
|
|
|
|
- pinval = 0x24;
|
|
|
|
- else
|
|
|
|
- pinval = 0x20;
|
|
|
|
- /* mic2 vref pin is used for mute LED control */
|
|
|
|
- snd_hda_codec_update_cache(codec, 0x19, 0,
|
|
|
|
- AC_VERB_SET_PIN_WIDGET_CONTROL,
|
|
|
|
- pinval);
|
|
|
|
- }
|
|
|
|
- return alc_check_power_status(codec, nid);
|
|
|
|
-}
|
|
|
|
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
|
|
|
|
-
|
|
|
|
/* different alc269-variants */
|
|
/* different alc269-variants */
|
|
enum {
|
|
enum {
|
|
ALC269_TYPE_ALC269VA,
|
|
ALC269_TYPE_ALC269VA,
|
|
@@ -5258,6 +5878,31 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec,
|
|
spec->automute_hook = alc269_quanta_automute;
|
|
spec->automute_hook = alc269_quanta_automute;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* update mute-LED according to the speaker mute state via mic2 VREF pin */
|
|
|
|
+static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled)
|
|
|
|
+{
|
|
|
|
+ struct hda_codec *codec = private_data;
|
|
|
|
+ unsigned int pinval = enabled ? 0x20 : 0x24;
|
|
|
|
+ snd_hda_codec_update_cache(codec, 0x19, 0,
|
|
|
|
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
|
|
|
|
+ pinval);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void alc269_fixup_mic2_mute(struct hda_codec *codec,
|
|
|
|
+ const struct alc_fixup *fix, int action)
|
|
|
|
+{
|
|
|
|
+ struct alc_spec *spec = codec->spec;
|
|
|
|
+ switch (action) {
|
|
|
|
+ case ALC_FIXUP_ACT_BUILD:
|
|
|
|
+ spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook;
|
|
|
|
+ snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true);
|
|
|
|
+ /* fallthru */
|
|
|
|
+ case ALC_FIXUP_ACT_INIT:
|
|
|
|
+ snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
enum {
|
|
enum {
|
|
ALC269_FIXUP_SONY_VAIO,
|
|
ALC269_FIXUP_SONY_VAIO,
|
|
ALC275_FIXUP_SONY_VAIO_GPIO2,
|
|
ALC275_FIXUP_SONY_VAIO_GPIO2,
|
|
@@ -5275,6 +5920,7 @@ enum {
|
|
ALC269_FIXUP_DMIC,
|
|
ALC269_FIXUP_DMIC,
|
|
ALC269VB_FIXUP_AMIC,
|
|
ALC269VB_FIXUP_AMIC,
|
|
ALC269VB_FIXUP_DMIC,
|
|
ALC269VB_FIXUP_DMIC,
|
|
|
|
+ ALC269_FIXUP_MIC2_MUTE_LED,
|
|
};
|
|
};
|
|
|
|
|
|
static const struct alc_fixup alc269_fixups[] = {
|
|
static const struct alc_fixup alc269_fixups[] = {
|
|
@@ -5395,9 +6041,14 @@ static const struct alc_fixup alc269_fixups[] = {
|
|
{ }
|
|
{ }
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
+ [ALC269_FIXUP_MIC2_MUTE_LED] = {
|
|
|
|
+ .type = ALC_FIXUP_FUNC,
|
|
|
|
+ .v.func = alc269_fixup_mic2_mute,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
|
|
+ SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED),
|
|
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
|
|
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
|
|
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
|
|
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
|
|
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
|
|
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
|
|
@@ -5420,7 +6071,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
|
|
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
|
|
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
|
|
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
|
|
|
|
|
|
-#if 1
|
|
|
|
|
|
+#if 0
|
|
/* Below is a quirk table taken from the old code.
|
|
/* Below is a quirk table taken from the old code.
|
|
* Basically the device should work as is without the fixup table.
|
|
* Basically the device should work as is without the fixup table.
|
|
* If BIOS doesn't give a proper info, enable the corresponding
|
|
* If BIOS doesn't give a proper info, enable the corresponding
|
|
@@ -5478,13 +6129,13 @@ static const struct alc_model_fixup alc269_fixup_models[] = {
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
-static int alc269_fill_coef(struct hda_codec *codec)
|
|
|
|
|
|
+static void alc269_fill_coef(struct hda_codec *codec)
|
|
{
|
|
{
|
|
struct alc_spec *spec = codec->spec;
|
|
struct alc_spec *spec = codec->spec;
|
|
int val;
|
|
int val;
|
|
|
|
|
|
if (spec->codec_variant != ALC269_TYPE_ALC269VB)
|
|
if (spec->codec_variant != ALC269_TYPE_ALC269VB)
|
|
- return 0;
|
|
|
|
|
|
+ return;
|
|
|
|
|
|
if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
|
|
if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
|
|
alc_write_coef_idx(codec, 0xf, 0x960b);
|
|
alc_write_coef_idx(codec, 0xf, 0x960b);
|
|
@@ -5520,8 +6171,6 @@ static int alc269_fill_coef(struct hda_codec *codec)
|
|
|
|
|
|
val = alc_read_coef_idx(codec, 0x4); /* HP */
|
|
val = alc_read_coef_idx(codec, 0x4); /* HP */
|
|
alc_write_coef_idx(codec, 0x4, val | (1<<11));
|
|
alc_write_coef_idx(codec, 0x4, val | (1<<11));
|
|
-
|
|
|
|
- return 0;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -5565,6 +6214,7 @@ static int patch_alc269(struct hda_codec *codec)
|
|
}
|
|
}
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto error;
|
|
goto error;
|
|
|
|
+ spec->init_hook = alc269_fill_coef;
|
|
alc269_fill_coef(codec);
|
|
alc269_fill_coef(codec);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -5577,15 +6227,6 @@ static int patch_alc269(struct hda_codec *codec)
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
- if (!spec->no_analog && !spec->adc_nids) {
|
|
|
|
- alc_auto_fill_adc_caps(codec);
|
|
|
|
- alc_rebuild_imux_for_auto_mic(codec);
|
|
|
|
- alc_remove_invalid_adc_nids(codec);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
-
|
|
|
|
if (!spec->no_analog && has_cdefine_beep(codec)) {
|
|
if (!spec->no_analog && has_cdefine_beep(codec)) {
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
@@ -5593,21 +6234,13 @@ static int patch_alc269(struct hda_codec *codec)
|
|
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
|
|
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
|
|
}
|
|
}
|
|
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
#ifdef CONFIG_PM
|
|
#ifdef CONFIG_PM
|
|
codec->patch_ops.resume = alc269_resume;
|
|
codec->patch_ops.resume = alc269_resume;
|
|
#endif
|
|
#endif
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
spec->shutup = alc269_shutup;
|
|
spec->shutup = alc269_shutup;
|
|
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
- if (!spec->loopback.amplist)
|
|
|
|
- spec->loopback.amplist = alc269_loopbacks;
|
|
|
|
- if (alc269_mic2_for_mute_led(codec))
|
|
|
|
- codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
|
|
|
|
-#endif
|
|
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -5627,21 +6260,12 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
|
|
return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
|
|
return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
-static const struct hda_amp_list alc861_loopbacks[] = {
|
|
|
|
- { 0x15, HDA_INPUT, 0 },
|
|
|
|
- { 0x15, HDA_INPUT, 1 },
|
|
|
|
- { 0x15, HDA_INPUT, 2 },
|
|
|
|
- { 0x15, HDA_INPUT, 3 },
|
|
|
|
- { } /* end */
|
|
|
|
-};
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-
|
|
|
|
/* Pin config fixes */
|
|
/* Pin config fixes */
|
|
enum {
|
|
enum {
|
|
- PINFIX_FSC_AMILO_PI1505,
|
|
|
|
- PINFIX_ASUS_A6RP,
|
|
|
|
|
|
+ ALC861_FIXUP_FSC_AMILO_PI1505,
|
|
|
|
+ ALC861_FIXUP_AMP_VREF_0F,
|
|
|
|
+ ALC861_FIXUP_NO_JACK_DETECT,
|
|
|
|
+ ALC861_FIXUP_ASUS_A6RP,
|
|
};
|
|
};
|
|
|
|
|
|
/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
|
|
/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
|
|
@@ -5663,8 +6287,16 @@ static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
|
|
spec->keep_vref_in_automute = 1;
|
|
spec->keep_vref_in_automute = 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* suppress the jack-detection */
|
|
|
|
+static void alc_fixup_no_jack_detect(struct hda_codec *codec,
|
|
|
|
+ const struct alc_fixup *fix, int action)
|
|
|
|
+{
|
|
|
|
+ if (action == ALC_FIXUP_ACT_PRE_PROBE)
|
|
|
|
+ codec->no_jack_detect = 1;
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct alc_fixup alc861_fixups[] = {
|
|
static const struct alc_fixup alc861_fixups[] = {
|
|
- [PINFIX_FSC_AMILO_PI1505] = {
|
|
|
|
|
|
+ [ALC861_FIXUP_FSC_AMILO_PI1505] = {
|
|
.type = ALC_FIXUP_PINS,
|
|
.type = ALC_FIXUP_PINS,
|
|
.v.pins = (const struct alc_pincfg[]) {
|
|
.v.pins = (const struct alc_pincfg[]) {
|
|
{ 0x0b, 0x0221101f }, /* HP */
|
|
{ 0x0b, 0x0221101f }, /* HP */
|
|
@@ -5672,17 +6304,29 @@ static const struct alc_fixup alc861_fixups[] = {
|
|
{ }
|
|
{ }
|
|
}
|
|
}
|
|
},
|
|
},
|
|
- [PINFIX_ASUS_A6RP] = {
|
|
|
|
|
|
+ [ALC861_FIXUP_AMP_VREF_0F] = {
|
|
.type = ALC_FIXUP_FUNC,
|
|
.type = ALC_FIXUP_FUNC,
|
|
.v.func = alc861_fixup_asus_amp_vref_0f,
|
|
.v.func = alc861_fixup_asus_amp_vref_0f,
|
|
},
|
|
},
|
|
|
|
+ [ALC861_FIXUP_NO_JACK_DETECT] = {
|
|
|
|
+ .type = ALC_FIXUP_FUNC,
|
|
|
|
+ .v.func = alc_fixup_no_jack_detect,
|
|
|
|
+ },
|
|
|
|
+ [ALC861_FIXUP_ASUS_A6RP] = {
|
|
|
|
+ .type = ALC_FIXUP_FUNC,
|
|
|
|
+ .v.func = alc861_fixup_asus_amp_vref_0f,
|
|
|
|
+ .chained = true,
|
|
|
|
+ .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
|
|
|
|
+ }
|
|
};
|
|
};
|
|
|
|
|
|
static const struct snd_pci_quirk alc861_fixup_tbl[] = {
|
|
static const struct snd_pci_quirk alc861_fixup_tbl[] = {
|
|
- SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP),
|
|
|
|
- SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP),
|
|
|
|
- SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
|
|
|
|
- SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
|
|
|
|
|
|
+ SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
|
|
|
|
+ SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
|
|
|
|
+ SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
|
|
|
|
+ SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
|
|
|
|
+ SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
|
|
|
|
+ SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
|
|
{}
|
|
{}
|
|
};
|
|
};
|
|
|
|
|
|
@@ -5709,15 +6353,6 @@ static int patch_alc861(struct hda_codec *codec)
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
- if (!spec->no_analog && !spec->adc_nids) {
|
|
|
|
- alc_auto_fill_adc_caps(codec);
|
|
|
|
- alc_rebuild_imux_for_auto_mic(codec);
|
|
|
|
- alc_remove_invalid_adc_nids(codec);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
-
|
|
|
|
if (!spec->no_analog) {
|
|
if (!spec->no_analog) {
|
|
err = snd_hda_attach_beep_device(codec, 0x23);
|
|
err = snd_hda_attach_beep_device(codec, 0x23);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
@@ -5725,16 +6360,13 @@ static int patch_alc861(struct hda_codec *codec)
|
|
set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
|
|
set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
|
|
}
|
|
}
|
|
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
spec->power_hook = alc_power_eapd;
|
|
spec->power_hook = alc_power_eapd;
|
|
- if (!spec->loopback.amplist)
|
|
|
|
- spec->loopback.amplist = alc861_loopbacks;
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
error:
|
|
error:
|
|
@@ -5749,10 +6381,6 @@ static int patch_alc861(struct hda_codec *codec)
|
|
*
|
|
*
|
|
* In addition, an independent DAC
|
|
* In addition, an independent DAC
|
|
*/
|
|
*/
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
-#define alc861vd_loopbacks alc880_loopbacks
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
static int alc861vd_parse_auto_config(struct hda_codec *codec)
|
|
static int alc861vd_parse_auto_config(struct hda_codec *codec)
|
|
{
|
|
{
|
|
static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
|
|
static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
|
|
@@ -5833,15 +6461,6 @@ static int patch_alc861vd(struct hda_codec *codec)
|
|
add_verb(spec, alc660vd_eapd_verbs);
|
|
add_verb(spec, alc660vd_eapd_verbs);
|
|
}
|
|
}
|
|
|
|
|
|
- if (!spec->no_analog && !spec->adc_nids) {
|
|
|
|
- alc_auto_fill_adc_caps(codec);
|
|
|
|
- alc_rebuild_imux_for_auto_mic(codec);
|
|
|
|
- alc_remove_invalid_adc_nids(codec);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
-
|
|
|
|
if (!spec->no_analog) {
|
|
if (!spec->no_analog) {
|
|
err = snd_hda_attach_beep_device(codec, 0x23);
|
|
err = snd_hda_attach_beep_device(codec, 0x23);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
@@ -5849,16 +6468,11 @@ static int patch_alc861vd(struct hda_codec *codec)
|
|
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
|
|
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
|
|
}
|
|
}
|
|
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
|
|
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
spec->shutup = alc_eapd_shutup;
|
|
spec->shutup = alc_eapd_shutup;
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
- if (!spec->loopback.amplist)
|
|
|
|
- spec->loopback.amplist = alc861vd_loopbacks;
|
|
|
|
-#endif
|
|
|
|
|
|
+
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -5878,9 +6492,6 @@ static int patch_alc861vd(struct hda_codec *codec)
|
|
* In addition, an independent DAC for the multi-playback (not used in this
|
|
* In addition, an independent DAC for the multi-playback (not used in this
|
|
* driver yet).
|
|
* driver yet).
|
|
*/
|
|
*/
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
-#define alc662_loopbacks alc880_loopbacks
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
* BIOS auto configuration
|
|
* BIOS auto configuration
|
|
@@ -5930,6 +6541,7 @@ enum {
|
|
ALC662_FIXUP_ASUS_MODE6,
|
|
ALC662_FIXUP_ASUS_MODE6,
|
|
ALC662_FIXUP_ASUS_MODE7,
|
|
ALC662_FIXUP_ASUS_MODE7,
|
|
ALC662_FIXUP_ASUS_MODE8,
|
|
ALC662_FIXUP_ASUS_MODE8,
|
|
|
|
+ ALC662_FIXUP_NO_JACK_DETECT,
|
|
};
|
|
};
|
|
|
|
|
|
static const struct alc_fixup alc662_fixups[] = {
|
|
static const struct alc_fixup alc662_fixups[] = {
|
|
@@ -6075,6 +6687,10 @@ static const struct alc_fixup alc662_fixups[] = {
|
|
.chained = true,
|
|
.chained = true,
|
|
.chain_id = ALC662_FIXUP_SKU_IGNORE
|
|
.chain_id = ALC662_FIXUP_SKU_IGNORE
|
|
},
|
|
},
|
|
|
|
+ [ALC662_FIXUP_NO_JACK_DETECT] = {
|
|
|
|
+ .type = ALC_FIXUP_FUNC,
|
|
|
|
+ .v.func = alc_fixup_no_jack_detect,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
|
|
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
|
|
@@ -6083,6 +6699,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
|
|
SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
|
|
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
|
|
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
|
|
SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
|
|
SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
|
|
|
|
+ SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
|
|
SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
|
|
SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
|
|
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
|
|
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
|
|
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
|
|
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
|
|
@@ -6204,15 +6821,6 @@ static int patch_alc662(struct hda_codec *codec)
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto error;
|
|
goto error;
|
|
|
|
|
|
- if (!spec->no_analog && !spec->adc_nids) {
|
|
|
|
- alc_auto_fill_adc_caps(codec);
|
|
|
|
- alc_rebuild_imux_for_auto_mic(codec);
|
|
|
|
- alc_remove_invalid_adc_nids(codec);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
-
|
|
|
|
if (!spec->no_analog && has_cdefine_beep(codec)) {
|
|
if (!spec->no_analog && has_cdefine_beep(codec)) {
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
err = snd_hda_attach_beep_device(codec, 0x1);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
@@ -6232,16 +6840,10 @@ static int patch_alc662(struct hda_codec *codec)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
spec->shutup = alc_eapd_shutup;
|
|
spec->shutup = alc_eapd_shutup;
|
|
|
|
|
|
-#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
- if (!spec->loopback.amplist)
|
|
|
|
- spec->loopback.amplist = alc662_loopbacks;
|
|
|
|
-#endif
|
|
|
|
|
|
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -6281,11 +6883,7 @@ static int patch_alc680(struct hda_codec *codec)
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!spec->no_analog && !spec->cap_mixer)
|
|
|
|
- set_capture_mixer(codec);
|
|
|
|
-
|
|
|
|
codec->patch_ops = alc_patch_ops;
|
|
codec->patch_ops = alc_patch_ops;
|
|
- spec->init_hook = alc_auto_init_std;
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|