^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Universal Interface for Intel High Definition Audio Codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * HD audio interface patch for VIA VT17xx/VT18xx/VT20xx codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (C) 2006-2009 VIA Technology, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * (C) 2006-2008 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) /* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /* 2006-03-03 Lydia Wang Create the basic patch to support VT1708 codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /* 2006-08-02 Lydia Wang Add support to VT1709 codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* 2007-09-17 Lydia Wang Add VT1708B codec support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* 2007-11-14 Lydia Wang Add VT1708A codec HP and CD pin connect config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* 2008-02-03 Lydia Wang Fix Rear channels and Back channels inverse issue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* 2008-04-09 Lydia Wang Add Independent HP feature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* 2008-09-15 Logan Li Add VT1708S Mic Boost workaround/backdoor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* 2009-02-16 Logan Li Add support for VT1718S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* 2009-03-13 Logan Li Add support for VT1716S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* 2009-04-14 Lydai Wang Add support for VT1828S and VT2020 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* 2009-07-08 Lydia Wang Add support for VT2002P */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* 2009-07-21 Lydia Wang Add support for VT1812 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* 2009-09-19 Lydia Wang Add support for VT1818S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <sound/hda_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include "hda_local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include "hda_auto_parser.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include "hda_jack.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include "hda_generic.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* Pin Widget NID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define VT1708_HP_PIN_NID 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define VT1708_CD_PIN_NID 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) enum VIA_HDA_CODEC {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) UNKNOWN = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) VT1708,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) VT1709_10CH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) VT1709_6CH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) VT1708B_8CH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) VT1708B_4CH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) VT1708S,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) VT1708BCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) VT1702,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) VT1718S,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) VT1716S,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) VT2002P,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) VT1812,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) VT1802,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) VT1705CF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) VT1808,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) CODEC_TYPES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define VT2002P_COMPATIBLE(spec) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ((spec)->codec_type == VT2002P ||\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) (spec)->codec_type == VT1812 ||\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) (spec)->codec_type == VT1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct via_spec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct hda_gen_spec gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* HP mode source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int dmic_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) enum VIA_HDA_CODEC codec_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* analog low-power control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) bool alc_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* work to check hp jack state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int hp_work_active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int vt1708_jack_detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct hda_codec *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int action);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static const struct hda_codec_ops via_patch_ops; /* defined below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static struct via_spec *via_new_spec(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) spec = kzalloc(sizeof(*spec), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) codec->spec = spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) snd_hda_gen_spec_init(&spec->gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) spec->codec_type = get_codec_type(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* VT1708BCE & VT1708S are almost same */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (spec->codec_type == VT1708BCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) spec->codec_type = VT1708S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) spec->gen.indep_hp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) spec->gen.keep_eapd_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) spec->gen.dac_min_mute = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) spec->gen.pcm_playback_hook = via_playback_pcm_hook;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) codec->power_save_node = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) spec->gen.power_down_unused = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) codec->patch_ops = via_patch_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u32 vendor_id = codec->core.vendor_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u16 ven_id = vendor_id >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u16 dev_id = vendor_id & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) enum VIA_HDA_CODEC codec_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* get codec type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (ven_id != 0x1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) codec_type = UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) else if (dev_id >= 0x1708 && dev_id <= 0x170b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) codec_type = VT1708;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) else if (dev_id >= 0xe710 && dev_id <= 0xe713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) codec_type = VT1709_10CH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) else if (dev_id >= 0xe714 && dev_id <= 0xe717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) codec_type = VT1709_6CH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) else if (dev_id >= 0xe720 && dev_id <= 0xe723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) codec_type = VT1708B_8CH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (snd_hda_param_read(codec, 0x16, AC_PAR_CONNLIST_LEN) == 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) codec_type = VT1708BCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) } else if (dev_id >= 0xe724 && dev_id <= 0xe727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) codec_type = VT1708B_4CH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else if ((dev_id & 0xfff) == 0x397
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) && (dev_id >> 12) < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) codec_type = VT1708S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) else if ((dev_id & 0xfff) == 0x398
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) && (dev_id >> 12) < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) codec_type = VT1702;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) else if ((dev_id & 0xfff) == 0x428
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) && (dev_id >> 12) < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) codec_type = VT1718S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) else if (dev_id == 0x0433 || dev_id == 0xa721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) codec_type = VT1716S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) else if (dev_id == 0x0441 || dev_id == 0x4441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) codec_type = VT1718S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) else if (dev_id == 0x0438 || dev_id == 0x4438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) codec_type = VT2002P;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) else if (dev_id == 0x0448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) codec_type = VT1812;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) else if (dev_id == 0x0440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) codec_type = VT1708S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) else if ((dev_id & 0xfff) == 0x446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) codec_type = VT1802;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) else if (dev_id == 0x4760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) codec_type = VT1705CF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) else if (dev_id == 0x4761 || dev_id == 0x4762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) codec_type = VT1808;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) codec_type = UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return codec_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void analog_low_current_mode(struct hda_codec *codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static bool is_aa_path_mute(struct hda_codec *codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define hp_detect_with_aa(codec) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) !is_aa_path_mute(codec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static void vt1708_stop_hp_work(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (spec->hp_work_active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) codec->jackpoll_interval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) cancel_delayed_work_sync(&codec->jackpoll_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) spec->hp_work_active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static void vt1708_update_hp_work(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (spec->vt1708_jack_detect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!spec->hp_work_active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) codec->jackpoll_interval = msecs_to_jiffies(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) snd_hda_codec_write(codec, 0x1, 0, 0xf81, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) schedule_delayed_work(&codec->jackpoll_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) spec->hp_work_active = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) } else if (!hp_detect_with_aa(codec))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) vt1708_stop_hp_work(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ucontrol->value.enumerated.item[0] = spec->gen.power_down_unused;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) bool val = !!ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (val == spec->gen.power_down_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* codec->power_save_node = val; */ /* widget PM seems yet broken */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) spec->gen.power_down_unused = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) analog_low_current_mode(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) static const struct snd_kcontrol_new via_pin_power_ctl_enum = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .name = "Dynamic Power-Control",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .info = via_pin_power_ctl_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .get = via_pin_power_ctl_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .put = via_pin_power_ctl_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) #ifdef CONFIG_SND_HDA_INPUT_BEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* additional beep mixers; the actual parameters are overwritten at build */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static const struct snd_kcontrol_new via_beep_mixer[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int set_beep_amp(struct via_spec *spec, hda_nid_t nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) int idx, int dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct snd_kcontrol_new *knew;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) spec->gen.beep_nid = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) for (i = 0; i < ARRAY_SIZE(via_beep_mixer); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) &via_beep_mixer[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (!knew)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) knew->private_value = beep_amp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int auto_parse_beep(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) hda_nid_t nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) for_each_hda_codec_node(nid, codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return set_beep_amp(spec, nid, 0, HDA_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #define auto_parse_beep(codec) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* check AA path's mute status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static bool is_aa_path_mute(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) const struct hda_amp_list *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) int ch, v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) p = spec->gen.loopback.amplist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) for (; p->nid; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) for (ch = 0; ch < 2; ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) p->idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!(v & HDA_AMP_MUTE) && v > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* enter/exit analog low-current mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static void __analog_low_current_mode(struct hda_codec *codec, bool force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) bool enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) unsigned int verb, parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (!codec->power_save_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) enable = is_aa_path_mute(codec) && !spec->gen.active_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (enable == spec->alc_mode && !force)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) spec->alc_mode = enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* decide low current mode's verb & parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) switch (spec->codec_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) case VT1708B_8CH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) case VT1708B_4CH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) verb = 0xf70;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) parm = enable ? 0x02 : 0x00; /* 0x02: 2/3x, 0x00: 1x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) case VT1708S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case VT1718S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) case VT1716S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) verb = 0xf73;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case VT1702:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) verb = 0xf73;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case VT2002P:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) case VT1812:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case VT1802:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) verb = 0xf93;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) case VT1705CF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) case VT1808:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) verb = 0xf82;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return; /* other codecs are not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* send verb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) snd_hda_codec_write(codec, codec->core.afg, 0, verb, parm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static void analog_low_current_mode(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return __analog_low_current_mode(codec, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct hda_codec *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) analog_low_current_mode(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) vt1708_update_hp_work(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static void via_free(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) vt1708_stop_hp_work(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) snd_hda_gen_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static int via_suspend(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) vt1708_stop_hp_work(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* Fix pop noise on headphones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (spec->codec_type == VT1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) snd_hda_shutup_pins(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static int via_resume(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* some delay here to make jack detection working (bko#98921) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) codec->patch_ops.init(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) snd_hda_regmap_sync(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) analog_low_current_mode(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) vt1708_update_hp_work(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static int via_init(struct hda_codec *codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static const struct hda_codec_ops via_patch_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .build_controls = snd_hda_gen_build_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .build_pcms = snd_hda_gen_build_pcms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .init = via_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .free = via_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) .unsol_event = snd_hda_jack_unsol_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .suspend = via_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) .resume = via_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .check_power_status = via_check_power_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static const struct hda_verb vt1708_init_verbs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* power down jack detect function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {0x1, 0xf81, 0x1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) unsigned int def_conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) unsigned char seqassoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) def_conf = snd_hda_codec_get_pincfg(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) seqassoc = (unsigned char) get_defcfg_association(def_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) && (seqassoc == 0xf0 || seqassoc == 0xff)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) snd_hda_codec_set_pincfg(codec, nid, def_conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (spec->codec_type != VT1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (spec->codec_type != VT1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) val = !!ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (spec->vt1708_jack_detect == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) spec->vt1708_jack_detect = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) vt1708_update_hp_work(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) .name = "Jack Detect",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) .count = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) .info = snd_ctl_boolean_mono_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) .get = vt1708_jack_detect_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) .put = vt1708_jack_detect_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static const struct badness_table via_main_out_badness = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) .no_primary_dac = 0x10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) .no_dac = 0x4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) .shared_primary = 0x10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) .shared_surr = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) .shared_clfe = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) .shared_surr_main = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static const struct badness_table via_extra_out_badness = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) .no_primary_dac = 0x4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) .no_dac = 0x4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) .shared_primary = 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) .shared_surr = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .shared_clfe = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .shared_surr_main = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static int via_parse_auto_config(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) spec->gen.main_out_badness = &via_main_out_badness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) spec->gen.extra_out_badness = &via_extra_out_badness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) err = auto_parse_beep(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &via_pin_power_ctl_enum))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* disable widget PM at start for compatibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) codec->power_save_node = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) spec->gen.power_down_unused = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static int via_init(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* init power states */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) __analog_low_current_mode(codec, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) snd_hda_gen_init(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) vt1708_update_hp_work(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static int vt1708_build_controls(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* In order not to create "Phantom Jack" controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) temporary enable jackpoll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int old_interval = codec->jackpoll_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) codec->jackpoll_interval = msecs_to_jiffies(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) err = snd_hda_gen_build_controls(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) codec->jackpoll_interval = old_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static int vt1708_build_pcms(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) err = snd_hda_gen_build_pcms(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (err < 0 || codec->core.vendor_id != 0x11061708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /* We got noisy outputs on the right channel on VT1708 when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * 24bit samples are used. Until any workaround is found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * disable the 24bit format, so far.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) for (i = 0; i < ARRAY_SIZE(spec->gen.pcm_rec); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) struct hda_pcm *info = spec->gen.pcm_rec[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) info->pcm_type != HDA_PCM_TYPE_AUDIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) SNDRV_PCM_FMTBIT_S16_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static int patch_vt1708(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* override some patch_ops */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) codec->patch_ops.build_controls = vt1708_build_controls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) codec->patch_ops.build_pcms = vt1708_build_pcms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) spec->gen.mixer_nid = 0x17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* set jackpoll_interval while parsing the codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) codec->jackpoll_interval = msecs_to_jiffies(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) spec->vt1708_jack_detect = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* don't support the input jack switching due to lack of unsol event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /* (it may work with polling, though, but it needs testing) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) spec->gen.suppress_auto_mic = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* Some machines show the broken speaker mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) spec->gen.auto_mute_via_amp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* Add HP and CD pin config connect bit re-config action */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) err = snd_hda_add_verbs(codec, vt1708_init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) /* automatic parse from the BIOS config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* add jack detect on/off control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1708_jack_detect_ctl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /* clear jackpoll_interval again; it's set dynamically */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) codec->jackpoll_interval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) static int patch_vt1709(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) spec->gen.mixer_nid = 0x18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static int patch_vt1708S(struct hda_codec *codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static int patch_vt1708B(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (get_codec_type(codec) == VT1708BCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return patch_vt1708S(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) spec->gen.mixer_nid = 0x16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /* automatic parse from the BIOS config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /* Patch for VT1708S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) static const struct hda_verb vt1708S_init_verbs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) /* Enable Mic Boost Volume backdoor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {0x1, 0xf98, 0x1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* don't bybass mixer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {0x1, 0xf88, 0xc0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int offset, int num_steps, int step_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) snd_hda_override_wcaps(codec, pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) (offset << AC_AMPCAP_OFFSET_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) (0 << AC_AMPCAP_MUTE_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static int patch_vt1708S(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) spec->gen.mixer_nid = 0x16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) override_mic_boost(codec, 0x1a, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) override_mic_boost(codec, 0x1e, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /* correct names for VT1708BCE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (get_codec_type(codec) == VT1708BCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) snd_hda_codec_set_name(codec, "VT1708BCE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* correct names for VT1705 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (codec->core.vendor_id == 0x11064397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) snd_hda_codec_set_name(codec, "VT1705");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) err = snd_hda_add_verbs(codec, vt1708S_init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* automatic parse from the BIOS config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* Patch for VT1702 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) static const struct hda_verb vt1702_init_verbs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) /* mixer enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {0x1, 0xF88, 0x3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* GPIO 0~2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {0x1, 0xF82, 0x3F},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static int patch_vt1702(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) spec->gen.mixer_nid = 0x1a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) /* limit AA path volume to 0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) (1 << AC_AMPCAP_MUTE_SHIFT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) err = snd_hda_add_verbs(codec, vt1702_init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* automatic parse from the BIOS config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) /* Patch for VT1718S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static const struct hda_verb vt1718S_init_verbs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /* Enable MW0 adjust Gain 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) {0x1, 0xfb2, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /* Enable Boost Volume backdoor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {0x1, 0xf88, 0x8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) /* Add a connection to the primary DAC from AA-mixer for some codecs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * This isn't listed from the raw info, but the chip has a secret connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) static int add_secret_dac_path(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) int i, nums;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) hda_nid_t conn[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) hda_nid_t nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) if (!spec->gen.mixer_nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ARRAY_SIZE(conn) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) for (i = 0; i < nums; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) /* find the primary DAC and add to the connection list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) for_each_hda_codec_node(nid, codec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) unsigned int caps = get_wcaps(codec, nid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) !(caps & AC_WCAP_DIGITAL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) conn[nums++] = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) return snd_hda_override_conn_list(codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) spec->gen.mixer_nid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) nums, conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) static int patch_vt1718S(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) spec->gen.mixer_nid = 0x21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) override_mic_boost(codec, 0x2b, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) override_mic_boost(codec, 0x29, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) add_secret_dac_path(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) err = snd_hda_add_verbs(codec, vt1718S_init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /* automatic parse from the BIOS config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) /* Patch for VT1716S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) uinfo->value.integer.max = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) int index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) index = snd_hda_codec_read(codec, 0x26, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) AC_VERB_GET_CONNECT_SEL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (index != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) *ucontrol->value.integer.value = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct via_spec *spec = codec->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) int index = *ucontrol->value.integer.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) snd_hda_codec_write(codec, 0x26, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) AC_VERB_SET_CONNECT_SEL, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) spec->dmic_enabled = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static const struct snd_kcontrol_new vt1716s_dmic_mixer_vol =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) static const struct snd_kcontrol_new vt1716s_dmic_mixer_sw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) .name = "Digital Mic Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .count = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .info = vt1716s_dmic_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .get = vt1716s_dmic_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .put = vt1716s_dmic_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* mono-out mixer elements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) static const struct snd_kcontrol_new vt1716S_mono_out_mixer =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static const struct hda_verb vt1716S_init_verbs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /* Enable Boost Volume backdoor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {0x1, 0xf8a, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) /* don't bybass mixer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {0x1, 0xf88, 0xc0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /* Enable mono output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) {0x1, 0xf90, 0x08},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int patch_vt1716S(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) spec->gen.mixer_nid = 0x16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) override_mic_boost(codec, 0x1a, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) override_mic_boost(codec, 0x1e, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) err = snd_hda_add_verbs(codec, vt1716S_init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /* automatic parse from the BIOS config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /* for vt2002P */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) static const struct hda_verb vt2002P_init_verbs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) /* Class-D speaker related verbs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) {0x1, 0xfe0, 0x4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) {0x1, 0xfe9, 0x80},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {0x1, 0xfe2, 0x22},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) /* Enable Boost Volume backdoor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) {0x1, 0xfb9, 0x24},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) /* Enable AOW0 to MW9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {0x1, 0xfb8, 0x88},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) static const struct hda_verb vt1802_init_verbs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /* Enable Boost Volume backdoor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) {0x1, 0xfb9, 0x24},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) /* Enable AOW0 to MW9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) {0x1, 0xfb8, 0x88},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * pin fix-up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) VIA_FIXUP_INTMIC_BOOST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) VIA_FIXUP_ASUS_G75,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) VIA_FIXUP_POWER_SAVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static void via_fixup_intmic_boost(struct hda_codec *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) const struct hda_fixup *fix, int action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if (action == HDA_FIXUP_ACT_PRE_PROBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) override_mic_boost(codec, 0x30, 0, 2, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) static void via_fixup_power_save(struct hda_codec *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) const struct hda_fixup *fix, int action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (action == HDA_FIXUP_ACT_PRE_PROBE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) codec->power_save_node = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) static const struct hda_fixup via_fixups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) [VIA_FIXUP_INTMIC_BOOST] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) .type = HDA_FIXUP_FUNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) .v.func = via_fixup_intmic_boost,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) [VIA_FIXUP_ASUS_G75] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) .type = HDA_FIXUP_PINS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) .v.pins = (const struct hda_pintbl[]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) /* set 0x24 and 0x33 as speakers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) { 0x24, 0x991301f0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) { 0x33, 0x991301f1 }, /* subwoofer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) [VIA_FIXUP_POWER_SAVE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) .type = HDA_FIXUP_FUNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) .v.func = via_fixup_power_save,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) static const struct snd_pci_quirk vt2002p_fixups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) SND_PCI_QUIRK(0x1043, 0x13f7, "Asus B23E", VIA_FIXUP_POWER_SAVE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", VIA_FIXUP_POWER_SAVE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) * Replace this with mixer NID 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) static void fix_vt1802_connections(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) static const hda_nid_t conn_24[] = { 0x14, 0x1c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) static const hda_nid_t conn_33[] = { 0x1c };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* patch for vt2002P */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static int patch_vt2002P(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) spec->gen.mixer_nid = 0x21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) override_mic_boost(codec, 0x2b, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) override_mic_boost(codec, 0x29, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (spec->codec_type == VT1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) fix_vt1802_connections(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) add_secret_dac_path(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (spec->codec_type == VT1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) err = snd_hda_add_verbs(codec, vt1802_init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) err = snd_hda_add_verbs(codec, vt2002P_init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) /* automatic parse from the BIOS config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) /* for vt1812 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) static const struct hda_verb vt1812_init_verbs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) /* Enable Boost Volume backdoor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) {0x1, 0xfb9, 0x24},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) /* Enable AOW0 to MW9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) {0x1, 0xfb8, 0xa8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) /* patch for vt1812 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) static int patch_vt1812(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) spec->gen.mixer_nid = 0x21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) override_mic_boost(codec, 0x2b, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) override_mic_boost(codec, 0x29, 0, 3, 40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) add_secret_dac_path(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) err = snd_hda_add_verbs(codec, vt1812_init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /* automatic parse from the BIOS config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) /* patch for vt3476 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) static const struct hda_verb vt3476_init_verbs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /* Enable DMic 8/16/32K */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) {0x1, 0xF7B, 0x30},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /* Enable Boost Volume backdoor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) {0x1, 0xFB9, 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /* Enable AOW-MW9 path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) {0x1, 0xFB8, 0x10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) static int patch_vt3476(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) struct via_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) /* create a codec specific record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) spec = via_new_spec(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (spec == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) spec->gen.mixer_nid = 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) add_secret_dac_path(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) err = snd_hda_add_verbs(codec, vt3476_init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) /* automatic parse from the BIOS config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) err = via_parse_auto_config(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) via_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * patch entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static const struct hda_device_id snd_hda_id_via[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) HDA_CODEC_ENTRY(0x11061708, "VT1708", patch_vt1708),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) HDA_CODEC_ENTRY(0x11061709, "VT1708", patch_vt1708),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) HDA_CODEC_ENTRY(0x1106170a, "VT1708", patch_vt1708),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) HDA_CODEC_ENTRY(0x1106170b, "VT1708", patch_vt1708),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) HDA_CODEC_ENTRY(0x1106e710, "VT1709 10-Ch", patch_vt1709),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) HDA_CODEC_ENTRY(0x1106e711, "VT1709 10-Ch", patch_vt1709),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) HDA_CODEC_ENTRY(0x1106e712, "VT1709 10-Ch", patch_vt1709),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) HDA_CODEC_ENTRY(0x1106e713, "VT1709 10-Ch", patch_vt1709),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) HDA_CODEC_ENTRY(0x1106e714, "VT1709 6-Ch", patch_vt1709),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) HDA_CODEC_ENTRY(0x1106e715, "VT1709 6-Ch", patch_vt1709),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) HDA_CODEC_ENTRY(0x1106e716, "VT1709 6-Ch", patch_vt1709),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) HDA_CODEC_ENTRY(0x1106e717, "VT1709 6-Ch", patch_vt1709),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) HDA_CODEC_ENTRY(0x1106e720, "VT1708B 8-Ch", patch_vt1708B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) HDA_CODEC_ENTRY(0x1106e721, "VT1708B 8-Ch", patch_vt1708B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) HDA_CODEC_ENTRY(0x1106e722, "VT1708B 8-Ch", patch_vt1708B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) HDA_CODEC_ENTRY(0x1106e723, "VT1708B 8-Ch", patch_vt1708B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) HDA_CODEC_ENTRY(0x1106e724, "VT1708B 4-Ch", patch_vt1708B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) HDA_CODEC_ENTRY(0x1106e725, "VT1708B 4-Ch", patch_vt1708B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) HDA_CODEC_ENTRY(0x1106e726, "VT1708B 4-Ch", patch_vt1708B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) HDA_CODEC_ENTRY(0x1106e727, "VT1708B 4-Ch", patch_vt1708B),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) HDA_CODEC_ENTRY(0x11060397, "VT1708S", patch_vt1708S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) HDA_CODEC_ENTRY(0x11061397, "VT1708S", patch_vt1708S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) HDA_CODEC_ENTRY(0x11062397, "VT1708S", patch_vt1708S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) HDA_CODEC_ENTRY(0x11063397, "VT1708S", patch_vt1708S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) HDA_CODEC_ENTRY(0x11064397, "VT1705", patch_vt1708S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) HDA_CODEC_ENTRY(0x11065397, "VT1708S", patch_vt1708S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) HDA_CODEC_ENTRY(0x11066397, "VT1708S", patch_vt1708S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) HDA_CODEC_ENTRY(0x11067397, "VT1708S", patch_vt1708S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) HDA_CODEC_ENTRY(0x11060398, "VT1702", patch_vt1702),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) HDA_CODEC_ENTRY(0x11061398, "VT1702", patch_vt1702),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) HDA_CODEC_ENTRY(0x11062398, "VT1702", patch_vt1702),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) HDA_CODEC_ENTRY(0x11063398, "VT1702", patch_vt1702),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) HDA_CODEC_ENTRY(0x11064398, "VT1702", patch_vt1702),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) HDA_CODEC_ENTRY(0x11065398, "VT1702", patch_vt1702),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) HDA_CODEC_ENTRY(0x11066398, "VT1702", patch_vt1702),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) HDA_CODEC_ENTRY(0x11067398, "VT1702", patch_vt1702),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) HDA_CODEC_ENTRY(0x11060428, "VT1718S", patch_vt1718S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) HDA_CODEC_ENTRY(0x11064428, "VT1718S", patch_vt1718S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) HDA_CODEC_ENTRY(0x11060441, "VT2020", patch_vt1718S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) HDA_CODEC_ENTRY(0x11064441, "VT1828S", patch_vt1718S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) HDA_CODEC_ENTRY(0x11060433, "VT1716S", patch_vt1716S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) HDA_CODEC_ENTRY(0x1106a721, "VT1716S", patch_vt1716S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) HDA_CODEC_ENTRY(0x11060438, "VT2002P", patch_vt2002P),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) HDA_CODEC_ENTRY(0x11064438, "VT2002P", patch_vt2002P),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) HDA_CODEC_ENTRY(0x11060448, "VT1812", patch_vt1812),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) HDA_CODEC_ENTRY(0x11060440, "VT1818S", patch_vt1708S),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) HDA_CODEC_ENTRY(0x11060446, "VT1802", patch_vt2002P),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) HDA_CODEC_ENTRY(0x11068446, "VT1802", patch_vt2002P),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) HDA_CODEC_ENTRY(0x11064760, "VT1705CF", patch_vt3476),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) HDA_CODEC_ENTRY(0x11064761, "VT1708SCE", patch_vt3476),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) HDA_CODEC_ENTRY(0x11064762, "VT1808", patch_vt3476),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) {} /* terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_via);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) static struct hda_codec_driver via_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) .id = snd_hda_id_via,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) MODULE_DESCRIPTION("VIA HD-audio codec");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) module_hda_codec_driver(via_driver);