0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/init.h>
0010 #include <linux/slab.h>
0011 #include <linux/module.h>
0012
0013 #include <sound/core.h>
0014 #include <sound/hda_codec.h>
0015 #include "hda_local.h"
0016 #include "hda_auto_parser.h"
0017 #include "hda_beep.h"
0018 #include "hda_jack.h"
0019 #include "hda_generic.h"
0020
0021
0022 struct ad198x_spec {
0023 struct hda_gen_spec gen;
0024
0025
0026 int smux_paths[4];
0027 unsigned int cur_smux;
0028 hda_nid_t eapd_nid;
0029
0030 unsigned int beep_amp;
0031 int num_smux_conns;
0032 };
0033
0034
0035 #ifdef CONFIG_SND_HDA_INPUT_BEEP
0036
0037 static const struct snd_kcontrol_new ad_beep_mixer[] = {
0038 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_OUTPUT),
0039 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_OUTPUT),
0040 { }
0041 };
0042
0043 #define set_beep_amp(spec, nid, idx, dir) \
0044 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir))
0045 #else
0046 #define set_beep_amp(spec, nid, idx, dir)
0047 #endif
0048
0049 #ifdef CONFIG_SND_HDA_INPUT_BEEP
0050 static int create_beep_ctls(struct hda_codec *codec)
0051 {
0052 struct ad198x_spec *spec = codec->spec;
0053 const struct snd_kcontrol_new *knew;
0054
0055 if (!spec->beep_amp)
0056 return 0;
0057
0058 for (knew = ad_beep_mixer ; knew->name; knew++) {
0059 int err;
0060 struct snd_kcontrol *kctl;
0061 kctl = snd_ctl_new1(knew, codec);
0062 if (!kctl)
0063 return -ENOMEM;
0064 kctl->private_value = spec->beep_amp;
0065 err = snd_hda_ctl_add(codec, 0, kctl);
0066 if (err < 0)
0067 return err;
0068 }
0069 return 0;
0070 }
0071 #else
0072 #define create_beep_ctls(codec) 0
0073 #endif
0074
0075 #ifdef CONFIG_PM
0076 static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
0077 hda_nid_t hp)
0078 {
0079 if (snd_hda_query_pin_caps(codec, front) & AC_PINCAP_EAPD)
0080 snd_hda_codec_write(codec, front, 0, AC_VERB_SET_EAPD_BTLENABLE,
0081 !codec->inv_eapd ? 0x00 : 0x02);
0082 if (snd_hda_query_pin_caps(codec, hp) & AC_PINCAP_EAPD)
0083 snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_EAPD_BTLENABLE,
0084 !codec->inv_eapd ? 0x00 : 0x02);
0085 }
0086
0087 static void ad198x_power_eapd(struct hda_codec *codec)
0088 {
0089
0090 switch (codec->core.vendor_id) {
0091 case 0x11d41882:
0092 case 0x11d4882a:
0093 case 0x11d41884:
0094 case 0x11d41984:
0095 case 0x11d41883:
0096 case 0x11d4184a:
0097 case 0x11d4194a:
0098 case 0x11d4194b:
0099 case 0x11d41988:
0100 case 0x11d4198b:
0101 case 0x11d4989a:
0102 case 0x11d4989b:
0103 ad198x_power_eapd_write(codec, 0x12, 0x11);
0104 break;
0105 case 0x11d41981:
0106 case 0x11d41983:
0107 ad198x_power_eapd_write(codec, 0x05, 0x06);
0108 break;
0109 case 0x11d41986:
0110 ad198x_power_eapd_write(codec, 0x1b, 0x1a);
0111 break;
0112 }
0113 }
0114
0115 static int ad198x_suspend(struct hda_codec *codec)
0116 {
0117 snd_hda_shutup_pins(codec);
0118 ad198x_power_eapd(codec);
0119 return 0;
0120 }
0121 #endif
0122
0123
0124 static void ad_vmaster_eapd_hook(void *private_data, int enabled)
0125 {
0126 struct hda_codec *codec = private_data;
0127 struct ad198x_spec *spec = codec->spec;
0128
0129 if (!spec->eapd_nid)
0130 return;
0131 if (codec->inv_eapd)
0132 enabled = !enabled;
0133 snd_hda_codec_write_cache(codec, spec->eapd_nid, 0,
0134 AC_VERB_SET_EAPD_BTLENABLE,
0135 enabled ? 0x02 : 0x00);
0136 }
0137
0138
0139
0140
0141
0142 static int ad198x_auto_build_controls(struct hda_codec *codec)
0143 {
0144 int err;
0145
0146 err = snd_hda_gen_build_controls(codec);
0147 if (err < 0)
0148 return err;
0149 err = create_beep_ctls(codec);
0150 if (err < 0)
0151 return err;
0152 return 0;
0153 }
0154
0155 static const struct hda_codec_ops ad198x_auto_patch_ops = {
0156 .build_controls = ad198x_auto_build_controls,
0157 .build_pcms = snd_hda_gen_build_pcms,
0158 .init = snd_hda_gen_init,
0159 .free = snd_hda_gen_free,
0160 .unsol_event = snd_hda_jack_unsol_event,
0161 #ifdef CONFIG_PM
0162 .check_power_status = snd_hda_gen_check_power_status,
0163 .suspend = ad198x_suspend,
0164 #endif
0165 };
0166
0167
0168 static int ad198x_parse_auto_config(struct hda_codec *codec, bool indep_hp)
0169 {
0170 struct ad198x_spec *spec = codec->spec;
0171 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
0172 int err;
0173
0174 codec->spdif_status_reset = 1;
0175 codec->no_trigger_sense = 1;
0176 codec->no_sticky_stream = 1;
0177
0178 spec->gen.indep_hp = indep_hp;
0179 if (!spec->gen.add_stereo_mix_input)
0180 spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
0181
0182 err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
0183 if (err < 0)
0184 return err;
0185 err = snd_hda_gen_parse_auto_config(codec, cfg);
0186 if (err < 0)
0187 return err;
0188
0189 return 0;
0190 }
0191
0192
0193
0194
0195
0196 static int alloc_ad_spec(struct hda_codec *codec)
0197 {
0198 struct ad198x_spec *spec;
0199
0200 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
0201 if (!spec)
0202 return -ENOMEM;
0203 codec->spec = spec;
0204 snd_hda_gen_spec_init(&spec->gen);
0205 codec->patch_ops = ad198x_auto_patch_ops;
0206 return 0;
0207 }
0208
0209
0210
0211
0212
0213
0214 static void ad_fixup_inv_jack_detect(struct hda_codec *codec,
0215 const struct hda_fixup *fix, int action)
0216 {
0217 struct ad198x_spec *spec = codec->spec;
0218
0219 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
0220 codec->inv_jack_detect = 1;
0221 spec->gen.keep_eapd_on = 1;
0222 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
0223 spec->eapd_nid = 0x1b;
0224 }
0225 }
0226
0227
0228 static void ad1986a_fixup_eapd(struct hda_codec *codec,
0229 const struct hda_fixup *fix, int action)
0230 {
0231 struct ad198x_spec *spec = codec->spec;
0232
0233 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
0234 codec->inv_eapd = 0;
0235 spec->gen.keep_eapd_on = 1;
0236 spec->eapd_nid = 0x1b;
0237 }
0238 }
0239
0240
0241 static void ad1986a_fixup_eapd_mix_in(struct hda_codec *codec,
0242 const struct hda_fixup *fix, int action)
0243 {
0244 struct ad198x_spec *spec = codec->spec;
0245
0246 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
0247 ad1986a_fixup_eapd(codec, fix, action);
0248 spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_ENABLE;
0249 }
0250 }
0251
0252 enum {
0253 AD1986A_FIXUP_INV_JACK_DETECT,
0254 AD1986A_FIXUP_ULTRA,
0255 AD1986A_FIXUP_SAMSUNG,
0256 AD1986A_FIXUP_3STACK,
0257 AD1986A_FIXUP_LAPTOP,
0258 AD1986A_FIXUP_LAPTOP_IMIC,
0259 AD1986A_FIXUP_EAPD,
0260 AD1986A_FIXUP_EAPD_MIX_IN,
0261 AD1986A_FIXUP_EASYNOTE,
0262 };
0263
0264 static const struct hda_fixup ad1986a_fixups[] = {
0265 [AD1986A_FIXUP_INV_JACK_DETECT] = {
0266 .type = HDA_FIXUP_FUNC,
0267 .v.func = ad_fixup_inv_jack_detect,
0268 },
0269 [AD1986A_FIXUP_ULTRA] = {
0270 .type = HDA_FIXUP_PINS,
0271 .v.pins = (const struct hda_pintbl[]) {
0272 { 0x1b, 0x90170110 },
0273 { 0x1d, 0x90a7013e },
0274 {}
0275 },
0276 },
0277 [AD1986A_FIXUP_SAMSUNG] = {
0278 .type = HDA_FIXUP_PINS,
0279 .v.pins = (const struct hda_pintbl[]) {
0280 { 0x1b, 0x90170110 },
0281 { 0x1d, 0x90a7013e },
0282 { 0x20, 0x411111f0 },
0283 { 0x24, 0x411111f0 },
0284 {}
0285 },
0286 },
0287 [AD1986A_FIXUP_3STACK] = {
0288 .type = HDA_FIXUP_PINS,
0289 .v.pins = (const struct hda_pintbl[]) {
0290 { 0x1a, 0x02214021 },
0291 { 0x1b, 0x01014011 },
0292 { 0x1c, 0x01813030 },
0293 { 0x1d, 0x01a19020 },
0294 { 0x1e, 0x411111f0 },
0295 { 0x1f, 0x02a190f0 },
0296 { 0x20, 0x411111f0 },
0297 {}
0298 },
0299 },
0300 [AD1986A_FIXUP_LAPTOP] = {
0301 .type = HDA_FIXUP_PINS,
0302 .v.pins = (const struct hda_pintbl[]) {
0303 { 0x1a, 0x02214021 },
0304 { 0x1b, 0x90170110 },
0305 { 0x1c, 0x411111f0 },
0306 { 0x1d, 0x411111f0 },
0307 { 0x1e, 0x411111f0 },
0308 { 0x1f, 0x02a191f0 },
0309 { 0x20, 0x411111f0 },
0310 {}
0311 },
0312 },
0313 [AD1986A_FIXUP_LAPTOP_IMIC] = {
0314 .type = HDA_FIXUP_PINS,
0315 .v.pins = (const struct hda_pintbl[]) {
0316 { 0x1d, 0x90a7013e },
0317 {}
0318 },
0319 .chained_before = 1,
0320 .chain_id = AD1986A_FIXUP_LAPTOP,
0321 },
0322 [AD1986A_FIXUP_EAPD] = {
0323 .type = HDA_FIXUP_FUNC,
0324 .v.func = ad1986a_fixup_eapd,
0325 },
0326 [AD1986A_FIXUP_EAPD_MIX_IN] = {
0327 .type = HDA_FIXUP_FUNC,
0328 .v.func = ad1986a_fixup_eapd_mix_in,
0329 },
0330 [AD1986A_FIXUP_EASYNOTE] = {
0331 .type = HDA_FIXUP_PINS,
0332 .v.pins = (const struct hda_pintbl[]) {
0333 { 0x1a, 0x0421402f },
0334 { 0x1b, 0x90170110 },
0335 { 0x1c, 0x411111f0 },
0336 { 0x1d, 0x90a70130 },
0337 { 0x1e, 0x411111f0 },
0338 { 0x1f, 0x04a19040 },
0339 { 0x20, 0x411111f0 },
0340 { 0x21, 0x411111f0 },
0341 { 0x22, 0x411111f0 },
0342 { 0x23, 0x411111f0 },
0343 { 0x24, 0x411111f0 },
0344 { 0x25, 0x411111f0 },
0345 {}
0346 },
0347 .chained = true,
0348 .chain_id = AD1986A_FIXUP_EAPD_MIX_IN,
0349 },
0350 };
0351
0352 static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
0353 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC),
0354 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9V", AD1986A_FIXUP_LAPTOP_IMIC),
0355 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS Z99He", AD1986A_FIXUP_EAPD),
0356 SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8JN", AD1986A_FIXUP_EAPD),
0357 SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK),
0358 SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK),
0359 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK),
0360 SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40", AD1986A_FIXUP_EAPD),
0361 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_FIXUP_LAPTOP),
0362 SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc000, "Samsung", AD1986A_FIXUP_SAMSUNG),
0363 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_FIXUP_ULTRA),
0364 SND_PCI_QUIRK(0x1631, 0xc022, "PackardBell EasyNote MX65", AD1986A_FIXUP_EASYNOTE),
0365 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_FIXUP_INV_JACK_DETECT),
0366 SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_FIXUP_3STACK),
0367 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_FIXUP_3STACK),
0368 {}
0369 };
0370
0371 static const struct hda_model_fixup ad1986a_fixup_models[] = {
0372 { .id = AD1986A_FIXUP_3STACK, .name = "3stack" },
0373 { .id = AD1986A_FIXUP_LAPTOP, .name = "laptop" },
0374 { .id = AD1986A_FIXUP_LAPTOP_IMIC, .name = "laptop-imic" },
0375 { .id = AD1986A_FIXUP_LAPTOP_IMIC, .name = "laptop-eapd" },
0376 { .id = AD1986A_FIXUP_EAPD, .name = "eapd" },
0377 {}
0378 };
0379
0380
0381
0382 static int patch_ad1986a(struct hda_codec *codec)
0383 {
0384 int err;
0385 struct ad198x_spec *spec;
0386 static const hda_nid_t preferred_pairs[] = {
0387 0x1a, 0x03,
0388 0x1b, 0x03,
0389 0x1c, 0x04,
0390 0x1d, 0x05,
0391 0x1e, 0x03,
0392 0
0393 };
0394
0395 err = alloc_ad_spec(codec);
0396 if (err < 0)
0397 return err;
0398 spec = codec->spec;
0399
0400
0401 codec->inv_eapd = 1;
0402
0403 spec->gen.mixer_nid = 0x07;
0404 spec->gen.beep_nid = 0x19;
0405 set_beep_amp(spec, 0x18, 0, HDA_OUTPUT);
0406
0407
0408
0409
0410
0411
0412
0413 spec->gen.multiout.no_share_stream = 1;
0414
0415 spec->gen.preferred_dacs = preferred_pairs;
0416
0417
0418 spec->gen.auto_mute_via_amp = 1;
0419
0420 snd_hda_pick_fixup(codec, ad1986a_fixup_models, ad1986a_fixup_tbl,
0421 ad1986a_fixups);
0422 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
0423
0424 err = ad198x_parse_auto_config(codec, false);
0425 if (err < 0) {
0426 snd_hda_gen_free(codec);
0427 return err;
0428 }
0429
0430 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
0431
0432 return 0;
0433 }
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443 static int ad1983_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
0444 struct snd_ctl_elem_info *uinfo)
0445 {
0446 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0447 struct ad198x_spec *spec = codec->spec;
0448 static const char * const texts2[] = { "PCM", "ADC" };
0449 static const char * const texts3[] = { "PCM", "ADC1", "ADC2" };
0450 int num_conns = spec->num_smux_conns;
0451
0452 if (num_conns == 2)
0453 return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts2);
0454 else if (num_conns == 3)
0455 return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
0456 else
0457 return -EINVAL;
0458 }
0459
0460 static int ad1983_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
0461 struct snd_ctl_elem_value *ucontrol)
0462 {
0463 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0464 struct ad198x_spec *spec = codec->spec;
0465
0466 ucontrol->value.enumerated.item[0] = spec->cur_smux;
0467 return 0;
0468 }
0469
0470 static int ad1983_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
0471 struct snd_ctl_elem_value *ucontrol)
0472 {
0473 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0474 struct ad198x_spec *spec = codec->spec;
0475 unsigned int val = ucontrol->value.enumerated.item[0];
0476 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
0477 int num_conns = spec->num_smux_conns;
0478
0479 if (val >= num_conns)
0480 return -EINVAL;
0481 if (spec->cur_smux == val)
0482 return 0;
0483 spec->cur_smux = val;
0484 snd_hda_codec_write_cache(codec, dig_out, 0,
0485 AC_VERB_SET_CONNECT_SEL, val);
0486 return 1;
0487 }
0488
0489 static const struct snd_kcontrol_new ad1983_auto_smux_mixer = {
0490 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0491 .name = "IEC958 Playback Source",
0492 .info = ad1983_auto_smux_enum_info,
0493 .get = ad1983_auto_smux_enum_get,
0494 .put = ad1983_auto_smux_enum_put,
0495 };
0496
0497 static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
0498 {
0499 struct ad198x_spec *spec = codec->spec;
0500 hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
0501 int num_conns;
0502
0503 if (!dig_out)
0504 return 0;
0505 num_conns = snd_hda_get_num_conns(codec, dig_out);
0506 if (num_conns != 2 && num_conns != 3)
0507 return 0;
0508 spec->num_smux_conns = num_conns;
0509 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1983_auto_smux_mixer))
0510 return -ENOMEM;
0511 return 0;
0512 }
0513
0514 static int patch_ad1983(struct hda_codec *codec)
0515 {
0516 static const hda_nid_t conn_0c[] = { 0x08 };
0517 static const hda_nid_t conn_0d[] = { 0x09 };
0518 struct ad198x_spec *spec;
0519 int err;
0520
0521 err = alloc_ad_spec(codec);
0522 if (err < 0)
0523 return err;
0524 spec = codec->spec;
0525
0526 spec->gen.mixer_nid = 0x0e;
0527 spec->gen.beep_nid = 0x10;
0528 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
0529
0530
0531 snd_hda_override_conn_list(codec, 0x0c, ARRAY_SIZE(conn_0c), conn_0c);
0532 snd_hda_override_conn_list(codec, 0x0d, ARRAY_SIZE(conn_0d), conn_0d);
0533
0534 err = ad198x_parse_auto_config(codec, false);
0535 if (err < 0)
0536 goto error;
0537 err = ad1983_add_spdif_mux_ctl(codec);
0538 if (err < 0)
0539 goto error;
0540 return 0;
0541
0542 error:
0543 snd_hda_gen_free(codec);
0544 return err;
0545 }
0546
0547
0548
0549
0550
0551
0552 static void ad1981_fixup_hp_eapd(struct hda_codec *codec,
0553 const struct hda_fixup *fix, int action)
0554 {
0555 struct ad198x_spec *spec = codec->spec;
0556
0557 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
0558 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
0559 spec->eapd_nid = 0x05;
0560 }
0561 }
0562
0563
0564
0565
0566 static void ad1981_fixup_amp_override(struct hda_codec *codec,
0567 const struct hda_fixup *fix, int action)
0568 {
0569 if (action == HDA_FIXUP_ACT_PRE_PROBE)
0570 snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
0571 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
0572 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
0573 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
0574 (1 << AC_AMPCAP_MUTE_SHIFT));
0575 }
0576
0577 enum {
0578 AD1981_FIXUP_AMP_OVERRIDE,
0579 AD1981_FIXUP_HP_EAPD,
0580 };
0581
0582 static const struct hda_fixup ad1981_fixups[] = {
0583 [AD1981_FIXUP_AMP_OVERRIDE] = {
0584 .type = HDA_FIXUP_FUNC,
0585 .v.func = ad1981_fixup_amp_override,
0586 },
0587 [AD1981_FIXUP_HP_EAPD] = {
0588 .type = HDA_FIXUP_FUNC,
0589 .v.func = ad1981_fixup_hp_eapd,
0590 .chained = true,
0591 .chain_id = AD1981_FIXUP_AMP_OVERRIDE,
0592 },
0593 };
0594
0595 static const struct snd_pci_quirk ad1981_fixup_tbl[] = {
0596 SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
0597 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD),
0598 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
0599
0600 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_FIXUP_HP_EAPD),
0601 {}
0602 };
0603
0604 static int patch_ad1981(struct hda_codec *codec)
0605 {
0606 struct ad198x_spec *spec;
0607 int err;
0608
0609 err = alloc_ad_spec(codec);
0610 if (err < 0)
0611 return -ENOMEM;
0612 spec = codec->spec;
0613
0614 spec->gen.mixer_nid = 0x0e;
0615 spec->gen.beep_nid = 0x10;
0616 set_beep_amp(spec, 0x0d, 0, HDA_OUTPUT);
0617
0618 snd_hda_pick_fixup(codec, NULL, ad1981_fixup_tbl, ad1981_fixups);
0619 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
0620
0621 err = ad198x_parse_auto_config(codec, false);
0622 if (err < 0)
0623 goto error;
0624 err = ad1983_add_spdif_mux_ctl(codec);
0625 if (err < 0)
0626 goto error;
0627
0628 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
0629
0630 return 0;
0631
0632 error:
0633 snd_hda_gen_free(codec);
0634 return err;
0635 }
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723 static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
0724 struct snd_ctl_elem_info *uinfo)
0725 {
0726 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0727 struct ad198x_spec *spec = codec->spec;
0728 static const char * const texts[] = {
0729 "PCM", "ADC1", "ADC2", "ADC3",
0730 };
0731 int num_conns = spec->num_smux_conns;
0732
0733 if (num_conns > 4)
0734 num_conns = 4;
0735 return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts);
0736 }
0737
0738 static int ad1988_auto_smux_enum_get(struct snd_kcontrol *kcontrol,
0739 struct snd_ctl_elem_value *ucontrol)
0740 {
0741 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0742 struct ad198x_spec *spec = codec->spec;
0743
0744 ucontrol->value.enumerated.item[0] = spec->cur_smux;
0745 return 0;
0746 }
0747
0748 static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
0749 struct snd_ctl_elem_value *ucontrol)
0750 {
0751 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0752 struct ad198x_spec *spec = codec->spec;
0753 unsigned int val = ucontrol->value.enumerated.item[0];
0754 struct nid_path *path;
0755 int num_conns = spec->num_smux_conns;
0756
0757 if (val >= num_conns)
0758 return -EINVAL;
0759 if (spec->cur_smux == val)
0760 return 0;
0761
0762 mutex_lock(&codec->control_mutex);
0763 path = snd_hda_get_path_from_idx(codec,
0764 spec->smux_paths[spec->cur_smux]);
0765 if (path)
0766 snd_hda_activate_path(codec, path, false, true);
0767 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[val]);
0768 if (path)
0769 snd_hda_activate_path(codec, path, true, true);
0770 spec->cur_smux = val;
0771 mutex_unlock(&codec->control_mutex);
0772 return 1;
0773 }
0774
0775 static const struct snd_kcontrol_new ad1988_auto_smux_mixer = {
0776 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0777 .name = "IEC958 Playback Source",
0778 .info = ad1988_auto_smux_enum_info,
0779 .get = ad1988_auto_smux_enum_get,
0780 .put = ad1988_auto_smux_enum_put,
0781 };
0782
0783 static int ad1988_auto_init(struct hda_codec *codec)
0784 {
0785 struct ad198x_spec *spec = codec->spec;
0786 int i, err;
0787
0788 err = snd_hda_gen_init(codec);
0789 if (err < 0)
0790 return err;
0791 if (!spec->gen.autocfg.dig_outs)
0792 return 0;
0793
0794 for (i = 0; i < 4; i++) {
0795 struct nid_path *path;
0796 path = snd_hda_get_path_from_idx(codec, spec->smux_paths[i]);
0797 if (path)
0798 snd_hda_activate_path(codec, path, path->active, false);
0799 }
0800
0801 return 0;
0802 }
0803
0804 static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec)
0805 {
0806 struct ad198x_spec *spec = codec->spec;
0807 int i, num_conns;
0808
0809
0810
0811 static const struct nid_path fake_paths[4] = {
0812 {
0813 .depth = 3,
0814 .path = { 0x02, 0x1d, 0x1b },
0815 .idx = { 0, 0, 0 },
0816 .multi = { 0, 0, 0 },
0817 },
0818 {
0819 .depth = 4,
0820 .path = { 0x08, 0x0b, 0x1d, 0x1b },
0821 .idx = { 0, 0, 1, 0 },
0822 .multi = { 0, 1, 0, 0 },
0823 },
0824 {
0825 .depth = 4,
0826 .path = { 0x09, 0x0b, 0x1d, 0x1b },
0827 .idx = { 0, 1, 1, 0 },
0828 .multi = { 0, 1, 0, 0 },
0829 },
0830 {
0831 .depth = 4,
0832 .path = { 0x0f, 0x0b, 0x1d, 0x1b },
0833 .idx = { 0, 2, 1, 0 },
0834 .multi = { 0, 1, 0, 0 },
0835 },
0836 };
0837
0838
0839 if (!spec->gen.autocfg.dig_outs ||
0840 get_wcaps_type(get_wcaps(codec, 0x1d)) != AC_WID_AUD_MIX)
0841 return 0;
0842
0843 num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
0844 if (num_conns != 3 && num_conns != 4)
0845 return 0;
0846 spec->num_smux_conns = num_conns;
0847
0848 for (i = 0; i < num_conns; i++) {
0849 struct nid_path *path = snd_array_new(&spec->gen.paths);
0850 if (!path)
0851 return -ENOMEM;
0852 *path = fake_paths[i];
0853 if (!i)
0854 path->active = 1;
0855 spec->smux_paths[i] = snd_hda_get_path_idx(codec, path);
0856 }
0857
0858 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1988_auto_smux_mixer))
0859 return -ENOMEM;
0860
0861 codec->patch_ops.init = ad1988_auto_init;
0862
0863 return 0;
0864 }
0865
0866
0867
0868
0869 enum {
0870 AD1988_FIXUP_6STACK_DIG,
0871 };
0872
0873 static const struct hda_fixup ad1988_fixups[] = {
0874 [AD1988_FIXUP_6STACK_DIG] = {
0875 .type = HDA_FIXUP_PINS,
0876 .v.pins = (const struct hda_pintbl[]) {
0877 { 0x11, 0x02214130 },
0878 { 0x12, 0x01014010 },
0879 { 0x14, 0x02a19122 },
0880 { 0x15, 0x01813021 },
0881 { 0x16, 0x01011012 },
0882 { 0x17, 0x01a19020 },
0883 { 0x1b, 0x0145f1f0 },
0884 { 0x24, 0x01016011 },
0885 { 0x25, 0x01012013 },
0886 { }
0887 }
0888 },
0889 };
0890
0891 static const struct hda_model_fixup ad1988_fixup_models[] = {
0892 { .id = AD1988_FIXUP_6STACK_DIG, .name = "6stack-dig" },
0893 {}
0894 };
0895
0896 static int patch_ad1988(struct hda_codec *codec)
0897 {
0898 struct ad198x_spec *spec;
0899 int err;
0900
0901 err = alloc_ad_spec(codec);
0902 if (err < 0)
0903 return err;
0904 spec = codec->spec;
0905
0906 spec->gen.mixer_nid = 0x20;
0907 spec->gen.mixer_merge_nid = 0x21;
0908 spec->gen.beep_nid = 0x10;
0909 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
0910
0911 snd_hda_pick_fixup(codec, ad1988_fixup_models, NULL, ad1988_fixups);
0912 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
0913
0914 err = ad198x_parse_auto_config(codec, true);
0915 if (err < 0)
0916 goto error;
0917 err = ad1988_add_spdif_mux_ctl(codec);
0918 if (err < 0)
0919 goto error;
0920
0921 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
0922
0923 return 0;
0924
0925 error:
0926 snd_hda_gen_free(codec);
0927 return err;
0928 }
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960 static void ad1884_fixup_amp_override(struct hda_codec *codec,
0961 const struct hda_fixup *fix, int action)
0962 {
0963 if (action == HDA_FIXUP_ACT_PRE_PROBE)
0964 snd_hda_override_amp_caps(codec, 0x20, HDA_INPUT,
0965 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
0966 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
0967 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
0968 (1 << AC_AMPCAP_MUTE_SHIFT));
0969 }
0970
0971
0972 static void ad1884_vmaster_hp_gpio_hook(void *private_data, int enabled)
0973 {
0974 struct hda_codec *codec = private_data;
0975 struct ad198x_spec *spec = codec->spec;
0976
0977 if (spec->eapd_nid)
0978 ad_vmaster_eapd_hook(private_data, enabled);
0979 snd_hda_codec_write_cache(codec, 0x01, 0,
0980 AC_VERB_SET_GPIO_DATA,
0981 enabled ? 0x00 : 0x02);
0982 }
0983
0984 static void ad1884_fixup_hp_eapd(struct hda_codec *codec,
0985 const struct hda_fixup *fix, int action)
0986 {
0987 struct ad198x_spec *spec = codec->spec;
0988
0989 switch (action) {
0990 case HDA_FIXUP_ACT_PRE_PROBE:
0991 spec->gen.vmaster_mute.hook = ad1884_vmaster_hp_gpio_hook;
0992 spec->gen.own_eapd_ctl = 1;
0993 snd_hda_codec_write_cache(codec, 0x01, 0,
0994 AC_VERB_SET_GPIO_MASK, 0x02);
0995 snd_hda_codec_write_cache(codec, 0x01, 0,
0996 AC_VERB_SET_GPIO_DIRECTION, 0x02);
0997 snd_hda_codec_write_cache(codec, 0x01, 0,
0998 AC_VERB_SET_GPIO_DATA, 0x02);
0999 break;
1000 case HDA_FIXUP_ACT_PROBE:
1001 if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
1002 spec->eapd_nid = spec->gen.autocfg.line_out_pins[0];
1003 else
1004 spec->eapd_nid = spec->gen.autocfg.speaker_pins[0];
1005 break;
1006 }
1007 }
1008
1009 static void ad1884_fixup_thinkpad(struct hda_codec *codec,
1010 const struct hda_fixup *fix, int action)
1011 {
1012 struct ad198x_spec *spec = codec->spec;
1013
1014 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
1015 spec->gen.keep_eapd_on = 1;
1016 spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
1017 spec->eapd_nid = 0x12;
1018
1019 spec->beep_amp = HDA_COMPOSE_AMP_VAL(0x20, 3, 3, HDA_INPUT);
1020 spec->gen.beep_nid = 0;
1021 }
1022 }
1023
1024
1025 static const struct hda_verb ad1884_dmic_init_verbs[] = {
1026 {0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
1027 {0x01, AC_VERB_SET_PROC_COEF, 0x08},
1028 {}
1029 };
1030
1031 enum {
1032 AD1884_FIXUP_AMP_OVERRIDE,
1033 AD1884_FIXUP_HP_EAPD,
1034 AD1884_FIXUP_DMIC_COEF,
1035 AD1884_FIXUP_THINKPAD,
1036 AD1884_FIXUP_HP_TOUCHSMART,
1037 };
1038
1039 static const struct hda_fixup ad1884_fixups[] = {
1040 [AD1884_FIXUP_AMP_OVERRIDE] = {
1041 .type = HDA_FIXUP_FUNC,
1042 .v.func = ad1884_fixup_amp_override,
1043 },
1044 [AD1884_FIXUP_HP_EAPD] = {
1045 .type = HDA_FIXUP_FUNC,
1046 .v.func = ad1884_fixup_hp_eapd,
1047 .chained = true,
1048 .chain_id = AD1884_FIXUP_AMP_OVERRIDE,
1049 },
1050 [AD1884_FIXUP_DMIC_COEF] = {
1051 .type = HDA_FIXUP_VERBS,
1052 .v.verbs = ad1884_dmic_init_verbs,
1053 },
1054 [AD1884_FIXUP_THINKPAD] = {
1055 .type = HDA_FIXUP_FUNC,
1056 .v.func = ad1884_fixup_thinkpad,
1057 .chained = true,
1058 .chain_id = AD1884_FIXUP_DMIC_COEF,
1059 },
1060 [AD1884_FIXUP_HP_TOUCHSMART] = {
1061 .type = HDA_FIXUP_VERBS,
1062 .v.verbs = ad1884_dmic_init_verbs,
1063 .chained = true,
1064 .chain_id = AD1884_FIXUP_HP_EAPD,
1065 },
1066 };
1067
1068 static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
1069 SND_PCI_QUIRK(0x103c, 0x2a82, "HP Touchsmart", AD1884_FIXUP_HP_TOUCHSMART),
1070 SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
1071 SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1884_FIXUP_THINKPAD),
1072 {}
1073 };
1074
1075
1076 static int patch_ad1884(struct hda_codec *codec)
1077 {
1078 struct ad198x_spec *spec;
1079 int err;
1080
1081 err = alloc_ad_spec(codec);
1082 if (err < 0)
1083 return err;
1084 spec = codec->spec;
1085
1086 spec->gen.mixer_nid = 0x20;
1087 spec->gen.mixer_merge_nid = 0x21;
1088 spec->gen.beep_nid = 0x10;
1089 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1090
1091 snd_hda_pick_fixup(codec, NULL, ad1884_fixup_tbl, ad1884_fixups);
1092 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1093
1094 err = ad198x_parse_auto_config(codec, true);
1095 if (err < 0)
1096 goto error;
1097 err = ad1983_add_spdif_mux_ctl(codec);
1098 if (err < 0)
1099 goto error;
1100
1101 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
1102
1103 return 0;
1104
1105 error:
1106 snd_hda_gen_free(codec);
1107 return err;
1108 }
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122 static int patch_ad1882(struct hda_codec *codec)
1123 {
1124 struct ad198x_spec *spec;
1125 int err;
1126
1127 err = alloc_ad_spec(codec);
1128 if (err < 0)
1129 return err;
1130 spec = codec->spec;
1131
1132 spec->gen.mixer_nid = 0x20;
1133 spec->gen.mixer_merge_nid = 0x21;
1134 spec->gen.beep_nid = 0x10;
1135 set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
1136 err = ad198x_parse_auto_config(codec, true);
1137 if (err < 0)
1138 goto error;
1139 err = ad1988_add_spdif_mux_ctl(codec);
1140 if (err < 0)
1141 goto error;
1142 return 0;
1143
1144 error:
1145 snd_hda_gen_free(codec);
1146 return err;
1147 }
1148
1149
1150
1151
1152
1153 static const struct hda_device_id snd_hda_id_analog[] = {
1154 HDA_CODEC_ENTRY(0x11d4184a, "AD1884A", patch_ad1884),
1155 HDA_CODEC_ENTRY(0x11d41882, "AD1882", patch_ad1882),
1156 HDA_CODEC_ENTRY(0x11d41883, "AD1883", patch_ad1884),
1157 HDA_CODEC_ENTRY(0x11d41884, "AD1884", patch_ad1884),
1158 HDA_CODEC_ENTRY(0x11d4194a, "AD1984A", patch_ad1884),
1159 HDA_CODEC_ENTRY(0x11d4194b, "AD1984B", patch_ad1884),
1160 HDA_CODEC_ENTRY(0x11d41981, "AD1981", patch_ad1981),
1161 HDA_CODEC_ENTRY(0x11d41983, "AD1983", patch_ad1983),
1162 HDA_CODEC_ENTRY(0x11d41984, "AD1984", patch_ad1884),
1163 HDA_CODEC_ENTRY(0x11d41986, "AD1986A", patch_ad1986a),
1164 HDA_CODEC_ENTRY(0x11d41988, "AD1988", patch_ad1988),
1165 HDA_CODEC_ENTRY(0x11d4198b, "AD1988B", patch_ad1988),
1166 HDA_CODEC_ENTRY(0x11d4882a, "AD1882A", patch_ad1882),
1167 HDA_CODEC_ENTRY(0x11d4989a, "AD1989A", patch_ad1988),
1168 HDA_CODEC_ENTRY(0x11d4989b, "AD1989B", patch_ad1988),
1169 {}
1170 };
1171 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_analog);
1172
1173 MODULE_LICENSE("GPL");
1174 MODULE_DESCRIPTION("Analog Devices HD-audio codec");
1175
1176 static struct hda_codec_driver analog_driver = {
1177 .id = snd_hda_id_analog,
1178 };
1179
1180 module_hda_codec_driver(analog_driver);