patch_realtek.c 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503
  1. /*
  2. * Universal Interface for Intel High Definition Audio Codec
  3. *
  4. * HD audio interface patch for ALC 260/880/882 codecs
  5. *
  6. * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw>
  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. #include <sound/driver.h>
  24. #include <linux/init.h>
  25. #include <linux/delay.h>
  26. #include <linux/slab.h>
  27. #include <linux/pci.h>
  28. #include <sound/core.h>
  29. #include "hda_codec.h"
  30. #include "hda_local.h"
  31. /* ALC880 board config type */
  32. enum {
  33. ALC880_MINIMAL,
  34. ALC880_3ST,
  35. ALC880_3ST_DIG,
  36. ALC880_5ST,
  37. ALC880_5ST_DIG,
  38. ALC880_W810,
  39. };
  40. struct alc_spec {
  41. /* codec parameterization */
  42. unsigned int front_panel: 1;
  43. snd_kcontrol_new_t* mixers[2];
  44. unsigned int num_mixers;
  45. struct hda_verb *init_verbs;
  46. char* stream_name_analog;
  47. struct hda_pcm_stream *stream_analog_playback;
  48. struct hda_pcm_stream *stream_analog_capture;
  49. char* stream_name_digital;
  50. struct hda_pcm_stream *stream_digital_playback;
  51. struct hda_pcm_stream *stream_digital_capture;
  52. /* playback */
  53. struct hda_multi_out multiout;
  54. /* capture */
  55. unsigned int num_adc_nids;
  56. hda_nid_t *adc_nids;
  57. hda_nid_t dig_in_nid;
  58. /* capture source */
  59. const struct hda_input_mux *input_mux;
  60. unsigned int cur_mux[3];
  61. /* channel model */
  62. const struct alc_channel_mode *channel_mode;
  63. int num_channel_mode;
  64. /* PCM information */
  65. struct hda_pcm pcm_rec[2];
  66. };
  67. /* DAC/ADC assignment */
  68. static hda_nid_t alc880_dac_nids[4] = {
  69. /* front, rear, clfe, rear_surr */
  70. 0x02, 0x05, 0x04, 0x03
  71. };
  72. static hda_nid_t alc880_w810_dac_nids[3] = {
  73. /* front, rear/surround, clfe */
  74. 0x02, 0x03, 0x04
  75. };
  76. static hda_nid_t alc880_adc_nids[3] = {
  77. /* ADC0-2 */
  78. 0x07, 0x08, 0x09,
  79. };
  80. #define ALC880_DIGOUT_NID 0x06
  81. #define ALC880_DIGIN_NID 0x0a
  82. static hda_nid_t alc260_dac_nids[1] = {
  83. /* front */
  84. 0x02,
  85. };
  86. static hda_nid_t alc260_adc_nids[2] = {
  87. /* ADC0-1 */
  88. 0x04, 0x05,
  89. };
  90. #define ALC260_DIGOUT_NID 0x03
  91. #define ALC260_DIGIN_NID 0x06
  92. static struct hda_input_mux alc880_capture_source = {
  93. .num_items = 4,
  94. .items = {
  95. { "Mic", 0x0 },
  96. { "Front Mic", 0x3 },
  97. { "Line", 0x2 },
  98. { "CD", 0x4 },
  99. },
  100. };
  101. static struct hda_input_mux alc260_capture_source = {
  102. .num_items = 4,
  103. .items = {
  104. { "Mic", 0x0 },
  105. { "Front Mic", 0x1 },
  106. { "Line", 0x2 },
  107. { "CD", 0x4 },
  108. },
  109. };
  110. /*
  111. * input MUX handling
  112. */
  113. static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  114. {
  115. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  116. struct alc_spec *spec = codec->spec;
  117. return snd_hda_input_mux_info(spec->input_mux, uinfo);
  118. }
  119. static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  120. {
  121. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  122. struct alc_spec *spec = codec->spec;
  123. unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  124. ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
  125. return 0;
  126. }
  127. static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  128. {
  129. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  130. struct alc_spec *spec = codec->spec;
  131. unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  132. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  133. spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
  134. }
  135. /*
  136. * channel mode setting
  137. */
  138. struct alc_channel_mode {
  139. int channels;
  140. const struct hda_verb *sequence;
  141. };
  142. /*
  143. * channel source setting (2/6 channel selection for 3-stack)
  144. */
  145. /*
  146. * set the path ways for 2 channel output
  147. * need to set the codec line out and mic 1 pin widgets to inputs
  148. */
  149. static struct hda_verb alc880_threestack_ch2_init[] = {
  150. /* set pin widget 1Ah (line in) for input */
  151. { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
  152. /* set pin widget 18h (mic1) for input, for mic also enable the vref */
  153. { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
  154. /* mute the output for Line In PW */
  155. { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
  156. /* mute for Mic1 PW */
  157. { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
  158. { } /* end */
  159. };
  160. /*
  161. * 6ch mode
  162. * need to set the codec line out and mic 1 pin widgets to outputs
  163. */
  164. static struct hda_verb alc880_threestack_ch6_init[] = {
  165. /* set pin widget 1Ah (line in) for output */
  166. { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  167. /* set pin widget 18h (mic1) for output */
  168. { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  169. /* unmute the output for Line In PW */
  170. { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
  171. /* unmute for Mic1 PW */
  172. { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
  173. /* for rear channel output using Line In 1
  174. * set select widget connection (nid = 0x12) - to summer node
  175. * for rear NID = 0x0f...offset 3 in connection list
  176. */
  177. { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
  178. /* for Mic1 - retask for center/lfe */
  179. /* set select widget connection (nid = 0x10) - to summer node for
  180. * front CLFE NID = 0x0e...offset 2 in connection list
  181. */
  182. { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
  183. { } /* end */
  184. };
  185. static struct alc_channel_mode alc880_threestack_modes[2] = {
  186. { 2, alc880_threestack_ch2_init },
  187. { 6, alc880_threestack_ch6_init },
  188. };
  189. /*
  190. * channel source setting (6/8 channel selection for 5-stack)
  191. */
  192. /* set the path ways for 6 channel output
  193. * need to set the codec line out and mic 1 pin widgets to inputs
  194. */
  195. static struct hda_verb alc880_fivestack_ch6_init[] = {
  196. /* set pin widget 1Ah (line in) for input */
  197. { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
  198. /* mute the output for Line In PW */
  199. { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
  200. { } /* end */
  201. };
  202. /* need to set the codec line out and mic 1 pin widgets to outputs */
  203. static struct hda_verb alc880_fivestack_ch8_init[] = {
  204. /* set pin widget 1Ah (line in) for output */
  205. { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  206. /* unmute the output for Line In PW */
  207. { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
  208. /* output for surround channel output using Line In 1 */
  209. /* set select widget connection (nid = 0x12) - to summer node
  210. * for surr_rear NID = 0x0d...offset 1 in connection list
  211. */
  212. { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
  213. { } /* end */
  214. };
  215. static struct alc_channel_mode alc880_fivestack_modes[2] = {
  216. { 6, alc880_fivestack_ch6_init },
  217. { 8, alc880_fivestack_ch8_init },
  218. };
  219. /*
  220. * channel source setting for W810 system
  221. *
  222. * W810 has rear IO for:
  223. * Front (DAC 02)
  224. * Surround (DAC 03)
  225. * Center/LFE (DAC 04)
  226. * Digital out (06)
  227. *
  228. * The system also has a pair of internal speakers, and a headphone jack.
  229. * These are both connected to Line2 on the codec, hence to DAC 02.
  230. *
  231. * There is a variable resistor to control the speaker or headphone
  232. * volume. This is a hardware-only device without a software API.
  233. *
  234. * Plugging headphones in will disable the internal speakers. This is
  235. * implemented in hardware, not via the driver using jack sense. In
  236. * a similar fashion, plugging into the rear socket marked "front" will
  237. * disable both the speakers and headphones.
  238. *
  239. * For input, there's a microphone jack, and an "audio in" jack.
  240. * These may not do anything useful with this driver yet, because I
  241. * haven't setup any initialization verbs for these yet...
  242. */
  243. static struct alc_channel_mode alc880_w810_modes[1] = {
  244. { 6, NULL }
  245. };
  246. /*
  247. */
  248. static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  249. {
  250. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  251. struct alc_spec *spec = codec->spec;
  252. snd_assert(spec->channel_mode, return -ENXIO);
  253. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  254. uinfo->count = 1;
  255. uinfo->value.enumerated.items = 2;
  256. if (uinfo->value.enumerated.item >= 2)
  257. uinfo->value.enumerated.item = 1;
  258. sprintf(uinfo->value.enumerated.name, "%dch",
  259. spec->channel_mode[uinfo->value.enumerated.item].channels);
  260. return 0;
  261. }
  262. static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  263. {
  264. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  265. struct alc_spec *spec = codec->spec;
  266. snd_assert(spec->channel_mode, return -ENXIO);
  267. ucontrol->value.enumerated.item[0] =
  268. (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
  269. return 0;
  270. }
  271. static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  272. {
  273. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  274. struct alc_spec *spec = codec->spec;
  275. int mode;
  276. snd_assert(spec->channel_mode, return -ENXIO);
  277. mode = ucontrol->value.enumerated.item[0] ? 1 : 0;
  278. if (spec->multiout.max_channels == spec->channel_mode[mode].channels &&
  279. ! codec->in_resume)
  280. return 0;
  281. /* change the current channel setting */
  282. spec->multiout.max_channels = spec->channel_mode[mode].channels;
  283. if (spec->channel_mode[mode].sequence)
  284. snd_hda_sequence_write(codec, spec->channel_mode[mode].sequence);
  285. return 1;
  286. }
  287. /*
  288. */
  289. /* 3-stack mode
  290. * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
  291. * HP=0x19
  292. */
  293. static snd_kcontrol_new_t alc880_base_mixer[] = {
  294. HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
  295. HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
  296. HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
  297. HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
  298. HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
  299. HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
  300. HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
  301. HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT),
  302. HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
  303. HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
  304. HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
  305. HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
  306. HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
  307. HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
  308. HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
  309. HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
  310. HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
  311. HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
  312. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
  313. HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
  314. HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
  315. HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
  316. HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
  317. HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
  318. {
  319. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  320. /* The multiple "Capture Source" controls confuse alsamixer
  321. * So call somewhat different..
  322. * FIXME: the controls appear in the "playback" view!
  323. */
  324. /* .name = "Capture Source", */
  325. .name = "Input Source",
  326. .count = 2,
  327. .info = alc_mux_enum_info,
  328. .get = alc_mux_enum_get,
  329. .put = alc_mux_enum_put,
  330. },
  331. {
  332. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  333. .name = "Channel Mode",
  334. .info = alc880_ch_mode_info,
  335. .get = alc880_ch_mode_get,
  336. .put = alc880_ch_mode_put,
  337. },
  338. { } /* end */
  339. };
  340. /* 5-stack mode
  341. * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
  342. * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
  343. */
  344. static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
  345. HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
  346. HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
  347. HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
  348. HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
  349. HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
  350. HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
  351. HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
  352. HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
  353. HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
  354. HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
  355. HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
  356. HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
  357. HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
  358. HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
  359. HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
  360. HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
  361. HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
  362. HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
  363. HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
  364. HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
  365. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
  366. HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
  367. HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
  368. HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
  369. HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
  370. HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
  371. {
  372. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  373. /* The multiple "Capture Source" controls confuse alsamixer
  374. * So call somewhat different..
  375. * FIXME: the controls appear in the "playback" view!
  376. */
  377. /* .name = "Capture Source", */
  378. .name = "Input Source",
  379. .count = 2,
  380. .info = alc_mux_enum_info,
  381. .get = alc_mux_enum_get,
  382. .put = alc_mux_enum_put,
  383. },
  384. {
  385. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  386. .name = "Channel Mode",
  387. .info = alc880_ch_mode_info,
  388. .get = alc880_ch_mode_get,
  389. .put = alc880_ch_mode_put,
  390. },
  391. { } /* end */
  392. };
  393. static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
  394. HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
  395. HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
  396. HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
  397. HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
  398. HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
  399. HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
  400. HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
  401. HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
  402. HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
  403. HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
  404. HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
  405. HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
  406. HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
  407. HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
  408. HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
  409. {
  410. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  411. /* The multiple "Capture Source" controls confuse alsamixer
  412. * So call somewhat different..
  413. * FIXME: the controls appear in the "playback" view!
  414. */
  415. /* .name = "Capture Source", */
  416. .name = "Input Source",
  417. .count = 3,
  418. .info = alc_mux_enum_info,
  419. .get = alc_mux_enum_get,
  420. .put = alc_mux_enum_put,
  421. },
  422. { } /* end */
  423. };
  424. /*
  425. */
  426. static int alc_build_controls(struct hda_codec *codec)
  427. {
  428. struct alc_spec *spec = codec->spec;
  429. int err;
  430. int i;
  431. for (i = 0; i < spec->num_mixers; i++) {
  432. err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
  433. if (err < 0)
  434. return err;
  435. }
  436. if (spec->multiout.dig_out_nid) {
  437. err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
  438. if (err < 0)
  439. return err;
  440. }
  441. if (spec->dig_in_nid) {
  442. err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
  443. if (err < 0)
  444. return err;
  445. }
  446. return 0;
  447. }
  448. /*
  449. * initialize the codec volumes, etc
  450. */
  451. static struct hda_verb alc880_init_verbs_three_stack[] = {
  452. /* Line In pin widget for input */
  453. {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  454. /* CD pin widget for input */
  455. {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  456. /* Mic1 (rear panel) pin widget for input and vref at 80% */
  457. {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
  458. /* Mic2 (front panel) pin widget for input and vref at 80% */
  459. {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
  460. /* unmute amp left and right */
  461. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
  462. /* set connection select to line in (default select for this ADC) */
  463. {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
  464. /* unmute front mixer amp left (volume = 0) */
  465. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  466. /* mute pin widget amp left and right (no gain on this amp) */
  467. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  468. /* unmute rear mixer amp left and right (volume = 0) */
  469. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  470. /* mute pin widget amp left and right (no gain on this amp) */
  471. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  472. /* unmute rear mixer amp left and right (volume = 0) */
  473. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  474. /* mute pin widget amp left and right (no gain on this amp) */
  475. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  476. /* using rear surround as the path for headphone output */
  477. /* unmute rear surround mixer amp left and right (volume = 0) */
  478. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  479. /* PASD 3 stack boards use the Mic 2 as the headphone output */
  480. /* need to program the selector associated with the Mic 2 pin widget to
  481. * surround path (index 0x01) for headphone output */
  482. {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
  483. /* mute pin widget amp left and right (no gain on this amp) */
  484. {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  485. /* need to retask the Mic 2 pin widget to output */
  486. {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  487. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
  488. * to support the input path of analog loopback
  489. * Note: PASD motherboards uses the Line In 2 as the input for front panel
  490. * mic (mic 2)
  491. */
  492. /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
  493. /* unmute CD */
  494. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
  495. /* unmute Line In */
  496. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
  497. /* unmute Mic 1 */
  498. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  499. /* unmute Line In 2 (for PASD boards Mic 2) */
  500. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
  501. /* Unmute input amps for the line out paths to support the output path of
  502. * analog loopback
  503. * the mixers on the output path has 2 inputs, one from the DAC and one
  504. * from the mixer
  505. */
  506. /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
  507. /* Unmute Front out path */
  508. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  509. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  510. /* Unmute Surround (used as HP) out path */
  511. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  512. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  513. /* Unmute C/LFE out path */
  514. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  515. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
  516. /* Unmute rear Surround out path */
  517. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  518. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  519. { }
  520. };
  521. static struct hda_verb alc880_init_verbs_five_stack[] = {
  522. /* Line In pin widget for input */
  523. {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  524. /* CD pin widget for input */
  525. {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  526. /* Mic1 (rear panel) pin widget for input and vref at 80% */
  527. {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
  528. /* Mic2 (front panel) pin widget for input and vref at 80% */
  529. {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
  530. /* unmute amp left and right */
  531. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
  532. /* set connection select to line in (default select for this ADC) */
  533. {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
  534. /* unmute front mixer amp left and right (volume = 0) */
  535. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  536. /* mute pin widget amp left and right (no gain on this amp) */
  537. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  538. /* five rear and clfe */
  539. /* unmute rear mixer amp left and right (volume = 0) */
  540. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  541. /* mute pin widget amp left and right (no gain on this amp) */
  542. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  543. /* unmute clfe mixer amp left and right (volume = 0) */
  544. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  545. /* mute pin widget amp left and right (no gain on this amp) */
  546. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  547. /* using rear surround as the path for headphone output */
  548. /* unmute rear surround mixer amp left and right (volume = 0) */
  549. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  550. /* PASD 3 stack boards use the Mic 2 as the headphone output */
  551. /* need to program the selector associated with the Mic 2 pin widget to
  552. * surround path (index 0x01) for headphone output
  553. */
  554. {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
  555. /* mute pin widget amp left and right (no gain on this amp) */
  556. {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  557. /* need to retask the Mic 2 pin widget to output */
  558. {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  559. /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
  560. * widget(nid=0x0B) to support the input path of analog loopback
  561. */
  562. /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
  563. /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
  564. /* unmute CD */
  565. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
  566. /* unmute Line In */
  567. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
  568. /* unmute Mic 1 */
  569. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  570. /* unmute Line In 2 (for PASD boards Mic 2) */
  571. {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
  572. /* Unmute input amps for the line out paths to support the output path of
  573. * analog loopback
  574. * the mixers on the output path has 2 inputs, one from the DAC and
  575. * one from the mixer
  576. */
  577. /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
  578. /* Unmute Front out path */
  579. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  580. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  581. /* Unmute Surround (used as HP) out path */
  582. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  583. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  584. /* Unmute C/LFE out path */
  585. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  586. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
  587. /* Unmute rear Surround out path */
  588. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  589. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  590. { }
  591. };
  592. static struct hda_verb alc880_w810_init_verbs[] = {
  593. /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
  594. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
  595. /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
  596. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
  597. /* front channel selector/amp: output 0: unmuted, max volume */
  598. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  599. /* front out pin: muted, (no volume selection) */
  600. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  601. /* front out pin: NOT headphone enable, out enable, vref disabled */
  602. {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  603. /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
  604. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
  605. /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
  606. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
  607. /* surround channel selector/amp: output 0: unmuted, max volume */
  608. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  609. /* surround out pin: muted, (no volume selection) */
  610. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  611. /* surround out pin: NOT headphone enable, out enable, vref disabled */
  612. {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  613. /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
  614. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
  615. /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
  616. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
  617. /* c/lfe channel selector/amp: output 0: unmuted, max volume */
  618. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  619. /* c/lfe out pin: muted, (no volume selection) */
  620. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  621. /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
  622. {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  623. /* hphone/speaker input selector: front DAC */
  624. {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
  625. /* hphone/speaker out pin: muted, (no volume selection) */
  626. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  627. /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
  628. {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  629. { }
  630. };
  631. static int alc_init(struct hda_codec *codec)
  632. {
  633. struct alc_spec *spec = codec->spec;
  634. snd_hda_sequence_write(codec, spec->init_verbs);
  635. return 0;
  636. }
  637. #ifdef CONFIG_PM
  638. /*
  639. * resume
  640. */
  641. static int alc_resume(struct hda_codec *codec)
  642. {
  643. struct alc_spec *spec = codec->spec;
  644. int i;
  645. alc_init(codec);
  646. for (i = 0; i < spec->num_mixers; i++) {
  647. snd_hda_resume_ctls(codec, spec->mixers[i]);
  648. }
  649. if (spec->multiout.dig_out_nid)
  650. snd_hda_resume_spdif_out(codec);
  651. if (spec->dig_in_nid)
  652. snd_hda_resume_spdif_in(codec);
  653. return 0;
  654. }
  655. #endif
  656. /*
  657. * Analog playback callbacks
  658. */
  659. static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
  660. struct hda_codec *codec,
  661. snd_pcm_substream_t *substream)
  662. {
  663. struct alc_spec *spec = codec->spec;
  664. return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
  665. }
  666. static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
  667. struct hda_codec *codec,
  668. unsigned int stream_tag,
  669. unsigned int format,
  670. snd_pcm_substream_t *substream)
  671. {
  672. struct alc_spec *spec = codec->spec;
  673. return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
  674. format, substream);
  675. }
  676. static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
  677. struct hda_codec *codec,
  678. snd_pcm_substream_t *substream)
  679. {
  680. struct alc_spec *spec = codec->spec;
  681. return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
  682. }
  683. /*
  684. * Digital out
  685. */
  686. static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
  687. struct hda_codec *codec,
  688. snd_pcm_substream_t *substream)
  689. {
  690. struct alc_spec *spec = codec->spec;
  691. return snd_hda_multi_out_dig_open(codec, &spec->multiout);
  692. }
  693. static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
  694. struct hda_codec *codec,
  695. snd_pcm_substream_t *substream)
  696. {
  697. struct alc_spec *spec = codec->spec;
  698. return snd_hda_multi_out_dig_close(codec, &spec->multiout);
  699. }
  700. /*
  701. * Analog capture
  702. */
  703. static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
  704. struct hda_codec *codec,
  705. unsigned int stream_tag,
  706. unsigned int format,
  707. snd_pcm_substream_t *substream)
  708. {
  709. struct alc_spec *spec = codec->spec;
  710. snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
  711. stream_tag, 0, format);
  712. return 0;
  713. }
  714. static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
  715. struct hda_codec *codec,
  716. snd_pcm_substream_t *substream)
  717. {
  718. struct alc_spec *spec = codec->spec;
  719. snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
  720. return 0;
  721. }
  722. /*
  723. */
  724. static struct hda_pcm_stream alc880_pcm_analog_playback = {
  725. .substreams = 1,
  726. .channels_min = 2,
  727. .channels_max = 8,
  728. .nid = 0x02, /* NID to query formats and rates */
  729. .ops = {
  730. .open = alc880_playback_pcm_open,
  731. .prepare = alc880_playback_pcm_prepare,
  732. .cleanup = alc880_playback_pcm_cleanup
  733. },
  734. };
  735. static struct hda_pcm_stream alc880_pcm_analog_capture = {
  736. .substreams = 2,
  737. .channels_min = 2,
  738. .channels_max = 2,
  739. .nid = 0x07, /* NID to query formats and rates */
  740. .ops = {
  741. .prepare = alc880_capture_pcm_prepare,
  742. .cleanup = alc880_capture_pcm_cleanup
  743. },
  744. };
  745. static struct hda_pcm_stream alc880_pcm_digital_playback = {
  746. .substreams = 1,
  747. .channels_min = 2,
  748. .channels_max = 2,
  749. /* NID is set in alc_build_pcms */
  750. .ops = {
  751. .open = alc880_dig_playback_pcm_open,
  752. .close = alc880_dig_playback_pcm_close
  753. },
  754. };
  755. static struct hda_pcm_stream alc880_pcm_digital_capture = {
  756. .substreams = 1,
  757. .channels_min = 2,
  758. .channels_max = 2,
  759. /* NID is set in alc_build_pcms */
  760. };
  761. static int alc_build_pcms(struct hda_codec *codec)
  762. {
  763. struct alc_spec *spec = codec->spec;
  764. struct hda_pcm *info = spec->pcm_rec;
  765. int i;
  766. codec->num_pcms = 1;
  767. codec->pcm_info = info;
  768. info->name = spec->stream_name_analog;
  769. info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
  770. info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
  771. info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
  772. for (i = 0; i < spec->num_channel_mode; i++) {
  773. if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
  774. info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
  775. }
  776. }
  777. if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
  778. codec->num_pcms++;
  779. info++;
  780. info->name = spec->stream_name_digital;
  781. if (spec->multiout.dig_out_nid) {
  782. info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
  783. info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
  784. }
  785. if (spec->dig_in_nid) {
  786. info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
  787. info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
  788. }
  789. }
  790. return 0;
  791. }
  792. static void alc_free(struct hda_codec *codec)
  793. {
  794. kfree(codec->spec);
  795. }
  796. /*
  797. */
  798. static struct hda_codec_ops alc_patch_ops = {
  799. .build_controls = alc_build_controls,
  800. .build_pcms = alc_build_pcms,
  801. .init = alc_init,
  802. .free = alc_free,
  803. #ifdef CONFIG_PM
  804. .resume = alc_resume,
  805. #endif
  806. };
  807. /*
  808. */
  809. static struct hda_board_config alc880_cfg_tbl[] = {
  810. /* Back 3 jack, front 2 jack */
  811. { .modelname = "3stack", .config = ALC880_3ST },
  812. { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
  813. { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
  814. { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
  815. { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
  816. { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
  817. { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
  818. { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
  819. { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
  820. { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
  821. { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
  822. { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
  823. { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
  824. { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
  825. { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
  826. { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
  827. { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
  828. { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
  829. { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
  830. { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
  831. { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
  832. { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
  833. { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
  834. { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
  835. { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
  836. { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
  837. { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
  838. { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
  839. { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
  840. { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
  841. { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
  842. { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
  843. { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
  844. /* Back 3 jack, front 2 jack (Internal add Aux-In) */
  845. { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
  846. /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
  847. { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
  848. { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
  849. /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
  850. { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
  851. { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
  852. { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
  853. /* Back 5 jack, front 2 jack */
  854. { .modelname = "5stack", .config = ALC880_5ST },
  855. { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
  856. { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
  857. { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
  858. { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
  859. /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
  860. { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
  861. { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
  862. { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
  863. { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
  864. { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
  865. { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
  866. { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
  867. { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
  868. { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
  869. { .modelname = "w810", .config = ALC880_W810 },
  870. { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
  871. {}
  872. };
  873. static int patch_alc880(struct hda_codec *codec)
  874. {
  875. struct alc_spec *spec;
  876. int board_config;
  877. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  878. if (spec == NULL)
  879. return -ENOMEM;
  880. codec->spec = spec;
  881. board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
  882. if (board_config < 0) {
  883. snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
  884. board_config = ALC880_MINIMAL;
  885. }
  886. switch (board_config) {
  887. case ALC880_W810:
  888. spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
  889. spec->num_mixers++;
  890. break;
  891. case ALC880_5ST:
  892. case ALC880_5ST_DIG:
  893. spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
  894. spec->num_mixers++;
  895. break;
  896. default:
  897. spec->mixers[spec->num_mixers] = alc880_base_mixer;
  898. spec->num_mixers++;
  899. break;
  900. }
  901. switch (board_config) {
  902. case ALC880_3ST_DIG:
  903. case ALC880_5ST_DIG:
  904. case ALC880_W810:
  905. spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
  906. break;
  907. default:
  908. break;
  909. }
  910. switch (board_config) {
  911. case ALC880_3ST:
  912. case ALC880_3ST_DIG:
  913. case ALC880_5ST:
  914. case ALC880_5ST_DIG:
  915. case ALC880_W810:
  916. spec->front_panel = 1;
  917. break;
  918. default:
  919. break;
  920. }
  921. switch (board_config) {
  922. case ALC880_5ST:
  923. case ALC880_5ST_DIG:
  924. spec->init_verbs = alc880_init_verbs_five_stack;
  925. spec->channel_mode = alc880_fivestack_modes;
  926. spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
  927. break;
  928. case ALC880_W810:
  929. spec->init_verbs = alc880_w810_init_verbs;
  930. spec->channel_mode = alc880_w810_modes;
  931. spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
  932. break;
  933. default:
  934. spec->init_verbs = alc880_init_verbs_three_stack;
  935. spec->channel_mode = alc880_threestack_modes;
  936. spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
  937. break;
  938. }
  939. spec->stream_name_analog = "ALC880 Analog";
  940. spec->stream_analog_playback = &alc880_pcm_analog_playback;
  941. spec->stream_analog_capture = &alc880_pcm_analog_capture;
  942. spec->stream_name_digital = "ALC880 Digital";
  943. spec->stream_digital_playback = &alc880_pcm_digital_playback;
  944. spec->stream_digital_capture = &alc880_pcm_digital_capture;
  945. spec->multiout.max_channels = spec->channel_mode[0].channels;
  946. switch (board_config) {
  947. case ALC880_W810:
  948. spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
  949. spec->multiout.dac_nids = alc880_w810_dac_nids;
  950. // No dedicated headphone socket - it's shared with built-in speakers.
  951. break;
  952. default:
  953. spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
  954. spec->multiout.dac_nids = alc880_dac_nids;
  955. spec->multiout.hp_nid = 0x03; /* rear-surround NID */
  956. break;
  957. }
  958. spec->input_mux = &alc880_capture_source;
  959. spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
  960. spec->adc_nids = alc880_adc_nids;
  961. codec->patch_ops = alc_patch_ops;
  962. return 0;
  963. }
  964. /*
  965. * ALC260 support
  966. */
  967. /*
  968. * This is just place-holder, so there's something for alc_build_pcms to look
  969. * at when it calculates the maximum number of channels. ALC260 has no mixer
  970. * element which allows changing the channel mode, so the verb list is
  971. * never used.
  972. */
  973. static struct alc_channel_mode alc260_modes[1] = {
  974. { 2, NULL },
  975. };
  976. snd_kcontrol_new_t alc260_base_mixer[] = {
  977. HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
  978. /* use LINE2 for the output */
  979. /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
  980. HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
  981. HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
  982. HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
  983. HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
  984. HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
  985. HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
  986. HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
  987. HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
  988. HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
  989. HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
  990. HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
  991. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
  992. HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
  993. HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
  994. HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
  995. HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
  996. HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
  997. {
  998. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  999. .name = "Capture Source",
  1000. .info = alc_mux_enum_info,
  1001. .get = alc_mux_enum_get,
  1002. .put = alc_mux_enum_put,
  1003. },
  1004. { } /* end */
  1005. };
  1006. static struct hda_verb alc260_init_verbs[] = {
  1007. /* Line In pin widget for input */
  1008. {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  1009. /* CD pin widget for input */
  1010. {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  1011. /* Mic1 (rear panel) pin widget for input and vref at 80% */
  1012. {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
  1013. /* Mic2 (front panel) pin widget for input and vref at 80% */
  1014. {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
  1015. /* LINE-2 is used for line-out in rear */
  1016. {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1017. /* select line-out */
  1018. {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
  1019. /* LINE-OUT pin */
  1020. {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1021. /* enable HP */
  1022. {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1023. /* enable Mono */
  1024. {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1025. /* unmute amp left and right */
  1026. {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
  1027. /* set connection select to line in (default select for this ADC) */
  1028. {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
  1029. /* unmute Line-Out mixer amp left and right (volume = 0) */
  1030. {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  1031. /* mute pin widget amp left and right (no gain on this amp) */
  1032. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  1033. /* unmute HP mixer amp left and right (volume = 0) */
  1034. {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  1035. /* mute pin widget amp left and right (no gain on this amp) */
  1036. {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  1037. /* unmute Mono mixer amp left and right (volume = 0) */
  1038. {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  1039. /* mute pin widget amp left and right (no gain on this amp) */
  1040. {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  1041. /* mute LINE-2 out */
  1042. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  1043. /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
  1044. /* unmute CD */
  1045. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
  1046. /* unmute Line In */
  1047. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
  1048. /* unmute Mic */
  1049. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1050. /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
  1051. /* Unmute Front out path */
  1052. {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1053. {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  1054. /* Unmute Headphone out path */
  1055. {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1056. {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  1057. /* Unmute Mono out path */
  1058. {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1059. {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  1060. { }
  1061. };
  1062. static struct hda_pcm_stream alc260_pcm_analog_playback = {
  1063. .substreams = 1,
  1064. .channels_min = 2,
  1065. .channels_max = 2,
  1066. .nid = 0x2,
  1067. };
  1068. static struct hda_pcm_stream alc260_pcm_analog_capture = {
  1069. .substreams = 1,
  1070. .channels_min = 2,
  1071. .channels_max = 2,
  1072. .nid = 0x4,
  1073. };
  1074. static int patch_alc260(struct hda_codec *codec)
  1075. {
  1076. struct alc_spec *spec;
  1077. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  1078. if (spec == NULL)
  1079. return -ENOMEM;
  1080. codec->spec = spec;
  1081. spec->mixers[spec->num_mixers] = alc260_base_mixer;
  1082. spec->num_mixers++;
  1083. spec->init_verbs = alc260_init_verbs;
  1084. spec->channel_mode = alc260_modes;
  1085. spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
  1086. spec->stream_name_analog = "ALC260 Analog";
  1087. spec->stream_analog_playback = &alc260_pcm_analog_playback;
  1088. spec->stream_analog_capture = &alc260_pcm_analog_capture;
  1089. spec->multiout.max_channels = spec->channel_mode[0].channels;
  1090. spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
  1091. spec->multiout.dac_nids = alc260_dac_nids;
  1092. spec->input_mux = &alc260_capture_source;
  1093. spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
  1094. spec->adc_nids = alc260_adc_nids;
  1095. codec->patch_ops = alc_patch_ops;
  1096. return 0;
  1097. }
  1098. /*
  1099. * ALC882 support
  1100. *
  1101. * ALC882 is almost identical with ALC880 but has cleaner and more flexible
  1102. * configuration. Each pin widget can choose any input DACs and a mixer.
  1103. * Each ADC is connected from a mixer of all inputs. This makes possible
  1104. * 6-channel independent captures.
  1105. *
  1106. * In addition, an independent DAC for the multi-playback (not used in this
  1107. * driver yet).
  1108. */
  1109. static struct alc_channel_mode alc882_ch_modes[1] = {
  1110. { 8, NULL }
  1111. };
  1112. static hda_nid_t alc882_dac_nids[4] = {
  1113. /* front, rear, clfe, rear_surr */
  1114. 0x02, 0x03, 0x04, 0x05
  1115. };
  1116. static hda_nid_t alc882_adc_nids[3] = {
  1117. /* ADC0-2 */
  1118. 0x07, 0x08, 0x09,
  1119. };
  1120. /* input MUX */
  1121. /* FIXME: should be a matrix-type input source selection */
  1122. static struct hda_input_mux alc882_capture_source = {
  1123. .num_items = 4,
  1124. .items = {
  1125. { "Mic", 0x0 },
  1126. { "Front Mic", 0x1 },
  1127. { "Line", 0x2 },
  1128. { "CD", 0x4 },
  1129. },
  1130. };
  1131. #define alc882_mux_enum_info alc_mux_enum_info
  1132. #define alc882_mux_enum_get alc_mux_enum_get
  1133. static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  1134. {
  1135. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  1136. struct alc_spec *spec = codec->spec;
  1137. const struct hda_input_mux *imux = spec->input_mux;
  1138. unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
  1139. static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
  1140. hda_nid_t nid = capture_mixers[adc_idx];
  1141. unsigned int *cur_val = &spec->cur_mux[adc_idx];
  1142. unsigned int i, idx;
  1143. idx = ucontrol->value.enumerated.item[0];
  1144. if (idx >= imux->num_items)
  1145. idx = imux->num_items - 1;
  1146. if (*cur_val == idx && ! codec->in_resume)
  1147. return 0;
  1148. for (i = 0; i < imux->num_items; i++) {
  1149. unsigned int v = (i == idx) ? 0x7000 : 0x7080;
  1150. snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
  1151. v | (imux->items[i].index << 8));
  1152. }
  1153. *cur_val = idx;
  1154. return 1;
  1155. }
  1156. /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
  1157. * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
  1158. */
  1159. static snd_kcontrol_new_t alc882_base_mixer[] = {
  1160. HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
  1161. HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
  1162. HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
  1163. HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
  1164. HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
  1165. HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
  1166. HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
  1167. HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
  1168. HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
  1169. HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
  1170. HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
  1171. HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
  1172. HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
  1173. HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
  1174. HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
  1175. HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
  1176. HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
  1177. HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
  1178. HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
  1179. HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
  1180. HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
  1181. HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
  1182. HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
  1183. HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
  1184. HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
  1185. HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
  1186. HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
  1187. {
  1188. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  1189. /* .name = "Capture Source", */
  1190. .name = "Input Source",
  1191. .count = 3,
  1192. .info = alc882_mux_enum_info,
  1193. .get = alc882_mux_enum_get,
  1194. .put = alc882_mux_enum_put,
  1195. },
  1196. { } /* end */
  1197. };
  1198. static struct hda_verb alc882_init_verbs[] = {
  1199. /* Front mixer: unmute input/output amp left and right (volume = 0) */
  1200. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  1201. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1202. /* Rear mixer */
  1203. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  1204. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1205. /* CLFE mixer */
  1206. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  1207. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1208. /* Side mixer */
  1209. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  1210. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1211. /* Front Pin: to output mode */
  1212. {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1213. /* Front Pin: mute amp left and right (no volume) */
  1214. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  1215. /* select Front mixer (0x0c, index 0) */
  1216. {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
  1217. /* Rear Pin */
  1218. {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1219. /* Rear Pin: mute amp left and right (no volume) */
  1220. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  1221. /* select Rear mixer (0x0d, index 1) */
  1222. {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
  1223. /* CLFE Pin */
  1224. {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1225. /* CLFE Pin: mute amp left and right (no volume) */
  1226. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  1227. /* select CLFE mixer (0x0e, index 2) */
  1228. {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
  1229. /* Side Pin */
  1230. {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1231. /* Side Pin: mute amp left and right (no volume) */
  1232. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  1233. /* select Side mixer (0x0f, index 3) */
  1234. {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
  1235. /* Headphone Pin */
  1236. {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
  1237. /* Headphone Pin: mute amp left and right (no volume) */
  1238. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
  1239. /* select Front mixer (0x0c, index 0) */
  1240. {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
  1241. /* Mic (rear) pin widget for input and vref at 80% */
  1242. {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
  1243. /* Front Mic pin widget for input and vref at 80% */
  1244. {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
  1245. /* Line In pin widget for input */
  1246. {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  1247. /* CD pin widget for input */
  1248. {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
  1249. /* FIXME: use matrix-type input source selection */
  1250. /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
  1251. /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
  1252. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1253. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
  1254. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
  1255. {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
  1256. /* Input mixer2 */
  1257. {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1258. {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
  1259. {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
  1260. {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
  1261. /* Input mixer3 */
  1262. {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
  1263. {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
  1264. {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
  1265. {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
  1266. /* ADC1: unmute amp left and right */
  1267. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
  1268. /* ADC2: unmute amp left and right */
  1269. {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
  1270. /* ADC3: unmute amp left and right */
  1271. {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
  1272. /* Unmute front loopback */
  1273. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  1274. /* Unmute rear loopback */
  1275. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  1276. /* Mute CLFE loopback */
  1277. {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
  1278. /* Unmute side loopback */
  1279. {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
  1280. { }
  1281. };
  1282. static int patch_alc882(struct hda_codec *codec)
  1283. {
  1284. struct alc_spec *spec;
  1285. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  1286. if (spec == NULL)
  1287. return -ENOMEM;
  1288. codec->spec = spec;
  1289. spec->mixers[spec->num_mixers] = alc882_base_mixer;
  1290. spec->num_mixers++;
  1291. spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
  1292. spec->dig_in_nid = ALC880_DIGIN_NID;
  1293. spec->front_panel = 1;
  1294. spec->init_verbs = alc882_init_verbs;
  1295. spec->channel_mode = alc882_ch_modes;
  1296. spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
  1297. spec->stream_name_analog = "ALC882 Analog";
  1298. spec->stream_analog_playback = &alc880_pcm_analog_playback;
  1299. spec->stream_analog_capture = &alc880_pcm_analog_capture;
  1300. spec->stream_name_digital = "ALC882 Digital";
  1301. spec->stream_digital_playback = &alc880_pcm_digital_playback;
  1302. spec->stream_digital_capture = &alc880_pcm_digital_capture;
  1303. spec->multiout.max_channels = spec->channel_mode[0].channels;
  1304. spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids);
  1305. spec->multiout.dac_nids = alc882_dac_nids;
  1306. spec->input_mux = &alc882_capture_source;
  1307. spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
  1308. spec->adc_nids = alc882_adc_nids;
  1309. codec->patch_ops = alc_patch_ops;
  1310. return 0;
  1311. }
  1312. /*
  1313. * patch entries
  1314. */
  1315. struct hda_codec_preset snd_hda_preset_realtek[] = {
  1316. { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
  1317. { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
  1318. { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
  1319. {} /* terminator */
  1320. };