patch_via.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396
  1. /*
  2. * Universal Interface for Intel High Definition Audio Codec
  3. *
  4. * HD audio interface patch for VIA VT1708 codec
  5. *
  6. * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
  7. * Takashi Iwai <tiwai@suse.de>
  8. *
  9. * This driver is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This driver is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. */
  23. /* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
  24. /* */
  25. /* 2006-03-03 Lydia Wang Create the basic patch to support VT1708 codec */
  26. /* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */
  27. /* 2006-08-02 Lydia Wang Add support to VT1709 codec */
  28. /* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */
  29. /* */
  30. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  31. #include <sound/driver.h>
  32. #include <linux/init.h>
  33. #include <linux/delay.h>
  34. #include <linux/slab.h>
  35. #include <linux/pci.h>
  36. #include <sound/core.h>
  37. #include "hda_codec.h"
  38. #include "hda_local.h"
  39. /* amp values */
  40. #define AMP_VAL_IDX_SHIFT 19
  41. #define AMP_VAL_IDX_MASK (0x0f<<19)
  42. #define NUM_CONTROL_ALLOC 32
  43. #define NUM_VERB_ALLOC 32
  44. /* Pin Widget NID */
  45. #define VT1708_HP_NID 0x13
  46. #define VT1708_DIGOUT_NID 0x14
  47. #define VT1708_DIGIN_NID 0x16
  48. #define VT1709_HP_DAC_NID 0x28
  49. #define VT1709_DIGOUT_NID 0x13
  50. #define VT1709_DIGIN_NID 0x17
  51. #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
  52. #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
  53. #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
  54. enum {
  55. VIA_CTL_WIDGET_VOL,
  56. VIA_CTL_WIDGET_MUTE,
  57. };
  58. enum {
  59. AUTO_SEQ_FRONT,
  60. AUTO_SEQ_SURROUND,
  61. AUTO_SEQ_CENLFE,
  62. AUTO_SEQ_SIDE
  63. };
  64. static struct snd_kcontrol_new vt1708_control_templates[] = {
  65. HDA_CODEC_VOLUME(NULL, 0, 0, 0),
  66. HDA_CODEC_MUTE(NULL, 0, 0, 0),
  67. };
  68. struct via_spec {
  69. /* codec parameterization */
  70. struct snd_kcontrol_new *mixers[3];
  71. unsigned int num_mixers;
  72. struct hda_verb *init_verbs;
  73. char *stream_name_analog;
  74. struct hda_pcm_stream *stream_analog_playback;
  75. struct hda_pcm_stream *stream_analog_capture;
  76. char *stream_name_digital;
  77. struct hda_pcm_stream *stream_digital_playback;
  78. struct hda_pcm_stream *stream_digital_capture;
  79. /* playback */
  80. struct hda_multi_out multiout;
  81. /* capture */
  82. unsigned int num_adc_nids;
  83. hda_nid_t *adc_nids;
  84. hda_nid_t dig_in_nid;
  85. /* capture source */
  86. const struct hda_input_mux *input_mux;
  87. unsigned int cur_mux[3];
  88. /* PCM information */
  89. struct hda_pcm pcm_rec[2];
  90. /* dynamic controls, init_verbs and input_mux */
  91. struct auto_pin_cfg autocfg;
  92. unsigned int num_kctl_alloc, num_kctl_used;
  93. struct snd_kcontrol_new *kctl_alloc;
  94. struct hda_input_mux private_imux;
  95. hda_nid_t private_dac_nids[4];
  96. };
  97. static hda_nid_t vt1708_adc_nids[2] = {
  98. /* ADC1-2 */
  99. 0x15, 0x27
  100. };
  101. static hda_nid_t vt1709_adc_nids[3] = {
  102. /* ADC1-2 */
  103. 0x14, 0x15, 0x16
  104. };
  105. /* add dynamic controls */
  106. static int via_add_control(struct via_spec *spec, int type, const char *name,
  107. unsigned long val)
  108. {
  109. struct snd_kcontrol_new *knew;
  110. if (spec->num_kctl_used >= spec->num_kctl_alloc) {
  111. int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
  112. /* array + terminator */
  113. knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
  114. if (!knew)
  115. return -ENOMEM;
  116. if (spec->kctl_alloc) {
  117. memcpy(knew, spec->kctl_alloc,
  118. sizeof(*knew) * spec->num_kctl_alloc);
  119. kfree(spec->kctl_alloc);
  120. }
  121. spec->kctl_alloc = knew;
  122. spec->num_kctl_alloc = num;
  123. }
  124. knew = &spec->kctl_alloc[spec->num_kctl_used];
  125. *knew = vt1708_control_templates[type];
  126. knew->name = kstrdup(name, GFP_KERNEL);
  127. if (!knew->name)
  128. return -ENOMEM;
  129. knew->private_value = val;
  130. spec->num_kctl_used++;
  131. return 0;
  132. }
  133. /* create input playback/capture controls for the given pin */
  134. static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
  135. const char *ctlname, int idx, int mix_nid)
  136. {
  137. char name[32];
  138. int err;
  139. sprintf(name, "%s Playback Volume", ctlname);
  140. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  141. HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
  142. if (err < 0)
  143. return err;
  144. sprintf(name, "%s Playback Switch", ctlname);
  145. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  146. HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
  147. if (err < 0)
  148. return err;
  149. return 0;
  150. }
  151. static void via_auto_set_output_and_unmute(struct hda_codec *codec,
  152. hda_nid_t nid, int pin_type,
  153. int dac_idx)
  154. {
  155. /* set as output */
  156. snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
  157. pin_type);
  158. snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
  159. AMP_OUT_UNMUTE);
  160. }
  161. static void via_auto_init_multi_out(struct hda_codec *codec)
  162. {
  163. struct via_spec *spec = codec->spec;
  164. int i;
  165. for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
  166. hda_nid_t nid = spec->autocfg.line_out_pins[i];
  167. if (nid)
  168. via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
  169. }
  170. }
  171. static void via_auto_init_hp_out(struct hda_codec *codec)
  172. {
  173. struct via_spec *spec = codec->spec;
  174. hda_nid_t pin;
  175. pin = spec->autocfg.hp_pins[0];
  176. if (pin) /* connect to front */
  177. via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
  178. }
  179. static void via_auto_init_analog_input(struct hda_codec *codec)
  180. {
  181. struct via_spec *spec = codec->spec;
  182. int i;
  183. for (i = 0; i < AUTO_PIN_LAST; i++) {
  184. hda_nid_t nid = spec->autocfg.input_pins[i];
  185. snd_hda_codec_write(codec, nid, 0,
  186. AC_VERB_SET_PIN_WIDGET_CONTROL,
  187. (i <= AUTO_PIN_FRONT_MIC ?
  188. PIN_VREF50 : PIN_IN));
  189. }
  190. }
  191. /*
  192. * input MUX handling
  193. */
  194. static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
  195. struct snd_ctl_elem_info *uinfo)
  196. {
  197. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  198. struct via_spec *spec = codec->spec;
  199. return snd_hda_input_mux_info(spec->input_mux, uinfo);
  200. }
  201. static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
  202. struct snd_ctl_elem_value *ucontrol)
  203. {
  204. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  205. struct via_spec *spec = codec->spec;
  206. unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  207. ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
  208. return 0;
  209. }
  210. static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
  211. struct snd_ctl_elem_value *ucontrol)
  212. {
  213. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  214. struct via_spec *spec = codec->spec;
  215. unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  216. unsigned int vendor_id = codec->vendor_id;
  217. /* AIW0 lydia 060801 add for correct sw0 input select */
  218. if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
  219. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  220. 0x18, &spec->cur_mux[adc_idx]);
  221. else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
  222. IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0) )
  223. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  224. 0x19, &spec->cur_mux[adc_idx]);
  225. else
  226. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  227. spec->adc_nids[adc_idx],
  228. &spec->cur_mux[adc_idx]);
  229. }
  230. /* capture mixer elements */
  231. static struct snd_kcontrol_new vt1708_capture_mixer[] = {
  232. HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
  233. HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
  234. HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
  235. HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
  236. {
  237. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  238. /* The multiple "Capture Source" controls confuse alsamixer
  239. * So call somewhat different..
  240. * FIXME: the controls appear in the "playback" view!
  241. */
  242. /* .name = "Capture Source", */
  243. .name = "Input Source",
  244. .count = 1,
  245. .info = via_mux_enum_info,
  246. .get = via_mux_enum_get,
  247. .put = via_mux_enum_put,
  248. },
  249. { } /* end */
  250. };
  251. /*
  252. * generic initialization of ADC, input mixers and output mixers
  253. */
  254. static struct hda_verb vt1708_volume_init_verbs[] = {
  255. /*
  256. * Unmute ADC0-1 and set the default input to mic-in
  257. */
  258. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  259. {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  260. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
  261. * mixer widget
  262. */
  263. /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
  264. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  265. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  266. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
  267. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
  268. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
  269. /*
  270. * Set up output mixers (0x19 - 0x1b)
  271. */
  272. /* set vol=0 to output mixers */
  273. {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  274. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  275. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  276. /* Setup default input to PW4 */
  277. {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
  278. /* Set mic as default input of sw0 */
  279. {0x18, AC_VERB_SET_CONNECT_SEL, 0x2},
  280. /* PW9 Output enable */
  281. {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  282. };
  283. static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
  284. struct hda_codec *codec,
  285. struct snd_pcm_substream *substream)
  286. {
  287. struct via_spec *spec = codec->spec;
  288. return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
  289. }
  290. static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
  291. struct hda_codec *codec,
  292. unsigned int stream_tag,
  293. unsigned int format,
  294. struct snd_pcm_substream *substream)
  295. {
  296. struct via_spec *spec = codec->spec;
  297. return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
  298. stream_tag, format, substream);
  299. }
  300. static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
  301. struct hda_codec *codec,
  302. struct snd_pcm_substream *substream)
  303. {
  304. struct via_spec *spec = codec->spec;
  305. return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
  306. }
  307. /*
  308. * Digital out
  309. */
  310. static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
  311. struct hda_codec *codec,
  312. struct snd_pcm_substream *substream)
  313. {
  314. struct via_spec *spec = codec->spec;
  315. return snd_hda_multi_out_dig_open(codec, &spec->multiout);
  316. }
  317. static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
  318. struct hda_codec *codec,
  319. struct snd_pcm_substream *substream)
  320. {
  321. struct via_spec *spec = codec->spec;
  322. return snd_hda_multi_out_dig_close(codec, &spec->multiout);
  323. }
  324. /*
  325. * Analog capture
  326. */
  327. static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
  328. struct hda_codec *codec,
  329. unsigned int stream_tag,
  330. unsigned int format,
  331. struct snd_pcm_substream *substream)
  332. {
  333. struct via_spec *spec = codec->spec;
  334. snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
  335. stream_tag, 0, format);
  336. return 0;
  337. }
  338. static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
  339. struct hda_codec *codec,
  340. struct snd_pcm_substream *substream)
  341. {
  342. struct via_spec *spec = codec->spec;
  343. snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
  344. 0, 0, 0);
  345. return 0;
  346. }
  347. static struct hda_pcm_stream vt1708_pcm_analog_playback = {
  348. .substreams = 1,
  349. .channels_min = 2,
  350. .channels_max = 8,
  351. .nid = 0x10, /* NID to query formats and rates */
  352. .ops = {
  353. .open = via_playback_pcm_open,
  354. .prepare = via_playback_pcm_prepare,
  355. .cleanup = via_playback_pcm_cleanup
  356. },
  357. };
  358. static struct hda_pcm_stream vt1708_pcm_analog_capture = {
  359. .substreams = 2,
  360. .channels_min = 2,
  361. .channels_max = 2,
  362. .nid = 0x15, /* NID to query formats and rates */
  363. .ops = {
  364. .prepare = via_capture_pcm_prepare,
  365. .cleanup = via_capture_pcm_cleanup
  366. },
  367. };
  368. static struct hda_pcm_stream vt1708_pcm_digital_playback = {
  369. .substreams = 1,
  370. .channels_min = 2,
  371. .channels_max = 2,
  372. /* NID is set in via_build_pcms */
  373. .ops = {
  374. .open = via_dig_playback_pcm_open,
  375. .close = via_dig_playback_pcm_close
  376. },
  377. };
  378. static struct hda_pcm_stream vt1708_pcm_digital_capture = {
  379. .substreams = 1,
  380. .channels_min = 2,
  381. .channels_max = 2,
  382. };
  383. static int via_build_controls(struct hda_codec *codec)
  384. {
  385. struct via_spec *spec = codec->spec;
  386. int err;
  387. int i;
  388. for (i = 0; i < spec->num_mixers; i++) {
  389. err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
  390. if (err < 0)
  391. return err;
  392. }
  393. if (spec->multiout.dig_out_nid) {
  394. err = snd_hda_create_spdif_out_ctls(codec,
  395. spec->multiout.dig_out_nid);
  396. if (err < 0)
  397. return err;
  398. }
  399. if (spec->dig_in_nid) {
  400. err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
  401. if (err < 0)
  402. return err;
  403. }
  404. return 0;
  405. }
  406. static int via_build_pcms(struct hda_codec *codec)
  407. {
  408. struct via_spec *spec = codec->spec;
  409. struct hda_pcm *info = spec->pcm_rec;
  410. codec->num_pcms = 1;
  411. codec->pcm_info = info;
  412. info->name = spec->stream_name_analog;
  413. info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
  414. info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
  415. info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
  416. info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
  417. info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
  418. spec->multiout.max_channels;
  419. if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
  420. codec->num_pcms++;
  421. info++;
  422. info->name = spec->stream_name_digital;
  423. if (spec->multiout.dig_out_nid) {
  424. info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
  425. *(spec->stream_digital_playback);
  426. info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
  427. spec->multiout.dig_out_nid;
  428. }
  429. if (spec->dig_in_nid) {
  430. info->stream[SNDRV_PCM_STREAM_CAPTURE] =
  431. *(spec->stream_digital_capture);
  432. info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
  433. spec->dig_in_nid;
  434. }
  435. }
  436. return 0;
  437. }
  438. static void via_free(struct hda_codec *codec)
  439. {
  440. struct via_spec *spec = codec->spec;
  441. unsigned int i;
  442. if (!spec)
  443. return;
  444. if (spec->kctl_alloc) {
  445. for (i = 0; i < spec->num_kctl_used; i++)
  446. kfree(spec->kctl_alloc[i].name);
  447. kfree(spec->kctl_alloc);
  448. }
  449. kfree(codec->spec);
  450. }
  451. static int via_init(struct hda_codec *codec)
  452. {
  453. struct via_spec *spec = codec->spec;
  454. snd_hda_sequence_write(codec, spec->init_verbs);
  455. return 0;
  456. }
  457. #ifdef CONFIG_PM
  458. /*
  459. * resume
  460. */
  461. static int via_resume(struct hda_codec *codec)
  462. {
  463. struct via_spec *spec = codec->spec;
  464. int i;
  465. via_init(codec);
  466. for (i = 0; i < spec->num_mixers; i++)
  467. snd_hda_resume_ctls(codec, spec->mixers[i]);
  468. if (spec->multiout.dig_out_nid)
  469. snd_hda_resume_spdif_out(codec);
  470. if (spec->dig_in_nid)
  471. snd_hda_resume_spdif_in(codec);
  472. return 0;
  473. }
  474. #endif
  475. /*
  476. */
  477. static struct hda_codec_ops via_patch_ops = {
  478. .build_controls = via_build_controls,
  479. .build_pcms = via_build_pcms,
  480. .init = via_init,
  481. .free = via_free,
  482. #ifdef CONFIG_PM
  483. .resume = via_resume,
  484. #endif
  485. };
  486. /* fill in the dac_nids table from the parsed pin configuration */
  487. static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
  488. const struct auto_pin_cfg *cfg)
  489. {
  490. int i;
  491. hda_nid_t nid;
  492. spec->multiout.num_dacs = cfg->line_outs;
  493. spec->multiout.dac_nids = spec->private_dac_nids;
  494. for(i = 0; i < 4; i++) {
  495. nid = cfg->line_out_pins[i];
  496. if (nid) {
  497. /* config dac list */
  498. switch (i) {
  499. case AUTO_SEQ_FRONT:
  500. spec->multiout.dac_nids[i] = 0x10;
  501. break;
  502. case AUTO_SEQ_CENLFE:
  503. spec->multiout.dac_nids[i] = 0x12;
  504. break;
  505. case AUTO_SEQ_SURROUND:
  506. spec->multiout.dac_nids[i] = 0x13;
  507. break;
  508. case AUTO_SEQ_SIDE:
  509. spec->multiout.dac_nids[i] = 0x11;
  510. break;
  511. }
  512. }
  513. }
  514. return 0;
  515. }
  516. /* add playback controls from the parsed DAC table */
  517. static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
  518. const struct auto_pin_cfg *cfg)
  519. {
  520. char name[32];
  521. static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
  522. hda_nid_t nid, nid_vol = 0;
  523. int i, err;
  524. for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
  525. nid = cfg->line_out_pins[i];
  526. if (!nid)
  527. continue;
  528. if (i != AUTO_SEQ_FRONT)
  529. nid_vol = 0x1b - i + 1;
  530. if (i == AUTO_SEQ_CENLFE) {
  531. /* Center/LFE */
  532. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  533. "Center Playback Volume",
  534. HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
  535. if (err < 0)
  536. return err;
  537. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  538. "LFE Playback Volume",
  539. HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
  540. if (err < 0)
  541. return err;
  542. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  543. "Center Playback Switch",
  544. HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
  545. if (err < 0)
  546. return err;
  547. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  548. "LFE Playback Switch",
  549. HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
  550. if (err < 0)
  551. return err;
  552. } else if (i == AUTO_SEQ_FRONT){
  553. /* add control to mixer index 0 */
  554. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  555. "Master Front Playback Volume",
  556. HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
  557. if (err < 0)
  558. return err;
  559. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  560. "Master Front Playback Switch",
  561. HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
  562. if (err < 0)
  563. return err;
  564. /* add control to PW3 */
  565. sprintf(name, "%s Playback Volume", chname[i]);
  566. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  567. HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
  568. if (err < 0)
  569. return err;
  570. sprintf(name, "%s Playback Switch", chname[i]);
  571. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  572. HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
  573. if (err < 0)
  574. return err;
  575. } else {
  576. sprintf(name, "%s Playback Volume", chname[i]);
  577. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  578. HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
  579. if (err < 0)
  580. return err;
  581. sprintf(name, "%s Playback Switch", chname[i]);
  582. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  583. HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
  584. if (err < 0)
  585. return err;
  586. }
  587. }
  588. return 0;
  589. }
  590. static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
  591. {
  592. int err;
  593. if (!pin)
  594. return 0;
  595. spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
  596. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  597. "Headphone Playback Volume",
  598. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  599. if (err < 0)
  600. return err;
  601. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  602. "Headphone Playback Switch",
  603. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  604. if (err < 0)
  605. return err;
  606. return 0;
  607. }
  608. /* create playback/capture controls for input pins */
  609. static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
  610. const struct auto_pin_cfg *cfg)
  611. {
  612. static char *labels[] = {
  613. "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
  614. };
  615. struct hda_input_mux *imux = &spec->private_imux;
  616. int i, err, idx = 0;
  617. /* for internal loopback recording select */
  618. imux->items[imux->num_items].label = "Stereo Mixer";
  619. imux->items[imux->num_items].index = idx;
  620. imux->num_items++;
  621. for (i = 0; i < AUTO_PIN_LAST; i++) {
  622. if (!cfg->input_pins[i])
  623. continue;
  624. switch (cfg->input_pins[i]) {
  625. case 0x1d: /* Mic */
  626. idx = 2;
  627. break;
  628. case 0x1e: /* Line In */
  629. idx = 3;
  630. break;
  631. case 0x21: /* Front Mic */
  632. idx = 4;
  633. break;
  634. case 0x24: /* CD */
  635. idx = 1;
  636. break;
  637. }
  638. err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
  639. idx, 0x17);
  640. if (err < 0)
  641. return err;
  642. imux->items[imux->num_items].label = labels[i];
  643. imux->items[imux->num_items].index = idx;
  644. imux->num_items++;
  645. }
  646. return 0;
  647. }
  648. static int vt1708_parse_auto_config(struct hda_codec *codec)
  649. {
  650. struct via_spec *spec = codec->spec;
  651. int err;
  652. err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
  653. if (err < 0)
  654. return err;
  655. err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
  656. if (err < 0)
  657. return err;
  658. if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
  659. return 0; /* can't find valid BIOS pin config */
  660. err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
  661. if (err < 0)
  662. return err;
  663. err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
  664. if (err < 0)
  665. return err;
  666. err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
  667. if (err < 0)
  668. return err;
  669. spec->multiout.max_channels = spec->multiout.num_dacs * 2;
  670. if (spec->autocfg.dig_out_pin)
  671. spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
  672. if (spec->autocfg.dig_in_pin)
  673. spec->dig_in_nid = VT1708_DIGIN_NID;
  674. if (spec->kctl_alloc)
  675. spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
  676. spec->init_verbs = vt1708_volume_init_verbs;
  677. spec->input_mux = &spec->private_imux;
  678. return 1;
  679. }
  680. /* init callback for auto-configuration model -- overriding the default init */
  681. static int via_auto_init(struct hda_codec *codec)
  682. {
  683. via_init(codec);
  684. via_auto_init_multi_out(codec);
  685. via_auto_init_hp_out(codec);
  686. via_auto_init_analog_input(codec);
  687. return 0;
  688. }
  689. static int patch_vt1708(struct hda_codec *codec)
  690. {
  691. struct via_spec *spec;
  692. int err;
  693. /* create a codec specific record */
  694. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  695. if (spec == NULL)
  696. return -ENOMEM;
  697. codec->spec = spec;
  698. /* automatic parse from the BIOS config */
  699. err = vt1708_parse_auto_config(codec);
  700. if (err < 0) {
  701. via_free(codec);
  702. return err;
  703. } else if (!err) {
  704. printk(KERN_INFO "hda_codec: Cannot set up configuration "
  705. "from BIOS. Using genenic mode...\n");
  706. }
  707. spec->stream_name_analog = "VT1708 Analog";
  708. spec->stream_analog_playback = &vt1708_pcm_analog_playback;
  709. spec->stream_analog_capture = &vt1708_pcm_analog_capture;
  710. spec->stream_name_digital = "VT1708 Digital";
  711. spec->stream_digital_playback = &vt1708_pcm_digital_playback;
  712. spec->stream_digital_capture = &vt1708_pcm_digital_capture;
  713. if (!spec->adc_nids && spec->input_mux) {
  714. spec->adc_nids = vt1708_adc_nids;
  715. spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
  716. spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
  717. spec->num_mixers++;
  718. }
  719. codec->patch_ops = via_patch_ops;
  720. codec->patch_ops.init = via_auto_init;
  721. return 0;
  722. }
  723. /* capture mixer elements */
  724. static struct snd_kcontrol_new vt1709_capture_mixer[] = {
  725. HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
  726. HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
  727. HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
  728. HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
  729. HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
  730. HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
  731. {
  732. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  733. /* The multiple "Capture Source" controls confuse alsamixer
  734. * So call somewhat different..
  735. * FIXME: the controls appear in the "playback" view!
  736. */
  737. /* .name = "Capture Source", */
  738. .name = "Input Source",
  739. .count = 1,
  740. .info = via_mux_enum_info,
  741. .get = via_mux_enum_get,
  742. .put = via_mux_enum_put,
  743. },
  744. { } /* end */
  745. };
  746. /*
  747. * generic initialization of ADC, input mixers and output mixers
  748. */
  749. static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
  750. /*
  751. * Unmute ADC0-2 and set the default input to mic-in
  752. */
  753. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  754. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  755. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  756. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
  757. * mixer widget
  758. */
  759. /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
  760. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  761. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  762. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
  763. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
  764. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
  765. /*
  766. * Set up output selector (0x1a, 0x1b, 0x29)
  767. */
  768. /* set vol=0 to output mixers */
  769. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  770. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  771. {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  772. /*
  773. * Unmute PW3 and PW4
  774. */
  775. {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  776. {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  777. /* Set input of PW4 as AOW4 */
  778. {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
  779. /* Set mic as default input of sw0 */
  780. {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
  781. /* PW9 Output enable */
  782. {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  783. { }
  784. };
  785. static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
  786. .substreams = 1,
  787. .channels_min = 2,
  788. .channels_max = 10,
  789. .nid = 0x10, /* NID to query formats and rates */
  790. .ops = {
  791. .open = via_playback_pcm_open,
  792. .prepare = via_playback_pcm_prepare,
  793. .cleanup = via_playback_pcm_cleanup
  794. },
  795. };
  796. static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
  797. .substreams = 1,
  798. .channels_min = 2,
  799. .channels_max = 6,
  800. .nid = 0x10, /* NID to query formats and rates */
  801. .ops = {
  802. .open = via_playback_pcm_open,
  803. .prepare = via_playback_pcm_prepare,
  804. .cleanup = via_playback_pcm_cleanup
  805. },
  806. };
  807. static struct hda_pcm_stream vt1709_pcm_analog_capture = {
  808. .substreams = 2,
  809. .channels_min = 2,
  810. .channels_max = 2,
  811. .nid = 0x14, /* NID to query formats and rates */
  812. .ops = {
  813. .prepare = via_capture_pcm_prepare,
  814. .cleanup = via_capture_pcm_cleanup
  815. },
  816. };
  817. static struct hda_pcm_stream vt1709_pcm_digital_playback = {
  818. .substreams = 1,
  819. .channels_min = 2,
  820. .channels_max = 2,
  821. /* NID is set in via_build_pcms */
  822. .ops = {
  823. .open = via_dig_playback_pcm_open,
  824. .close = via_dig_playback_pcm_close
  825. },
  826. };
  827. static struct hda_pcm_stream vt1709_pcm_digital_capture = {
  828. .substreams = 1,
  829. .channels_min = 2,
  830. .channels_max = 2,
  831. };
  832. static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
  833. const struct auto_pin_cfg *cfg)
  834. {
  835. int i;
  836. hda_nid_t nid;
  837. if (cfg->line_outs == 4) /* 10 channels */
  838. spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
  839. else if (cfg->line_outs == 3) /* 6 channels */
  840. spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
  841. spec->multiout.dac_nids = spec->private_dac_nids;
  842. if (cfg->line_outs == 4) { /* 10 channels */
  843. for (i = 0; i < cfg->line_outs; i++) {
  844. nid = cfg->line_out_pins[i];
  845. if (nid) {
  846. /* config dac list */
  847. switch (i) {
  848. case AUTO_SEQ_FRONT:
  849. /* AOW0 */
  850. spec->multiout.dac_nids[i] = 0x10;
  851. break;
  852. case AUTO_SEQ_CENLFE:
  853. /* AOW2 */
  854. spec->multiout.dac_nids[i] = 0x12;
  855. break;
  856. case AUTO_SEQ_SURROUND:
  857. /* AOW3 */
  858. spec->multiout.dac_nids[i] = 0x27;
  859. break;
  860. case AUTO_SEQ_SIDE:
  861. /* AOW1 */
  862. spec->multiout.dac_nids[i] = 0x11;
  863. break;
  864. default:
  865. break;
  866. }
  867. }
  868. }
  869. spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
  870. } else if (cfg->line_outs == 3) { /* 6 channels */
  871. for(i = 0; i < cfg->line_outs; i++) {
  872. nid = cfg->line_out_pins[i];
  873. if (nid) {
  874. /* config dac list */
  875. switch(i) {
  876. case AUTO_SEQ_FRONT:
  877. /* AOW0 */
  878. spec->multiout.dac_nids[i] = 0x10;
  879. break;
  880. case AUTO_SEQ_CENLFE:
  881. /* AOW2 */
  882. spec->multiout.dac_nids[i] = 0x12;
  883. break;
  884. case AUTO_SEQ_SURROUND:
  885. /* AOW1 */
  886. spec->multiout.dac_nids[i] = 0x11;
  887. break;
  888. default:
  889. break;
  890. }
  891. }
  892. }
  893. }
  894. return 0;
  895. }
  896. /* add playback controls from the parsed DAC table */
  897. static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
  898. const struct auto_pin_cfg *cfg)
  899. {
  900. char name[32];
  901. static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
  902. hda_nid_t nid = 0;
  903. int i, err;
  904. for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
  905. nid = cfg->line_out_pins[i];
  906. if (!nid)
  907. continue;
  908. if (i == AUTO_SEQ_CENLFE) {
  909. /* Center/LFE */
  910. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  911. "Center Playback Volume",
  912. HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
  913. if (err < 0)
  914. return err;
  915. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  916. "LFE Playback Volume",
  917. HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
  918. if (err < 0)
  919. return err;
  920. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  921. "Center Playback Switch",
  922. HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
  923. if (err < 0)
  924. return err;
  925. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  926. "LFE Playback Switch",
  927. HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
  928. if (err < 0)
  929. return err;
  930. } else if (i == AUTO_SEQ_FRONT){
  931. /* add control to mixer index 0 */
  932. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  933. "Master Front Playback Volume",
  934. HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
  935. if (err < 0)
  936. return err;
  937. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  938. "Master Front Playback Switch",
  939. HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
  940. if (err < 0)
  941. return err;
  942. /* add control to PW3 */
  943. sprintf(name, "%s Playback Volume", chname[i]);
  944. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  945. HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
  946. if (err < 0)
  947. return err;
  948. sprintf(name, "%s Playback Switch", chname[i]);
  949. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  950. HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
  951. if (err < 0)
  952. return err;
  953. } else if (i == AUTO_SEQ_SURROUND) {
  954. sprintf(name, "%s Playback Volume", chname[i]);
  955. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  956. HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
  957. if (err < 0)
  958. return err;
  959. sprintf(name, "%s Playback Switch", chname[i]);
  960. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  961. HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
  962. if (err < 0)
  963. return err;
  964. } else if (i == AUTO_SEQ_SIDE) {
  965. sprintf(name, "%s Playback Volume", chname[i]);
  966. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  967. HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
  968. if (err < 0)
  969. return err;
  970. sprintf(name, "%s Playback Switch", chname[i]);
  971. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  972. HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
  973. if (err < 0)
  974. return err;
  975. }
  976. }
  977. return 0;
  978. }
  979. static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
  980. {
  981. int err;
  982. if (!pin)
  983. return 0;
  984. if (spec->multiout.num_dacs == 5) /* 10 channels */
  985. spec->multiout.hp_nid = VT1709_HP_DAC_NID;
  986. else if (spec->multiout.num_dacs == 3) /* 6 channels */
  987. spec->multiout.hp_nid = 0;
  988. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  989. "Headphone Playback Volume",
  990. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  991. if (err < 0)
  992. return err;
  993. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  994. "Headphone Playback Switch",
  995. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  996. if (err < 0)
  997. return err;
  998. return 0;
  999. }
  1000. /* create playback/capture controls for input pins */
  1001. static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
  1002. const struct auto_pin_cfg *cfg)
  1003. {
  1004. static char *labels[] = {
  1005. "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
  1006. };
  1007. struct hda_input_mux *imux = &spec->private_imux;
  1008. int i, err, idx = 0;
  1009. /* for internal loopback recording select */
  1010. imux->items[imux->num_items].label = "Stereo Mixer";
  1011. imux->items[imux->num_items].index = idx;
  1012. imux->num_items++;
  1013. for (i = 0; i < AUTO_PIN_LAST; i++) {
  1014. if (!cfg->input_pins[i])
  1015. continue;
  1016. switch (cfg->input_pins[i]) {
  1017. case 0x1d: /* Mic */
  1018. idx = 2;
  1019. break;
  1020. case 0x1e: /* Line In */
  1021. idx = 3;
  1022. break;
  1023. case 0x21: /* Front Mic */
  1024. idx = 4;
  1025. break;
  1026. case 0x23: /* CD */
  1027. idx = 1;
  1028. break;
  1029. }
  1030. err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
  1031. idx, 0x18);
  1032. if (err < 0)
  1033. return err;
  1034. imux->items[imux->num_items].label = labels[i];
  1035. imux->items[imux->num_items].index = idx;
  1036. imux->num_items++;
  1037. }
  1038. return 0;
  1039. }
  1040. static int vt1709_parse_auto_config(struct hda_codec *codec)
  1041. {
  1042. struct via_spec *spec = codec->spec;
  1043. int err;
  1044. err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
  1045. if (err < 0)
  1046. return err;
  1047. err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
  1048. if (err < 0)
  1049. return err;
  1050. if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
  1051. return 0; /* can't find valid BIOS pin config */
  1052. err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
  1053. if (err < 0)
  1054. return err;
  1055. err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
  1056. if (err < 0)
  1057. return err;
  1058. err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
  1059. if (err < 0)
  1060. return err;
  1061. spec->multiout.max_channels = spec->multiout.num_dacs * 2;
  1062. if (spec->autocfg.dig_out_pin)
  1063. spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
  1064. if (spec->autocfg.dig_in_pin)
  1065. spec->dig_in_nid = VT1709_DIGIN_NID;
  1066. if (spec->kctl_alloc)
  1067. spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
  1068. spec->input_mux = &spec->private_imux;
  1069. return 1;
  1070. }
  1071. static int patch_vt1709_10ch(struct hda_codec *codec)
  1072. {
  1073. struct via_spec *spec;
  1074. int err;
  1075. /* create a codec specific record */
  1076. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  1077. if (spec == NULL)
  1078. return -ENOMEM;
  1079. codec->spec = spec;
  1080. err = vt1709_parse_auto_config(codec);
  1081. if (err < 0) {
  1082. via_free(codec);
  1083. return err;
  1084. } else if (!err) {
  1085. printk(KERN_INFO "hda_codec: Cannot set up configuration. "
  1086. "Using genenic mode...\n");
  1087. }
  1088. spec->init_verbs = vt1709_10ch_volume_init_verbs;
  1089. spec->stream_name_analog = "VT1709 Analog";
  1090. spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
  1091. spec->stream_analog_capture = &vt1709_pcm_analog_capture;
  1092. spec->stream_name_digital = "VT1709 Digital";
  1093. spec->stream_digital_playback = &vt1709_pcm_digital_playback;
  1094. spec->stream_digital_capture = &vt1709_pcm_digital_capture;
  1095. if (!spec->adc_nids && spec->input_mux) {
  1096. spec->adc_nids = vt1709_adc_nids;
  1097. spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
  1098. spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
  1099. spec->num_mixers++;
  1100. }
  1101. codec->patch_ops = via_patch_ops;
  1102. codec->patch_ops.init = via_auto_init;
  1103. return 0;
  1104. }
  1105. /*
  1106. * generic initialization of ADC, input mixers and output mixers
  1107. */
  1108. static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
  1109. /*
  1110. * Unmute ADC0-2 and set the default input to mic-in
  1111. */
  1112. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1113. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1114. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1115. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
  1116. * mixer widget
  1117. */
  1118. /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
  1119. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1120. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  1121. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
  1122. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
  1123. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
  1124. /*
  1125. * Set up output selector (0x1a, 0x1b, 0x29)
  1126. */
  1127. /* set vol=0 to output mixers */
  1128. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1129. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1130. {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1131. /*
  1132. * Unmute PW3 and PW4
  1133. */
  1134. {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1135. {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1136. /* Set input of PW4 as MW0 */
  1137. {0x20, AC_VERB_SET_CONNECT_SEL, 0},
  1138. /* Set mic as default input of sw0 */
  1139. {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
  1140. /* PW9 Output enable */
  1141. {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1142. { }
  1143. };
  1144. static int patch_vt1709_6ch(struct hda_codec *codec)
  1145. {
  1146. struct via_spec *spec;
  1147. int err;
  1148. /* create a codec specific record */
  1149. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  1150. if (spec == NULL)
  1151. return -ENOMEM;
  1152. codec->spec = spec;
  1153. err = vt1709_parse_auto_config(codec);
  1154. if (err < 0) {
  1155. via_free(codec);
  1156. return err;
  1157. } else if (!err) {
  1158. printk(KERN_INFO "hda_codec: Cannot set up configuration. "
  1159. "Using genenic mode...\n");
  1160. }
  1161. spec->init_verbs = vt1709_6ch_volume_init_verbs;
  1162. spec->stream_name_analog = "VT1709 Analog";
  1163. spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
  1164. spec->stream_analog_capture = &vt1709_pcm_analog_capture;
  1165. spec->stream_name_digital = "VT1709 Digital";
  1166. spec->stream_digital_playback = &vt1709_pcm_digital_playback;
  1167. spec->stream_digital_capture = &vt1709_pcm_digital_capture;
  1168. if (!spec->adc_nids && spec->input_mux) {
  1169. spec->adc_nids = vt1709_adc_nids;
  1170. spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
  1171. spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
  1172. spec->num_mixers++;
  1173. }
  1174. codec->patch_ops = via_patch_ops;
  1175. codec->patch_ops.init = via_auto_init;
  1176. return 0;
  1177. }
  1178. /*
  1179. * patch entries
  1180. */
  1181. struct hda_codec_preset snd_hda_preset_via[] = {
  1182. { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
  1183. { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
  1184. { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
  1185. { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
  1186. { .id = 0x1106E710, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
  1187. { .id = 0x1106E711, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
  1188. { .id = 0x1106E712, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
  1189. { .id = 0x1106E713, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
  1190. { .id = 0x1106E714, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
  1191. { .id = 0x1106E715, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
  1192. { .id = 0x1106E716, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
  1193. { .id = 0x1106E717, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
  1194. {} /* terminator */
  1195. };