aio-ld11.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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. .playback = {
  201. .stream_name = AUD_NAME_PCMOUT1,
  202. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  203. .rates = SNDRV_PCM_RATE_48000,
  204. .channels_min = 2,
  205. .channels_max = 2,
  206. },
  207. .capture = {
  208. .stream_name = AUD_NAME_PCMIN1,
  209. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  210. .rates = SNDRV_PCM_RATE_48000 |
  211. SNDRV_PCM_RATE_44100 |
  212. SNDRV_PCM_RATE_32000,
  213. .channels_min = 2,
  214. .channels_max = 2,
  215. },
  216. .ops = &uniphier_aio_i2s_ops,
  217. },
  218. {
  219. .name = AUD_NAME_PCMIN2,
  220. .probe = uniphier_aio_ld11_probe,
  221. .remove = uniphier_aio_dai_remove,
  222. .capture = {
  223. .stream_name = AUD_NAME_PCMIN2,
  224. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  225. .rates = SNDRV_PCM_RATE_48000,
  226. .channels_min = 2,
  227. .channels_max = 2,
  228. },
  229. .ops = &uniphier_aio_i2s_ops,
  230. },
  231. {
  232. .name = AUD_GNAME_LINE,
  233. .probe = uniphier_aio_ld11_probe,
  234. .remove = uniphier_aio_dai_remove,
  235. .playback = {
  236. .stream_name = AUD_NAME_PCMOUT2,
  237. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  238. .rates = SNDRV_PCM_RATE_48000,
  239. .channels_min = 2,
  240. .channels_max = 2,
  241. },
  242. .capture = {
  243. .stream_name = AUD_NAME_PCMIN3,
  244. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  245. .rates = SNDRV_PCM_RATE_48000,
  246. .channels_min = 2,
  247. .channels_max = 2,
  248. },
  249. .ops = &uniphier_aio_i2s_ops,
  250. },
  251. {
  252. .name = AUD_NAME_HPCMOUT1,
  253. .probe = uniphier_aio_ld11_probe,
  254. .remove = uniphier_aio_dai_remove,
  255. .playback = {
  256. .stream_name = AUD_NAME_HPCMOUT1,
  257. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  258. .rates = SNDRV_PCM_RATE_48000,
  259. .channels_min = 2,
  260. .channels_max = 8,
  261. },
  262. .ops = &uniphier_aio_i2s_ops,
  263. },
  264. {
  265. .name = AUD_NAME_PCMOUT3,
  266. .probe = uniphier_aio_ld11_probe,
  267. .remove = uniphier_aio_dai_remove,
  268. .playback = {
  269. .stream_name = AUD_NAME_PCMOUT3,
  270. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  271. .rates = SNDRV_PCM_RATE_48000,
  272. .channels_min = 2,
  273. .channels_max = 2,
  274. },
  275. .ops = &uniphier_aio_i2s_ops,
  276. },
  277. {
  278. .name = AUD_NAME_HIECOUT1,
  279. .probe = uniphier_aio_ld11_probe,
  280. .remove = uniphier_aio_dai_remove,
  281. .playback = {
  282. .stream_name = AUD_NAME_HIECOUT1,
  283. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  284. .rates = SNDRV_PCM_RATE_48000,
  285. .channels_min = 2,
  286. .channels_max = 2,
  287. },
  288. .ops = &uniphier_aio_spdif_ops,
  289. },
  290. {
  291. .name = AUD_NAME_EPCMOUT2,
  292. .probe = uniphier_aio_ld11_probe,
  293. .remove = uniphier_aio_dai_remove,
  294. .playback = {
  295. .stream_name = AUD_NAME_EPCMOUT2,
  296. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  297. .rates = SNDRV_PCM_RATE_48000 |
  298. SNDRV_PCM_RATE_44100 |
  299. SNDRV_PCM_RATE_32000,
  300. .channels_min = 2,
  301. .channels_max = 2,
  302. },
  303. .ops = &uniphier_aio_i2s_ops,
  304. },
  305. {
  306. .name = AUD_NAME_EPCMOUT3,
  307. .probe = uniphier_aio_ld11_probe,
  308. .remove = uniphier_aio_dai_remove,
  309. .playback = {
  310. .stream_name = AUD_NAME_EPCMOUT3,
  311. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  312. .rates = SNDRV_PCM_RATE_48000 |
  313. SNDRV_PCM_RATE_44100 |
  314. SNDRV_PCM_RATE_32000,
  315. .channels_min = 2,
  316. .channels_max = 2,
  317. },
  318. .ops = &uniphier_aio_i2s_ops,
  319. },
  320. {
  321. .name = AUD_NAME_HIECCOMPOUT1,
  322. .probe = uniphier_aio_ld11_probe,
  323. .remove = uniphier_aio_dai_remove,
  324. .compress_new = snd_soc_new_compress,
  325. .playback = {
  326. .stream_name = AUD_NAME_HIECCOMPOUT1,
  327. .channels_min = 1,
  328. .channels_max = 1,
  329. },
  330. .ops = &uniphier_aio_spdif_ops,
  331. },
  332. };
  333. static const struct uniphier_aio_chip_spec uniphier_aio_ld11_spec = {
  334. .specs = uniphier_aio_ld11,
  335. .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
  336. .dais = uniphier_aio_dai_ld11,
  337. .num_dais = ARRAY_SIZE(uniphier_aio_dai_ld11),
  338. .plls = uniphier_aio_pll_ld11,
  339. .num_plls = ARRAY_SIZE(uniphier_aio_pll_ld11),
  340. .addr_ext = 0,
  341. };
  342. static const struct uniphier_aio_chip_spec uniphier_aio_ld20_spec = {
  343. .specs = uniphier_aio_ld11,
  344. .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
  345. .dais = uniphier_aio_dai_ld11,
  346. .num_dais = ARRAY_SIZE(uniphier_aio_dai_ld11),
  347. .plls = uniphier_aio_pll_ld11,
  348. .num_plls = ARRAY_SIZE(uniphier_aio_pll_ld11),
  349. .addr_ext = 1,
  350. };
  351. static const struct of_device_id uniphier_aio_of_match[] __maybe_unused = {
  352. {
  353. .compatible = "socionext,uniphier-ld11-aio",
  354. .data = &uniphier_aio_ld11_spec,
  355. },
  356. {
  357. .compatible = "socionext,uniphier-ld20-aio",
  358. .data = &uniphier_aio_ld20_spec,
  359. },
  360. {},
  361. };
  362. MODULE_DEVICE_TABLE(of, uniphier_aio_of_match);
  363. static struct platform_driver uniphier_aio_driver = {
  364. .driver = {
  365. .name = "snd-uniphier-aio-ld11",
  366. .of_match_table = of_match_ptr(uniphier_aio_of_match),
  367. },
  368. .probe = uniphier_aio_probe,
  369. .remove = uniphier_aio_remove,
  370. };
  371. module_platform_driver(uniphier_aio_driver);
  372. MODULE_AUTHOR("Katsuhiro Suzuki <[email protected]>");
  373. MODULE_DESCRIPTION("UniPhier LD11/LD20 AIO driver.");
  374. MODULE_LICENSE("GPL v2");