patch_nvhdmi.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * Universal Interface for Intel High Definition Audio Codec
  3. *
  4. * HD audio interface patch for NVIDIA HDMI codecs
  5. *
  6. * Copyright (c) 2008 NVIDIA Corp. All rights reserved.
  7. * Copyright (c) 2008 Wei Ni <wni@nvidia.com>
  8. *
  9. *
  10. * This driver is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This driver is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. #include <linux/init.h>
  25. #include <linux/delay.h>
  26. #include <linux/slab.h>
  27. #include <sound/core.h>
  28. #include "hda_codec.h"
  29. #include "hda_local.h"
  30. struct nvhdmi_spec {
  31. struct hda_multi_out multiout;
  32. struct hda_pcm pcm_rec;
  33. };
  34. #define Nv_VERB_SET_Channel_Allocation 0xF79
  35. #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A
  36. #define Nv_VERB_SET_Audio_Protection_On 0xF98
  37. #define Nv_VERB_SET_Audio_Protection_Off 0xF99
  38. #define Nv_Master_Convert_nid 0x04
  39. #define Nv_Master_Pin_nid 0x05
  40. static hda_nid_t nvhdmi_convert_nids[4] = {
  41. /*front, rear, clfe, rear_surr */
  42. 0x6, 0x8, 0xa, 0xc,
  43. };
  44. static struct hda_verb nvhdmi_basic_init[] = {
  45. /* set audio protect on */
  46. { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
  47. /* enable digital output on pin widget */
  48. { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
  49. { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
  50. { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
  51. { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
  52. { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
  53. {} /* terminator */
  54. };
  55. /*
  56. * Controls
  57. */
  58. static int nvhdmi_build_controls(struct hda_codec *codec)
  59. {
  60. struct nvhdmi_spec *spec = codec->spec;
  61. int err;
  62. err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
  63. if (err < 0)
  64. return err;
  65. return 0;
  66. }
  67. static int nvhdmi_init(struct hda_codec *codec)
  68. {
  69. snd_hda_sequence_write(codec, nvhdmi_basic_init);
  70. return 0;
  71. }
  72. /*
  73. * Digital out
  74. */
  75. static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
  76. struct hda_codec *codec,
  77. struct snd_pcm_substream *substream)
  78. {
  79. struct nvhdmi_spec *spec = codec->spec;
  80. return snd_hda_multi_out_dig_open(codec, &spec->multiout);
  81. }
  82. static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
  83. struct hda_codec *codec,
  84. struct snd_pcm_substream *substream)
  85. {
  86. struct nvhdmi_spec *spec = codec->spec;
  87. int i;
  88. snd_hda_codec_write(codec, Nv_Master_Convert_nid,
  89. 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
  90. for (i = 0; i < 4; i++) {
  91. /* set the stream id */
  92. snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
  93. AC_VERB_SET_CHANNEL_STREAMID, 0);
  94. /* set the stream format */
  95. snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
  96. AC_VERB_SET_STREAM_FORMAT, 0);
  97. }
  98. return snd_hda_multi_out_dig_close(codec, &spec->multiout);
  99. }
  100. static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
  101. struct hda_codec *codec,
  102. struct snd_pcm_substream *substream)
  103. {
  104. struct nvhdmi_spec *spec = codec->spec;
  105. return snd_hda_multi_out_dig_close(codec, &spec->multiout);
  106. }
  107. static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
  108. struct hda_codec *codec,
  109. unsigned int stream_tag,
  110. unsigned int format,
  111. struct snd_pcm_substream *substream)
  112. {
  113. int chs;
  114. unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
  115. int i;
  116. mutex_lock(&codec->spdif_mutex);
  117. chs = substream->runtime->channels;
  118. chan = chs ? (chs - 1) : 1;
  119. switch (chs) {
  120. default:
  121. case 0:
  122. case 2:
  123. chanmask = 0x00;
  124. break;
  125. case 4:
  126. chanmask = 0x08;
  127. break;
  128. case 6:
  129. chanmask = 0x0b;
  130. break;
  131. case 8:
  132. chanmask = 0x13;
  133. break;
  134. }
  135. dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
  136. dataDCC2 = 0x2;
  137. /* set the Audio InforFrame Channel Allocation */
  138. snd_hda_codec_write(codec, 0x1, 0,
  139. Nv_VERB_SET_Channel_Allocation, chanmask);
  140. /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
  141. if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
  142. snd_hda_codec_write(codec,
  143. Nv_Master_Convert_nid,
  144. 0,
  145. AC_VERB_SET_DIGI_CONVERT_1,
  146. codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
  147. /* set the stream id */
  148. snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
  149. AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
  150. /* set the stream format */
  151. snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
  152. AC_VERB_SET_STREAM_FORMAT, format);
  153. /* turn on again (if needed) */
  154. /* enable and set the channel status audio/data flag */
  155. if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
  156. snd_hda_codec_write(codec,
  157. Nv_Master_Convert_nid,
  158. 0,
  159. AC_VERB_SET_DIGI_CONVERT_1,
  160. codec->spdif_ctls & 0xff);
  161. snd_hda_codec_write(codec,
  162. Nv_Master_Convert_nid,
  163. 0,
  164. AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
  165. }
  166. for (i = 0; i < 4; i++) {
  167. if (chs == 2)
  168. channel_id = 0;
  169. else
  170. channel_id = i * 2;
  171. /* turn off SPDIF once;
  172. *otherwise the IEC958 bits won't be updated
  173. */
  174. if (codec->spdif_status_reset &&
  175. (codec->spdif_ctls & AC_DIG1_ENABLE))
  176. snd_hda_codec_write(codec,
  177. nvhdmi_convert_nids[i],
  178. 0,
  179. AC_VERB_SET_DIGI_CONVERT_1,
  180. codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
  181. /* set the stream id */
  182. snd_hda_codec_write(codec,
  183. nvhdmi_convert_nids[i],
  184. 0,
  185. AC_VERB_SET_CHANNEL_STREAMID,
  186. (stream_tag << 4) | channel_id);
  187. /* set the stream format */
  188. snd_hda_codec_write(codec,
  189. nvhdmi_convert_nids[i],
  190. 0,
  191. AC_VERB_SET_STREAM_FORMAT,
  192. format);
  193. /* turn on again (if needed) */
  194. /* enable and set the channel status audio/data flag */
  195. if (codec->spdif_status_reset &&
  196. (codec->spdif_ctls & AC_DIG1_ENABLE)) {
  197. snd_hda_codec_write(codec,
  198. nvhdmi_convert_nids[i],
  199. 0,
  200. AC_VERB_SET_DIGI_CONVERT_1,
  201. codec->spdif_ctls & 0xff);
  202. snd_hda_codec_write(codec,
  203. nvhdmi_convert_nids[i],
  204. 0,
  205. AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
  206. }
  207. }
  208. /* set the Audio Info Frame Checksum */
  209. snd_hda_codec_write(codec, 0x1, 0,
  210. Nv_VERB_SET_Info_Frame_Checksum,
  211. (0x71 - chan - chanmask));
  212. mutex_unlock(&codec->spdif_mutex);
  213. return 0;
  214. }
  215. static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
  216. struct hda_codec *codec,
  217. unsigned int stream_tag,
  218. unsigned int format,
  219. struct snd_pcm_substream *substream)
  220. {
  221. struct nvhdmi_spec *spec = codec->spec;
  222. return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
  223. format, substream);
  224. }
  225. static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
  226. .substreams = 1,
  227. .channels_min = 2,
  228. .channels_max = 8,
  229. .nid = Nv_Master_Convert_nid,
  230. .rates = SNDRV_PCM_RATE_48000,
  231. .maxbps = 16,
  232. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  233. .ops = {
  234. .open = nvhdmi_dig_playback_pcm_open,
  235. .close = nvhdmi_dig_playback_pcm_close_8ch,
  236. .prepare = nvhdmi_dig_playback_pcm_prepare_8ch
  237. },
  238. };
  239. static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
  240. .substreams = 1,
  241. .channels_min = 2,
  242. .channels_max = 2,
  243. .nid = Nv_Master_Convert_nid,
  244. .rates = SNDRV_PCM_RATE_48000,
  245. .maxbps = 16,
  246. .formats = SNDRV_PCM_FMTBIT_S16_LE,
  247. .ops = {
  248. .open = nvhdmi_dig_playback_pcm_open,
  249. .close = nvhdmi_dig_playback_pcm_close_2ch,
  250. .prepare = nvhdmi_dig_playback_pcm_prepare_2ch
  251. },
  252. };
  253. static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
  254. {
  255. struct nvhdmi_spec *spec = codec->spec;
  256. struct hda_pcm *info = &spec->pcm_rec;
  257. codec->num_pcms = 1;
  258. codec->pcm_info = info;
  259. info->name = "NVIDIA HDMI";
  260. info->pcm_type = HDA_PCM_TYPE_HDMI;
  261. info->stream[SNDRV_PCM_STREAM_PLAYBACK]
  262. = nvhdmi_pcm_digital_playback_8ch;
  263. return 0;
  264. }
  265. static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
  266. {
  267. struct nvhdmi_spec *spec = codec->spec;
  268. struct hda_pcm *info = &spec->pcm_rec;
  269. codec->num_pcms = 1;
  270. codec->pcm_info = info;
  271. info->name = "NVIDIA HDMI";
  272. info->pcm_type = HDA_PCM_TYPE_HDMI;
  273. info->stream[SNDRV_PCM_STREAM_PLAYBACK]
  274. = nvhdmi_pcm_digital_playback_2ch;
  275. return 0;
  276. }
  277. static void nvhdmi_free(struct hda_codec *codec)
  278. {
  279. kfree(codec->spec);
  280. }
  281. static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
  282. .build_controls = nvhdmi_build_controls,
  283. .build_pcms = nvhdmi_build_pcms_8ch,
  284. .init = nvhdmi_init,
  285. .free = nvhdmi_free,
  286. };
  287. static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
  288. .build_controls = nvhdmi_build_controls,
  289. .build_pcms = nvhdmi_build_pcms_2ch,
  290. .init = nvhdmi_init,
  291. .free = nvhdmi_free,
  292. };
  293. static int patch_nvhdmi_8ch(struct hda_codec *codec)
  294. {
  295. struct nvhdmi_spec *spec;
  296. spec = kzalloc(sizeof(*spec), GFP_KERNEL);
  297. if (spec == NULL)
  298. return -ENOMEM;
  299. codec->spec = spec;
  300. spec->multiout.num_dacs = 0; /* no analog */
  301. spec->multiout.max_channels = 8;
  302. spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
  303. codec->patch_ops = nvhdmi_patch_ops_8ch;
  304. return 0;
  305. }
  306. static int patch_nvhdmi_2ch(struct hda_codec *codec)
  307. {
  308. struct nvhdmi_spec *spec;
  309. spec = kzalloc(sizeof(*spec), GFP_KERNEL);
  310. if (spec == NULL)
  311. return -ENOMEM;
  312. codec->spec = spec;
  313. spec->multiout.num_dacs = 0; /* no analog */
  314. spec->multiout.max_channels = 2;
  315. spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
  316. codec->patch_ops = nvhdmi_patch_ops_2ch;
  317. return 0;
  318. }
  319. /*
  320. * patch entries
  321. */
  322. static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
  323. { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
  324. { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
  325. { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
  326. { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
  327. { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
  328. {} /* terminator */
  329. };
  330. MODULE_ALIAS("snd-hda-codec-id:10de0002");
  331. MODULE_ALIAS("snd-hda-codec-id:10de0006");
  332. MODULE_ALIAS("snd-hda-codec-id:10de0007");
  333. MODULE_ALIAS("snd-hda-codec-id:10de0067");
  334. MODULE_ALIAS("snd-hda-codec-id:10de8001");
  335. MODULE_LICENSE("GPL");
  336. MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
  337. static struct hda_codec_preset_list nvhdmi_list = {
  338. .preset = snd_hda_preset_nvhdmi,
  339. .owner = THIS_MODULE,
  340. };
  341. static int __init patch_nvhdmi_init(void)
  342. {
  343. return snd_hda_add_codec_preset(&nvhdmi_list);
  344. }
  345. static void __exit patch_nvhdmi_exit(void)
  346. {
  347. snd_hda_delete_codec_preset(&nvhdmi_list);
  348. }
  349. module_init(patch_nvhdmi_init)
  350. module_exit(patch_nvhdmi_exit)