patch_via.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253
  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 <[email protected]>
  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. #ifdef CONFIG_PM
  342. static int via_suspend(struct hda_codec *codec)
  343. {
  344. struct via_spec *spec = codec->spec;
  345. vt1708_stop_hp_work(codec);
  346. /* Fix pop noise on headphones */
  347. if (spec->codec_type == VT1802)
  348. snd_hda_shutup_pins(codec);
  349. return 0;
  350. }
  351. static int via_resume(struct hda_codec *codec)
  352. {
  353. /* some delay here to make jack detection working (bko#98921) */
  354. msleep(10);
  355. codec->patch_ops.init(codec);
  356. snd_hda_regmap_sync(codec);
  357. return 0;
  358. }
  359. #endif
  360. #ifdef CONFIG_PM
  361. static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
  362. {
  363. struct via_spec *spec = codec->spec;
  364. analog_low_current_mode(codec);
  365. vt1708_update_hp_work(codec);
  366. return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
  367. }
  368. #endif
  369. /*
  370. */
  371. static int via_init(struct hda_codec *codec);
  372. static const struct hda_codec_ops via_patch_ops = {
  373. .build_controls = snd_hda_gen_build_controls,
  374. .build_pcms = snd_hda_gen_build_pcms,
  375. .init = via_init,
  376. .free = via_free,
  377. .unsol_event = snd_hda_jack_unsol_event,
  378. #ifdef CONFIG_PM
  379. .suspend = via_suspend,
  380. .resume = via_resume,
  381. .check_power_status = via_check_power_status,
  382. #endif
  383. };
  384. static const struct hda_verb vt1708_init_verbs[] = {
  385. /* power down jack detect function */
  386. {0x1, 0xf81, 0x1},
  387. { }
  388. };
  389. static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
  390. {
  391. unsigned int def_conf;
  392. unsigned char seqassoc;
  393. def_conf = snd_hda_codec_get_pincfg(codec, nid);
  394. seqassoc = (unsigned char) get_defcfg_association(def_conf);
  395. seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
  396. if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
  397. && (seqassoc == 0xf0 || seqassoc == 0xff)) {
  398. def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
  399. snd_hda_codec_set_pincfg(codec, nid, def_conf);
  400. }
  401. }
  402. static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
  403. struct snd_ctl_elem_value *ucontrol)
  404. {
  405. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  406. struct via_spec *spec = codec->spec;
  407. if (spec->codec_type != VT1708)
  408. return 0;
  409. ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
  410. return 0;
  411. }
  412. static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
  413. struct snd_ctl_elem_value *ucontrol)
  414. {
  415. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  416. struct via_spec *spec = codec->spec;
  417. int val;
  418. if (spec->codec_type != VT1708)
  419. return 0;
  420. val = !!ucontrol->value.integer.value[0];
  421. if (spec->vt1708_jack_detect == val)
  422. return 0;
  423. spec->vt1708_jack_detect = val;
  424. vt1708_update_hp_work(codec);
  425. return 1;
  426. }
  427. static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
  428. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  429. .name = "Jack Detect",
  430. .count = 1,
  431. .info = snd_ctl_boolean_mono_info,
  432. .get = vt1708_jack_detect_get,
  433. .put = vt1708_jack_detect_put,
  434. };
  435. static const struct badness_table via_main_out_badness = {
  436. .no_primary_dac = 0x10000,
  437. .no_dac = 0x4000,
  438. .shared_primary = 0x10000,
  439. .shared_surr = 0x20,
  440. .shared_clfe = 0x20,
  441. .shared_surr_main = 0x20,
  442. };
  443. static const struct badness_table via_extra_out_badness = {
  444. .no_primary_dac = 0x4000,
  445. .no_dac = 0x4000,
  446. .shared_primary = 0x12,
  447. .shared_surr = 0x20,
  448. .shared_clfe = 0x20,
  449. .shared_surr_main = 0x10,
  450. };
  451. static int via_parse_auto_config(struct hda_codec *codec)
  452. {
  453. struct via_spec *spec = codec->spec;
  454. int err;
  455. spec->gen.main_out_badness = &via_main_out_badness;
  456. spec->gen.extra_out_badness = &via_extra_out_badness;
  457. err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
  458. if (err < 0)
  459. return err;
  460. err = auto_parse_beep(codec);
  461. if (err < 0)
  462. return err;
  463. err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
  464. if (err < 0)
  465. return err;
  466. if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &via_pin_power_ctl_enum))
  467. return -ENOMEM;
  468. /* disable widget PM at start for compatibility */
  469. codec->power_save_node = 0;
  470. spec->gen.power_down_unused = 0;
  471. return 0;
  472. }
  473. static int via_init(struct hda_codec *codec)
  474. {
  475. /* init power states */
  476. __analog_low_current_mode(codec, true);
  477. snd_hda_gen_init(codec);
  478. vt1708_update_hp_work(codec);
  479. return 0;
  480. }
  481. static int vt1708_build_controls(struct hda_codec *codec)
  482. {
  483. /* In order not to create "Phantom Jack" controls,
  484. temporary enable jackpoll */
  485. int err;
  486. int old_interval = codec->jackpoll_interval;
  487. codec->jackpoll_interval = msecs_to_jiffies(100);
  488. err = snd_hda_gen_build_controls(codec);
  489. codec->jackpoll_interval = old_interval;
  490. return err;
  491. }
  492. static int vt1708_build_pcms(struct hda_codec *codec)
  493. {
  494. struct via_spec *spec = codec->spec;
  495. int i, err;
  496. err = snd_hda_gen_build_pcms(codec);
  497. if (err < 0 || codec->core.vendor_id != 0x11061708)
  498. return err;
  499. /* We got noisy outputs on the right channel on VT1708 when
  500. * 24bit samples are used. Until any workaround is found,
  501. * disable the 24bit format, so far.
  502. */
  503. for (i = 0; i < ARRAY_SIZE(spec->gen.pcm_rec); i++) {
  504. struct hda_pcm *info = spec->gen.pcm_rec[i];
  505. if (!info)
  506. continue;
  507. if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
  508. info->pcm_type != HDA_PCM_TYPE_AUDIO)
  509. continue;
  510. info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
  511. SNDRV_PCM_FMTBIT_S16_LE;
  512. }
  513. return 0;
  514. }
  515. static int patch_vt1708(struct hda_codec *codec)
  516. {
  517. struct via_spec *spec;
  518. int err;
  519. /* create a codec specific record */
  520. spec = via_new_spec(codec);
  521. if (spec == NULL)
  522. return -ENOMEM;
  523. /* override some patch_ops */
  524. codec->patch_ops.build_controls = vt1708_build_controls;
  525. codec->patch_ops.build_pcms = vt1708_build_pcms;
  526. spec->gen.mixer_nid = 0x17;
  527. /* set jackpoll_interval while parsing the codec */
  528. codec->jackpoll_interval = msecs_to_jiffies(100);
  529. spec->vt1708_jack_detect = 1;
  530. /* don't support the input jack switching due to lack of unsol event */
  531. /* (it may work with polling, though, but it needs testing) */
  532. spec->gen.suppress_auto_mic = 1;
  533. /* Some machines show the broken speaker mute */
  534. spec->gen.auto_mute_via_amp = 1;
  535. /* Add HP and CD pin config connect bit re-config action */
  536. vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
  537. vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
  538. err = snd_hda_add_verbs(codec, vt1708_init_verbs);
  539. if (err < 0)
  540. goto error;
  541. /* automatic parse from the BIOS config */
  542. err = via_parse_auto_config(codec);
  543. if (err < 0)
  544. goto error;
  545. /* add jack detect on/off control */
  546. if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1708_jack_detect_ctl)) {
  547. err = -ENOMEM;
  548. goto error;
  549. }
  550. /* clear jackpoll_interval again; it's set dynamically */
  551. codec->jackpoll_interval = 0;
  552. return 0;
  553. error:
  554. via_free(codec);
  555. return err;
  556. }
  557. static int patch_vt1709(struct hda_codec *codec)
  558. {
  559. struct via_spec *spec;
  560. int err;
  561. /* create a codec specific record */
  562. spec = via_new_spec(codec);
  563. if (spec == NULL)
  564. return -ENOMEM;
  565. spec->gen.mixer_nid = 0x18;
  566. err = via_parse_auto_config(codec);
  567. if (err < 0)
  568. goto error;
  569. return 0;
  570. error:
  571. via_free(codec);
  572. return err;
  573. }
  574. static int patch_vt1708S(struct hda_codec *codec);
  575. static int patch_vt1708B(struct hda_codec *codec)
  576. {
  577. struct via_spec *spec;
  578. int err;
  579. if (get_codec_type(codec) == VT1708BCE)
  580. return patch_vt1708S(codec);
  581. /* create a codec specific record */
  582. spec = via_new_spec(codec);
  583. if (spec == NULL)
  584. return -ENOMEM;
  585. spec->gen.mixer_nid = 0x16;
  586. /* automatic parse from the BIOS config */
  587. err = via_parse_auto_config(codec);
  588. if (err < 0)
  589. goto error;
  590. return 0;
  591. error:
  592. via_free(codec);
  593. return err;
  594. }
  595. /* Patch for VT1708S */
  596. static const struct hda_verb vt1708S_init_verbs[] = {
  597. /* Enable Mic Boost Volume backdoor */
  598. {0x1, 0xf98, 0x1},
  599. /* don't bybass mixer */
  600. {0x1, 0xf88, 0xc0},
  601. { }
  602. };
  603. static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
  604. int offset, int num_steps, int step_size)
  605. {
  606. snd_hda_override_wcaps(codec, pin,
  607. get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
  608. snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
  609. (offset << AC_AMPCAP_OFFSET_SHIFT) |
  610. (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
  611. (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
  612. (0 << AC_AMPCAP_MUTE_SHIFT));
  613. }
  614. static int patch_vt1708S(struct hda_codec *codec)
  615. {
  616. struct via_spec *spec;
  617. int err;
  618. /* create a codec specific record */
  619. spec = via_new_spec(codec);
  620. if (spec == NULL)
  621. return -ENOMEM;
  622. spec->gen.mixer_nid = 0x16;
  623. override_mic_boost(codec, 0x1a, 0, 3, 40);
  624. override_mic_boost(codec, 0x1e, 0, 3, 40);
  625. /* correct names for VT1708BCE */
  626. if (get_codec_type(codec) == VT1708BCE)
  627. snd_hda_codec_set_name(codec, "VT1708BCE");
  628. /* correct names for VT1705 */
  629. if (codec->core.vendor_id == 0x11064397)
  630. snd_hda_codec_set_name(codec, "VT1705");
  631. err = snd_hda_add_verbs(codec, vt1708S_init_verbs);
  632. if (err < 0)
  633. goto error;
  634. /* automatic parse from the BIOS config */
  635. err = via_parse_auto_config(codec);
  636. if (err < 0)
  637. goto error;
  638. return 0;
  639. error:
  640. via_free(codec);
  641. return err;
  642. }
  643. /* Patch for VT1702 */
  644. static const struct hda_verb vt1702_init_verbs[] = {
  645. /* mixer enable */
  646. {0x1, 0xF88, 0x3},
  647. /* GPIO 0~2 */
  648. {0x1, 0xF82, 0x3F},
  649. { }
  650. };
  651. static int patch_vt1702(struct hda_codec *codec)
  652. {
  653. struct via_spec *spec;
  654. int err;
  655. /* create a codec specific record */
  656. spec = via_new_spec(codec);
  657. if (spec == NULL)
  658. return -ENOMEM;
  659. spec->gen.mixer_nid = 0x1a;
  660. /* limit AA path volume to 0 dB */
  661. snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
  662. (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
  663. (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
  664. (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
  665. (1 << AC_AMPCAP_MUTE_SHIFT));
  666. err = snd_hda_add_verbs(codec, vt1702_init_verbs);
  667. if (err < 0)
  668. goto error;
  669. /* automatic parse from the BIOS config */
  670. err = via_parse_auto_config(codec);
  671. if (err < 0)
  672. goto error;
  673. return 0;
  674. error:
  675. via_free(codec);
  676. return err;
  677. }
  678. /* Patch for VT1718S */
  679. static const struct hda_verb vt1718S_init_verbs[] = {
  680. /* Enable MW0 adjust Gain 5 */
  681. {0x1, 0xfb2, 0x10},
  682. /* Enable Boost Volume backdoor */
  683. {0x1, 0xf88, 0x8},
  684. { }
  685. };
  686. /* Add a connection to the primary DAC from AA-mixer for some codecs
  687. * This isn't listed from the raw info, but the chip has a secret connection.
  688. */
  689. static int add_secret_dac_path(struct hda_codec *codec)
  690. {
  691. struct via_spec *spec = codec->spec;
  692. int i, nums;
  693. hda_nid_t conn[8];
  694. hda_nid_t nid;
  695. if (!spec->gen.mixer_nid)
  696. return 0;
  697. nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
  698. ARRAY_SIZE(conn) - 1);
  699. if (nums < 0)
  700. return nums;
  701. for (i = 0; i < nums; i++) {
  702. if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
  703. return 0;
  704. }
  705. /* find the primary DAC and add to the connection list */
  706. for_each_hda_codec_node(nid, codec) {
  707. unsigned int caps = get_wcaps(codec, nid);
  708. if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
  709. !(caps & AC_WCAP_DIGITAL)) {
  710. conn[nums++] = nid;
  711. return snd_hda_override_conn_list(codec,
  712. spec->gen.mixer_nid,
  713. nums, conn);
  714. }
  715. }
  716. return 0;
  717. }
  718. static int patch_vt1718S(struct hda_codec *codec)
  719. {
  720. struct via_spec *spec;
  721. int err;
  722. /* create a codec specific record */
  723. spec = via_new_spec(codec);
  724. if (spec == NULL)
  725. return -ENOMEM;
  726. spec->gen.mixer_nid = 0x21;
  727. override_mic_boost(codec, 0x2b, 0, 3, 40);
  728. override_mic_boost(codec, 0x29, 0, 3, 40);
  729. add_secret_dac_path(codec);
  730. err = snd_hda_add_verbs(codec, vt1718S_init_verbs);
  731. if (err < 0)
  732. goto error;
  733. /* automatic parse from the BIOS config */
  734. err = via_parse_auto_config(codec);
  735. if (err < 0)
  736. goto error;
  737. return 0;
  738. error:
  739. via_free(codec);
  740. return err;
  741. }
  742. /* Patch for VT1716S */
  743. static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
  744. struct snd_ctl_elem_info *uinfo)
  745. {
  746. uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
  747. uinfo->count = 1;
  748. uinfo->value.integer.min = 0;
  749. uinfo->value.integer.max = 1;
  750. return 0;
  751. }
  752. static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
  753. struct snd_ctl_elem_value *ucontrol)
  754. {
  755. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  756. int index = 0;
  757. index = snd_hda_codec_read(codec, 0x26, 0,
  758. AC_VERB_GET_CONNECT_SEL, 0);
  759. if (index != -1)
  760. *ucontrol->value.integer.value = index;
  761. return 0;
  762. }
  763. static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
  764. struct snd_ctl_elem_value *ucontrol)
  765. {
  766. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  767. struct via_spec *spec = codec->spec;
  768. int index = *ucontrol->value.integer.value;
  769. snd_hda_codec_write(codec, 0x26, 0,
  770. AC_VERB_SET_CONNECT_SEL, index);
  771. spec->dmic_enabled = index;
  772. return 1;
  773. }
  774. static const struct snd_kcontrol_new vt1716s_dmic_mixer_vol =
  775. HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT);
  776. static const struct snd_kcontrol_new vt1716s_dmic_mixer_sw = {
  777. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  778. .name = "Digital Mic Capture Switch",
  779. .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
  780. .count = 1,
  781. .info = vt1716s_dmic_info,
  782. .get = vt1716s_dmic_get,
  783. .put = vt1716s_dmic_put,
  784. };
  785. /* mono-out mixer elements */
  786. static const struct snd_kcontrol_new vt1716S_mono_out_mixer =
  787. HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT);
  788. static const struct hda_verb vt1716S_init_verbs[] = {
  789. /* Enable Boost Volume backdoor */
  790. {0x1, 0xf8a, 0x80},
  791. /* don't bybass mixer */
  792. {0x1, 0xf88, 0xc0},
  793. /* Enable mono output */
  794. {0x1, 0xf90, 0x08},
  795. { }
  796. };
  797. static int patch_vt1716S(struct hda_codec *codec)
  798. {
  799. struct via_spec *spec;
  800. int err;
  801. /* create a codec specific record */
  802. spec = via_new_spec(codec);
  803. if (spec == NULL)
  804. return -ENOMEM;
  805. spec->gen.mixer_nid = 0x16;
  806. override_mic_boost(codec, 0x1a, 0, 3, 40);
  807. override_mic_boost(codec, 0x1e, 0, 3, 40);
  808. err = snd_hda_add_verbs(codec, vt1716S_init_verbs);
  809. if (err < 0)
  810. goto error;
  811. /* automatic parse from the BIOS config */
  812. err = via_parse_auto_config(codec);
  813. if (err < 0)
  814. goto error;
  815. if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) ||
  816. !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) ||
  817. !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) {
  818. err = -ENOMEM;
  819. goto error;
  820. }
  821. return 0;
  822. error:
  823. via_free(codec);
  824. return err;
  825. }
  826. /* for vt2002P */
  827. static const struct hda_verb vt2002P_init_verbs[] = {
  828. /* Class-D speaker related verbs */
  829. {0x1, 0xfe0, 0x4},
  830. {0x1, 0xfe9, 0x80},
  831. {0x1, 0xfe2, 0x22},
  832. /* Enable Boost Volume backdoor */
  833. {0x1, 0xfb9, 0x24},
  834. /* Enable AOW0 to MW9 */
  835. {0x1, 0xfb8, 0x88},
  836. { }
  837. };
  838. static const struct hda_verb vt1802_init_verbs[] = {
  839. /* Enable Boost Volume backdoor */
  840. {0x1, 0xfb9, 0x24},
  841. /* Enable AOW0 to MW9 */
  842. {0x1, 0xfb8, 0x88},
  843. { }
  844. };
  845. /*
  846. * pin fix-up
  847. */
  848. enum {
  849. VIA_FIXUP_INTMIC_BOOST,
  850. VIA_FIXUP_ASUS_G75,
  851. VIA_FIXUP_POWER_SAVE,
  852. };
  853. static void via_fixup_intmic_boost(struct hda_codec *codec,
  854. const struct hda_fixup *fix, int action)
  855. {
  856. if (action == HDA_FIXUP_ACT_PRE_PROBE)
  857. override_mic_boost(codec, 0x30, 0, 2, 40);
  858. }
  859. static void via_fixup_power_save(struct hda_codec *codec,
  860. const struct hda_fixup *fix, int action)
  861. {
  862. if (action == HDA_FIXUP_ACT_PRE_PROBE)
  863. codec->power_save_node = 0;
  864. }
  865. static const struct hda_fixup via_fixups[] = {
  866. [VIA_FIXUP_INTMIC_BOOST] = {
  867. .type = HDA_FIXUP_FUNC,
  868. .v.func = via_fixup_intmic_boost,
  869. },
  870. [VIA_FIXUP_ASUS_G75] = {
  871. .type = HDA_FIXUP_PINS,
  872. .v.pins = (const struct hda_pintbl[]) {
  873. /* set 0x24 and 0x33 as speakers */
  874. { 0x24, 0x991301f0 },
  875. { 0x33, 0x991301f1 }, /* subwoofer */
  876. { }
  877. }
  878. },
  879. [VIA_FIXUP_POWER_SAVE] = {
  880. .type = HDA_FIXUP_FUNC,
  881. .v.func = via_fixup_power_save,
  882. },
  883. };
  884. static const struct snd_pci_quirk vt2002p_fixups[] = {
  885. SND_PCI_QUIRK(0x1043, 0x13f7, "Asus B23E", VIA_FIXUP_POWER_SAVE),
  886. SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
  887. SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
  888. SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", VIA_FIXUP_POWER_SAVE),
  889. {}
  890. };
  891. /* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
  892. * Replace this with mixer NID 0x1c
  893. */
  894. static void fix_vt1802_connections(struct hda_codec *codec)
  895. {
  896. static const hda_nid_t conn_24[] = { 0x14, 0x1c };
  897. static const hda_nid_t conn_33[] = { 0x1c };
  898. snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
  899. snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
  900. }
  901. /* patch for vt2002P */
  902. static int patch_vt2002P(struct hda_codec *codec)
  903. {
  904. struct via_spec *spec;
  905. int err;
  906. /* create a codec specific record */
  907. spec = via_new_spec(codec);
  908. if (spec == NULL)
  909. return -ENOMEM;
  910. spec->gen.mixer_nid = 0x21;
  911. override_mic_boost(codec, 0x2b, 0, 3, 40);
  912. override_mic_boost(codec, 0x29, 0, 3, 40);
  913. if (spec->codec_type == VT1802)
  914. fix_vt1802_connections(codec);
  915. add_secret_dac_path(codec);
  916. snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
  917. snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
  918. if (spec->codec_type == VT1802)
  919. err = snd_hda_add_verbs(codec, vt1802_init_verbs);
  920. else
  921. err = snd_hda_add_verbs(codec, vt2002P_init_verbs);
  922. if (err < 0)
  923. goto error;
  924. /* automatic parse from the BIOS config */
  925. err = via_parse_auto_config(codec);
  926. if (err < 0)
  927. goto error;
  928. return 0;
  929. error:
  930. via_free(codec);
  931. return err;
  932. }
  933. /* for vt1812 */
  934. static const struct hda_verb vt1812_init_verbs[] = {
  935. /* Enable Boost Volume backdoor */
  936. {0x1, 0xfb9, 0x24},
  937. /* Enable AOW0 to MW9 */
  938. {0x1, 0xfb8, 0xa8},
  939. { }
  940. };
  941. /* patch for vt1812 */
  942. static int patch_vt1812(struct hda_codec *codec)
  943. {
  944. struct via_spec *spec;
  945. int err;
  946. /* create a codec specific record */
  947. spec = via_new_spec(codec);
  948. if (spec == NULL)
  949. return -ENOMEM;
  950. spec->gen.mixer_nid = 0x21;
  951. override_mic_boost(codec, 0x2b, 0, 3, 40);
  952. override_mic_boost(codec, 0x29, 0, 3, 40);
  953. add_secret_dac_path(codec);
  954. err = snd_hda_add_verbs(codec, vt1812_init_verbs);
  955. if (err < 0)
  956. goto error;
  957. /* automatic parse from the BIOS config */
  958. err = via_parse_auto_config(codec);
  959. if (err < 0)
  960. goto error;
  961. return 0;
  962. error:
  963. via_free(codec);
  964. return err;
  965. }
  966. /* patch for vt3476 */
  967. static const struct hda_verb vt3476_init_verbs[] = {
  968. /* Enable DMic 8/16/32K */
  969. {0x1, 0xF7B, 0x30},
  970. /* Enable Boost Volume backdoor */
  971. {0x1, 0xFB9, 0x20},
  972. /* Enable AOW-MW9 path */
  973. {0x1, 0xFB8, 0x10},
  974. { }
  975. };
  976. static int patch_vt3476(struct hda_codec *codec)
  977. {
  978. struct via_spec *spec;
  979. int err;
  980. /* create a codec specific record */
  981. spec = via_new_spec(codec);
  982. if (spec == NULL)
  983. return -ENOMEM;
  984. spec->gen.mixer_nid = 0x3f;
  985. add_secret_dac_path(codec);
  986. err = snd_hda_add_verbs(codec, vt3476_init_verbs);
  987. if (err < 0)
  988. goto error;
  989. /* automatic parse from the BIOS config */
  990. err = via_parse_auto_config(codec);
  991. if (err < 0)
  992. goto error;
  993. return 0;
  994. error:
  995. via_free(codec);
  996. return err;
  997. }
  998. /*
  999. * patch entries
  1000. */
  1001. static const struct hda_device_id snd_hda_id_via[] = {
  1002. HDA_CODEC_ENTRY(0x11061708, "VT1708", patch_vt1708),
  1003. HDA_CODEC_ENTRY(0x11061709, "VT1708", patch_vt1708),
  1004. HDA_CODEC_ENTRY(0x1106170a, "VT1708", patch_vt1708),
  1005. HDA_CODEC_ENTRY(0x1106170b, "VT1708", patch_vt1708),
  1006. HDA_CODEC_ENTRY(0x1106e710, "VT1709 10-Ch", patch_vt1709),
  1007. HDA_CODEC_ENTRY(0x1106e711, "VT1709 10-Ch", patch_vt1709),
  1008. HDA_CODEC_ENTRY(0x1106e712, "VT1709 10-Ch", patch_vt1709),
  1009. HDA_CODEC_ENTRY(0x1106e713, "VT1709 10-Ch", patch_vt1709),
  1010. HDA_CODEC_ENTRY(0x1106e714, "VT1709 6-Ch", patch_vt1709),
  1011. HDA_CODEC_ENTRY(0x1106e715, "VT1709 6-Ch", patch_vt1709),
  1012. HDA_CODEC_ENTRY(0x1106e716, "VT1709 6-Ch", patch_vt1709),
  1013. HDA_CODEC_ENTRY(0x1106e717, "VT1709 6-Ch", patch_vt1709),
  1014. HDA_CODEC_ENTRY(0x1106e720, "VT1708B 8-Ch", patch_vt1708B),
  1015. HDA_CODEC_ENTRY(0x1106e721, "VT1708B 8-Ch", patch_vt1708B),
  1016. HDA_CODEC_ENTRY(0x1106e722, "VT1708B 8-Ch", patch_vt1708B),
  1017. HDA_CODEC_ENTRY(0x1106e723, "VT1708B 8-Ch", patch_vt1708B),
  1018. HDA_CODEC_ENTRY(0x1106e724, "VT1708B 4-Ch", patch_vt1708B),
  1019. HDA_CODEC_ENTRY(0x1106e725, "VT1708B 4-Ch", patch_vt1708B),
  1020. HDA_CODEC_ENTRY(0x1106e726, "VT1708B 4-Ch", patch_vt1708B),
  1021. HDA_CODEC_ENTRY(0x1106e727, "VT1708B 4-Ch", patch_vt1708B),
  1022. HDA_CODEC_ENTRY(0x11060397, "VT1708S", patch_vt1708S),
  1023. HDA_CODEC_ENTRY(0x11061397, "VT1708S", patch_vt1708S),
  1024. HDA_CODEC_ENTRY(0x11062397, "VT1708S", patch_vt1708S),
  1025. HDA_CODEC_ENTRY(0x11063397, "VT1708S", patch_vt1708S),
  1026. HDA_CODEC_ENTRY(0x11064397, "VT1705", patch_vt1708S),
  1027. HDA_CODEC_ENTRY(0x11065397, "VT1708S", patch_vt1708S),
  1028. HDA_CODEC_ENTRY(0x11066397, "VT1708S", patch_vt1708S),
  1029. HDA_CODEC_ENTRY(0x11067397, "VT1708S", patch_vt1708S),
  1030. HDA_CODEC_ENTRY(0x11060398, "VT1702", patch_vt1702),
  1031. HDA_CODEC_ENTRY(0x11061398, "VT1702", patch_vt1702),
  1032. HDA_CODEC_ENTRY(0x11062398, "VT1702", patch_vt1702),
  1033. HDA_CODEC_ENTRY(0x11063398, "VT1702", patch_vt1702),
  1034. HDA_CODEC_ENTRY(0x11064398, "VT1702", patch_vt1702),
  1035. HDA_CODEC_ENTRY(0x11065398, "VT1702", patch_vt1702),
  1036. HDA_CODEC_ENTRY(0x11066398, "VT1702", patch_vt1702),
  1037. HDA_CODEC_ENTRY(0x11067398, "VT1702", patch_vt1702),
  1038. HDA_CODEC_ENTRY(0x11060428, "VT1718S", patch_vt1718S),
  1039. HDA_CODEC_ENTRY(0x11064428, "VT1718S", patch_vt1718S),
  1040. HDA_CODEC_ENTRY(0x11060441, "VT2020", patch_vt1718S),
  1041. HDA_CODEC_ENTRY(0x11064441, "VT1828S", patch_vt1718S),
  1042. HDA_CODEC_ENTRY(0x11060433, "VT1716S", patch_vt1716S),
  1043. HDA_CODEC_ENTRY(0x1106a721, "VT1716S", patch_vt1716S),
  1044. HDA_CODEC_ENTRY(0x11060438, "VT2002P", patch_vt2002P),
  1045. HDA_CODEC_ENTRY(0x11064438, "VT2002P", patch_vt2002P),
  1046. HDA_CODEC_ENTRY(0x11060448, "VT1812", patch_vt1812),
  1047. HDA_CODEC_ENTRY(0x11060440, "VT1818S", patch_vt1708S),
  1048. HDA_CODEC_ENTRY(0x11060446, "VT1802", patch_vt2002P),
  1049. HDA_CODEC_ENTRY(0x11068446, "VT1802", patch_vt2002P),
  1050. HDA_CODEC_ENTRY(0x11064760, "VT1705CF", patch_vt3476),
  1051. HDA_CODEC_ENTRY(0x11064761, "VT1708SCE", patch_vt3476),
  1052. HDA_CODEC_ENTRY(0x11064762, "VT1808", patch_vt3476),
  1053. {} /* terminator */
  1054. };
  1055. MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_via);
  1056. static struct hda_codec_driver via_driver = {
  1057. .id = snd_hda_id_via,
  1058. };
  1059. MODULE_LICENSE("GPL");
  1060. MODULE_DESCRIPTION("VIA HD-audio codec");
  1061. module_hda_codec_driver(via_driver);