patch_analog.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. /*
  2. * HD audio interface patch for AD1981HD, AD1983, AD1986A
  3. *
  4. * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
  5. *
  6. * This driver is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This driver is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include <sound/driver.h>
  21. #include <linux/init.h>
  22. #include <linux/delay.h>
  23. #include <linux/slab.h>
  24. #include <linux/pci.h>
  25. #include <sound/core.h>
  26. #include "hda_codec.h"
  27. #include "hda_local.h"
  28. struct ad198x_spec {
  29. struct semaphore amp_mutex; /* PCM volume/mute control mutex */
  30. struct hda_multi_out multiout; /* playback */
  31. hda_nid_t adc_nid;
  32. const struct hda_input_mux *input_mux;
  33. unsigned int cur_mux; /* capture source */
  34. unsigned int spdif_route;
  35. snd_kcontrol_new_t *mixers;
  36. const struct hda_verb *init_verbs;
  37. struct hda_pcm pcm_rec[2]; /* PCM information */
  38. };
  39. /*
  40. * input MUX handling (common part)
  41. */
  42. static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  43. {
  44. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  45. struct ad198x_spec *spec = codec->spec;
  46. return snd_hda_input_mux_info(spec->input_mux, uinfo);
  47. }
  48. static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  49. {
  50. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  51. struct ad198x_spec *spec = codec->spec;
  52. ucontrol->value.enumerated.item[0] = spec->cur_mux;
  53. return 0;
  54. }
  55. static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  56. {
  57. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  58. struct ad198x_spec *spec = codec->spec;
  59. return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
  60. spec->adc_nid, &spec->cur_mux);
  61. }
  62. /*
  63. * initialization (common callbacks)
  64. */
  65. static int ad198x_init(struct hda_codec *codec)
  66. {
  67. struct ad198x_spec *spec = codec->spec;
  68. snd_hda_sequence_write(codec, spec->init_verbs);
  69. return 0;
  70. }
  71. static int ad198x_build_controls(struct hda_codec *codec)
  72. {
  73. struct ad198x_spec *spec = codec->spec;
  74. int err;
  75. err = snd_hda_add_new_ctls(codec, spec->mixers);
  76. if (err < 0)
  77. return err;
  78. if (spec->multiout.dig_out_nid)
  79. err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
  80. if (err < 0)
  81. return err;
  82. return 0;
  83. }
  84. /*
  85. * Analog playback callbacks
  86. */
  87. static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
  88. struct hda_codec *codec,
  89. snd_pcm_substream_t *substream)
  90. {
  91. struct ad198x_spec *spec = codec->spec;
  92. return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
  93. }
  94. static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
  95. struct hda_codec *codec,
  96. unsigned int stream_tag,
  97. unsigned int format,
  98. snd_pcm_substream_t *substream)
  99. {
  100. struct ad198x_spec *spec = codec->spec;
  101. return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
  102. format, substream);
  103. }
  104. static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
  105. struct hda_codec *codec,
  106. snd_pcm_substream_t *substream)
  107. {
  108. struct ad198x_spec *spec = codec->spec;
  109. return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
  110. }
  111. /*
  112. * Digital out
  113. */
  114. static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
  115. struct hda_codec *codec,
  116. snd_pcm_substream_t *substream)
  117. {
  118. struct ad198x_spec *spec = codec->spec;
  119. return snd_hda_multi_out_dig_open(codec, &spec->multiout);
  120. }
  121. static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
  122. struct hda_codec *codec,
  123. snd_pcm_substream_t *substream)
  124. {
  125. struct ad198x_spec *spec = codec->spec;
  126. return snd_hda_multi_out_dig_close(codec, &spec->multiout);
  127. }
  128. /*
  129. * Analog capture
  130. */
  131. static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
  132. struct hda_codec *codec,
  133. unsigned int stream_tag,
  134. unsigned int format,
  135. snd_pcm_substream_t *substream)
  136. {
  137. struct ad198x_spec *spec = codec->spec;
  138. snd_hda_codec_setup_stream(codec, spec->adc_nid, stream_tag, 0, format);
  139. return 0;
  140. }
  141. static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
  142. struct hda_codec *codec,
  143. snd_pcm_substream_t *substream)
  144. {
  145. struct ad198x_spec *spec = codec->spec;
  146. snd_hda_codec_setup_stream(codec, spec->adc_nid, 0, 0, 0);
  147. return 0;
  148. }
  149. /*
  150. */
  151. static struct hda_pcm_stream ad198x_pcm_analog_playback = {
  152. .substreams = 1,
  153. .channels_min = 2,
  154. .channels_max = 6,
  155. .nid = 0, /* fill later */
  156. .ops = {
  157. .open = ad198x_playback_pcm_open,
  158. .prepare = ad198x_playback_pcm_prepare,
  159. .cleanup = ad198x_playback_pcm_cleanup
  160. },
  161. };
  162. static struct hda_pcm_stream ad198x_pcm_analog_capture = {
  163. .substreams = 2,
  164. .channels_min = 2,
  165. .channels_max = 2,
  166. .nid = 0, /* fill later */
  167. .ops = {
  168. .prepare = ad198x_capture_pcm_prepare,
  169. .cleanup = ad198x_capture_pcm_cleanup
  170. },
  171. };
  172. static struct hda_pcm_stream ad198x_pcm_digital_playback = {
  173. .substreams = 1,
  174. .channels_min = 2,
  175. .channels_max = 2,
  176. .nid = 0, /* fill later */
  177. .ops = {
  178. .open = ad198x_dig_playback_pcm_open,
  179. .close = ad198x_dig_playback_pcm_close
  180. },
  181. };
  182. static int ad198x_build_pcms(struct hda_codec *codec)
  183. {
  184. struct ad198x_spec *spec = codec->spec;
  185. struct hda_pcm *info = spec->pcm_rec;
  186. codec->num_pcms = 1;
  187. codec->pcm_info = info;
  188. info->name = "AD198x Analog";
  189. info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
  190. info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
  191. info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
  192. info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
  193. info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid;
  194. if (spec->multiout.dig_out_nid) {
  195. info++;
  196. codec->num_pcms++;
  197. info->name = "AD198x Digital";
  198. info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
  199. info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
  200. }
  201. return 0;
  202. }
  203. static void ad198x_free(struct hda_codec *codec)
  204. {
  205. kfree(codec->spec);
  206. }
  207. #ifdef CONFIG_PM
  208. static int ad198x_resume(struct hda_codec *codec)
  209. {
  210. struct ad198x_spec *spec = codec->spec;
  211. ad198x_init(codec);
  212. snd_hda_resume_ctls(codec, spec->mixers);
  213. snd_hda_resume_spdif_out(codec);
  214. return 0;
  215. }
  216. #endif
  217. static struct hda_codec_ops ad198x_patch_ops = {
  218. .build_controls = ad198x_build_controls,
  219. .build_pcms = ad198x_build_pcms,
  220. .init = ad198x_init,
  221. .free = ad198x_free,
  222. #ifdef CONFIG_PM
  223. .resume = ad198x_resume,
  224. #endif
  225. };
  226. /*
  227. * AD1986A specific
  228. */
  229. #define AD1986A_SPDIF_OUT 0x02
  230. #define AD1986A_FRONT_DAC 0x03
  231. #define AD1986A_SURR_DAC 0x04
  232. #define AD1986A_CLFE_DAC 0x05
  233. #define AD1986A_ADC 0x06
  234. static hda_nid_t ad1986a_dac_nids[3] = {
  235. AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
  236. };
  237. static struct hda_input_mux ad1986a_capture_source = {
  238. .num_items = 7,
  239. .items = {
  240. { "Mic", 0x0 },
  241. { "CD", 0x1 },
  242. { "Aux", 0x3 },
  243. { "Line", 0x4 },
  244. { "Mix", 0x5 },
  245. { "Mono", 0x6 },
  246. { "Phone", 0x7 },
  247. },
  248. };
  249. /*
  250. * PCM control
  251. *
  252. * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
  253. */
  254. #define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info
  255. static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  256. {
  257. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  258. struct ad198x_spec *ad = codec->spec;
  259. down(&ad->amp_mutex);
  260. snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
  261. up(&ad->amp_mutex);
  262. return 0;
  263. }
  264. static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  265. {
  266. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  267. struct ad198x_spec *ad = codec->spec;
  268. int i, change = 0;
  269. down(&ad->amp_mutex);
  270. for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
  271. kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
  272. change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
  273. }
  274. kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
  275. up(&ad->amp_mutex);
  276. return change;
  277. }
  278. #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info
  279. static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  280. {
  281. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  282. struct ad198x_spec *ad = codec->spec;
  283. down(&ad->amp_mutex);
  284. snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
  285. up(&ad->amp_mutex);
  286. return 0;
  287. }
  288. static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  289. {
  290. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  291. struct ad198x_spec *ad = codec->spec;
  292. int i, change = 0;
  293. down(&ad->amp_mutex);
  294. for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
  295. kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
  296. change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
  297. }
  298. kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
  299. up(&ad->amp_mutex);
  300. return change;
  301. }
  302. /*
  303. * mixers
  304. */
  305. static snd_kcontrol_new_t ad1986a_mixers[] = {
  306. {
  307. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  308. .name = "PCM Playback Volume",
  309. .info = ad1986a_pcm_amp_vol_info,
  310. .get = ad1986a_pcm_amp_vol_get,
  311. .put = ad1986a_pcm_amp_vol_put,
  312. .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
  313. },
  314. {
  315. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  316. .name = "PCM Playback Switch",
  317. .info = ad1986a_pcm_amp_sw_info,
  318. .get = ad1986a_pcm_amp_sw_get,
  319. .put = ad1986a_pcm_amp_sw_put,
  320. .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
  321. },
  322. HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
  323. HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
  324. HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
  325. HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
  326. HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
  327. HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
  328. HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
  329. HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
  330. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
  331. HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
  332. HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
  333. HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
  334. HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
  335. HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
  336. HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
  337. HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
  338. HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
  339. HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
  340. HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
  341. HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
  342. HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
  343. HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
  344. HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
  345. HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
  346. {
  347. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  348. .name = "Capture Source",
  349. .info = ad198x_mux_enum_info,
  350. .get = ad198x_mux_enum_get,
  351. .put = ad198x_mux_enum_put,
  352. },
  353. HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
  354. { } /* end */
  355. };
  356. /*
  357. * initialization verbs
  358. */
  359. static struct hda_verb ad1986a_init_verbs[] = {
  360. /* Front, Surround, CLFE DAC; mute as default */
  361. {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  362. {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  363. {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  364. /* Downmix - off */
  365. {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  366. /* HP, Line-Out, Surround, CLFE selectors */
  367. {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
  368. {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
  369. {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
  370. {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
  371. /* Mono selector */
  372. {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
  373. /* Mic selector: Mic 1/2 pin */
  374. {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
  375. /* Line-in selector: Line-in */
  376. {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
  377. /* Mic 1/2 swap */
  378. {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
  379. /* Record selector: mic */
  380. {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
  381. /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
  382. {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  383. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  384. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  385. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  386. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  387. /* PC beep */
  388. {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
  389. /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
  390. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  391. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  392. {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  393. {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  394. {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  395. /* HP Pin */
  396. {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
  397. /* Front, Surround, CLFE Pins */
  398. {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  399. {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  400. {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  401. /* Mono Pin */
  402. {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  403. /* Mic Pin */
  404. {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
  405. /* Line, Aux, CD, Beep-In Pin */
  406. {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
  407. {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
  408. {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
  409. {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
  410. {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
  411. { } /* end */
  412. };
  413. static int patch_ad1986a(struct hda_codec *codec)
  414. {
  415. struct ad198x_spec *spec;
  416. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  417. if (spec == NULL)
  418. return -ENOMEM;
  419. init_MUTEX(&spec->amp_mutex);
  420. codec->spec = spec;
  421. spec->multiout.max_channels = 6;
  422. spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
  423. spec->multiout.dac_nids = ad1986a_dac_nids;
  424. spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
  425. spec->adc_nid = AD1986A_ADC;
  426. spec->input_mux = &ad1986a_capture_source;
  427. spec->mixers = ad1986a_mixers;
  428. spec->init_verbs = ad1986a_init_verbs;
  429. codec->patch_ops = ad198x_patch_ops;
  430. return 0;
  431. }
  432. /*
  433. * AD1983 specific
  434. */
  435. #define AD1983_SPDIF_OUT 0x02
  436. #define AD1983_DAC 0x03
  437. #define AD1983_ADC 0x04
  438. static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
  439. static struct hda_input_mux ad1983_capture_source = {
  440. .num_items = 4,
  441. .items = {
  442. { "Mic", 0x0 },
  443. { "Line", 0x1 },
  444. { "Mix", 0x2 },
  445. { "Mix Mono", 0x3 },
  446. },
  447. };
  448. /*
  449. * SPDIF playback route
  450. */
  451. static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  452. {
  453. static char *texts[] = { "PCM", "ADC" };
  454. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  455. uinfo->count = 1;
  456. uinfo->value.enumerated.items = 2;
  457. if (uinfo->value.enumerated.item > 1)
  458. uinfo->value.enumerated.item = 1;
  459. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  460. return 0;
  461. }
  462. static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  463. {
  464. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  465. struct ad198x_spec *spec = codec->spec;
  466. ucontrol->value.enumerated.item[0] = spec->spdif_route;
  467. return 0;
  468. }
  469. static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  470. {
  471. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  472. struct ad198x_spec *spec = codec->spec;
  473. if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
  474. spec->spdif_route = ucontrol->value.enumerated.item[0];
  475. snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
  476. AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
  477. return 1;
  478. }
  479. return 0;
  480. }
  481. static snd_kcontrol_new_t ad1983_mixers[] = {
  482. HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
  483. HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
  484. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
  485. HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
  486. HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
  487. HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
  488. HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
  489. HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
  490. HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
  491. HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
  492. HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
  493. HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
  494. HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
  495. HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
  496. HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
  497. HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
  498. HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
  499. {
  500. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  501. .name = "Capture Source",
  502. .info = ad198x_mux_enum_info,
  503. .get = ad198x_mux_enum_get,
  504. .put = ad198x_mux_enum_put,
  505. },
  506. {
  507. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  508. .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
  509. .info = ad1983_spdif_route_info,
  510. .get = ad1983_spdif_route_get,
  511. .put = ad1983_spdif_route_put,
  512. },
  513. { } /* end */
  514. };
  515. static struct hda_verb ad1983_init_verbs[] = {
  516. /* Front, HP, Mono; mute as default */
  517. {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  518. {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  519. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  520. /* Beep, PCM, Mic, Line-In: mute */
  521. {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  522. {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  523. {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  524. {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  525. /* Front, HP selectors; from Mix */
  526. {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
  527. {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
  528. /* Mono selector; from Mix */
  529. {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
  530. /* Mic selector; Mic */
  531. {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
  532. /* Line-in selector: Line-in */
  533. {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
  534. /* Mic boost: 0dB */
  535. {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  536. /* Record selector: mic */
  537. {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
  538. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  539. /* SPDIF route: PCM */
  540. {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
  541. /* Front Pin */
  542. {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  543. /* HP Pin */
  544. {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
  545. /* Mono Pin */
  546. {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  547. /* Mic Pin */
  548. {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
  549. /* Line Pin */
  550. {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
  551. { } /* end */
  552. };
  553. static int patch_ad1983(struct hda_codec *codec)
  554. {
  555. struct ad198x_spec *spec;
  556. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  557. if (spec == NULL)
  558. return -ENOMEM;
  559. init_MUTEX(&spec->amp_mutex);
  560. codec->spec = spec;
  561. spec->multiout.max_channels = 2;
  562. spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
  563. spec->multiout.dac_nids = ad1983_dac_nids;
  564. spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
  565. spec->adc_nid = AD1983_ADC;
  566. spec->input_mux = &ad1983_capture_source;
  567. spec->mixers = ad1983_mixers;
  568. spec->init_verbs = ad1983_init_verbs;
  569. spec->spdif_route = 0;
  570. codec->patch_ops = ad198x_patch_ops;
  571. return 0;
  572. }
  573. /*
  574. * AD1981 HD specific
  575. */
  576. #define AD1981_SPDIF_OUT 0x02
  577. #define AD1981_DAC 0x03
  578. #define AD1981_ADC 0x04
  579. static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
  580. /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
  581. static struct hda_input_mux ad1981_capture_source = {
  582. .num_items = 7,
  583. .items = {
  584. { "Front Mic", 0x0 },
  585. { "Line", 0x1 },
  586. { "Mix", 0x2 },
  587. { "Mix Mono", 0x3 },
  588. { "CD", 0x4 },
  589. { "Mic", 0x6 },
  590. { "Aux", 0x7 },
  591. },
  592. };
  593. static snd_kcontrol_new_t ad1981_mixers[] = {
  594. HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
  595. HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
  596. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
  597. HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
  598. HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
  599. HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
  600. HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
  601. HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
  602. HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
  603. HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
  604. HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
  605. HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
  606. HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
  607. HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
  608. HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
  609. HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
  610. HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
  611. HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
  612. HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
  613. HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
  614. HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
  615. HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
  616. HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
  617. HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
  618. {
  619. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  620. .name = "Capture Source",
  621. .info = ad198x_mux_enum_info,
  622. .get = ad198x_mux_enum_get,
  623. .put = ad198x_mux_enum_put,
  624. },
  625. /* identical with AD1983 */
  626. {
  627. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  628. .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
  629. .info = ad1983_spdif_route_info,
  630. .get = ad1983_spdif_route_get,
  631. .put = ad1983_spdif_route_put,
  632. },
  633. { } /* end */
  634. };
  635. static struct hda_verb ad1981_init_verbs[] = {
  636. /* Front, HP, Mono; mute as default */
  637. {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  638. {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  639. {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  640. /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
  641. {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  642. {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  643. {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  644. {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  645. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  646. {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  647. {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  648. /* Front, HP selectors; from Mix */
  649. {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
  650. {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
  651. /* Mono selector; from Mix */
  652. {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
  653. /* Mic Mixer; select Front Mic */
  654. {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  655. {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  656. /* Mic boost: 0dB */
  657. {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  658. {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
  659. /* Record selector: Front mic */
  660. {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
  661. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  662. /* SPDIF route: PCM */
  663. {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
  664. /* Front Pin */
  665. {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  666. /* HP Pin */
  667. {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
  668. /* Mono Pin */
  669. {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
  670. /* Front & Rear Mic Pins */
  671. {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
  672. {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
  673. /* Line Pin */
  674. {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
  675. /* Digital Beep */
  676. {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
  677. /* Line-Out as Input: disabled */
  678. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  679. { } /* end */
  680. };
  681. static int patch_ad1981(struct hda_codec *codec)
  682. {
  683. struct ad198x_spec *spec;
  684. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  685. if (spec == NULL)
  686. return -ENOMEM;
  687. init_MUTEX(&spec->amp_mutex);
  688. codec->spec = spec;
  689. spec->multiout.max_channels = 2;
  690. spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
  691. spec->multiout.dac_nids = ad1981_dac_nids;
  692. spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
  693. spec->adc_nid = AD1981_ADC;
  694. spec->input_mux = &ad1981_capture_source;
  695. spec->mixers = ad1981_mixers;
  696. spec->init_verbs = ad1981_init_verbs;
  697. spec->spdif_route = 0;
  698. codec->patch_ops = ad198x_patch_ops;
  699. return 0;
  700. }
  701. /*
  702. * patch entries
  703. */
  704. struct hda_codec_preset snd_hda_preset_analog[] = {
  705. { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
  706. { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
  707. { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
  708. {} /* terminator */
  709. };