patch_via.c 32 KB

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