0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <linux/init.h>
0037 #include <linux/delay.h>
0038 #include <linux/slab.h>
0039 #include <linux/module.h>
0040 #include <sound/core.h>
0041 #include <sound/asoundef.h>
0042 #include <sound/hda_codec.h>
0043 #include "hda_local.h"
0044 #include "hda_auto_parser.h"
0045 #include "hda_jack.h"
0046 #include "hda_generic.h"
0047
0048
0049 #define VT1708_HP_PIN_NID 0x20
0050 #define VT1708_CD_PIN_NID 0x24
0051
0052 enum VIA_HDA_CODEC {
0053 UNKNOWN = -1,
0054 VT1708,
0055 VT1709_10CH,
0056 VT1709_6CH,
0057 VT1708B_8CH,
0058 VT1708B_4CH,
0059 VT1708S,
0060 VT1708BCE,
0061 VT1702,
0062 VT1718S,
0063 VT1716S,
0064 VT2002P,
0065 VT1812,
0066 VT1802,
0067 VT1705CF,
0068 VT1808,
0069 CODEC_TYPES,
0070 };
0071
0072 #define VT2002P_COMPATIBLE(spec) \
0073 ((spec)->codec_type == VT2002P ||\
0074 (spec)->codec_type == VT1812 ||\
0075 (spec)->codec_type == VT1802)
0076
0077 struct via_spec {
0078 struct hda_gen_spec gen;
0079
0080
0081 unsigned int dmic_enabled;
0082 enum VIA_HDA_CODEC codec_type;
0083
0084
0085 bool alc_mode;
0086
0087
0088 int hp_work_active;
0089 int vt1708_jack_detect;
0090 };
0091
0092 static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
0093 static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
0094 struct hda_codec *codec,
0095 struct snd_pcm_substream *substream,
0096 int action);
0097
0098 static const struct hda_codec_ops via_patch_ops;
0099
0100 static struct via_spec *via_new_spec(struct hda_codec *codec)
0101 {
0102 struct via_spec *spec;
0103
0104 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
0105 if (spec == NULL)
0106 return NULL;
0107
0108 codec->spec = spec;
0109 snd_hda_gen_spec_init(&spec->gen);
0110 spec->codec_type = get_codec_type(codec);
0111
0112 if (spec->codec_type == VT1708BCE)
0113 spec->codec_type = VT1708S;
0114 spec->gen.indep_hp = 1;
0115 spec->gen.keep_eapd_on = 1;
0116 spec->gen.dac_min_mute = 1;
0117 spec->gen.pcm_playback_hook = via_playback_pcm_hook;
0118 spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
0119 codec->power_save_node = 1;
0120 spec->gen.power_down_unused = 1;
0121 codec->patch_ops = via_patch_ops;
0122 return spec;
0123 }
0124
0125 static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
0126 {
0127 u32 vendor_id = codec->core.vendor_id;
0128 u16 ven_id = vendor_id >> 16;
0129 u16 dev_id = vendor_id & 0xffff;
0130 enum VIA_HDA_CODEC codec_type;
0131
0132
0133 if (ven_id != 0x1106)
0134 codec_type = UNKNOWN;
0135 else if (dev_id >= 0x1708 && dev_id <= 0x170b)
0136 codec_type = VT1708;
0137 else if (dev_id >= 0xe710 && dev_id <= 0xe713)
0138 codec_type = VT1709_10CH;
0139 else if (dev_id >= 0xe714 && dev_id <= 0xe717)
0140 codec_type = VT1709_6CH;
0141 else if (dev_id >= 0xe720 && dev_id <= 0xe723) {
0142 codec_type = VT1708B_8CH;
0143 if (snd_hda_param_read(codec, 0x16, AC_PAR_CONNLIST_LEN) == 0x7)
0144 codec_type = VT1708BCE;
0145 } else if (dev_id >= 0xe724 && dev_id <= 0xe727)
0146 codec_type = VT1708B_4CH;
0147 else if ((dev_id & 0xfff) == 0x397
0148 && (dev_id >> 12) < 8)
0149 codec_type = VT1708S;
0150 else if ((dev_id & 0xfff) == 0x398
0151 && (dev_id >> 12) < 8)
0152 codec_type = VT1702;
0153 else if ((dev_id & 0xfff) == 0x428
0154 && (dev_id >> 12) < 8)
0155 codec_type = VT1718S;
0156 else if (dev_id == 0x0433 || dev_id == 0xa721)
0157 codec_type = VT1716S;
0158 else if (dev_id == 0x0441 || dev_id == 0x4441)
0159 codec_type = VT1718S;
0160 else if (dev_id == 0x0438 || dev_id == 0x4438)
0161 codec_type = VT2002P;
0162 else if (dev_id == 0x0448)
0163 codec_type = VT1812;
0164 else if (dev_id == 0x0440)
0165 codec_type = VT1708S;
0166 else if ((dev_id & 0xfff) == 0x446)
0167 codec_type = VT1802;
0168 else if (dev_id == 0x4760)
0169 codec_type = VT1705CF;
0170 else if (dev_id == 0x4761 || dev_id == 0x4762)
0171 codec_type = VT1808;
0172 else
0173 codec_type = UNKNOWN;
0174 return codec_type;
0175 };
0176
0177 static void analog_low_current_mode(struct hda_codec *codec);
0178 static bool is_aa_path_mute(struct hda_codec *codec);
0179
0180 #define hp_detect_with_aa(codec) \
0181 (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
0182 !is_aa_path_mute(codec))
0183
0184 static void vt1708_stop_hp_work(struct hda_codec *codec)
0185 {
0186 struct via_spec *spec = codec->spec;
0187 if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
0188 return;
0189 if (spec->hp_work_active) {
0190 snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
0191 codec->jackpoll_interval = 0;
0192 cancel_delayed_work_sync(&codec->jackpoll_work);
0193 spec->hp_work_active = false;
0194 }
0195 }
0196
0197 static void vt1708_update_hp_work(struct hda_codec *codec)
0198 {
0199 struct via_spec *spec = codec->spec;
0200 if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
0201 return;
0202 if (spec->vt1708_jack_detect) {
0203 if (!spec->hp_work_active) {
0204 codec->jackpoll_interval = msecs_to_jiffies(100);
0205 snd_hda_codec_write(codec, 0x1, 0, 0xf81, 0);
0206 schedule_delayed_work(&codec->jackpoll_work, 0);
0207 spec->hp_work_active = true;
0208 }
0209 } else if (!hp_detect_with_aa(codec))
0210 vt1708_stop_hp_work(codec);
0211 }
0212
0213 static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
0214 struct snd_ctl_elem_info *uinfo)
0215 {
0216 return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
0217 }
0218
0219 static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
0220 struct snd_ctl_elem_value *ucontrol)
0221 {
0222 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0223 struct via_spec *spec = codec->spec;
0224
0225 ucontrol->value.enumerated.item[0] = spec->gen.power_down_unused;
0226 return 0;
0227 }
0228
0229 static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
0230 struct snd_ctl_elem_value *ucontrol)
0231 {
0232 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0233 struct via_spec *spec = codec->spec;
0234 bool val = !!ucontrol->value.enumerated.item[0];
0235
0236 if (val == spec->gen.power_down_unused)
0237 return 0;
0238
0239 spec->gen.power_down_unused = val;
0240 analog_low_current_mode(codec);
0241 return 1;
0242 }
0243
0244 static const struct snd_kcontrol_new via_pin_power_ctl_enum = {
0245 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0246 .name = "Dynamic Power-Control",
0247 .info = via_pin_power_ctl_info,
0248 .get = via_pin_power_ctl_get,
0249 .put = via_pin_power_ctl_put,
0250 };
0251
0252 #ifdef CONFIG_SND_HDA_INPUT_BEEP
0253
0254 static const struct snd_kcontrol_new via_beep_mixer[] = {
0255 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
0256 HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
0257 };
0258
0259 static int set_beep_amp(struct via_spec *spec, hda_nid_t nid,
0260 int idx, int dir)
0261 {
0262 struct snd_kcontrol_new *knew;
0263 unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
0264 int i;
0265
0266 spec->gen.beep_nid = nid;
0267 for (i = 0; i < ARRAY_SIZE(via_beep_mixer); i++) {
0268 knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
0269 &via_beep_mixer[i]);
0270 if (!knew)
0271 return -ENOMEM;
0272 knew->private_value = beep_amp;
0273 }
0274 return 0;
0275 }
0276
0277 static int auto_parse_beep(struct hda_codec *codec)
0278 {
0279 struct via_spec *spec = codec->spec;
0280 hda_nid_t nid;
0281
0282 for_each_hda_codec_node(nid, codec)
0283 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP)
0284 return set_beep_amp(spec, nid, 0, HDA_OUTPUT);
0285 return 0;
0286 }
0287 #else
0288 #define auto_parse_beep(codec) 0
0289 #endif
0290
0291
0292 static bool is_aa_path_mute(struct hda_codec *codec)
0293 {
0294 struct via_spec *spec = codec->spec;
0295 const struct hda_amp_list *p;
0296 int ch, v;
0297
0298 p = spec->gen.loopback.amplist;
0299 if (!p)
0300 return true;
0301 for (; p->nid; p++) {
0302 for (ch = 0; ch < 2; ch++) {
0303 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
0304 p->idx);
0305 if (!(v & HDA_AMP_MUTE) && v > 0)
0306 return false;
0307 }
0308 }
0309 return true;
0310 }
0311
0312
0313 static void __analog_low_current_mode(struct hda_codec *codec, bool force)
0314 {
0315 struct via_spec *spec = codec->spec;
0316 bool enable;
0317 unsigned int verb, parm;
0318
0319 if (!codec->power_save_node)
0320 enable = false;
0321 else
0322 enable = is_aa_path_mute(codec) && !spec->gen.active_streams;
0323 if (enable == spec->alc_mode && !force)
0324 return;
0325 spec->alc_mode = enable;
0326
0327
0328 switch (spec->codec_type) {
0329 case VT1708B_8CH:
0330 case VT1708B_4CH:
0331 verb = 0xf70;
0332 parm = enable ? 0x02 : 0x00;
0333 break;
0334 case VT1708S:
0335 case VT1718S:
0336 case VT1716S:
0337 verb = 0xf73;
0338 parm = enable ? 0x51 : 0xe1;
0339 break;
0340 case VT1702:
0341 verb = 0xf73;
0342 parm = enable ? 0x01 : 0x1d;
0343 break;
0344 case VT2002P:
0345 case VT1812:
0346 case VT1802:
0347 verb = 0xf93;
0348 parm = enable ? 0x00 : 0xe0;
0349 break;
0350 case VT1705CF:
0351 case VT1808:
0352 verb = 0xf82;
0353 parm = enable ? 0x00 : 0xe0;
0354 break;
0355 default:
0356 return;
0357 }
0358
0359 snd_hda_codec_write(codec, codec->core.afg, 0, verb, parm);
0360 }
0361
0362 static void analog_low_current_mode(struct hda_codec *codec)
0363 {
0364 return __analog_low_current_mode(codec, false);
0365 }
0366
0367 static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
0368 struct hda_codec *codec,
0369 struct snd_pcm_substream *substream,
0370 int action)
0371 {
0372 analog_low_current_mode(codec);
0373 vt1708_update_hp_work(codec);
0374 }
0375
0376 static void via_free(struct hda_codec *codec)
0377 {
0378 vt1708_stop_hp_work(codec);
0379 snd_hda_gen_free(codec);
0380 }
0381
0382 #ifdef CONFIG_PM
0383 static int via_suspend(struct hda_codec *codec)
0384 {
0385 struct via_spec *spec = codec->spec;
0386 vt1708_stop_hp_work(codec);
0387
0388
0389 if (spec->codec_type == VT1802)
0390 snd_hda_shutup_pins(codec);
0391
0392 return 0;
0393 }
0394
0395 static int via_resume(struct hda_codec *codec)
0396 {
0397
0398 msleep(10);
0399 codec->patch_ops.init(codec);
0400 snd_hda_regmap_sync(codec);
0401 return 0;
0402 }
0403 #endif
0404
0405 #ifdef CONFIG_PM
0406 static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
0407 {
0408 struct via_spec *spec = codec->spec;
0409 analog_low_current_mode(codec);
0410 vt1708_update_hp_work(codec);
0411 return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
0412 }
0413 #endif
0414
0415
0416
0417
0418 static int via_init(struct hda_codec *codec);
0419
0420 static const struct hda_codec_ops via_patch_ops = {
0421 .build_controls = snd_hda_gen_build_controls,
0422 .build_pcms = snd_hda_gen_build_pcms,
0423 .init = via_init,
0424 .free = via_free,
0425 .unsol_event = snd_hda_jack_unsol_event,
0426 #ifdef CONFIG_PM
0427 .suspend = via_suspend,
0428 .resume = via_resume,
0429 .check_power_status = via_check_power_status,
0430 #endif
0431 };
0432
0433
0434 static const struct hda_verb vt1708_init_verbs[] = {
0435
0436 {0x1, 0xf81, 0x1},
0437 { }
0438 };
0439 static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
0440 {
0441 unsigned int def_conf;
0442 unsigned char seqassoc;
0443
0444 def_conf = snd_hda_codec_get_pincfg(codec, nid);
0445 seqassoc = (unsigned char) get_defcfg_association(def_conf);
0446 seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
0447 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
0448 && (seqassoc == 0xf0 || seqassoc == 0xff)) {
0449 def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
0450 snd_hda_codec_set_pincfg(codec, nid, def_conf);
0451 }
0452 }
0453
0454 static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
0455 struct snd_ctl_elem_value *ucontrol)
0456 {
0457 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0458 struct via_spec *spec = codec->spec;
0459
0460 if (spec->codec_type != VT1708)
0461 return 0;
0462 ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
0463 return 0;
0464 }
0465
0466 static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
0467 struct snd_ctl_elem_value *ucontrol)
0468 {
0469 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0470 struct via_spec *spec = codec->spec;
0471 int val;
0472
0473 if (spec->codec_type != VT1708)
0474 return 0;
0475 val = !!ucontrol->value.integer.value[0];
0476 if (spec->vt1708_jack_detect == val)
0477 return 0;
0478 spec->vt1708_jack_detect = val;
0479 vt1708_update_hp_work(codec);
0480 return 1;
0481 }
0482
0483 static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
0484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0485 .name = "Jack Detect",
0486 .count = 1,
0487 .info = snd_ctl_boolean_mono_info,
0488 .get = vt1708_jack_detect_get,
0489 .put = vt1708_jack_detect_put,
0490 };
0491
0492 static const struct badness_table via_main_out_badness = {
0493 .no_primary_dac = 0x10000,
0494 .no_dac = 0x4000,
0495 .shared_primary = 0x10000,
0496 .shared_surr = 0x20,
0497 .shared_clfe = 0x20,
0498 .shared_surr_main = 0x20,
0499 };
0500 static const struct badness_table via_extra_out_badness = {
0501 .no_primary_dac = 0x4000,
0502 .no_dac = 0x4000,
0503 .shared_primary = 0x12,
0504 .shared_surr = 0x20,
0505 .shared_clfe = 0x20,
0506 .shared_surr_main = 0x10,
0507 };
0508
0509 static int via_parse_auto_config(struct hda_codec *codec)
0510 {
0511 struct via_spec *spec = codec->spec;
0512 int err;
0513
0514 spec->gen.main_out_badness = &via_main_out_badness;
0515 spec->gen.extra_out_badness = &via_extra_out_badness;
0516
0517 err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
0518 if (err < 0)
0519 return err;
0520
0521 err = auto_parse_beep(codec);
0522 if (err < 0)
0523 return err;
0524
0525 err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
0526 if (err < 0)
0527 return err;
0528
0529 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &via_pin_power_ctl_enum))
0530 return -ENOMEM;
0531
0532
0533 codec->power_save_node = 0;
0534 spec->gen.power_down_unused = 0;
0535 return 0;
0536 }
0537
0538 static int via_init(struct hda_codec *codec)
0539 {
0540
0541 __analog_low_current_mode(codec, true);
0542
0543 snd_hda_gen_init(codec);
0544
0545 vt1708_update_hp_work(codec);
0546
0547 return 0;
0548 }
0549
0550 static int vt1708_build_controls(struct hda_codec *codec)
0551 {
0552
0553
0554 int err;
0555 int old_interval = codec->jackpoll_interval;
0556 codec->jackpoll_interval = msecs_to_jiffies(100);
0557 err = snd_hda_gen_build_controls(codec);
0558 codec->jackpoll_interval = old_interval;
0559 return err;
0560 }
0561
0562 static int vt1708_build_pcms(struct hda_codec *codec)
0563 {
0564 struct via_spec *spec = codec->spec;
0565 int i, err;
0566
0567 err = snd_hda_gen_build_pcms(codec);
0568 if (err < 0 || codec->core.vendor_id != 0x11061708)
0569 return err;
0570
0571
0572
0573
0574
0575 for (i = 0; i < ARRAY_SIZE(spec->gen.pcm_rec); i++) {
0576 struct hda_pcm *info = spec->gen.pcm_rec[i];
0577 if (!info)
0578 continue;
0579 if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
0580 info->pcm_type != HDA_PCM_TYPE_AUDIO)
0581 continue;
0582 info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
0583 SNDRV_PCM_FMTBIT_S16_LE;
0584 }
0585
0586 return 0;
0587 }
0588
0589 static int patch_vt1708(struct hda_codec *codec)
0590 {
0591 struct via_spec *spec;
0592 int err;
0593
0594
0595 spec = via_new_spec(codec);
0596 if (spec == NULL)
0597 return -ENOMEM;
0598
0599
0600 codec->patch_ops.build_controls = vt1708_build_controls;
0601 codec->patch_ops.build_pcms = vt1708_build_pcms;
0602 spec->gen.mixer_nid = 0x17;
0603
0604
0605 codec->jackpoll_interval = msecs_to_jiffies(100);
0606 spec->vt1708_jack_detect = 1;
0607
0608
0609
0610 spec->gen.suppress_auto_mic = 1;
0611
0612 spec->gen.auto_mute_via_amp = 1;
0613
0614
0615 vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
0616 vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
0617
0618 err = snd_hda_add_verbs(codec, vt1708_init_verbs);
0619 if (err < 0)
0620 goto error;
0621
0622
0623 err = via_parse_auto_config(codec);
0624 if (err < 0)
0625 goto error;
0626
0627
0628 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1708_jack_detect_ctl)) {
0629 err = -ENOMEM;
0630 goto error;
0631 }
0632
0633
0634 codec->jackpoll_interval = 0;
0635
0636 return 0;
0637
0638 error:
0639 via_free(codec);
0640 return err;
0641 }
0642
0643 static int patch_vt1709(struct hda_codec *codec)
0644 {
0645 struct via_spec *spec;
0646 int err;
0647
0648
0649 spec = via_new_spec(codec);
0650 if (spec == NULL)
0651 return -ENOMEM;
0652
0653 spec->gen.mixer_nid = 0x18;
0654
0655 err = via_parse_auto_config(codec);
0656 if (err < 0)
0657 goto error;
0658
0659 return 0;
0660
0661 error:
0662 via_free(codec);
0663 return err;
0664 }
0665
0666 static int patch_vt1708S(struct hda_codec *codec);
0667 static int patch_vt1708B(struct hda_codec *codec)
0668 {
0669 struct via_spec *spec;
0670 int err;
0671
0672 if (get_codec_type(codec) == VT1708BCE)
0673 return patch_vt1708S(codec);
0674
0675
0676 spec = via_new_spec(codec);
0677 if (spec == NULL)
0678 return -ENOMEM;
0679
0680 spec->gen.mixer_nid = 0x16;
0681
0682
0683 err = via_parse_auto_config(codec);
0684 if (err < 0)
0685 goto error;
0686
0687 return 0;
0688
0689 error:
0690 via_free(codec);
0691 return err;
0692 }
0693
0694
0695 static const struct hda_verb vt1708S_init_verbs[] = {
0696
0697 {0x1, 0xf98, 0x1},
0698
0699 {0x1, 0xf88, 0xc0},
0700 { }
0701 };
0702
0703 static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
0704 int offset, int num_steps, int step_size)
0705 {
0706 snd_hda_override_wcaps(codec, pin,
0707 get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
0708 snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
0709 (offset << AC_AMPCAP_OFFSET_SHIFT) |
0710 (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
0711 (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
0712 (0 << AC_AMPCAP_MUTE_SHIFT));
0713 }
0714
0715 static int patch_vt1708S(struct hda_codec *codec)
0716 {
0717 struct via_spec *spec;
0718 int err;
0719
0720
0721 spec = via_new_spec(codec);
0722 if (spec == NULL)
0723 return -ENOMEM;
0724
0725 spec->gen.mixer_nid = 0x16;
0726 override_mic_boost(codec, 0x1a, 0, 3, 40);
0727 override_mic_boost(codec, 0x1e, 0, 3, 40);
0728
0729
0730 if (get_codec_type(codec) == VT1708BCE)
0731 snd_hda_codec_set_name(codec, "VT1708BCE");
0732
0733 if (codec->core.vendor_id == 0x11064397)
0734 snd_hda_codec_set_name(codec, "VT1705");
0735
0736 err = snd_hda_add_verbs(codec, vt1708S_init_verbs);
0737 if (err < 0)
0738 goto error;
0739
0740
0741 err = via_parse_auto_config(codec);
0742 if (err < 0)
0743 goto error;
0744
0745 return 0;
0746
0747 error:
0748 via_free(codec);
0749 return err;
0750 }
0751
0752
0753
0754 static const struct hda_verb vt1702_init_verbs[] = {
0755
0756 {0x1, 0xF88, 0x3},
0757
0758 {0x1, 0xF82, 0x3F},
0759 { }
0760 };
0761
0762 static int patch_vt1702(struct hda_codec *codec)
0763 {
0764 struct via_spec *spec;
0765 int err;
0766
0767
0768 spec = via_new_spec(codec);
0769 if (spec == NULL)
0770 return -ENOMEM;
0771
0772 spec->gen.mixer_nid = 0x1a;
0773
0774
0775 snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
0776 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
0777 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
0778 (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
0779 (1 << AC_AMPCAP_MUTE_SHIFT));
0780
0781 err = snd_hda_add_verbs(codec, vt1702_init_verbs);
0782 if (err < 0)
0783 goto error;
0784
0785
0786 err = via_parse_auto_config(codec);
0787 if (err < 0)
0788 goto error;
0789
0790 return 0;
0791
0792 error:
0793 via_free(codec);
0794 return err;
0795 }
0796
0797
0798
0799 static const struct hda_verb vt1718S_init_verbs[] = {
0800
0801 {0x1, 0xfb2, 0x10},
0802
0803 {0x1, 0xf88, 0x8},
0804
0805 { }
0806 };
0807
0808
0809
0810
0811 static int add_secret_dac_path(struct hda_codec *codec)
0812 {
0813 struct via_spec *spec = codec->spec;
0814 int i, nums;
0815 hda_nid_t conn[8];
0816 hda_nid_t nid;
0817
0818 if (!spec->gen.mixer_nid)
0819 return 0;
0820 nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
0821 ARRAY_SIZE(conn) - 1);
0822 for (i = 0; i < nums; i++) {
0823 if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
0824 return 0;
0825 }
0826
0827
0828 for_each_hda_codec_node(nid, codec) {
0829 unsigned int caps = get_wcaps(codec, nid);
0830 if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
0831 !(caps & AC_WCAP_DIGITAL)) {
0832 conn[nums++] = nid;
0833 return snd_hda_override_conn_list(codec,
0834 spec->gen.mixer_nid,
0835 nums, conn);
0836 }
0837 }
0838 return 0;
0839 }
0840
0841
0842 static int patch_vt1718S(struct hda_codec *codec)
0843 {
0844 struct via_spec *spec;
0845 int err;
0846
0847
0848 spec = via_new_spec(codec);
0849 if (spec == NULL)
0850 return -ENOMEM;
0851
0852 spec->gen.mixer_nid = 0x21;
0853 override_mic_boost(codec, 0x2b, 0, 3, 40);
0854 override_mic_boost(codec, 0x29, 0, 3, 40);
0855 add_secret_dac_path(codec);
0856
0857 err = snd_hda_add_verbs(codec, vt1718S_init_verbs);
0858 if (err < 0)
0859 goto error;
0860
0861
0862 err = via_parse_auto_config(codec);
0863 if (err < 0)
0864 goto error;
0865
0866 return 0;
0867
0868 error:
0869 via_free(codec);
0870 return err;
0871 }
0872
0873
0874
0875 static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
0876 struct snd_ctl_elem_info *uinfo)
0877 {
0878 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0879 uinfo->count = 1;
0880 uinfo->value.integer.min = 0;
0881 uinfo->value.integer.max = 1;
0882 return 0;
0883 }
0884
0885 static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
0886 struct snd_ctl_elem_value *ucontrol)
0887 {
0888 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0889 int index = 0;
0890
0891 index = snd_hda_codec_read(codec, 0x26, 0,
0892 AC_VERB_GET_CONNECT_SEL, 0);
0893 if (index != -1)
0894 *ucontrol->value.integer.value = index;
0895
0896 return 0;
0897 }
0898
0899 static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
0900 struct snd_ctl_elem_value *ucontrol)
0901 {
0902 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
0903 struct via_spec *spec = codec->spec;
0904 int index = *ucontrol->value.integer.value;
0905
0906 snd_hda_codec_write(codec, 0x26, 0,
0907 AC_VERB_SET_CONNECT_SEL, index);
0908 spec->dmic_enabled = index;
0909 return 1;
0910 }
0911
0912 static const struct snd_kcontrol_new vt1716s_dmic_mixer_vol =
0913 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT);
0914 static const struct snd_kcontrol_new vt1716s_dmic_mixer_sw = {
0915 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0916 .name = "Digital Mic Capture Switch",
0917 .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
0918 .count = 1,
0919 .info = vt1716s_dmic_info,
0920 .get = vt1716s_dmic_get,
0921 .put = vt1716s_dmic_put,
0922 };
0923
0924
0925
0926 static const struct snd_kcontrol_new vt1716S_mono_out_mixer =
0927 HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT);
0928
0929 static const struct hda_verb vt1716S_init_verbs[] = {
0930
0931 {0x1, 0xf8a, 0x80},
0932
0933 {0x1, 0xf88, 0xc0},
0934
0935 {0x1, 0xf90, 0x08},
0936 { }
0937 };
0938
0939 static int patch_vt1716S(struct hda_codec *codec)
0940 {
0941 struct via_spec *spec;
0942 int err;
0943
0944
0945 spec = via_new_spec(codec);
0946 if (spec == NULL)
0947 return -ENOMEM;
0948
0949 spec->gen.mixer_nid = 0x16;
0950 override_mic_boost(codec, 0x1a, 0, 3, 40);
0951 override_mic_boost(codec, 0x1e, 0, 3, 40);
0952
0953 err = snd_hda_add_verbs(codec, vt1716S_init_verbs);
0954 if (err < 0)
0955 goto error;
0956
0957
0958 err = via_parse_auto_config(codec);
0959 if (err < 0)
0960 goto error;
0961
0962 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) ||
0963 !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) ||
0964 !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) {
0965 err = -ENOMEM;
0966 goto error;
0967 }
0968
0969 return 0;
0970
0971 error:
0972 via_free(codec);
0973 return err;
0974 }
0975
0976
0977
0978 static const struct hda_verb vt2002P_init_verbs[] = {
0979
0980 {0x1, 0xfe0, 0x4},
0981 {0x1, 0xfe9, 0x80},
0982 {0x1, 0xfe2, 0x22},
0983
0984 {0x1, 0xfb9, 0x24},
0985
0986 {0x1, 0xfb8, 0x88},
0987 { }
0988 };
0989
0990 static const struct hda_verb vt1802_init_verbs[] = {
0991
0992 {0x1, 0xfb9, 0x24},
0993
0994 {0x1, 0xfb8, 0x88},
0995 { }
0996 };
0997
0998
0999
1000
1001 enum {
1002 VIA_FIXUP_INTMIC_BOOST,
1003 VIA_FIXUP_ASUS_G75,
1004 VIA_FIXUP_POWER_SAVE,
1005 };
1006
1007 static void via_fixup_intmic_boost(struct hda_codec *codec,
1008 const struct hda_fixup *fix, int action)
1009 {
1010 if (action == HDA_FIXUP_ACT_PRE_PROBE)
1011 override_mic_boost(codec, 0x30, 0, 2, 40);
1012 }
1013
1014 static void via_fixup_power_save(struct hda_codec *codec,
1015 const struct hda_fixup *fix, int action)
1016 {
1017 if (action == HDA_FIXUP_ACT_PRE_PROBE)
1018 codec->power_save_node = 0;
1019 }
1020
1021 static const struct hda_fixup via_fixups[] = {
1022 [VIA_FIXUP_INTMIC_BOOST] = {
1023 .type = HDA_FIXUP_FUNC,
1024 .v.func = via_fixup_intmic_boost,
1025 },
1026 [VIA_FIXUP_ASUS_G75] = {
1027 .type = HDA_FIXUP_PINS,
1028 .v.pins = (const struct hda_pintbl[]) {
1029
1030 { 0x24, 0x991301f0 },
1031 { 0x33, 0x991301f1 },
1032 { }
1033 }
1034 },
1035 [VIA_FIXUP_POWER_SAVE] = {
1036 .type = HDA_FIXUP_FUNC,
1037 .v.func = via_fixup_power_save,
1038 },
1039 };
1040
1041 static const struct snd_pci_quirk vt2002p_fixups[] = {
1042 SND_PCI_QUIRK(0x1043, 0x13f7, "Asus B23E", VIA_FIXUP_POWER_SAVE),
1043 SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
1044 SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
1045 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", VIA_FIXUP_POWER_SAVE),
1046 {}
1047 };
1048
1049
1050
1051
1052 static void fix_vt1802_connections(struct hda_codec *codec)
1053 {
1054 static const hda_nid_t conn_24[] = { 0x14, 0x1c };
1055 static const hda_nid_t conn_33[] = { 0x1c };
1056
1057 snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
1058 snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
1059 }
1060
1061
1062 static int patch_vt2002P(struct hda_codec *codec)
1063 {
1064 struct via_spec *spec;
1065 int err;
1066
1067
1068 spec = via_new_spec(codec);
1069 if (spec == NULL)
1070 return -ENOMEM;
1071
1072 spec->gen.mixer_nid = 0x21;
1073 override_mic_boost(codec, 0x2b, 0, 3, 40);
1074 override_mic_boost(codec, 0x29, 0, 3, 40);
1075 if (spec->codec_type == VT1802)
1076 fix_vt1802_connections(codec);
1077 add_secret_dac_path(codec);
1078
1079 snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
1080 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1081
1082 if (spec->codec_type == VT1802)
1083 err = snd_hda_add_verbs(codec, vt1802_init_verbs);
1084 else
1085 err = snd_hda_add_verbs(codec, vt2002P_init_verbs);
1086 if (err < 0)
1087 goto error;
1088
1089
1090 err = via_parse_auto_config(codec);
1091 if (err < 0)
1092 goto error;
1093
1094 return 0;
1095
1096 error:
1097 via_free(codec);
1098 return err;
1099 }
1100
1101
1102
1103 static const struct hda_verb vt1812_init_verbs[] = {
1104
1105 {0x1, 0xfb9, 0x24},
1106
1107 {0x1, 0xfb8, 0xa8},
1108 { }
1109 };
1110
1111
1112 static int patch_vt1812(struct hda_codec *codec)
1113 {
1114 struct via_spec *spec;
1115 int err;
1116
1117
1118 spec = via_new_spec(codec);
1119 if (spec == NULL)
1120 return -ENOMEM;
1121
1122 spec->gen.mixer_nid = 0x21;
1123 override_mic_boost(codec, 0x2b, 0, 3, 40);
1124 override_mic_boost(codec, 0x29, 0, 3, 40);
1125 add_secret_dac_path(codec);
1126
1127 err = snd_hda_add_verbs(codec, vt1812_init_verbs);
1128 if (err < 0)
1129 goto error;
1130
1131
1132 err = via_parse_auto_config(codec);
1133 if (err < 0)
1134 goto error;
1135
1136 return 0;
1137
1138 error:
1139 via_free(codec);
1140 return err;
1141 }
1142
1143
1144
1145 static const struct hda_verb vt3476_init_verbs[] = {
1146
1147 {0x1, 0xF7B, 0x30},
1148
1149 {0x1, 0xFB9, 0x20},
1150
1151 {0x1, 0xFB8, 0x10},
1152 { }
1153 };
1154
1155 static int patch_vt3476(struct hda_codec *codec)
1156 {
1157 struct via_spec *spec;
1158 int err;
1159
1160
1161 spec = via_new_spec(codec);
1162 if (spec == NULL)
1163 return -ENOMEM;
1164
1165 spec->gen.mixer_nid = 0x3f;
1166 add_secret_dac_path(codec);
1167
1168 err = snd_hda_add_verbs(codec, vt3476_init_verbs);
1169 if (err < 0)
1170 goto error;
1171
1172
1173 err = via_parse_auto_config(codec);
1174 if (err < 0)
1175 goto error;
1176
1177 return 0;
1178
1179 error:
1180 via_free(codec);
1181 return err;
1182 }
1183
1184
1185
1186
1187 static const struct hda_device_id snd_hda_id_via[] = {
1188 HDA_CODEC_ENTRY(0x11061708, "VT1708", patch_vt1708),
1189 HDA_CODEC_ENTRY(0x11061709, "VT1708", patch_vt1708),
1190 HDA_CODEC_ENTRY(0x1106170a, "VT1708", patch_vt1708),
1191 HDA_CODEC_ENTRY(0x1106170b, "VT1708", patch_vt1708),
1192 HDA_CODEC_ENTRY(0x1106e710, "VT1709 10-Ch", patch_vt1709),
1193 HDA_CODEC_ENTRY(0x1106e711, "VT1709 10-Ch", patch_vt1709),
1194 HDA_CODEC_ENTRY(0x1106e712, "VT1709 10-Ch", patch_vt1709),
1195 HDA_CODEC_ENTRY(0x1106e713, "VT1709 10-Ch", patch_vt1709),
1196 HDA_CODEC_ENTRY(0x1106e714, "VT1709 6-Ch", patch_vt1709),
1197 HDA_CODEC_ENTRY(0x1106e715, "VT1709 6-Ch", patch_vt1709),
1198 HDA_CODEC_ENTRY(0x1106e716, "VT1709 6-Ch", patch_vt1709),
1199 HDA_CODEC_ENTRY(0x1106e717, "VT1709 6-Ch", patch_vt1709),
1200 HDA_CODEC_ENTRY(0x1106e720, "VT1708B 8-Ch", patch_vt1708B),
1201 HDA_CODEC_ENTRY(0x1106e721, "VT1708B 8-Ch", patch_vt1708B),
1202 HDA_CODEC_ENTRY(0x1106e722, "VT1708B 8-Ch", patch_vt1708B),
1203 HDA_CODEC_ENTRY(0x1106e723, "VT1708B 8-Ch", patch_vt1708B),
1204 HDA_CODEC_ENTRY(0x1106e724, "VT1708B 4-Ch", patch_vt1708B),
1205 HDA_CODEC_ENTRY(0x1106e725, "VT1708B 4-Ch", patch_vt1708B),
1206 HDA_CODEC_ENTRY(0x1106e726, "VT1708B 4-Ch", patch_vt1708B),
1207 HDA_CODEC_ENTRY(0x1106e727, "VT1708B 4-Ch", patch_vt1708B),
1208 HDA_CODEC_ENTRY(0x11060397, "VT1708S", patch_vt1708S),
1209 HDA_CODEC_ENTRY(0x11061397, "VT1708S", patch_vt1708S),
1210 HDA_CODEC_ENTRY(0x11062397, "VT1708S", patch_vt1708S),
1211 HDA_CODEC_ENTRY(0x11063397, "VT1708S", patch_vt1708S),
1212 HDA_CODEC_ENTRY(0x11064397, "VT1705", patch_vt1708S),
1213 HDA_CODEC_ENTRY(0x11065397, "VT1708S", patch_vt1708S),
1214 HDA_CODEC_ENTRY(0x11066397, "VT1708S", patch_vt1708S),
1215 HDA_CODEC_ENTRY(0x11067397, "VT1708S", patch_vt1708S),
1216 HDA_CODEC_ENTRY(0x11060398, "VT1702", patch_vt1702),
1217 HDA_CODEC_ENTRY(0x11061398, "VT1702", patch_vt1702),
1218 HDA_CODEC_ENTRY(0x11062398, "VT1702", patch_vt1702),
1219 HDA_CODEC_ENTRY(0x11063398, "VT1702", patch_vt1702),
1220 HDA_CODEC_ENTRY(0x11064398, "VT1702", patch_vt1702),
1221 HDA_CODEC_ENTRY(0x11065398, "VT1702", patch_vt1702),
1222 HDA_CODEC_ENTRY(0x11066398, "VT1702", patch_vt1702),
1223 HDA_CODEC_ENTRY(0x11067398, "VT1702", patch_vt1702),
1224 HDA_CODEC_ENTRY(0x11060428, "VT1718S", patch_vt1718S),
1225 HDA_CODEC_ENTRY(0x11064428, "VT1718S", patch_vt1718S),
1226 HDA_CODEC_ENTRY(0x11060441, "VT2020", patch_vt1718S),
1227 HDA_CODEC_ENTRY(0x11064441, "VT1828S", patch_vt1718S),
1228 HDA_CODEC_ENTRY(0x11060433, "VT1716S", patch_vt1716S),
1229 HDA_CODEC_ENTRY(0x1106a721, "VT1716S", patch_vt1716S),
1230 HDA_CODEC_ENTRY(0x11060438, "VT2002P", patch_vt2002P),
1231 HDA_CODEC_ENTRY(0x11064438, "VT2002P", patch_vt2002P),
1232 HDA_CODEC_ENTRY(0x11060448, "VT1812", patch_vt1812),
1233 HDA_CODEC_ENTRY(0x11060440, "VT1818S", patch_vt1708S),
1234 HDA_CODEC_ENTRY(0x11060446, "VT1802", patch_vt2002P),
1235 HDA_CODEC_ENTRY(0x11068446, "VT1802", patch_vt2002P),
1236 HDA_CODEC_ENTRY(0x11064760, "VT1705CF", patch_vt3476),
1237 HDA_CODEC_ENTRY(0x11064761, "VT1708SCE", patch_vt3476),
1238 HDA_CODEC_ENTRY(0x11064762, "VT1808", patch_vt3476),
1239 {}
1240 };
1241 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_via);
1242
1243 static struct hda_codec_driver via_driver = {
1244 .id = snd_hda_id_via,
1245 };
1246
1247 MODULE_LICENSE("GPL");
1248 MODULE_DESCRIPTION("VIA HD-audio codec");
1249
1250 module_hda_codec_driver(via_driver);