18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// Socionext UniPhier AIO ALSA driver for PXs2. 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Copyright (c) 2018 Socionext Inc. 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/module.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "aio.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cistatic const struct uniphier_aio_spec uniphier_aio_pxs2[] = { 128c2ecf20Sopenharmony_ci /* for Line PCM In, Pin:AI1Dx */ 138c2ecf20Sopenharmony_ci { 148c2ecf20Sopenharmony_ci .name = AUD_NAME_PCMIN1, 158c2ecf20Sopenharmony_ci .gname = AUD_GNAME_LINE, 168c2ecf20Sopenharmony_ci .swm = { 178c2ecf20Sopenharmony_ci .type = PORT_TYPE_I2S, 188c2ecf20Sopenharmony_ci .dir = PORT_DIR_INPUT, 198c2ecf20Sopenharmony_ci .rb = { 16, 11, }, 208c2ecf20Sopenharmony_ci .ch = { 16, 11, }, 218c2ecf20Sopenharmony_ci .iif = { 0, 0, }, 228c2ecf20Sopenharmony_ci .iport = { 0, AUD_HW_PCMIN1, }, 238c2ecf20Sopenharmony_ci }, 248c2ecf20Sopenharmony_ci }, 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci /* for Speaker/Headphone/Mic PCM In, Pin:AI2Dx */ 278c2ecf20Sopenharmony_ci { 288c2ecf20Sopenharmony_ci .name = AUD_NAME_PCMIN2, 298c2ecf20Sopenharmony_ci .gname = AUD_GNAME_AUX, 308c2ecf20Sopenharmony_ci .swm = { 318c2ecf20Sopenharmony_ci .type = PORT_TYPE_I2S, 328c2ecf20Sopenharmony_ci .dir = PORT_DIR_INPUT, 338c2ecf20Sopenharmony_ci .rb = { 17, 12, }, 348c2ecf20Sopenharmony_ci .ch = { 17, 12, }, 358c2ecf20Sopenharmony_ci .iif = { 1, 1, }, 368c2ecf20Sopenharmony_ci .iport = { 1, AUD_HW_PCMIN2, }, 378c2ecf20Sopenharmony_ci }, 388c2ecf20Sopenharmony_ci }, 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* for HDMI PCM Out, Pin:AO1Dx (inner) */ 418c2ecf20Sopenharmony_ci { 428c2ecf20Sopenharmony_ci .name = AUD_NAME_HPCMOUT1, 438c2ecf20Sopenharmony_ci .gname = AUD_GNAME_HDMI, 448c2ecf20Sopenharmony_ci .swm = { 458c2ecf20Sopenharmony_ci .type = PORT_TYPE_I2S, 468c2ecf20Sopenharmony_ci .dir = PORT_DIR_OUTPUT, 478c2ecf20Sopenharmony_ci .rb = { 0, 0, }, 488c2ecf20Sopenharmony_ci .ch = { 0, 0, }, 498c2ecf20Sopenharmony_ci .oif = { 0, 0, }, 508c2ecf20Sopenharmony_ci .oport = { 3, AUD_HW_HPCMOUT1, }, 518c2ecf20Sopenharmony_ci }, 528c2ecf20Sopenharmony_ci }, 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* for Line PCM Out, Pin:AO2Dx */ 558c2ecf20Sopenharmony_ci { 568c2ecf20Sopenharmony_ci .name = AUD_NAME_PCMOUT1, 578c2ecf20Sopenharmony_ci .gname = AUD_GNAME_LINE, 588c2ecf20Sopenharmony_ci .swm = { 598c2ecf20Sopenharmony_ci .type = PORT_TYPE_I2S, 608c2ecf20Sopenharmony_ci .dir = PORT_DIR_OUTPUT, 618c2ecf20Sopenharmony_ci .rb = { 1, 1, }, 628c2ecf20Sopenharmony_ci .ch = { 1, 1, }, 638c2ecf20Sopenharmony_ci .oif = { 1, 1, }, 648c2ecf20Sopenharmony_ci .oport = { 0, AUD_HW_PCMOUT1, }, 658c2ecf20Sopenharmony_ci }, 668c2ecf20Sopenharmony_ci }, 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci /* for Speaker/Headphone/Mic PCM Out, Pin:AO3Dx */ 698c2ecf20Sopenharmony_ci { 708c2ecf20Sopenharmony_ci .name = AUD_NAME_PCMOUT2, 718c2ecf20Sopenharmony_ci .gname = AUD_GNAME_AUX, 728c2ecf20Sopenharmony_ci .swm = { 738c2ecf20Sopenharmony_ci .type = PORT_TYPE_I2S, 748c2ecf20Sopenharmony_ci .dir = PORT_DIR_OUTPUT, 758c2ecf20Sopenharmony_ci .rb = { 2, 2, }, 768c2ecf20Sopenharmony_ci .ch = { 2, 2, }, 778c2ecf20Sopenharmony_ci .oif = { 2, 2, }, 788c2ecf20Sopenharmony_ci .oport = { 1, AUD_HW_PCMOUT2, }, 798c2ecf20Sopenharmony_ci }, 808c2ecf20Sopenharmony_ci }, 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* for HDMI Out, Pin:AO1IEC */ 838c2ecf20Sopenharmony_ci { 848c2ecf20Sopenharmony_ci .name = AUD_NAME_HIECOUT1, 858c2ecf20Sopenharmony_ci .swm = { 868c2ecf20Sopenharmony_ci .type = PORT_TYPE_SPDIF, 878c2ecf20Sopenharmony_ci .dir = PORT_DIR_OUTPUT, 888c2ecf20Sopenharmony_ci .rb = { 6, 4, }, 898c2ecf20Sopenharmony_ci .ch = { 6, 4, }, 908c2ecf20Sopenharmony_ci .oif = { 6, 4, }, 918c2ecf20Sopenharmony_ci .oport = { 12, AUD_HW_HIECOUT1, }, 928c2ecf20Sopenharmony_ci }, 938c2ecf20Sopenharmony_ci }, 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* for HDMI Out, Pin:AO1IEC, Compress */ 968c2ecf20Sopenharmony_ci { 978c2ecf20Sopenharmony_ci .name = AUD_NAME_HIECCOMPOUT1, 988c2ecf20Sopenharmony_ci .swm = { 998c2ecf20Sopenharmony_ci .type = PORT_TYPE_SPDIF, 1008c2ecf20Sopenharmony_ci .dir = PORT_DIR_OUTPUT, 1018c2ecf20Sopenharmony_ci .rb = { 6, 4, }, 1028c2ecf20Sopenharmony_ci .ch = { 6, 4, }, 1038c2ecf20Sopenharmony_ci .oif = { 6, 4, }, 1048c2ecf20Sopenharmony_ci .oport = { 12, AUD_HW_HIECOUT1, }, 1058c2ecf20Sopenharmony_ci }, 1068c2ecf20Sopenharmony_ci }, 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* for S/PDIF Out, Pin:AO2IEC */ 1098c2ecf20Sopenharmony_ci { 1108c2ecf20Sopenharmony_ci .name = AUD_NAME_IECOUT1, 1118c2ecf20Sopenharmony_ci .swm = { 1128c2ecf20Sopenharmony_ci .type = PORT_TYPE_SPDIF, 1138c2ecf20Sopenharmony_ci .dir = PORT_DIR_OUTPUT, 1148c2ecf20Sopenharmony_ci .rb = { 7, 5, }, 1158c2ecf20Sopenharmony_ci .ch = { 7, 5, }, 1168c2ecf20Sopenharmony_ci .oif = { 7, 5, }, 1178c2ecf20Sopenharmony_ci .oport = { 13, AUD_HW_IECOUT1, }, 1188c2ecf20Sopenharmony_ci }, 1198c2ecf20Sopenharmony_ci }, 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* for S/PDIF Out, Pin:AO2IEC */ 1228c2ecf20Sopenharmony_ci { 1238c2ecf20Sopenharmony_ci .name = AUD_NAME_IECCOMPOUT1, 1248c2ecf20Sopenharmony_ci .swm = { 1258c2ecf20Sopenharmony_ci .type = PORT_TYPE_SPDIF, 1268c2ecf20Sopenharmony_ci .dir = PORT_DIR_OUTPUT, 1278c2ecf20Sopenharmony_ci .rb = { 7, 5, }, 1288c2ecf20Sopenharmony_ci .ch = { 7, 5, }, 1298c2ecf20Sopenharmony_ci .oif = { 7, 5, }, 1308c2ecf20Sopenharmony_ci .oport = { 13, AUD_HW_IECOUT1, }, 1318c2ecf20Sopenharmony_ci }, 1328c2ecf20Sopenharmony_ci }, 1338c2ecf20Sopenharmony_ci}; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic const struct uniphier_aio_pll uniphier_aio_pll_pxs2[] = { 1368c2ecf20Sopenharmony_ci [AUD_PLL_A1] = { .enable = true, }, 1378c2ecf20Sopenharmony_ci [AUD_PLL_F1] = { .enable = true, }, 1388c2ecf20Sopenharmony_ci [AUD_PLL_A2] = { .enable = true, }, 1398c2ecf20Sopenharmony_ci [AUD_PLL_F2] = { .enable = true, }, 1408c2ecf20Sopenharmony_ci [AUD_PLL_APLL] = { .enable = true, }, 1418c2ecf20Sopenharmony_ci [AUD_PLL_HSC0] = { .enable = true, }, 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic int uniphier_aio_pxs2_probe(struct snd_soc_dai *dai) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci int ret; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci ret = uniphier_aio_dai_probe(dai); 1498c2ecf20Sopenharmony_ci if (ret < 0) 1508c2ecf20Sopenharmony_ci return ret; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_pll(dai, AUD_PLL_A1, 0, 0, 36864000); 1538c2ecf20Sopenharmony_ci if (ret < 0) 1548c2ecf20Sopenharmony_ci return ret; 1558c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_pll(dai, AUD_PLL_F1, 0, 0, 36864000); 1568c2ecf20Sopenharmony_ci if (ret < 0) 1578c2ecf20Sopenharmony_ci return ret; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_pll(dai, AUD_PLL_A2, 0, 0, 33868800); 1608c2ecf20Sopenharmony_ci if (ret < 0) 1618c2ecf20Sopenharmony_ci return ret; 1628c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_pll(dai, AUD_PLL_F2, 0, 0, 33868800); 1638c2ecf20Sopenharmony_ci if (ret < 0) 1648c2ecf20Sopenharmony_ci return ret; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci return 0; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver uniphier_aio_dai_pxs2[] = { 1708c2ecf20Sopenharmony_ci { 1718c2ecf20Sopenharmony_ci .name = AUD_GNAME_HDMI, 1728c2ecf20Sopenharmony_ci .probe = uniphier_aio_pxs2_probe, 1738c2ecf20Sopenharmony_ci .remove = uniphier_aio_dai_remove, 1748c2ecf20Sopenharmony_ci .playback = { 1758c2ecf20Sopenharmony_ci .stream_name = AUD_NAME_HPCMOUT1, 1768c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 1778c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000, 1788c2ecf20Sopenharmony_ci .channels_min = 2, 1798c2ecf20Sopenharmony_ci .channels_max = 2, 1808c2ecf20Sopenharmony_ci }, 1818c2ecf20Sopenharmony_ci .ops = &uniphier_aio_i2s_ops, 1828c2ecf20Sopenharmony_ci }, 1838c2ecf20Sopenharmony_ci { 1848c2ecf20Sopenharmony_ci .name = AUD_GNAME_LINE, 1858c2ecf20Sopenharmony_ci .probe = uniphier_aio_pxs2_probe, 1868c2ecf20Sopenharmony_ci .remove = uniphier_aio_dai_remove, 1878c2ecf20Sopenharmony_ci .playback = { 1888c2ecf20Sopenharmony_ci .stream_name = AUD_NAME_PCMOUT1, 1898c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 1908c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000, 1918c2ecf20Sopenharmony_ci .channels_min = 2, 1928c2ecf20Sopenharmony_ci .channels_max = 2, 1938c2ecf20Sopenharmony_ci }, 1948c2ecf20Sopenharmony_ci .capture = { 1958c2ecf20Sopenharmony_ci .stream_name = AUD_NAME_PCMIN1, 1968c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 1978c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000, 1988c2ecf20Sopenharmony_ci .channels_min = 2, 1998c2ecf20Sopenharmony_ci .channels_max = 2, 2008c2ecf20Sopenharmony_ci }, 2018c2ecf20Sopenharmony_ci .ops = &uniphier_aio_i2s_ops, 2028c2ecf20Sopenharmony_ci }, 2038c2ecf20Sopenharmony_ci { 2048c2ecf20Sopenharmony_ci .name = AUD_GNAME_AUX, 2058c2ecf20Sopenharmony_ci .probe = uniphier_aio_pxs2_probe, 2068c2ecf20Sopenharmony_ci .remove = uniphier_aio_dai_remove, 2078c2ecf20Sopenharmony_ci .playback = { 2088c2ecf20Sopenharmony_ci .stream_name = AUD_NAME_PCMOUT2, 2098c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 2108c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000, 2118c2ecf20Sopenharmony_ci .channels_min = 2, 2128c2ecf20Sopenharmony_ci .channels_max = 2, 2138c2ecf20Sopenharmony_ci }, 2148c2ecf20Sopenharmony_ci .capture = { 2158c2ecf20Sopenharmony_ci .stream_name = AUD_NAME_PCMIN2, 2168c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 2178c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000, 2188c2ecf20Sopenharmony_ci .channels_min = 2, 2198c2ecf20Sopenharmony_ci .channels_max = 2, 2208c2ecf20Sopenharmony_ci }, 2218c2ecf20Sopenharmony_ci .ops = &uniphier_aio_i2s_ops, 2228c2ecf20Sopenharmony_ci }, 2238c2ecf20Sopenharmony_ci { 2248c2ecf20Sopenharmony_ci .name = AUD_NAME_HIECOUT1, 2258c2ecf20Sopenharmony_ci .probe = uniphier_aio_pxs2_probe, 2268c2ecf20Sopenharmony_ci .remove = uniphier_aio_dai_remove, 2278c2ecf20Sopenharmony_ci .playback = { 2288c2ecf20Sopenharmony_ci .stream_name = AUD_NAME_HIECOUT1, 2298c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 2308c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000, 2318c2ecf20Sopenharmony_ci .channels_min = 2, 2328c2ecf20Sopenharmony_ci .channels_max = 2, 2338c2ecf20Sopenharmony_ci }, 2348c2ecf20Sopenharmony_ci .ops = &uniphier_aio_spdif_ops, 2358c2ecf20Sopenharmony_ci }, 2368c2ecf20Sopenharmony_ci { 2378c2ecf20Sopenharmony_ci .name = AUD_NAME_IECOUT1, 2388c2ecf20Sopenharmony_ci .probe = uniphier_aio_pxs2_probe, 2398c2ecf20Sopenharmony_ci .remove = uniphier_aio_dai_remove, 2408c2ecf20Sopenharmony_ci .playback = { 2418c2ecf20Sopenharmony_ci .stream_name = AUD_NAME_IECOUT1, 2428c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 2438c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_48000, 2448c2ecf20Sopenharmony_ci .channels_min = 2, 2458c2ecf20Sopenharmony_ci .channels_max = 2, 2468c2ecf20Sopenharmony_ci }, 2478c2ecf20Sopenharmony_ci .ops = &uniphier_aio_spdif_ops, 2488c2ecf20Sopenharmony_ci }, 2498c2ecf20Sopenharmony_ci { 2508c2ecf20Sopenharmony_ci .name = AUD_NAME_HIECCOMPOUT1, 2518c2ecf20Sopenharmony_ci .probe = uniphier_aio_pxs2_probe, 2528c2ecf20Sopenharmony_ci .remove = uniphier_aio_dai_remove, 2538c2ecf20Sopenharmony_ci .compress_new = snd_soc_new_compress, 2548c2ecf20Sopenharmony_ci .playback = { 2558c2ecf20Sopenharmony_ci .stream_name = AUD_NAME_HIECCOMPOUT1, 2568c2ecf20Sopenharmony_ci .channels_min = 1, 2578c2ecf20Sopenharmony_ci .channels_max = 1, 2588c2ecf20Sopenharmony_ci }, 2598c2ecf20Sopenharmony_ci .ops = &uniphier_aio_spdif_ops, 2608c2ecf20Sopenharmony_ci }, 2618c2ecf20Sopenharmony_ci { 2628c2ecf20Sopenharmony_ci .name = AUD_NAME_IECCOMPOUT1, 2638c2ecf20Sopenharmony_ci .probe = uniphier_aio_pxs2_probe, 2648c2ecf20Sopenharmony_ci .remove = uniphier_aio_dai_remove, 2658c2ecf20Sopenharmony_ci .compress_new = snd_soc_new_compress, 2668c2ecf20Sopenharmony_ci .playback = { 2678c2ecf20Sopenharmony_ci .stream_name = AUD_NAME_IECCOMPOUT1, 2688c2ecf20Sopenharmony_ci .channels_min = 1, 2698c2ecf20Sopenharmony_ci .channels_max = 1, 2708c2ecf20Sopenharmony_ci }, 2718c2ecf20Sopenharmony_ci .ops = &uniphier_aio_spdif_ops, 2728c2ecf20Sopenharmony_ci }, 2738c2ecf20Sopenharmony_ci}; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic const struct uniphier_aio_chip_spec uniphier_aio_pxs2_spec = { 2768c2ecf20Sopenharmony_ci .specs = uniphier_aio_pxs2, 2778c2ecf20Sopenharmony_ci .num_specs = ARRAY_SIZE(uniphier_aio_pxs2), 2788c2ecf20Sopenharmony_ci .dais = uniphier_aio_dai_pxs2, 2798c2ecf20Sopenharmony_ci .num_dais = ARRAY_SIZE(uniphier_aio_dai_pxs2), 2808c2ecf20Sopenharmony_ci .plls = uniphier_aio_pll_pxs2, 2818c2ecf20Sopenharmony_ci .num_plls = ARRAY_SIZE(uniphier_aio_pll_pxs2), 2828c2ecf20Sopenharmony_ci .addr_ext = 0, 2838c2ecf20Sopenharmony_ci}; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistatic const struct of_device_id uniphier_aio_of_match[] = { 2868c2ecf20Sopenharmony_ci { 2878c2ecf20Sopenharmony_ci .compatible = "socionext,uniphier-pxs2-aio", 2888c2ecf20Sopenharmony_ci .data = &uniphier_aio_pxs2_spec, 2898c2ecf20Sopenharmony_ci }, 2908c2ecf20Sopenharmony_ci {}, 2918c2ecf20Sopenharmony_ci}; 2928c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, uniphier_aio_of_match); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic struct platform_driver uniphier_aio_driver = { 2958c2ecf20Sopenharmony_ci .driver = { 2968c2ecf20Sopenharmony_ci .name = "snd-uniphier-aio-pxs2", 2978c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(uniphier_aio_of_match), 2988c2ecf20Sopenharmony_ci }, 2998c2ecf20Sopenharmony_ci .probe = uniphier_aio_probe, 3008c2ecf20Sopenharmony_ci .remove = uniphier_aio_remove, 3018c2ecf20Sopenharmony_ci}; 3028c2ecf20Sopenharmony_cimodule_platform_driver(uniphier_aio_driver); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ciMODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>"); 3058c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("UniPhier PXs2 AIO driver."); 3068c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 307