Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Socionext UniPhier AIO ALSA driver for LD11/LD20.
0004 //
0005 // Copyright (c) 2016-2018 Socionext Inc.
0006 
0007 #include <linux/module.h>
0008 
0009 #include "aio.h"
0010 
0011 static const struct uniphier_aio_spec uniphier_aio_ld11[] = {
0012     /* for HDMI PCM In, Pin:AI1Dx */
0013     {
0014         .name = AUD_NAME_PCMIN1,
0015         .gname = AUD_GNAME_HDMI,
0016         .swm = {
0017             .type  = PORT_TYPE_I2S,
0018             .dir   = PORT_DIR_INPUT,
0019             .rb    = { 21, 14, },
0020             .ch    = { 21, 14, },
0021             .iif   = { 5, 3, },
0022             .iport = { 0, AUD_HW_PCMIN1, },
0023         },
0024     },
0025 
0026     /* for SIF In, Pin:AI2Dx */
0027     {
0028         .name = AUD_NAME_PCMIN2,
0029         .swm = {
0030             .type  = PORT_TYPE_I2S,
0031             .dir   = PORT_DIR_INPUT,
0032             .rb    = { 22, 15, },
0033             .ch    = { 22, 15, },
0034             .iif   = { 6, 4, },
0035             .iport = { 1, AUD_HW_PCMIN2, },
0036         },
0037     },
0038 
0039     /* for Line In, Pin:AI3Dx */
0040     {
0041         .name = AUD_NAME_PCMIN3,
0042         .gname = AUD_GNAME_LINE,
0043         .swm = {
0044             .type  = PORT_TYPE_EVE,
0045             .dir   = PORT_DIR_INPUT,
0046             .rb    = { 23, 16, },
0047             .ch    = { 23, 16, },
0048             .iif   = { 7, 5, },
0049             .iport = { 2, AUD_HW_PCMIN3, },
0050         },
0051     },
0052 
0053     /* for S/PDIF In, Pin:AI1IEC */
0054     {
0055         .name = AUD_NAME_IECIN1,
0056         .gname = AUD_GNAME_IEC,
0057         .swm = {
0058             .type  = PORT_TYPE_SPDIF,
0059             .dir   = PORT_DIR_INPUT,
0060             .rb    = { 26, 17, },
0061             .ch    = { 26, 17, },
0062             .iif   = { 10, 6, },
0063             .iport = { 3, AUD_HW_IECIN1, },
0064         },
0065     },
0066 
0067     /* for Speaker, Pin:AO1Dx */
0068     {
0069         .name = AUD_NAME_HPCMOUT1,
0070         .swm = {
0071             .type  = PORT_TYPE_I2S,
0072             .dir   = PORT_DIR_OUTPUT,
0073             .rb    = { 0, 0, },
0074             .ch    = { 0, 0, },
0075             .oif   = { 0, 0, },
0076             .oport = { 0, AUD_HW_HPCMOUT1, },
0077         },
0078     },
0079 
0080     /* for HDMI PCM, Pin:AO2Dx */
0081     {
0082         .name = AUD_NAME_PCMOUT1,
0083         .gname = AUD_GNAME_HDMI,
0084         .swm = {
0085             .type  = PORT_TYPE_I2S,
0086             .dir   = PORT_DIR_OUTPUT,
0087             .rb    = { 0, 0, },
0088             .ch    = { 0, 0, },
0089             .oif   = { 0, 0, },
0090             .oport = { 3, AUD_HW_PCMOUT1, },
0091         },
0092     },
0093 
0094     /* for Line Out, Pin:LO2_x */
0095     {
0096         .name = AUD_NAME_PCMOUT2,
0097         .gname = AUD_GNAME_LINE,
0098         .swm = {
0099             .type  = PORT_TYPE_EVE,
0100             .dir   = PORT_DIR_OUTPUT,
0101             .rb    = { 2, 2, },
0102             .ch    = { 2, 2, },
0103             .oif   = { 2, 2, },
0104             .oport = { 1, AUD_HW_PCMOUT2, },
0105         },
0106     },
0107 
0108     /* for Headphone, Pin:HP1_x */
0109     {
0110         .name = AUD_NAME_PCMOUT3,
0111         .swm = {
0112             .type  = PORT_TYPE_EVE,
0113             .dir   = PORT_DIR_OUTPUT,
0114             .rb    = { 3, 3, },
0115             .ch    = { 3, 3, },
0116             .oif   = { 3, 3, },
0117             .oport = { 2, AUD_HW_PCMOUT3, },
0118         },
0119     },
0120 
0121     /* for HW Sampling Rate Converter */
0122     {
0123         .name = AUD_NAME_EPCMOUT2,
0124         .swm = {
0125             .type  = PORT_TYPE_CONV,
0126             .dir   = PORT_DIR_OUTPUT,
0127             .rb    = { 7, 5, },
0128             .ch    = { 7, 5, },
0129             .oif   = { 7, 5, },
0130             .oport = { 6, AUD_HW_EPCMOUT2, },
0131             .och   = { 17, 12, },
0132             .iif   = { 1, 1, },
0133         },
0134     },
0135 
0136     /* for HW Sampling Rate Converter 2 */
0137     {
0138         .name = AUD_NAME_EPCMOUT3,
0139         .swm = {
0140             .type  = PORT_TYPE_CONV,
0141             .dir   = PORT_DIR_OUTPUT,
0142             .rb    = { 8, 6, },
0143             .ch    = { 8, 6, },
0144             .oif   = { 8, 6, },
0145             .oport = { 7, AUD_HW_EPCMOUT3, },
0146             .och   = { 18, 13, },
0147             .iif   = { 2, 2, },
0148         },
0149     },
0150 
0151     /* for S/PDIF Out, Pin:AO1IEC */
0152     {
0153         .name = AUD_NAME_HIECOUT1,
0154         .gname = AUD_GNAME_IEC,
0155         .swm = {
0156             .type  = PORT_TYPE_SPDIF,
0157             .dir   = PORT_DIR_OUTPUT,
0158             .rb    = { 1, 1, },
0159             .ch    = { 1, 1, },
0160             .oif   = { 1, 1, },
0161             .oport = { 12, AUD_HW_HIECOUT1, },
0162         },
0163     },
0164 
0165     /* for S/PDIF Out, Pin:AO1IEC, Compress */
0166     {
0167         .name = AUD_NAME_HIECCOMPOUT1,
0168         .gname = AUD_GNAME_IEC,
0169         .swm = {
0170             .type  = PORT_TYPE_SPDIF,
0171             .dir   = PORT_DIR_OUTPUT,
0172             .rb    = { 1, 1, },
0173             .ch    = { 1, 1, },
0174             .oif   = { 1, 1, },
0175             .oport = { 12, AUD_HW_HIECOUT1, },
0176         },
0177     },
0178 };
0179 
0180 static const struct uniphier_aio_pll uniphier_aio_pll_ld11[] = {
0181     [AUD_PLL_A1]   = { .enable = true, },
0182     [AUD_PLL_F1]   = { .enable = true, },
0183     [AUD_PLL_A2]   = { .enable = true, },
0184     [AUD_PLL_F2]   = { .enable = true, },
0185     [AUD_PLL_APLL] = { .enable = true, },
0186     [AUD_PLL_RX0]  = { .enable = true, },
0187     [AUD_PLL_USB0] = { .enable = true, },
0188     [AUD_PLL_HSC0] = { .enable = true, },
0189 };
0190 
0191 static int uniphier_aio_ld11_probe(struct snd_soc_dai *dai)
0192 {
0193     int ret;
0194 
0195     ret = uniphier_aio_dai_probe(dai);
0196     if (ret < 0)
0197         return ret;
0198 
0199     ret = snd_soc_dai_set_pll(dai, AUD_PLL_A1, 0, 0, 36864000);
0200     if (ret < 0)
0201         return ret;
0202     ret = snd_soc_dai_set_pll(dai, AUD_PLL_F1, 0, 0, 36864000);
0203     if (ret < 0)
0204         return ret;
0205 
0206     ret = snd_soc_dai_set_pll(dai, AUD_PLL_A2, 0, 0, 33868800);
0207     if (ret < 0)
0208         return ret;
0209     ret = snd_soc_dai_set_pll(dai, AUD_PLL_F2, 0, 0, 33868800);
0210     if (ret < 0)
0211         return ret;
0212 
0213     return 0;
0214 }
0215 
0216 static struct snd_soc_dai_driver uniphier_aio_dai_ld11[] = {
0217     {
0218         .name    = AUD_GNAME_HDMI,
0219         .probe   = uniphier_aio_ld11_probe,
0220         .remove  = uniphier_aio_dai_remove,
0221         .playback = {
0222             .stream_name = AUD_NAME_PCMOUT1,
0223             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0224             .rates       = SNDRV_PCM_RATE_48000,
0225             .channels_min = 2,
0226             .channels_max = 2,
0227         },
0228         .capture = {
0229             .stream_name = AUD_NAME_PCMIN1,
0230             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0231             .rates       = SNDRV_PCM_RATE_48000 |
0232                 SNDRV_PCM_RATE_44100 |
0233                 SNDRV_PCM_RATE_32000,
0234             .channels_min = 2,
0235             .channels_max = 2,
0236         },
0237         .ops = &uniphier_aio_i2s_ops,
0238     },
0239     {
0240         .name    = AUD_NAME_PCMIN2,
0241         .probe   = uniphier_aio_ld11_probe,
0242         .remove  = uniphier_aio_dai_remove,
0243         .capture = {
0244             .stream_name = AUD_NAME_PCMIN2,
0245             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0246             .rates       = SNDRV_PCM_RATE_48000,
0247             .channels_min = 2,
0248             .channels_max = 2,
0249         },
0250         .ops = &uniphier_aio_i2s_ops,
0251     },
0252     {
0253         .name    = AUD_GNAME_LINE,
0254         .probe   = uniphier_aio_ld11_probe,
0255         .remove  = uniphier_aio_dai_remove,
0256         .playback = {
0257             .stream_name = AUD_NAME_PCMOUT2,
0258             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0259             .rates       = SNDRV_PCM_RATE_48000,
0260             .channels_min = 2,
0261             .channels_max = 2,
0262         },
0263         .capture = {
0264             .stream_name = AUD_NAME_PCMIN3,
0265             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0266             .rates       = SNDRV_PCM_RATE_48000,
0267             .channels_min = 2,
0268             .channels_max = 2,
0269         },
0270         .ops = &uniphier_aio_i2s_ops,
0271     },
0272     {
0273         .name    = AUD_NAME_HPCMOUT1,
0274         .probe   = uniphier_aio_ld11_probe,
0275         .remove  = uniphier_aio_dai_remove,
0276         .playback = {
0277             .stream_name = AUD_NAME_HPCMOUT1,
0278             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0279             .rates       = SNDRV_PCM_RATE_48000,
0280             .channels_min = 2,
0281             .channels_max = 8,
0282         },
0283         .ops = &uniphier_aio_i2s_ops,
0284     },
0285     {
0286         .name    = AUD_NAME_PCMOUT3,
0287         .probe   = uniphier_aio_ld11_probe,
0288         .remove  = uniphier_aio_dai_remove,
0289         .playback = {
0290             .stream_name = AUD_NAME_PCMOUT3,
0291             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0292             .rates       = SNDRV_PCM_RATE_48000,
0293             .channels_min = 2,
0294             .channels_max = 2,
0295         },
0296         .ops = &uniphier_aio_i2s_ops,
0297     },
0298     {
0299         .name    = AUD_NAME_HIECOUT1,
0300         .probe   = uniphier_aio_ld11_probe,
0301         .remove  = uniphier_aio_dai_remove,
0302         .playback = {
0303             .stream_name = AUD_NAME_HIECOUT1,
0304             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0305             .rates       = SNDRV_PCM_RATE_48000,
0306             .channels_min = 2,
0307             .channels_max = 2,
0308         },
0309         .ops = &uniphier_aio_spdif_ops,
0310     },
0311     {
0312         .name    = AUD_NAME_EPCMOUT2,
0313         .probe   = uniphier_aio_ld11_probe,
0314         .remove  = uniphier_aio_dai_remove,
0315         .playback = {
0316             .stream_name = AUD_NAME_EPCMOUT2,
0317             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0318             .rates       = SNDRV_PCM_RATE_48000 |
0319                 SNDRV_PCM_RATE_44100 |
0320                 SNDRV_PCM_RATE_32000,
0321             .channels_min = 2,
0322             .channels_max = 2,
0323         },
0324         .ops = &uniphier_aio_i2s_ops,
0325     },
0326     {
0327         .name    = AUD_NAME_EPCMOUT3,
0328         .probe   = uniphier_aio_ld11_probe,
0329         .remove  = uniphier_aio_dai_remove,
0330         .playback = {
0331             .stream_name = AUD_NAME_EPCMOUT3,
0332             .formats     = SNDRV_PCM_FMTBIT_S32_LE,
0333             .rates       = SNDRV_PCM_RATE_48000 |
0334                 SNDRV_PCM_RATE_44100 |
0335                 SNDRV_PCM_RATE_32000,
0336             .channels_min = 2,
0337             .channels_max = 2,
0338         },
0339         .ops = &uniphier_aio_i2s_ops,
0340     },
0341     {
0342         .name    = AUD_NAME_HIECCOMPOUT1,
0343         .probe   = uniphier_aio_ld11_probe,
0344         .remove  = uniphier_aio_dai_remove,
0345         .compress_new = snd_soc_new_compress,
0346         .playback = {
0347             .stream_name = AUD_NAME_HIECCOMPOUT1,
0348             .channels_min = 1,
0349             .channels_max = 1,
0350         },
0351         .ops = &uniphier_aio_spdif_ops,
0352     },
0353 };
0354 
0355 static const struct uniphier_aio_chip_spec uniphier_aio_ld11_spec = {
0356     .specs     = uniphier_aio_ld11,
0357     .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
0358     .dais      = uniphier_aio_dai_ld11,
0359     .num_dais  = ARRAY_SIZE(uniphier_aio_dai_ld11),
0360     .plls      = uniphier_aio_pll_ld11,
0361     .num_plls  = ARRAY_SIZE(uniphier_aio_pll_ld11),
0362     .addr_ext  = 0,
0363 };
0364 
0365 static const struct uniphier_aio_chip_spec uniphier_aio_ld20_spec = {
0366     .specs     = uniphier_aio_ld11,
0367     .num_specs = ARRAY_SIZE(uniphier_aio_ld11),
0368     .dais      = uniphier_aio_dai_ld11,
0369     .num_dais  = ARRAY_SIZE(uniphier_aio_dai_ld11),
0370     .plls      = uniphier_aio_pll_ld11,
0371     .num_plls  = ARRAY_SIZE(uniphier_aio_pll_ld11),
0372     .addr_ext  = 1,
0373 };
0374 
0375 static const struct of_device_id uniphier_aio_of_match[] __maybe_unused = {
0376     {
0377         .compatible = "socionext,uniphier-ld11-aio",
0378         .data = &uniphier_aio_ld11_spec,
0379     },
0380     {
0381         .compatible = "socionext,uniphier-ld20-aio",
0382         .data = &uniphier_aio_ld20_spec,
0383     },
0384     {},
0385 };
0386 MODULE_DEVICE_TABLE(of, uniphier_aio_of_match);
0387 
0388 static struct platform_driver uniphier_aio_driver = {
0389     .driver = {
0390         .name = "snd-uniphier-aio-ld11",
0391         .of_match_table = of_match_ptr(uniphier_aio_of_match),
0392     },
0393     .probe    = uniphier_aio_probe,
0394     .remove   = uniphier_aio_remove,
0395 };
0396 module_platform_driver(uniphier_aio_driver);
0397 
0398 MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
0399 MODULE_DESCRIPTION("UniPhier LD11/LD20 AIO driver.");
0400 MODULE_LICENSE("GPL v2");