patch_via.c 55 KB

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