patch_via.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002
  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. /* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */
  30. /* 2007-09-17 Lydia Wang Add VT1708B codec support */
  31. /* */
  32. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  33. #include <sound/driver.h>
  34. #include <linux/init.h>
  35. #include <linux/delay.h>
  36. #include <linux/slab.h>
  37. #include <sound/core.h>
  38. #include "hda_codec.h"
  39. #include "hda_local.h"
  40. /* amp values */
  41. #define AMP_VAL_IDX_SHIFT 19
  42. #define AMP_VAL_IDX_MASK (0x0f<<19)
  43. #define NUM_CONTROL_ALLOC 32
  44. #define NUM_VERB_ALLOC 32
  45. /* Pin Widget NID */
  46. #define VT1708_HP_NID 0x13
  47. #define VT1708_DIGOUT_NID 0x14
  48. #define VT1708_DIGIN_NID 0x16
  49. #define VT1708_DIGIN_PIN 0x26
  50. #define VT1709_HP_DAC_NID 0x28
  51. #define VT1709_DIGOUT_NID 0x13
  52. #define VT1709_DIGIN_NID 0x17
  53. #define VT1709_DIGIN_PIN 0x25
  54. #define VT1708B_HP_NID 0x25
  55. #define VT1708B_DIGOUT_NID 0x12
  56. #define VT1708B_DIGIN_NID 0x15
  57. #define VT1708B_DIGIN_PIN 0x21
  58. #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
  59. #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
  60. #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
  61. #define IS_VT1708B_8CH_VENDORID(x) ((x) >= 0x1106e720 && (x) <= 0x1106e723)
  62. #define IS_VT1708B_4CH_VENDORID(x) ((x) >= 0x1106e724 && (x) <= 0x1106e727)
  63. enum {
  64. VIA_CTL_WIDGET_VOL,
  65. VIA_CTL_WIDGET_MUTE,
  66. };
  67. enum {
  68. AUTO_SEQ_FRONT,
  69. AUTO_SEQ_SURROUND,
  70. AUTO_SEQ_CENLFE,
  71. AUTO_SEQ_SIDE
  72. };
  73. static struct snd_kcontrol_new vt1708_control_templates[] = {
  74. HDA_CODEC_VOLUME(NULL, 0, 0, 0),
  75. HDA_CODEC_MUTE(NULL, 0, 0, 0),
  76. };
  77. struct via_spec {
  78. /* codec parameterization */
  79. struct snd_kcontrol_new *mixers[3];
  80. unsigned int num_mixers;
  81. struct hda_verb *init_verbs;
  82. char *stream_name_analog;
  83. struct hda_pcm_stream *stream_analog_playback;
  84. struct hda_pcm_stream *stream_analog_capture;
  85. char *stream_name_digital;
  86. struct hda_pcm_stream *stream_digital_playback;
  87. struct hda_pcm_stream *stream_digital_capture;
  88. /* playback */
  89. struct hda_multi_out multiout;
  90. /* capture */
  91. unsigned int num_adc_nids;
  92. hda_nid_t *adc_nids;
  93. hda_nid_t dig_in_nid;
  94. /* capture source */
  95. const struct hda_input_mux *input_mux;
  96. unsigned int cur_mux[3];
  97. /* PCM information */
  98. struct hda_pcm pcm_rec[2];
  99. /* dynamic controls, init_verbs and input_mux */
  100. struct auto_pin_cfg autocfg;
  101. unsigned int num_kctl_alloc, num_kctl_used;
  102. struct snd_kcontrol_new *kctl_alloc;
  103. struct hda_input_mux private_imux;
  104. hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
  105. #ifdef CONFIG_SND_HDA_POWER_SAVE
  106. struct hda_loopback_check loopback;
  107. #endif
  108. };
  109. static hda_nid_t vt1708_adc_nids[2] = {
  110. /* ADC1-2 */
  111. 0x15, 0x27
  112. };
  113. static hda_nid_t vt1709_adc_nids[3] = {
  114. /* ADC1-2 */
  115. 0x14, 0x15, 0x16
  116. };
  117. static hda_nid_t vt1708B_adc_nids[2] = {
  118. /* ADC1-2 */
  119. 0x13, 0x14
  120. };
  121. /* add dynamic controls */
  122. static int via_add_control(struct via_spec *spec, int type, const char *name,
  123. unsigned long val)
  124. {
  125. struct snd_kcontrol_new *knew;
  126. if (spec->num_kctl_used >= spec->num_kctl_alloc) {
  127. int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
  128. /* array + terminator */
  129. knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
  130. if (!knew)
  131. return -ENOMEM;
  132. if (spec->kctl_alloc) {
  133. memcpy(knew, spec->kctl_alloc,
  134. sizeof(*knew) * spec->num_kctl_alloc);
  135. kfree(spec->kctl_alloc);
  136. }
  137. spec->kctl_alloc = knew;
  138. spec->num_kctl_alloc = num;
  139. }
  140. knew = &spec->kctl_alloc[spec->num_kctl_used];
  141. *knew = vt1708_control_templates[type];
  142. knew->name = kstrdup(name, GFP_KERNEL);
  143. if (!knew->name)
  144. return -ENOMEM;
  145. knew->private_value = val;
  146. spec->num_kctl_used++;
  147. return 0;
  148. }
  149. /* create input playback/capture controls for the given pin */
  150. static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
  151. const char *ctlname, int idx, int mix_nid)
  152. {
  153. char name[32];
  154. int err;
  155. sprintf(name, "%s Playback Volume", ctlname);
  156. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  157. HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
  158. if (err < 0)
  159. return err;
  160. sprintf(name, "%s Playback Switch", ctlname);
  161. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  162. HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
  163. if (err < 0)
  164. return err;
  165. return 0;
  166. }
  167. static void via_auto_set_output_and_unmute(struct hda_codec *codec,
  168. hda_nid_t nid, int pin_type,
  169. int dac_idx)
  170. {
  171. /* set as output */
  172. snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
  173. pin_type);
  174. snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
  175. AMP_OUT_UNMUTE);
  176. }
  177. static void via_auto_init_multi_out(struct hda_codec *codec)
  178. {
  179. struct via_spec *spec = codec->spec;
  180. int i;
  181. for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
  182. hda_nid_t nid = spec->autocfg.line_out_pins[i];
  183. if (nid)
  184. via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
  185. }
  186. }
  187. static void via_auto_init_hp_out(struct hda_codec *codec)
  188. {
  189. struct via_spec *spec = codec->spec;
  190. hda_nid_t pin;
  191. pin = spec->autocfg.hp_pins[0];
  192. if (pin) /* connect to front */
  193. via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
  194. }
  195. static void via_auto_init_analog_input(struct hda_codec *codec)
  196. {
  197. struct via_spec *spec = codec->spec;
  198. int i;
  199. for (i = 0; i < AUTO_PIN_LAST; i++) {
  200. hda_nid_t nid = spec->autocfg.input_pins[i];
  201. snd_hda_codec_write(codec, nid, 0,
  202. AC_VERB_SET_PIN_WIDGET_CONTROL,
  203. (i <= AUTO_PIN_FRONT_MIC ?
  204. PIN_VREF50 : PIN_IN));
  205. }
  206. }
  207. /*
  208. * input MUX handling
  209. */
  210. static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
  211. struct snd_ctl_elem_info *uinfo)
  212. {
  213. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  214. struct via_spec *spec = codec->spec;
  215. return snd_hda_input_mux_info(spec->input_mux, uinfo);
  216. }
  217. static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
  218. struct snd_ctl_elem_value *ucontrol)
  219. {
  220. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  221. struct via_spec *spec = codec->spec;
  222. unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  223. ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
  224. return 0;
  225. }
  226. static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
  227. struct snd_ctl_elem_value *ucontrol)
  228. {
  229. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  230. struct via_spec *spec = codec->spec;
  231. unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  232. unsigned int vendor_id = codec->vendor_id;
  233. /* AIW0 lydia 060801 add for correct sw0 input select */
  234. if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
  235. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  236. 0x18, &spec->cur_mux[adc_idx]);
  237. else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
  238. IS_VT1709_6CH_VENDORID(vendor_id)) && adc_idx == 0)
  239. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  240. 0x19, &spec->cur_mux[adc_idx]);
  241. else if ((IS_VT1708B_8CH_VENDORID(vendor_id) ||
  242. IS_VT1708B_4CH_VENDORID(vendor_id)) && adc_idx == 0)
  243. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  244. 0x17, &spec->cur_mux[adc_idx]);
  245. else
  246. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  247. spec->adc_nids[adc_idx],
  248. &spec->cur_mux[adc_idx]);
  249. }
  250. /* capture mixer elements */
  251. static struct snd_kcontrol_new vt1708_capture_mixer[] = {
  252. HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
  253. HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
  254. HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
  255. HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
  256. {
  257. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  258. /* The multiple "Capture Source" controls confuse alsamixer
  259. * So call somewhat different..
  260. * FIXME: the controls appear in the "playback" view!
  261. */
  262. /* .name = "Capture Source", */
  263. .name = "Input Source",
  264. .count = 1,
  265. .info = via_mux_enum_info,
  266. .get = via_mux_enum_get,
  267. .put = via_mux_enum_put,
  268. },
  269. { } /* end */
  270. };
  271. /*
  272. * generic initialization of ADC, input mixers and output mixers
  273. */
  274. static struct hda_verb vt1708_volume_init_verbs[] = {
  275. /*
  276. * Unmute ADC0-1 and set the default input to mic-in
  277. */
  278. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  279. {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  280. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
  281. * mixer widget
  282. */
  283. /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
  284. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  285. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  286. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
  287. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
  288. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
  289. /*
  290. * Set up output mixers (0x19 - 0x1b)
  291. */
  292. /* set vol=0 to output mixers */
  293. {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  294. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  295. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  296. /* Setup default input to PW4 */
  297. {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
  298. /* PW9 Output enable */
  299. {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  300. { }
  301. };
  302. static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
  303. struct hda_codec *codec,
  304. struct snd_pcm_substream *substream)
  305. {
  306. struct via_spec *spec = codec->spec;
  307. return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
  308. }
  309. static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
  310. struct hda_codec *codec,
  311. unsigned int stream_tag,
  312. unsigned int format,
  313. struct snd_pcm_substream *substream)
  314. {
  315. struct via_spec *spec = codec->spec;
  316. return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
  317. stream_tag, format, substream);
  318. }
  319. static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
  320. struct hda_codec *codec,
  321. struct snd_pcm_substream *substream)
  322. {
  323. struct via_spec *spec = codec->spec;
  324. return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
  325. }
  326. /*
  327. * Digital out
  328. */
  329. static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
  330. struct hda_codec *codec,
  331. struct snd_pcm_substream *substream)
  332. {
  333. struct via_spec *spec = codec->spec;
  334. return snd_hda_multi_out_dig_open(codec, &spec->multiout);
  335. }
  336. static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
  337. struct hda_codec *codec,
  338. struct snd_pcm_substream *substream)
  339. {
  340. struct via_spec *spec = codec->spec;
  341. return snd_hda_multi_out_dig_close(codec, &spec->multiout);
  342. }
  343. static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
  344. struct hda_codec *codec,
  345. unsigned int stream_tag,
  346. unsigned int format,
  347. struct snd_pcm_substream *substream)
  348. {
  349. struct via_spec *spec = codec->spec;
  350. return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
  351. stream_tag, format, substream);
  352. }
  353. /*
  354. * Analog capture
  355. */
  356. static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
  357. struct hda_codec *codec,
  358. unsigned int stream_tag,
  359. unsigned int format,
  360. struct snd_pcm_substream *substream)
  361. {
  362. struct via_spec *spec = codec->spec;
  363. snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
  364. stream_tag, 0, format);
  365. return 0;
  366. }
  367. static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
  368. struct hda_codec *codec,
  369. struct snd_pcm_substream *substream)
  370. {
  371. struct via_spec *spec = codec->spec;
  372. snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
  373. 0, 0, 0);
  374. return 0;
  375. }
  376. static struct hda_pcm_stream vt1708_pcm_analog_playback = {
  377. .substreams = 1,
  378. .channels_min = 2,
  379. .channels_max = 8,
  380. .nid = 0x10, /* NID to query formats and rates */
  381. .ops = {
  382. .open = via_playback_pcm_open,
  383. .prepare = via_playback_pcm_prepare,
  384. .cleanup = via_playback_pcm_cleanup
  385. },
  386. };
  387. static struct hda_pcm_stream vt1708_pcm_analog_capture = {
  388. .substreams = 2,
  389. .channels_min = 2,
  390. .channels_max = 2,
  391. .nid = 0x15, /* NID to query formats and rates */
  392. .ops = {
  393. .prepare = via_capture_pcm_prepare,
  394. .cleanup = via_capture_pcm_cleanup
  395. },
  396. };
  397. static struct hda_pcm_stream vt1708_pcm_digital_playback = {
  398. .substreams = 1,
  399. .channels_min = 2,
  400. .channels_max = 2,
  401. /* NID is set in via_build_pcms */
  402. .ops = {
  403. .open = via_dig_playback_pcm_open,
  404. .close = via_dig_playback_pcm_close,
  405. .prepare = via_dig_playback_pcm_prepare
  406. },
  407. };
  408. static struct hda_pcm_stream vt1708_pcm_digital_capture = {
  409. .substreams = 1,
  410. .channels_min = 2,
  411. .channels_max = 2,
  412. };
  413. static int via_build_controls(struct hda_codec *codec)
  414. {
  415. struct via_spec *spec = codec->spec;
  416. int err;
  417. int i;
  418. for (i = 0; i < spec->num_mixers; i++) {
  419. err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
  420. if (err < 0)
  421. return err;
  422. }
  423. if (spec->multiout.dig_out_nid) {
  424. err = snd_hda_create_spdif_out_ctls(codec,
  425. spec->multiout.dig_out_nid);
  426. if (err < 0)
  427. return err;
  428. }
  429. if (spec->dig_in_nid) {
  430. err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
  431. if (err < 0)
  432. return err;
  433. }
  434. return 0;
  435. }
  436. static int via_build_pcms(struct hda_codec *codec)
  437. {
  438. struct via_spec *spec = codec->spec;
  439. struct hda_pcm *info = spec->pcm_rec;
  440. codec->num_pcms = 1;
  441. codec->pcm_info = info;
  442. info->name = spec->stream_name_analog;
  443. info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
  444. info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
  445. info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
  446. info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
  447. info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
  448. spec->multiout.max_channels;
  449. if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
  450. codec->num_pcms++;
  451. info++;
  452. info->name = spec->stream_name_digital;
  453. if (spec->multiout.dig_out_nid) {
  454. info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
  455. *(spec->stream_digital_playback);
  456. info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
  457. spec->multiout.dig_out_nid;
  458. }
  459. if (spec->dig_in_nid) {
  460. info->stream[SNDRV_PCM_STREAM_CAPTURE] =
  461. *(spec->stream_digital_capture);
  462. info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
  463. spec->dig_in_nid;
  464. }
  465. }
  466. return 0;
  467. }
  468. static void via_free(struct hda_codec *codec)
  469. {
  470. struct via_spec *spec = codec->spec;
  471. unsigned int i;
  472. if (!spec)
  473. return;
  474. if (spec->kctl_alloc) {
  475. for (i = 0; i < spec->num_kctl_used; i++)
  476. kfree(spec->kctl_alloc[i].name);
  477. kfree(spec->kctl_alloc);
  478. }
  479. kfree(codec->spec);
  480. }
  481. static int via_init(struct hda_codec *codec)
  482. {
  483. struct via_spec *spec = codec->spec;
  484. snd_hda_sequence_write(codec, spec->init_verbs);
  485. /* Lydia Add for EAPD enable */
  486. if (!spec->dig_in_nid) { /* No Digital In connection */
  487. if (IS_VT1708_VENDORID(codec->vendor_id)) {
  488. snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
  489. AC_VERB_SET_PIN_WIDGET_CONTROL,
  490. 0x40);
  491. snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
  492. AC_VERB_SET_EAPD_BTLENABLE, 0x02);
  493. } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
  494. IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
  495. snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
  496. AC_VERB_SET_PIN_WIDGET_CONTROL,
  497. 0x40);
  498. snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
  499. AC_VERB_SET_EAPD_BTLENABLE, 0x02);
  500. } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
  501. IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
  502. snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
  503. AC_VERB_SET_PIN_WIDGET_CONTROL,
  504. 0x40);
  505. snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
  506. AC_VERB_SET_EAPD_BTLENABLE, 0x02);
  507. }
  508. }
  509. return 0;
  510. }
  511. #ifdef CONFIG_SND_HDA_POWER_SAVE
  512. static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
  513. {
  514. struct via_spec *spec = codec->spec;
  515. return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
  516. }
  517. #endif
  518. /*
  519. */
  520. static struct hda_codec_ops via_patch_ops = {
  521. .build_controls = via_build_controls,
  522. .build_pcms = via_build_pcms,
  523. .init = via_init,
  524. .free = via_free,
  525. #ifdef CONFIG_SND_HDA_POWER_SAVE
  526. .check_power_status = via_check_power_status,
  527. #endif
  528. };
  529. /* fill in the dac_nids table from the parsed pin configuration */
  530. static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
  531. const struct auto_pin_cfg *cfg)
  532. {
  533. int i;
  534. hda_nid_t nid;
  535. spec->multiout.num_dacs = cfg->line_outs;
  536. spec->multiout.dac_nids = spec->private_dac_nids;
  537. for(i = 0; i < 4; i++) {
  538. nid = cfg->line_out_pins[i];
  539. if (nid) {
  540. /* config dac list */
  541. switch (i) {
  542. case AUTO_SEQ_FRONT:
  543. spec->multiout.dac_nids[i] = 0x10;
  544. break;
  545. case AUTO_SEQ_CENLFE:
  546. spec->multiout.dac_nids[i] = 0x12;
  547. break;
  548. case AUTO_SEQ_SURROUND:
  549. spec->multiout.dac_nids[i] = 0x13;
  550. break;
  551. case AUTO_SEQ_SIDE:
  552. spec->multiout.dac_nids[i] = 0x11;
  553. break;
  554. }
  555. }
  556. }
  557. return 0;
  558. }
  559. /* add playback controls from the parsed DAC table */
  560. static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
  561. const struct auto_pin_cfg *cfg)
  562. {
  563. char name[32];
  564. static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
  565. hda_nid_t nid, nid_vol = 0;
  566. int i, err;
  567. for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
  568. nid = cfg->line_out_pins[i];
  569. if (!nid)
  570. continue;
  571. if (i != AUTO_SEQ_FRONT)
  572. nid_vol = 0x1b - i + 1;
  573. if (i == AUTO_SEQ_CENLFE) {
  574. /* Center/LFE */
  575. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  576. "Center Playback Volume",
  577. HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
  578. HDA_OUTPUT));
  579. if (err < 0)
  580. return err;
  581. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  582. "LFE Playback Volume",
  583. HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
  584. HDA_OUTPUT));
  585. if (err < 0)
  586. return err;
  587. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  588. "Center Playback Switch",
  589. HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
  590. HDA_OUTPUT));
  591. if (err < 0)
  592. return err;
  593. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  594. "LFE Playback Switch",
  595. HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
  596. HDA_OUTPUT));
  597. if (err < 0)
  598. return err;
  599. } else if (i == AUTO_SEQ_FRONT){
  600. /* add control to mixer index 0 */
  601. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  602. "Master Front Playback Volume",
  603. HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
  604. HDA_INPUT));
  605. if (err < 0)
  606. return err;
  607. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  608. "Master Front Playback Switch",
  609. HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
  610. HDA_INPUT));
  611. if (err < 0)
  612. return err;
  613. /* add control to PW3 */
  614. sprintf(name, "%s Playback Volume", chname[i]);
  615. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  616. HDA_COMPOSE_AMP_VAL(nid, 3, 0,
  617. HDA_OUTPUT));
  618. if (err < 0)
  619. return err;
  620. sprintf(name, "%s Playback Switch", chname[i]);
  621. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  622. HDA_COMPOSE_AMP_VAL(nid, 3, 0,
  623. HDA_OUTPUT));
  624. if (err < 0)
  625. return err;
  626. } else {
  627. sprintf(name, "%s Playback Volume", chname[i]);
  628. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  629. HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
  630. HDA_OUTPUT));
  631. if (err < 0)
  632. return err;
  633. sprintf(name, "%s Playback Switch", chname[i]);
  634. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  635. HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
  636. HDA_OUTPUT));
  637. if (err < 0)
  638. return err;
  639. }
  640. }
  641. return 0;
  642. }
  643. static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
  644. {
  645. int err;
  646. if (!pin)
  647. return 0;
  648. spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
  649. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  650. "Headphone Playback Volume",
  651. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  652. if (err < 0)
  653. return err;
  654. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  655. "Headphone Playback Switch",
  656. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  657. if (err < 0)
  658. return err;
  659. return 0;
  660. }
  661. /* create playback/capture controls for input pins */
  662. static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
  663. const struct auto_pin_cfg *cfg)
  664. {
  665. static char *labels[] = {
  666. "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
  667. };
  668. struct hda_input_mux *imux = &spec->private_imux;
  669. int i, err, idx = 0;
  670. /* for internal loopback recording select */
  671. imux->items[imux->num_items].label = "Stereo Mixer";
  672. imux->items[imux->num_items].index = idx;
  673. imux->num_items++;
  674. for (i = 0; i < AUTO_PIN_LAST; i++) {
  675. if (!cfg->input_pins[i])
  676. continue;
  677. switch (cfg->input_pins[i]) {
  678. case 0x1d: /* Mic */
  679. idx = 2;
  680. break;
  681. case 0x1e: /* Line In */
  682. idx = 3;
  683. break;
  684. case 0x21: /* Front Mic */
  685. idx = 4;
  686. break;
  687. case 0x24: /* CD */
  688. idx = 1;
  689. break;
  690. }
  691. err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
  692. idx, 0x17);
  693. if (err < 0)
  694. return err;
  695. imux->items[imux->num_items].label = labels[i];
  696. imux->items[imux->num_items].index = idx;
  697. imux->num_items++;
  698. }
  699. return 0;
  700. }
  701. #ifdef CONFIG_SND_HDA_POWER_SAVE
  702. static struct hda_amp_list vt1708_loopbacks[] = {
  703. { 0x17, HDA_INPUT, 1 },
  704. { 0x17, HDA_INPUT, 2 },
  705. { 0x17, HDA_INPUT, 3 },
  706. { 0x17, HDA_INPUT, 4 },
  707. { } /* end */
  708. };
  709. #endif
  710. static int vt1708_parse_auto_config(struct hda_codec *codec)
  711. {
  712. struct via_spec *spec = codec->spec;
  713. int err;
  714. err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
  715. if (err < 0)
  716. return err;
  717. err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
  718. if (err < 0)
  719. return err;
  720. if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
  721. return 0; /* can't find valid BIOS pin config */
  722. err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
  723. if (err < 0)
  724. return err;
  725. err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
  726. if (err < 0)
  727. return err;
  728. err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
  729. if (err < 0)
  730. return err;
  731. spec->multiout.max_channels = spec->multiout.num_dacs * 2;
  732. if (spec->autocfg.dig_out_pin)
  733. spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
  734. if (spec->autocfg.dig_in_pin)
  735. spec->dig_in_nid = VT1708_DIGIN_NID;
  736. if (spec->kctl_alloc)
  737. spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
  738. spec->init_verbs = vt1708_volume_init_verbs;
  739. spec->input_mux = &spec->private_imux;
  740. return 1;
  741. }
  742. /* init callback for auto-configuration model -- overriding the default init */
  743. static int via_auto_init(struct hda_codec *codec)
  744. {
  745. via_init(codec);
  746. via_auto_init_multi_out(codec);
  747. via_auto_init_hp_out(codec);
  748. via_auto_init_analog_input(codec);
  749. return 0;
  750. }
  751. static int patch_vt1708(struct hda_codec *codec)
  752. {
  753. struct via_spec *spec;
  754. int err;
  755. /* create a codec specific record */
  756. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  757. if (spec == NULL)
  758. return -ENOMEM;
  759. codec->spec = spec;
  760. /* automatic parse from the BIOS config */
  761. err = vt1708_parse_auto_config(codec);
  762. if (err < 0) {
  763. via_free(codec);
  764. return err;
  765. } else if (!err) {
  766. printk(KERN_INFO "hda_codec: Cannot set up configuration "
  767. "from BIOS. Using genenic mode...\n");
  768. }
  769. spec->stream_name_analog = "VT1708 Analog";
  770. spec->stream_analog_playback = &vt1708_pcm_analog_playback;
  771. spec->stream_analog_capture = &vt1708_pcm_analog_capture;
  772. spec->stream_name_digital = "VT1708 Digital";
  773. spec->stream_digital_playback = &vt1708_pcm_digital_playback;
  774. spec->stream_digital_capture = &vt1708_pcm_digital_capture;
  775. if (!spec->adc_nids && spec->input_mux) {
  776. spec->adc_nids = vt1708_adc_nids;
  777. spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
  778. spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
  779. spec->num_mixers++;
  780. }
  781. codec->patch_ops = via_patch_ops;
  782. codec->patch_ops.init = via_auto_init;
  783. #ifdef CONFIG_SND_HDA_POWER_SAVE
  784. spec->loopback.amplist = vt1708_loopbacks;
  785. #endif
  786. return 0;
  787. }
  788. /* capture mixer elements */
  789. static struct snd_kcontrol_new vt1709_capture_mixer[] = {
  790. HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
  791. HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
  792. HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
  793. HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
  794. HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
  795. HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
  796. {
  797. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  798. /* The multiple "Capture Source" controls confuse alsamixer
  799. * So call somewhat different..
  800. * FIXME: the controls appear in the "playback" view!
  801. */
  802. /* .name = "Capture Source", */
  803. .name = "Input Source",
  804. .count = 1,
  805. .info = via_mux_enum_info,
  806. .get = via_mux_enum_get,
  807. .put = via_mux_enum_put,
  808. },
  809. { } /* end */
  810. };
  811. /*
  812. * generic initialization of ADC, input mixers and output mixers
  813. */
  814. static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
  815. /*
  816. * Unmute ADC0-2 and set the default input to mic-in
  817. */
  818. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  819. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  820. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  821. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
  822. * mixer widget
  823. */
  824. /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
  825. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  826. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  827. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
  828. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
  829. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
  830. /*
  831. * Set up output selector (0x1a, 0x1b, 0x29)
  832. */
  833. /* set vol=0 to output mixers */
  834. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  835. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  836. {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  837. /*
  838. * Unmute PW3 and PW4
  839. */
  840. {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  841. {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  842. /* Set input of PW4 as AOW4 */
  843. {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
  844. /* PW9 Output enable */
  845. {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  846. { }
  847. };
  848. static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
  849. .substreams = 1,
  850. .channels_min = 2,
  851. .channels_max = 10,
  852. .nid = 0x10, /* NID to query formats and rates */
  853. .ops = {
  854. .open = via_playback_pcm_open,
  855. .prepare = via_playback_pcm_prepare,
  856. .cleanup = via_playback_pcm_cleanup
  857. },
  858. };
  859. static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
  860. .substreams = 1,
  861. .channels_min = 2,
  862. .channels_max = 6,
  863. .nid = 0x10, /* NID to query formats and rates */
  864. .ops = {
  865. .open = via_playback_pcm_open,
  866. .prepare = via_playback_pcm_prepare,
  867. .cleanup = via_playback_pcm_cleanup
  868. },
  869. };
  870. static struct hda_pcm_stream vt1709_pcm_analog_capture = {
  871. .substreams = 2,
  872. .channels_min = 2,
  873. .channels_max = 2,
  874. .nid = 0x14, /* NID to query formats and rates */
  875. .ops = {
  876. .prepare = via_capture_pcm_prepare,
  877. .cleanup = via_capture_pcm_cleanup
  878. },
  879. };
  880. static struct hda_pcm_stream vt1709_pcm_digital_playback = {
  881. .substreams = 1,
  882. .channels_min = 2,
  883. .channels_max = 2,
  884. /* NID is set in via_build_pcms */
  885. .ops = {
  886. .open = via_dig_playback_pcm_open,
  887. .close = via_dig_playback_pcm_close
  888. },
  889. };
  890. static struct hda_pcm_stream vt1709_pcm_digital_capture = {
  891. .substreams = 1,
  892. .channels_min = 2,
  893. .channels_max = 2,
  894. };
  895. static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
  896. const struct auto_pin_cfg *cfg)
  897. {
  898. int i;
  899. hda_nid_t nid;
  900. if (cfg->line_outs == 4) /* 10 channels */
  901. spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
  902. else if (cfg->line_outs == 3) /* 6 channels */
  903. spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
  904. spec->multiout.dac_nids = spec->private_dac_nids;
  905. if (cfg->line_outs == 4) { /* 10 channels */
  906. for (i = 0; i < cfg->line_outs; i++) {
  907. nid = cfg->line_out_pins[i];
  908. if (nid) {
  909. /* config dac list */
  910. switch (i) {
  911. case AUTO_SEQ_FRONT:
  912. /* AOW0 */
  913. spec->multiout.dac_nids[i] = 0x10;
  914. break;
  915. case AUTO_SEQ_CENLFE:
  916. /* AOW2 */
  917. spec->multiout.dac_nids[i] = 0x12;
  918. break;
  919. case AUTO_SEQ_SURROUND:
  920. /* AOW3 */
  921. spec->multiout.dac_nids[i] = 0x27;
  922. break;
  923. case AUTO_SEQ_SIDE:
  924. /* AOW1 */
  925. spec->multiout.dac_nids[i] = 0x11;
  926. break;
  927. default:
  928. break;
  929. }
  930. }
  931. }
  932. spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
  933. } else if (cfg->line_outs == 3) { /* 6 channels */
  934. for(i = 0; i < cfg->line_outs; i++) {
  935. nid = cfg->line_out_pins[i];
  936. if (nid) {
  937. /* config dac list */
  938. switch(i) {
  939. case AUTO_SEQ_FRONT:
  940. /* AOW0 */
  941. spec->multiout.dac_nids[i] = 0x10;
  942. break;
  943. case AUTO_SEQ_CENLFE:
  944. /* AOW2 */
  945. spec->multiout.dac_nids[i] = 0x12;
  946. break;
  947. case AUTO_SEQ_SURROUND:
  948. /* AOW1 */
  949. spec->multiout.dac_nids[i] = 0x11;
  950. break;
  951. default:
  952. break;
  953. }
  954. }
  955. }
  956. }
  957. return 0;
  958. }
  959. /* add playback controls from the parsed DAC table */
  960. static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
  961. const struct auto_pin_cfg *cfg)
  962. {
  963. char name[32];
  964. static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
  965. hda_nid_t nid = 0;
  966. int i, err;
  967. for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
  968. nid = cfg->line_out_pins[i];
  969. if (!nid)
  970. continue;
  971. if (i == AUTO_SEQ_CENLFE) {
  972. /* Center/LFE */
  973. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  974. "Center Playback Volume",
  975. HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
  976. HDA_OUTPUT));
  977. if (err < 0)
  978. return err;
  979. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  980. "LFE Playback Volume",
  981. HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
  982. HDA_OUTPUT));
  983. if (err < 0)
  984. return err;
  985. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  986. "Center Playback Switch",
  987. HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
  988. HDA_OUTPUT));
  989. if (err < 0)
  990. return err;
  991. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  992. "LFE Playback Switch",
  993. HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
  994. HDA_OUTPUT));
  995. if (err < 0)
  996. return err;
  997. } else if (i == AUTO_SEQ_FRONT){
  998. /* add control to mixer index 0 */
  999. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  1000. "Master Front Playback Volume",
  1001. HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
  1002. HDA_INPUT));
  1003. if (err < 0)
  1004. return err;
  1005. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  1006. "Master Front Playback Switch",
  1007. HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
  1008. HDA_INPUT));
  1009. if (err < 0)
  1010. return err;
  1011. /* add control to PW3 */
  1012. sprintf(name, "%s Playback Volume", chname[i]);
  1013. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  1014. HDA_COMPOSE_AMP_VAL(nid, 3, 0,
  1015. HDA_OUTPUT));
  1016. if (err < 0)
  1017. return err;
  1018. sprintf(name, "%s Playback Switch", chname[i]);
  1019. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  1020. HDA_COMPOSE_AMP_VAL(nid, 3, 0,
  1021. HDA_OUTPUT));
  1022. if (err < 0)
  1023. return err;
  1024. } else if (i == AUTO_SEQ_SURROUND) {
  1025. sprintf(name, "%s Playback Volume", chname[i]);
  1026. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  1027. HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
  1028. HDA_OUTPUT));
  1029. if (err < 0)
  1030. return err;
  1031. sprintf(name, "%s Playback Switch", chname[i]);
  1032. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  1033. HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
  1034. HDA_OUTPUT));
  1035. if (err < 0)
  1036. return err;
  1037. } else if (i == AUTO_SEQ_SIDE) {
  1038. sprintf(name, "%s Playback Volume", chname[i]);
  1039. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  1040. HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
  1041. HDA_OUTPUT));
  1042. if (err < 0)
  1043. return err;
  1044. sprintf(name, "%s Playback Switch", chname[i]);
  1045. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  1046. HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
  1047. HDA_OUTPUT));
  1048. if (err < 0)
  1049. return err;
  1050. }
  1051. }
  1052. return 0;
  1053. }
  1054. static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
  1055. {
  1056. int err;
  1057. if (!pin)
  1058. return 0;
  1059. if (spec->multiout.num_dacs == 5) /* 10 channels */
  1060. spec->multiout.hp_nid = VT1709_HP_DAC_NID;
  1061. else if (spec->multiout.num_dacs == 3) /* 6 channels */
  1062. spec->multiout.hp_nid = 0;
  1063. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  1064. "Headphone Playback Volume",
  1065. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  1066. if (err < 0)
  1067. return err;
  1068. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  1069. "Headphone Playback Switch",
  1070. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  1071. if (err < 0)
  1072. return err;
  1073. return 0;
  1074. }
  1075. /* create playback/capture controls for input pins */
  1076. static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
  1077. const struct auto_pin_cfg *cfg)
  1078. {
  1079. static char *labels[] = {
  1080. "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
  1081. };
  1082. struct hda_input_mux *imux = &spec->private_imux;
  1083. int i, err, idx = 0;
  1084. /* for internal loopback recording select */
  1085. imux->items[imux->num_items].label = "Stereo Mixer";
  1086. imux->items[imux->num_items].index = idx;
  1087. imux->num_items++;
  1088. for (i = 0; i < AUTO_PIN_LAST; i++) {
  1089. if (!cfg->input_pins[i])
  1090. continue;
  1091. switch (cfg->input_pins[i]) {
  1092. case 0x1d: /* Mic */
  1093. idx = 2;
  1094. break;
  1095. case 0x1e: /* Line In */
  1096. idx = 3;
  1097. break;
  1098. case 0x21: /* Front Mic */
  1099. idx = 4;
  1100. break;
  1101. case 0x23: /* CD */
  1102. idx = 1;
  1103. break;
  1104. }
  1105. err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
  1106. idx, 0x18);
  1107. if (err < 0)
  1108. return err;
  1109. imux->items[imux->num_items].label = labels[i];
  1110. imux->items[imux->num_items].index = idx;
  1111. imux->num_items++;
  1112. }
  1113. return 0;
  1114. }
  1115. static int vt1709_parse_auto_config(struct hda_codec *codec)
  1116. {
  1117. struct via_spec *spec = codec->spec;
  1118. int err;
  1119. err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
  1120. if (err < 0)
  1121. return err;
  1122. err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
  1123. if (err < 0)
  1124. return err;
  1125. if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
  1126. return 0; /* can't find valid BIOS pin config */
  1127. err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
  1128. if (err < 0)
  1129. return err;
  1130. err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
  1131. if (err < 0)
  1132. return err;
  1133. err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
  1134. if (err < 0)
  1135. return err;
  1136. spec->multiout.max_channels = spec->multiout.num_dacs * 2;
  1137. if (spec->autocfg.dig_out_pin)
  1138. spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
  1139. if (spec->autocfg.dig_in_pin)
  1140. spec->dig_in_nid = VT1709_DIGIN_NID;
  1141. if (spec->kctl_alloc)
  1142. spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
  1143. spec->input_mux = &spec->private_imux;
  1144. return 1;
  1145. }
  1146. #ifdef CONFIG_SND_HDA_POWER_SAVE
  1147. static struct hda_amp_list vt1709_loopbacks[] = {
  1148. { 0x18, HDA_INPUT, 1 },
  1149. { 0x18, HDA_INPUT, 2 },
  1150. { 0x18, HDA_INPUT, 3 },
  1151. { 0x18, HDA_INPUT, 4 },
  1152. { } /* end */
  1153. };
  1154. #endif
  1155. static int patch_vt1709_10ch(struct hda_codec *codec)
  1156. {
  1157. struct via_spec *spec;
  1158. int err;
  1159. /* create a codec specific record */
  1160. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  1161. if (spec == NULL)
  1162. return -ENOMEM;
  1163. codec->spec = spec;
  1164. err = vt1709_parse_auto_config(codec);
  1165. if (err < 0) {
  1166. via_free(codec);
  1167. return err;
  1168. } else if (!err) {
  1169. printk(KERN_INFO "hda_codec: Cannot set up configuration. "
  1170. "Using genenic mode...\n");
  1171. }
  1172. spec->init_verbs = vt1709_10ch_volume_init_verbs;
  1173. spec->stream_name_analog = "VT1709 Analog";
  1174. spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
  1175. spec->stream_analog_capture = &vt1709_pcm_analog_capture;
  1176. spec->stream_name_digital = "VT1709 Digital";
  1177. spec->stream_digital_playback = &vt1709_pcm_digital_playback;
  1178. spec->stream_digital_capture = &vt1709_pcm_digital_capture;
  1179. if (!spec->adc_nids && spec->input_mux) {
  1180. spec->adc_nids = vt1709_adc_nids;
  1181. spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
  1182. spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
  1183. spec->num_mixers++;
  1184. }
  1185. codec->patch_ops = via_patch_ops;
  1186. codec->patch_ops.init = via_auto_init;
  1187. #ifdef CONFIG_SND_HDA_POWER_SAVE
  1188. spec->loopback.amplist = vt1709_loopbacks;
  1189. #endif
  1190. return 0;
  1191. }
  1192. /*
  1193. * generic initialization of ADC, input mixers and output mixers
  1194. */
  1195. static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
  1196. /*
  1197. * Unmute ADC0-2 and set the default input to mic-in
  1198. */
  1199. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1200. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1201. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1202. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
  1203. * mixer widget
  1204. */
  1205. /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
  1206. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1207. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  1208. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
  1209. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
  1210. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
  1211. /*
  1212. * Set up output selector (0x1a, 0x1b, 0x29)
  1213. */
  1214. /* set vol=0 to output mixers */
  1215. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1216. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1217. {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1218. /*
  1219. * Unmute PW3 and PW4
  1220. */
  1221. {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1222. {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1223. /* Set input of PW4 as MW0 */
  1224. {0x20, AC_VERB_SET_CONNECT_SEL, 0},
  1225. /* PW9 Output enable */
  1226. {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1227. { }
  1228. };
  1229. static int patch_vt1709_6ch(struct hda_codec *codec)
  1230. {
  1231. struct via_spec *spec;
  1232. int err;
  1233. /* create a codec specific record */
  1234. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  1235. if (spec == NULL)
  1236. return -ENOMEM;
  1237. codec->spec = spec;
  1238. err = vt1709_parse_auto_config(codec);
  1239. if (err < 0) {
  1240. via_free(codec);
  1241. return err;
  1242. } else if (!err) {
  1243. printk(KERN_INFO "hda_codec: Cannot set up configuration. "
  1244. "Using genenic mode...\n");
  1245. }
  1246. spec->init_verbs = vt1709_6ch_volume_init_verbs;
  1247. spec->stream_name_analog = "VT1709 Analog";
  1248. spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
  1249. spec->stream_analog_capture = &vt1709_pcm_analog_capture;
  1250. spec->stream_name_digital = "VT1709 Digital";
  1251. spec->stream_digital_playback = &vt1709_pcm_digital_playback;
  1252. spec->stream_digital_capture = &vt1709_pcm_digital_capture;
  1253. if (!spec->adc_nids && spec->input_mux) {
  1254. spec->adc_nids = vt1709_adc_nids;
  1255. spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
  1256. spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
  1257. spec->num_mixers++;
  1258. }
  1259. codec->patch_ops = via_patch_ops;
  1260. codec->patch_ops.init = via_auto_init;
  1261. #ifdef CONFIG_SND_HDA_POWER_SAVE
  1262. spec->loopback.amplist = vt1709_loopbacks;
  1263. #endif
  1264. return 0;
  1265. }
  1266. /* capture mixer elements */
  1267. static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
  1268. HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
  1269. HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
  1270. HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
  1271. HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
  1272. {
  1273. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1274. /* The multiple "Capture Source" controls confuse alsamixer
  1275. * So call somewhat different..
  1276. * FIXME: the controls appear in the "playback" view!
  1277. */
  1278. /* .name = "Capture Source", */
  1279. .name = "Input Source",
  1280. .count = 1,
  1281. .info = via_mux_enum_info,
  1282. .get = via_mux_enum_get,
  1283. .put = via_mux_enum_put,
  1284. },
  1285. { } /* end */
  1286. };
  1287. /*
  1288. * generic initialization of ADC, input mixers and output mixers
  1289. */
  1290. static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
  1291. /*
  1292. * Unmute ADC0-1 and set the default input to mic-in
  1293. */
  1294. {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1295. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1296. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
  1297. * mixer widget
  1298. */
  1299. /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
  1300. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1301. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  1302. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
  1303. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
  1304. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
  1305. /*
  1306. * Set up output mixers
  1307. */
  1308. /* set vol=0 to output mixers */
  1309. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1310. {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1311. {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1312. /* Setup default input to PW4 */
  1313. {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
  1314. /* PW9 Output enable */
  1315. {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1316. /* PW10 Input enable */
  1317. {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  1318. { }
  1319. };
  1320. static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
  1321. /*
  1322. * Unmute ADC0-1 and set the default input to mic-in
  1323. */
  1324. {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1325. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1326. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
  1327. * mixer widget
  1328. */
  1329. /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
  1330. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
  1331. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
  1332. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
  1333. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
  1334. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
  1335. /*
  1336. * Set up output mixers
  1337. */
  1338. /* set vol=0 to output mixers */
  1339. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1340. {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1341. {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
  1342. /* Setup default input of PW4 to MW0 */
  1343. {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
  1344. /* PW9 Output enable */
  1345. {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1346. /* PW10 Input enable */
  1347. {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  1348. { }
  1349. };
  1350. static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
  1351. .substreams = 1,
  1352. .channels_min = 2,
  1353. .channels_max = 8,
  1354. .nid = 0x10, /* NID to query formats and rates */
  1355. .ops = {
  1356. .open = via_playback_pcm_open,
  1357. .prepare = via_playback_pcm_prepare,
  1358. .cleanup = via_playback_pcm_cleanup
  1359. },
  1360. };
  1361. static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
  1362. .substreams = 1,
  1363. .channels_min = 2,
  1364. .channels_max = 4,
  1365. .nid = 0x10, /* NID to query formats and rates */
  1366. .ops = {
  1367. .open = via_playback_pcm_open,
  1368. .prepare = via_playback_pcm_prepare,
  1369. .cleanup = via_playback_pcm_cleanup
  1370. },
  1371. };
  1372. static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
  1373. .substreams = 2,
  1374. .channels_min = 2,
  1375. .channels_max = 2,
  1376. .nid = 0x13, /* NID to query formats and rates */
  1377. .ops = {
  1378. .prepare = via_capture_pcm_prepare,
  1379. .cleanup = via_capture_pcm_cleanup
  1380. },
  1381. };
  1382. static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
  1383. .substreams = 1,
  1384. .channels_min = 2,
  1385. .channels_max = 2,
  1386. /* NID is set in via_build_pcms */
  1387. .ops = {
  1388. .open = via_dig_playback_pcm_open,
  1389. .close = via_dig_playback_pcm_close,
  1390. .prepare = via_dig_playback_pcm_prepare
  1391. },
  1392. };
  1393. static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
  1394. .substreams = 1,
  1395. .channels_min = 2,
  1396. .channels_max = 2,
  1397. };
  1398. /* fill in the dac_nids table from the parsed pin configuration */
  1399. static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
  1400. const struct auto_pin_cfg *cfg)
  1401. {
  1402. int i;
  1403. hda_nid_t nid;
  1404. spec->multiout.num_dacs = cfg->line_outs;
  1405. spec->multiout.dac_nids = spec->private_dac_nids;
  1406. for (i = 0; i < 4; i++) {
  1407. nid = cfg->line_out_pins[i];
  1408. if (nid) {
  1409. /* config dac list */
  1410. switch (i) {
  1411. case AUTO_SEQ_FRONT:
  1412. spec->multiout.dac_nids[i] = 0x10;
  1413. break;
  1414. case AUTO_SEQ_CENLFE:
  1415. spec->multiout.dac_nids[i] = 0x24;
  1416. break;
  1417. case AUTO_SEQ_SURROUND:
  1418. spec->multiout.dac_nids[i] = 0x25;
  1419. break;
  1420. case AUTO_SEQ_SIDE:
  1421. spec->multiout.dac_nids[i] = 0x11;
  1422. break;
  1423. }
  1424. }
  1425. }
  1426. return 0;
  1427. }
  1428. /* add playback controls from the parsed DAC table */
  1429. static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
  1430. const struct auto_pin_cfg *cfg)
  1431. {
  1432. char name[32];
  1433. static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
  1434. hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18};
  1435. hda_nid_t nid, nid_vol = 0;
  1436. int i, err;
  1437. for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
  1438. nid = cfg->line_out_pins[i];
  1439. if (!nid)
  1440. continue;
  1441. nid_vol = nid_vols[i];
  1442. if (i == AUTO_SEQ_CENLFE) {
  1443. /* Center/LFE */
  1444. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  1445. "Center Playback Volume",
  1446. HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
  1447. HDA_OUTPUT));
  1448. if (err < 0)
  1449. return err;
  1450. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  1451. "LFE Playback Volume",
  1452. HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
  1453. HDA_OUTPUT));
  1454. if (err < 0)
  1455. return err;
  1456. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  1457. "Center Playback Switch",
  1458. HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
  1459. HDA_OUTPUT));
  1460. if (err < 0)
  1461. return err;
  1462. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  1463. "LFE Playback Switch",
  1464. HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
  1465. HDA_OUTPUT));
  1466. if (err < 0)
  1467. return err;
  1468. } else if (i == AUTO_SEQ_FRONT) {
  1469. /* add control to mixer index 0 */
  1470. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  1471. "Master Front Playback Volume",
  1472. HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
  1473. HDA_INPUT));
  1474. if (err < 0)
  1475. return err;
  1476. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  1477. "Master Front Playback Switch",
  1478. HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
  1479. HDA_INPUT));
  1480. if (err < 0)
  1481. return err;
  1482. /* add control to PW3 */
  1483. sprintf(name, "%s Playback Volume", chname[i]);
  1484. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  1485. HDA_COMPOSE_AMP_VAL(nid, 3, 0,
  1486. HDA_OUTPUT));
  1487. if (err < 0)
  1488. return err;
  1489. sprintf(name, "%s Playback Switch", chname[i]);
  1490. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  1491. HDA_COMPOSE_AMP_VAL(nid, 3, 0,
  1492. HDA_OUTPUT));
  1493. if (err < 0)
  1494. return err;
  1495. } else {
  1496. sprintf(name, "%s Playback Volume", chname[i]);
  1497. err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
  1498. HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
  1499. HDA_OUTPUT));
  1500. if (err < 0)
  1501. return err;
  1502. sprintf(name, "%s Playback Switch", chname[i]);
  1503. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
  1504. HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
  1505. HDA_OUTPUT));
  1506. if (err < 0)
  1507. return err;
  1508. }
  1509. }
  1510. return 0;
  1511. }
  1512. static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
  1513. {
  1514. int err;
  1515. if (!pin)
  1516. return 0;
  1517. spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
  1518. err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
  1519. "Headphone Playback Volume",
  1520. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  1521. if (err < 0)
  1522. return err;
  1523. err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
  1524. "Headphone Playback Switch",
  1525. HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
  1526. if (err < 0)
  1527. return err;
  1528. return 0;
  1529. }
  1530. /* create playback/capture controls for input pins */
  1531. static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
  1532. const struct auto_pin_cfg *cfg)
  1533. {
  1534. static char *labels[] = {
  1535. "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
  1536. };
  1537. struct hda_input_mux *imux = &spec->private_imux;
  1538. int i, err, idx = 0;
  1539. /* for internal loopback recording select */
  1540. imux->items[imux->num_items].label = "Stereo Mixer";
  1541. imux->items[imux->num_items].index = idx;
  1542. imux->num_items++;
  1543. for (i = 0; i < AUTO_PIN_LAST; i++) {
  1544. if (!cfg->input_pins[i])
  1545. continue;
  1546. switch (cfg->input_pins[i]) {
  1547. case 0x1a: /* Mic */
  1548. idx = 2;
  1549. break;
  1550. case 0x1b: /* Line In */
  1551. idx = 3;
  1552. break;
  1553. case 0x1e: /* Front Mic */
  1554. idx = 4;
  1555. break;
  1556. case 0x1f: /* CD */
  1557. idx = 1;
  1558. break;
  1559. }
  1560. err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
  1561. idx, 0x16);
  1562. if (err < 0)
  1563. return err;
  1564. imux->items[imux->num_items].label = labels[i];
  1565. imux->items[imux->num_items].index = idx;
  1566. imux->num_items++;
  1567. }
  1568. return 0;
  1569. }
  1570. static int vt1708B_parse_auto_config(struct hda_codec *codec)
  1571. {
  1572. struct via_spec *spec = codec->spec;
  1573. int err;
  1574. err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
  1575. if (err < 0)
  1576. return err;
  1577. err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
  1578. if (err < 0)
  1579. return err;
  1580. if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
  1581. return 0; /* can't find valid BIOS pin config */
  1582. err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
  1583. if (err < 0)
  1584. return err;
  1585. err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
  1586. if (err < 0)
  1587. return err;
  1588. err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
  1589. if (err < 0)
  1590. return err;
  1591. spec->multiout.max_channels = spec->multiout.num_dacs * 2;
  1592. if (spec->autocfg.dig_out_pin)
  1593. spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
  1594. if (spec->autocfg.dig_in_pin)
  1595. spec->dig_in_nid = VT1708B_DIGIN_NID;
  1596. if (spec->kctl_alloc)
  1597. spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
  1598. spec->input_mux = &spec->private_imux;
  1599. return 1;
  1600. }
  1601. #ifdef CONFIG_SND_HDA_POWER_SAVE
  1602. static struct hda_amp_list vt1708B_loopbacks[] = {
  1603. { 0x16, HDA_INPUT, 1 },
  1604. { 0x16, HDA_INPUT, 2 },
  1605. { 0x16, HDA_INPUT, 3 },
  1606. { 0x16, HDA_INPUT, 4 },
  1607. { } /* end */
  1608. };
  1609. #endif
  1610. static int patch_vt1708B_8ch(struct hda_codec *codec)
  1611. {
  1612. struct via_spec *spec;
  1613. int err;
  1614. /* create a codec specific record */
  1615. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  1616. if (spec == NULL)
  1617. return -ENOMEM;
  1618. codec->spec = spec;
  1619. /* automatic parse from the BIOS config */
  1620. err = vt1708B_parse_auto_config(codec);
  1621. if (err < 0) {
  1622. via_free(codec);
  1623. return err;
  1624. } else if (!err) {
  1625. printk(KERN_INFO "hda_codec: Cannot set up configuration "
  1626. "from BIOS. Using genenic mode...\n");
  1627. }
  1628. spec->init_verbs = vt1708B_8ch_volume_init_verbs;
  1629. spec->stream_name_analog = "VT1708B Analog";
  1630. spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
  1631. spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
  1632. spec->stream_name_digital = "VT1708B Digital";
  1633. spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
  1634. spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
  1635. if (!spec->adc_nids && spec->input_mux) {
  1636. spec->adc_nids = vt1708B_adc_nids;
  1637. spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
  1638. spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
  1639. spec->num_mixers++;
  1640. }
  1641. codec->patch_ops = via_patch_ops;
  1642. codec->patch_ops.init = via_auto_init;
  1643. #ifdef CONFIG_SND_HDA_POWER_SAVE
  1644. spec->loopback.amplist = vt1708B_loopbacks;
  1645. #endif
  1646. return 0;
  1647. }
  1648. static int patch_vt1708B_4ch(struct hda_codec *codec)
  1649. {
  1650. struct via_spec *spec;
  1651. int err;
  1652. /* create a codec specific record */
  1653. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  1654. if (spec == NULL)
  1655. return -ENOMEM;
  1656. codec->spec = spec;
  1657. /* automatic parse from the BIOS config */
  1658. err = vt1708B_parse_auto_config(codec);
  1659. if (err < 0) {
  1660. via_free(codec);
  1661. return err;
  1662. } else if (!err) {
  1663. printk(KERN_INFO "hda_codec: Cannot set up configuration "
  1664. "from BIOS. Using genenic mode...\n");
  1665. }
  1666. spec->init_verbs = vt1708B_4ch_volume_init_verbs;
  1667. spec->stream_name_analog = "VT1708B Analog";
  1668. spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
  1669. spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
  1670. spec->stream_name_digital = "VT1708B Digital";
  1671. spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
  1672. spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
  1673. if (!spec->adc_nids && spec->input_mux) {
  1674. spec->adc_nids = vt1708B_adc_nids;
  1675. spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
  1676. spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
  1677. spec->num_mixers++;
  1678. }
  1679. codec->patch_ops = via_patch_ops;
  1680. codec->patch_ops.init = via_auto_init;
  1681. #ifdef CONFIG_SND_HDA_POWER_SAVE
  1682. spec->loopback.amplist = vt1708B_loopbacks;
  1683. #endif
  1684. return 0;
  1685. }
  1686. /*
  1687. * patch entries
  1688. */
  1689. struct hda_codec_preset snd_hda_preset_via[] = {
  1690. { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
  1691. { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
  1692. { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
  1693. { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
  1694. { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
  1695. .patch = patch_vt1709_10ch},
  1696. { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
  1697. .patch = patch_vt1709_10ch},
  1698. { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
  1699. .patch = patch_vt1709_10ch},
  1700. { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
  1701. .patch = patch_vt1709_10ch},
  1702. { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
  1703. .patch = patch_vt1709_6ch},
  1704. { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
  1705. .patch = patch_vt1709_6ch},
  1706. { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
  1707. .patch = patch_vt1709_6ch},
  1708. { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
  1709. .patch = patch_vt1709_6ch},
  1710. { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
  1711. .patch = patch_vt1708B_8ch},
  1712. { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
  1713. .patch = patch_vt1708B_8ch},
  1714. { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
  1715. .patch = patch_vt1708B_8ch},
  1716. { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
  1717. .patch = patch_vt1708B_8ch},
  1718. { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
  1719. .patch = patch_vt1708B_4ch},
  1720. { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
  1721. .patch = patch_vt1708B_4ch},
  1722. { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
  1723. .patch = patch_vt1708B_4ch},
  1724. { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
  1725. .patch = patch_vt1708B_4ch},
  1726. {} /* terminator */
  1727. };