patch_analog.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. * HD audio interface patch for 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 ad1986a_spec {
  29. struct semaphore amp_mutex; /* PCM volume/mute control mutex */
  30. struct hda_multi_out multiout; /* playback */
  31. unsigned int cur_mux; /* capture source */
  32. struct hda_pcm pcm_rec[2]; /* PCM information */
  33. };
  34. #define AD1986A_SPDIF_OUT 0x02
  35. #define AD1986A_FRONT_DAC 0x03
  36. #define AD1986A_SURR_DAC 0x04
  37. #define AD1986A_CLFE_DAC 0x05
  38. #define AD1986A_ADC 0x06
  39. static hda_nid_t ad1986a_dac_nids[3] = {
  40. AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
  41. };
  42. static struct hda_input_mux ad1986a_capture_source = {
  43. .num_items = 7,
  44. .items = {
  45. { "Mic", 0x0 },
  46. { "CD", 0x1 },
  47. { "Aux", 0x3 },
  48. { "Line", 0x4 },
  49. { "Mix", 0x5 },
  50. { "Mono", 0x6 },
  51. { "Phone", 0x7 },
  52. },
  53. };
  54. /*
  55. * PCM control
  56. *
  57. * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
  58. */
  59. #define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info
  60. static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  61. {
  62. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  63. struct ad1986a_spec *ad = codec->spec;
  64. down(&ad->amp_mutex);
  65. snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
  66. up(&ad->amp_mutex);
  67. return 0;
  68. }
  69. static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  70. {
  71. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  72. struct ad1986a_spec *ad = codec->spec;
  73. int i, change = 0;
  74. down(&ad->amp_mutex);
  75. for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
  76. kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
  77. change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
  78. }
  79. kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
  80. up(&ad->amp_mutex);
  81. return change;
  82. }
  83. #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_volume_info
  84. static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  85. {
  86. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  87. struct ad1986a_spec *ad = codec->spec;
  88. down(&ad->amp_mutex);
  89. snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
  90. up(&ad->amp_mutex);
  91. return 0;
  92. }
  93. static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  94. {
  95. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  96. struct ad1986a_spec *ad = codec->spec;
  97. int i, change = 0;
  98. down(&ad->amp_mutex);
  99. for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
  100. kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
  101. change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
  102. }
  103. kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
  104. up(&ad->amp_mutex);
  105. return change;
  106. }
  107. /*
  108. * input MUX handling
  109. */
  110. static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
  111. {
  112. return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo);
  113. }
  114. static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  115. {
  116. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  117. struct ad1986a_spec *spec = codec->spec;
  118. ucontrol->value.enumerated.item[0] = spec->cur_mux;
  119. return 0;
  120. }
  121. static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
  122. {
  123. struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
  124. struct ad1986a_spec *spec = codec->spec;
  125. return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol,
  126. AD1986A_ADC, &spec->cur_mux);
  127. }
  128. /*
  129. * mixers
  130. */
  131. static snd_kcontrol_new_t ad1986a_mixers[] = {
  132. {
  133. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  134. .name = "PCM Playback Volume",
  135. .info = ad1986a_pcm_amp_vol_info,
  136. .get = ad1986a_pcm_amp_vol_get,
  137. .put = ad1986a_pcm_amp_vol_put,
  138. .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
  139. },
  140. {
  141. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  142. .name = "PCM Playback Switch",
  143. .info = ad1986a_pcm_amp_sw_info,
  144. .get = ad1986a_pcm_amp_sw_get,
  145. .put = ad1986a_pcm_amp_sw_put,
  146. .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
  147. },
  148. HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
  149. HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
  150. HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
  151. HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
  152. HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
  153. HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
  154. HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
  155. HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
  156. HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
  157. HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
  158. HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
  159. HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
  160. HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
  161. HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
  162. HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
  163. HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
  164. HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
  165. HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
  166. HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
  167. HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
  168. HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
  169. HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
  170. HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
  171. HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
  172. {
  173. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  174. .name = "Capture Source",
  175. .info = ad1986a_mux_enum_info,
  176. .get = ad1986a_mux_enum_get,
  177. .put = ad1986a_mux_enum_put,
  178. },
  179. HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
  180. { } /* end */
  181. };
  182. /*
  183. * initialization verbs
  184. */
  185. static struct hda_verb ad1986a_init_verbs[] = {
  186. /* Front, Surround, CLFE DAC; mute as default */
  187. {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  188. {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  189. {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  190. /* Downmix - off */
  191. {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  192. /* HP, Line-Out, Surround, CLFE selectors */
  193. {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
  194. {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
  195. {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
  196. {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
  197. /* Mono selector */
  198. {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
  199. /* Mic selector: Mic 1/2 pin */
  200. {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
  201. /* Line-in selector: Line-in */
  202. {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
  203. /* Mic 1/2 swap */
  204. {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
  205. /* Record selector: mic */
  206. {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
  207. /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
  208. {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  209. {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  210. {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  211. {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  212. {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  213. /* PC beep */
  214. {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
  215. /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
  216. {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  217. {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  218. {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  219. {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  220. {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
  221. { } /* end */
  222. };
  223. static int ad1986a_init(struct hda_codec *codec)
  224. {
  225. snd_hda_sequence_write(codec, ad1986a_init_verbs);
  226. return 0;
  227. }
  228. static int ad1986a_build_controls(struct hda_codec *codec)
  229. {
  230. int err;
  231. err = snd_hda_add_new_ctls(codec, ad1986a_mixers);
  232. if (err < 0)
  233. return err;
  234. err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT);
  235. if (err < 0)
  236. return err;
  237. return 0;
  238. }
  239. /*
  240. * Analog playback callbacks
  241. */
  242. static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo,
  243. struct hda_codec *codec,
  244. snd_pcm_substream_t *substream)
  245. {
  246. struct ad1986a_spec *spec = codec->spec;
  247. return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
  248. }
  249. static int ad1986a_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
  250. struct hda_codec *codec,
  251. unsigned int stream_tag,
  252. unsigned int format,
  253. snd_pcm_substream_t *substream)
  254. {
  255. struct ad1986a_spec *spec = codec->spec;
  256. return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
  257. format, substream);
  258. }
  259. static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
  260. struct hda_codec *codec,
  261. snd_pcm_substream_t *substream)
  262. {
  263. struct ad1986a_spec *spec = codec->spec;
  264. return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
  265. }
  266. /*
  267. * Digital out
  268. */
  269. static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
  270. struct hda_codec *codec,
  271. snd_pcm_substream_t *substream)
  272. {
  273. struct ad1986a_spec *spec = codec->spec;
  274. return snd_hda_multi_out_dig_open(codec, &spec->multiout);
  275. }
  276. static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
  277. struct hda_codec *codec,
  278. snd_pcm_substream_t *substream)
  279. {
  280. struct ad1986a_spec *spec = codec->spec;
  281. return snd_hda_multi_out_dig_close(codec, &spec->multiout);
  282. }
  283. /*
  284. * Analog capture
  285. */
  286. static int ad1986a_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
  287. struct hda_codec *codec,
  288. unsigned int stream_tag,
  289. unsigned int format,
  290. snd_pcm_substream_t *substream)
  291. {
  292. snd_hda_codec_setup_stream(codec, AD1986A_ADC, stream_tag, 0, format);
  293. return 0;
  294. }
  295. static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
  296. struct hda_codec *codec,
  297. snd_pcm_substream_t *substream)
  298. {
  299. snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0);
  300. return 0;
  301. }
  302. /*
  303. */
  304. static struct hda_pcm_stream ad1986a_pcm_analog_playback = {
  305. .substreams = 1,
  306. .channels_min = 2,
  307. .channels_max = 6,
  308. .nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */
  309. .ops = {
  310. .open = ad1986a_playback_pcm_open,
  311. .prepare = ad1986a_playback_pcm_prepare,
  312. .cleanup = ad1986a_playback_pcm_cleanup
  313. },
  314. };
  315. static struct hda_pcm_stream ad1986a_pcm_analog_capture = {
  316. .substreams = 2,
  317. .channels_min = 2,
  318. .channels_max = 2,
  319. .nid = AD1986A_ADC, /* NID to query formats and rates */
  320. .ops = {
  321. .prepare = ad1986a_capture_pcm_prepare,
  322. .cleanup = ad1986a_capture_pcm_cleanup
  323. },
  324. };
  325. static struct hda_pcm_stream ad1986a_pcm_digital_playback = {
  326. .substreams = 1,
  327. .channels_min = 2,
  328. .channels_max = 2,
  329. .nid = AD1986A_SPDIF_OUT,
  330. .ops = {
  331. .open = ad1986a_dig_playback_pcm_open,
  332. .close = ad1986a_dig_playback_pcm_close
  333. },
  334. };
  335. static int ad1986a_build_pcms(struct hda_codec *codec)
  336. {
  337. struct ad1986a_spec *spec = codec->spec;
  338. struct hda_pcm *info = spec->pcm_rec;
  339. codec->num_pcms = 2;
  340. codec->pcm_info = info;
  341. info->name = "AD1986A Analog";
  342. info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback;
  343. info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture;
  344. info++;
  345. info->name = "AD1986A Digital";
  346. info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback;
  347. return 0;
  348. }
  349. static void ad1986a_free(struct hda_codec *codec)
  350. {
  351. kfree(codec->spec);
  352. }
  353. #ifdef CONFIG_PM
  354. static int ad1986a_resume(struct hda_codec *codec)
  355. {
  356. ad1986a_init(codec);
  357. snd_hda_resume_ctls(codec, ad1986a_mixers);
  358. snd_hda_resume_spdif_out(codec);
  359. return 0;
  360. }
  361. #endif
  362. static struct hda_codec_ops ad1986a_patch_ops = {
  363. .build_controls = ad1986a_build_controls,
  364. .build_pcms = ad1986a_build_pcms,
  365. .init = ad1986a_init,
  366. .free = ad1986a_free,
  367. #ifdef CONFIG_PM
  368. .resume = ad1986a_resume,
  369. #endif
  370. };
  371. static int patch_ad1986a(struct hda_codec *codec)
  372. {
  373. struct ad1986a_spec *spec;
  374. spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
  375. if (spec == NULL)
  376. return -ENOMEM;
  377. init_MUTEX(&spec->amp_mutex);
  378. codec->spec = spec;
  379. spec->multiout.max_channels = 6;
  380. spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
  381. spec->multiout.dac_nids = ad1986a_dac_nids;
  382. spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
  383. codec->patch_ops = ad1986a_patch_ops;
  384. return 0;
  385. }
  386. /*
  387. * patch entries
  388. */
  389. struct hda_codec_preset snd_hda_preset_analog[] = {
  390. { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
  391. {} /* terminator */
  392. };