aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/patch_analog.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 98cbc983435a..9692265eef33 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -40,6 +40,7 @@ struct ad198x_spec {
40 /* for auto parser */ 40 /* for auto parser */
41 int smux_paths[4]; 41 int smux_paths[4];
42 unsigned int cur_smux; 42 unsigned int cur_smux;
43 hda_nid_t eapd_nid;
43 44
44 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ 45 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
45 hda_nid_t beep_dev_nid; 46 hda_nid_t beep_dev_nid;
@@ -1196,6 +1197,34 @@ static int alloc_ad_spec(struct hda_codec *codec)
1196} 1197}
1197 1198
1198/* 1199/*
1200 * AD1986A fixup codes
1201 */
1202
1203/* Lenovo N100 seems to report the reversed bit for HP jack-sensing */
1204static void ad_fixup_inv_jack_detect(struct hda_codec *codec,
1205 const struct hda_fixup *fix, int action)
1206{
1207 if (action == HDA_FIXUP_ACT_PRE_PROBE)
1208 codec->inv_jack_detect = 1;
1209}
1210
1211enum {
1212 AD1986A_FIXUP_INV_JACK_DETECT,
1213};
1214
1215static const struct hda_fixup ad1986a_fixups[] = {
1216 [AD1986A_FIXUP_INV_JACK_DETECT] = {
1217 .type = HDA_FIXUP_FUNC,
1218 .v.func = ad_fixup_inv_jack_detect,
1219 },
1220};
1221
1222static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
1223 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_FIXUP_INV_JACK_DETECT),
1224 {}
1225};
1226
1227/*
1199 */ 1228 */
1200static int ad1986a_parse_auto_config(struct hda_codec *codec) 1229static int ad1986a_parse_auto_config(struct hda_codec *codec)
1201{ 1230{
@@ -1222,12 +1251,17 @@ static int ad1986a_parse_auto_config(struct hda_codec *codec)
1222 */ 1251 */
1223 spec->gen.multiout.no_share_stream = 1; 1252 spec->gen.multiout.no_share_stream = 1;
1224 1253
1254 snd_hda_pick_fixup(codec, NULL, ad1986a_fixup_tbl, ad1986a_fixups);
1255 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1256
1225 err = ad198x_parse_auto_config(codec); 1257 err = ad198x_parse_auto_config(codec);
1226 if (err < 0) { 1258 if (err < 0) {
1227 ad198x_free(codec); 1259 ad198x_free(codec);
1228 return err; 1260 return err;
1229 } 1261 }
1230 1262
1263 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
1264
1231 return 0; 1265 return 0;
1232} 1266}
1233 1267
@@ -2068,6 +2102,68 @@ static const struct snd_pci_quirk ad1981_cfg_tbl[] = {
2068#endif /* ENABLE_AD_STATIC_QUIRKS */ 2102#endif /* ENABLE_AD_STATIC_QUIRKS */
2069 2103
2070 2104
2105/* follow EAPD via vmaster hook */
2106static void ad_vmaster_eapd_hook(void *private_data, int enabled)
2107{
2108 struct hda_codec *codec = private_data;
2109 struct ad198x_spec *spec = codec->spec;
2110 snd_hda_codec_update_cache(codec, spec->eapd_nid, 0,
2111 AC_VERB_SET_EAPD_BTLENABLE,
2112 enabled ? 0x02 : 0x00);
2113}
2114
2115static void ad1981_fixup_hp_eapd(struct hda_codec *codec,
2116 const struct hda_fixup *fix, int action)
2117{
2118 struct ad198x_spec *spec = codec->spec;
2119
2120 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2121 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
2122 spec->eapd_nid = 0x05;
2123 }
2124}
2125
2126/* set the upper-limit for mixer amp to 0dB for avoiding the possible
2127 * damage by overloading
2128 */
2129static void ad1981_fixup_amp_override(struct hda_codec *codec,
2130 const struct hda_fixup *fix, int action)
2131{
2132 if (action == HDA_FIXUP_ACT_PRE_PROBE)
2133 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
2134 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
2135 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
2136 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2137 (1 << AC_AMPCAP_MUTE_SHIFT));
2138}
2139
2140enum {
2141 AD1981_FIXUP_AMP_OVERRIDE,
2142 AD1981_FIXUP_HP_EAPD,
2143};
2144
2145static const struct hda_fixup ad1981_fixups[] = {
2146 [AD1981_FIXUP_AMP_OVERRIDE] = {
2147 .type = HDA_FIXUP_FUNC,
2148 .v.func = ad1981_fixup_amp_override,
2149 },
2150 [AD1981_FIXUP_HP_EAPD] = {
2151 .type = HDA_FIXUP_FUNC,
2152 .v.func = ad1981_fixup_hp_eapd,
2153 .chained = true,
2154 .chain_id = AD1981_FIXUP_AMP_OVERRIDE,
2155 },
2156};
2157
2158static const struct snd_pci_quirk ad1981_fixup_tbl[] = {
2159 SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
2160 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD),
2161 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
2162 /* HP nx6320 (reversed SSID, H/W bug) */
2163 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_FIXUP_HP_EAPD),
2164 {}
2165};
2166
2071static int ad1981_parse_auto_config(struct hda_codec *codec) 2167static int ad1981_parse_auto_config(struct hda_codec *codec)
2072{ 2168{
2073 struct ad198x_spec *spec; 2169 struct ad198x_spec *spec;
@@ -2081,12 +2177,19 @@ static int ad1981_parse_auto_config(struct hda_codec *codec)
2081 spec->gen.mixer_nid = 0x0e; 2177 spec->gen.mixer_nid = 0x0e;
2082 spec->beep_dev_nid = 0x10; 2178 spec->beep_dev_nid = 0x10;
2083 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT); 2179 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
2180
2181 snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
2182 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
2183
2084 err = ad198x_parse_auto_config(codec); 2184 err = ad198x_parse_auto_config(codec);
2085 if (err < 0) 2185 if (err < 0)
2086 goto error; 2186 goto error;
2087 err = ad1983_add_spdif_mux_ctl(codec); 2187 err = ad1983_add_spdif_mux_ctl(codec);
2088 if (err < 0) 2188 if (err < 0)
2089 goto error; 2189 goto error;
2190
2191 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
2192
2090 return 0; 2193 return 0;
2091 2194
2092 error: 2195 error:
@@ -3466,6 +3569,60 @@ static const char * const ad1884_models[AD1884_MODELS] = {
3466}; 3569};
3467#endif /* ENABLE_AD_STATIC_QUIRKS */ 3570#endif /* ENABLE_AD_STATIC_QUIRKS */
3468 3571
3572
3573/* set the upper-limit for mixer amp to 0dB for avoiding the possible
3574 * damage by overloading
3575 */
3576static void ad1884_fixup_amp_override(struct hda_codec *codec,
3577 const struct hda_fixup *fix, int action)
3578{
3579 if (action == HDA_FIXUP_ACT_PRE_PROBE)
3580 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
3581 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
3582 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
3583 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
3584 (1 << AC_AMPCAP_MUTE_SHIFT));
3585}
3586
3587static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
3588 const struct hda_fixup *fix, int action)
3589{
3590 struct ad198x_spec *spec = codec->spec;
3591
3592 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3593 if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3594 spec->eapd_nid = spec->gen.autocfg.line_out_pins[0];
3595 else
3596 spec->eapd_nid = spec->gen.autocfg.speaker_pins[0];
3597 if (spec->eapd_nid)
3598 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
3599 }
3600}
3601
3602enum {
3603 AD1884_FIXUP_AMP_OVERRIDE,
3604 AD1884_FIXUP_HP_EAPD,
3605};
3606
3607static const struct hda_fixup ad1884_fixups[] = {
3608 [AD1884_FIXUP_AMP_OVERRIDE] = {
3609 .type = HDA_FIXUP_FUNC,
3610 .v.func = ad1884_fixup_amp_override,
3611 },
3612 [AD1884_FIXUP_HP_EAPD] = {
3613 .type = HDA_FIXUP_FUNC,
3614 .v.func = ad1884_fixup_hp_eapd,
3615 .chained = true,
3616 .chain_id = AD1884_FIXUP_AMP_OVERRIDE,
3617 },
3618};
3619
3620static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
3621 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
3622 {}
3623};
3624
3625
3469static int ad1884_parse_auto_config(struct hda_codec *codec) 3626static int ad1884_parse_auto_config(struct hda_codec *codec)
3470{ 3627{
3471 struct ad198x_spec *spec; 3628 struct ad198x_spec *spec;
@@ -3479,12 +3636,19 @@ static int ad1884_parse_auto_config(struct hda_codec *codec)
3479 spec->gen.mixer_nid = 0x20; 3636 spec->gen.mixer_nid = 0x20;
3480 spec->beep_dev_nid = 0x10; 3637 spec->beep_dev_nid = 0x10;
3481 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT); 3638 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
3639
3640 snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
3641 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
3642
3482 err = ad198x_parse_auto_config(codec); 3643 err = ad198x_parse_auto_config(codec);
3483 if (err < 0) 3644 if (err < 0)
3484 goto error; 3645 goto error;
3485 err = ad1983_add_spdif_mux_ctl(codec); 3646 err = ad1983_add_spdif_mux_ctl(codec);
3486 if (err < 0) 3647 if (err < 0)
3487 goto error; 3648 goto error;
3649
3650 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
3651
3488 return 0; 3652 return 0;
3489 3653
3490 error: 3654 error: