aio-ld11.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Socionext UniPhier AIO ALSA driver for LD11/LD20.
  4. //
  5. // Copyright (c) 2016-2018 Socionext Inc.
  6. #include <linux/module.h>
  7. #include "aio.h"
  8. static const struct uniphier_aio_spec uniphier_aio_ld11[] = {
  9. /* for HDMI PCM In, Pin:AI1Dx */
  10. {
  11. .name = AUD_NAME_PCMIN1,
  12. .gname = AUD_GNAME_HDMI,
  13. .swm = {
  14. .type = PORT_TYPE_I2S,
  15. .dir = PORT_DIR_INPUT,
  16. .rb = { 21, 14, },
  17. .ch = { 21, 14, },
  18. .iif = { 5, 3, },
  19. .iport = { 0, AUD_HW_PCMIN1, },
  20. },
  21. },
  22. /* for SIF In, Pin:AI2Dx */
  23. {
  24. .name = AUD_NAME_PCMIN2,
  25. .swm = {
  26. .type = PORT_TYPE_I2S,
  27. .dir = PORT_DIR_INPUT,
  28. .rb = { 22, 15, },
  29. .ch = { 22, 15, },
  30. .iif = { 6, 4, },
  31. .iport = { 1, AUD_HW_PCMIN2, },
  32. },
  33. },
  34. /* for Line In, Pin:AI3Dx */
  35. {
  36. .name = AUD_NAME_PCMIN3,
  37. .gname = AUD_GNAME_LINE,
  38. .swm = {
  39. .type = PORT_TYPE_EVE,
  40. .dir = PORT_DIR_INPUT,
  41. .rb = { 23, 16, },
  42. .ch = { 23, 16, },
  43. .iif = { 7, 5, },
  44. .iport = { 2, AUD_HW_PCMIN3, },
  45. },
  46. },
  47. /* for S/PDIF In, Pin:AI1IEC */
  48. {
  49. .name = AUD_NAME_IECIN1,
  50. .gname = AUD_GNAME_IEC,
  51. .swm = {
  52. .type = PORT_TYPE_SPDIF,
  53. .dir = PORT_DIR_INPUT,
  54. .rb = { 26, 17, },
  55. .ch = { 26, 17, },
  56. .iif = { 10, 6, },
  57. .iport = { 3, AUD_HW_IECIN1, },
  58. },
  59. },
  60. /* for Speaker, Pin:AO1Dx */
  61. {
  62. .name = AUD_NAME_HPCMOUT1,
  63. .swm = {
  64. .type = PORT_TYPE_I2S,
  65. .dir = PORT_DIR_OUTPUT,
  66. .rb = { 0, 0, },
  67. .ch = { 0, 0, },
  68. .oif = { 0, 0, },
  69. .oport = { 0, AUD_HW_HPCMOUT1, },
  70. },
  71. },
  72. /* for HDMI PCM, Pin:AO2Dx */
  73. {
  74. .name = AUD_NAME_PCMOUT1,
  75. .gname = AUD_GNAME_HDMI,
  76. .swm = {
  77. .type = PORT_TYPE_I2S,
  78. .dir = PORT_DIR_OUTPUT,
  79. .rb = { 0, 0, },
  80. .ch = { 0, 0, },
  81. .oif = { 0, 0, },
  82. .oport = { 3, AUD_HW_PCMOUT1, },
  83. },
  84. },
  85. /* for Line Out, Pin:LO2_x */
  86. {
  87. .name = AUD_NAME_PCMOUT2,
  88. .gname = AUD_GNAME_LINE,
  89. .swm = {
  90. .type = PORT_TYPE_EVE,
  91. .dir = PORT_DIR_OUTPUT,
  92. .rb = { 2, 2, },
  93. .ch = { 2, 2, },
  94. .oif = { 2, 2, },
  95. .oport = { 1, AUD_HW_PCMOUT2, },
  96. },
  97. },
  98. /* for Headphone, Pin:HP1_x */
  99. {
  100. .name = AUD_NAME_PCMOUT3,
  101. .swm = {
  102. .type = PORT_TYPE_EVE,
  103. .dir = PORT_DIR_OUTPUT,
  104. .rb = { 3, 3, },
  105. .ch = { 3, 3, },
  106. .oif = { 3, 3, },
  107. .oport = { 2, AUD_HW_PCMOUT3, },
  108. },
  109. },
  110. /* for HW Sampling Rate Converter */
  111. {
  112. .name = AUD_NAME_EPCMOUT2,
  113. .swm = {
  114. .type = PORT_TYPE_CONV,
  115. .dir = PORT_DIR_OUTPUT,
  116. .rb = { 7, 5, },
  117. .ch = { 7, 5, },
  118. .oif = { 7, 5, },
  119. .oport = { 6, AUD_HW_EPCMOUT2, },
  120. .och = { 17, 12, },
  121. .iif = { 1, 1, },
  122. },
  123. },
  124. /* for HW Sampling Rate Converter 2 */
  125. {
  126. .name = AUD_NAME_EPCMOUT3,
  127. .swm = {
  128. .type = PORT_TYPE_CONV,
  129. .dir = PORT_DIR_OUTPUT,
  130. .rb = { 8, 6, },
  131. .ch = { 8, 6, },
  132. .oif = { 8, 6, },
  133. .oport = { 7, AUD_HW_EPCMOUT3, },
  134. .och = { 18, 13, },
  135. .iif = { 2, 2, },
  136. },
  137. },
  138. /* for S/PDIF Out, Pin:AO1IEC */
  139. {
  140. .name = AUD_NAME_HIECOUT1,
  141. .gname = AUD_GNAME_IEC,
  142. .swm = {
  143. .type = PORT_TYPE_SPDIF,
  144. .dir = PORT_DIR_OUTPUT,
  145. .rb = { 1, 1, },
  146. .ch = { 1, 1, },
  147. .oif = { 1, 1, },
  148. .oport = { 12, AUD_HW_HIECOUT1, },
  149. },
  150. },
  151. /* for S/PDIF Out, Pin:AO1IEC, Compress */
  152. {
  153. .name = AUD_NAME_HIECCOMPOUT1,
  154. .gname = AUD_GNAME_IEC,
  155. .swm = {
  156. .type = PORT_TYPE_SPDIF,
  157. .dir = PORT_DIR_OUTPUT,
  158. .rb = { 1, 1, },
  159. .ch = { 1, 1, },
  160. .oif = { 1, 1, },
  161. .oport = { 12, AUD_HW_HIECOUT1, },
  162. },
  163. },
  164. };
  165. static const struct uniphier_aio_pll uniphier_aio_pll_ld11[] = {
  166. [AUD_PLL_A1] = { .enable = true, },
  167. [AUD_PLL_F1] = { .enable = true, },
  168. [AUD_PLL_A2] = { .enable = true, },
  169. [AUD_PLL_F2] = { .enable = true, },
  170. [AUD_PLL_APLL] = { .enable = true, },
  171. [AUD_PLL_RX0] = { .enable = true, },
  172. [AUD_PLL_USB0] = { .enable = true, },
  173. [AUD_PLL_HSC0] = { .enable = true, },
  174. };
  175. static int uniphier_aio_ld11_probe(struct snd_soc_dai *dai)
  176. {
  177. int ret;
  178. ret = uniphier_aio_dai_probe(dai);
  179. if (ret < 0)
  180. return ret;
  181. ret = snd_soc_dai_set_pll(dai, AUD_PLL_A1, 0, 0, 36864000);
  182. if (ret < 0)
  183. return ret;
  184. ret = snd_soc_dai_set_pll(dai, AUD_PLL_F1, 0, 0, 36864000);
  185. if (ret < 0)
  186. return ret;
  187. ret = snd_soc_dai_set_pll(dai, AUD_PLL_A2, 0, 0, 33868800);
  188. if (ret < 0)
  189. return ret;
  190. ret = snd_soc_dai_set_pll(dai, AUD_PLL_F2, 0, 0, 33868800);
  191. if (ret < 0)
  192. return ret;
  193. return 0;
  194. }
  195. static struct snd_soc_dai_driver uniphier_aio_dai_ld11[] = {
  196. {
  197. .name = AUD_GNAME_HDMI,
  198. .probe = uniphier_aio_ld11_probe,
  199. .remove = uniphier_aio_dai_remove,
  200. .suspend = uniphier_aio_dai_suspend,
  201. .resume = uniphier_aio_dai_resume,
  202. .playback = {
  203. .stream_name = AUD_NAME_PCMOUT1,
  204. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  205. .rates = SNDRV_PCM_RATE_48000,
  206. .channels_min = 2,
  207. .channels_max = 2,
  208. },
  209. .capture = {
  210. .stream_name = AUD_NAME_PCMIN1,
  211. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  212. .rates = SNDRV_PCM_RATE_48000 |
  213. SNDRV_PCM_RATE_44100 |
  214. SNDRV_PCM_RATE_32000,
  215. .channels_min = 2,
  216. .channels_max = 2,
  217. },
  218. .ops = &uniphier_aio_i2s_ops,
  219. },
  220. {
  221. .name = AUD_NAME_PCMIN2,
  222. .probe = uniphier_aio_ld11_probe,
  223. .remove = uniphier_aio_dai_remove,
  224. .suspend = uniphier_aio_dai_suspend,
  225. .resume = uniphier_aio_dai_resume,
  226. .capture = {
  227. .stream_name = AUD_NAME_PCMIN2,
  228. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  229. .rates = SNDRV_PCM_RATE_48000,
  230. .channels_min = 2,
  231. .channels_max = 2,
  232. },
  233. .ops = &uniphier_aio_i2s_ops,
  234. },
  235. {
  236. .name = AUD_GNAME_LINE,
  237. .probe = uniphier_aio_ld11_probe,
  238. .remove = uniphier_aio_dai_remove,
  239. .suspend = uniphier_aio_dai_suspend,
  240. .resume = uniphier_aio_dai_resume,
  241. .playback = {
  242. .stream_name = AUD_NAME_PCMOUT2,
  243. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  244. .rates = SNDRV_PCM_RATE_48000,
  245. .channels_min = 2,
  246. .channels_max = 2,
  247. },
  248. .capture = {
  249. .stream_name = AUD_NAME_PCMIN3,
  250. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  251. .rates = SNDRV_PCM_RATE_48000,
  252. .channels_min = 2,
  253. .channels_max = 2,
  254. },
  255. .ops = &uniphier_aio_i2s_ops,
  256. },
  257. {
  258. .name = AUD_NAME_HPCMOUT1,
  259. .probe = uniphier_aio_ld11_probe,
  260. .remove = uniphier_aio_dai_remove,
  261. .suspend = uniphier_aio_dai_suspend,
  262. .resume = uniphier_aio_dai_resume,
  263. .playback = {
  264. .stream_name = AUD_NAME_HPCMOUT1,
  265. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  266. .rates = SNDRV_PCM_RATE_48000,
  267. .channels_min = 2,
  268. .channels_max = 8,
  269. },
  270. .ops = &uniphier_aio_i2s_ops,
  271. },
  272. {
  273. .name = AUD_NAME_PCMOUT3,
  274. .probe = uniphier_aio_ld11_probe,
  275. .remove = uniphier_aio_dai_remove,
  276. .suspend = uniphier_aio_dai_suspend,
  277. .resume = uniphier_aio_dai_resume,
  278. .playback = {
  279. .stream_name = AUD_NAME_PCMOUT3,
  280. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  281. .rates = SNDRV_PCM_RATE_48000,
  282. .channels_min = 2,
  283. .channels_max = 2,
  284. },
  285. .ops = &uniphier_aio_i2s_ops,
  286. },
  287. {
  288. .name = AUD_NAME_HIECOUT1,
  289. .probe = uniphier_aio_ld11_probe,
  290. .remove = uniphier_aio_dai_remove,
  291. .suspend = uniphier_aio_dai_suspend,
  292. .resume = uniphier_aio_dai_resume,
  293. .playback = {
  294. .stream_name = AUD_NAME_HIECOUT1,
  295. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  296. .rates = SNDRV_PCM_RATE_48000,
  297. .channels_min = 2,
  298. .channels_max = 2,
  299. },
  300. .ops = &uniphier_aio_spdif_ops,
  301. },
  302. {
  303. .name = AUD_NAME_EPCMOUT2,
  304. .probe = uniphier_aio_ld11_probe,
  305. .remove = uniphier_aio_dai_remove,
  306. .suspend = uniphier_aio_dai_suspend,
  307. .resume = uniphier_aio_dai_resume,
  308. .playback = {
  309. .stream_name = AUD_NAME_EPCMOUT2,
  310. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  311. .rates = SNDRV_PCM_RATE_48000 |
  312. SNDRV_PCM_RATE_44100 |
  313. SNDRV_PCM_RATE_32000,
  314. .channels_min = 2,
  315. .channels_max = 2,
  316. },
  317. .ops = &uniphier_aio_i2s_ops,
  318. },
  319. {
  320. .name = AUD_NAME_EPCMOUT3,
  321. .probe = uniphier_aio_ld11_probe,
  322. .remove = uniphier_aio_dai_remove,
  323. .suspend = uniphier_aio_dai_suspend,
  324. .resume = uniphier_aio_dai_resume,
  325. .playback = {
  326. .stream_name = AUD_NAME_EPCMOUT3,
  327. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  328. .rates = SNDRV_PCM_RATE_48000 |
  329. SNDRV_PCM_RATE_44100 |
  330. SNDRV_PCM_RATE_32000,
  331. .channels_min = 2,
  332. .channels_max = 2,
  333. },
  334. .ops = &uniphier_aio_i2s_ops,
  335. },
  336. {
  337. .name = AUD_NAME_HIECCOMPOUT1,
  338. .probe = uniphier_aio_ld11_probe,
  339. .remove = uniphier_aio_dai_remove,
  340. .suspend = uniphier_aio_dai_suspend,
  341. .resume = uniphier_aio_dai_resume,
  342. .compress_new = snd_soc_new_compress,
  343. .playback = {
  344. .stream_name = AUD_NAME_HIECCOMPOUT1,
  345. .channels_min = 1,
  346. .channels_max = 1,
  347. },
  348. .ops = &uniphier_aio_spdif_ops,
  349. },
  350. };
  351. static const struct uniphier_aio_chip_spec uniphier_aio_ld11_spec = {
  352. .specs = uniphier_aio_ld11,
  353. .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
  354. .dais = uniphier_aio_dai_ld11,
  355. .num_dais = ARRAY_SIZE(uniphier_aio_dai_ld11),
  356. .plls = uniphier_aio_pll_ld11,
  357. .num_plls = ARRAY_SIZE(uniphier_aio_pll_ld11),
  358. .addr_ext = 0,
  359. };
  360. static const struct uniphier_aio_chip_spec uniphier_aio_ld20_spec = {
  361. .specs = uniphier_aio_ld11,
  362. .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
  363. .dais = uniphier_aio_dai_ld11,
  364. .num_dais = ARRAY_SIZE(uniphier_aio_dai_ld11),
  365. .plls = uniphier_aio_pll_ld11,
  366. .num_plls = ARRAY_SIZE(uniphier_aio_pll_ld11),
  367. .addr_ext = 1,
  368. };
  369. static const struct of_device_id uniphier_aio_of_match[] = {
  370. {
  371. .compatible = "socionext,uniphier-ld11-aio",
  372. .data = &uniphier_aio_ld11_spec,
  373. },
  374. {
  375. .compatible = "socionext,uniphier-ld20-aio",
  376. .data = &uniphier_aio_ld20_spec,
  377. },
  378. {},
  379. };
  380. MODULE_DEVICE_TABLE(of, uniphier_aio_of_match);
  381. static struct platform_driver uniphier_aio_driver = {
  382. .driver = {
  383. .name = "snd-uniphier-aio-ld11",
  384. .of_match_table = of_match_ptr(uniphier_aio_of_match),
  385. },
  386. .probe = uniphier_aio_probe,
  387. .remove = uniphier_aio_remove,
  388. };
  389. module_platform_driver(uniphier_aio_driver);
  390. MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
  391. MODULE_DESCRIPTION("UniPhier LD11/LD20 AIO driver.");
  392. MODULE_LICENSE("GPL v2");