patch_via.c 54 KB

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