patch_via.c 53 KB

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