Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
0002 //
0003 // Copyright (c) 2018 BayLibre, SAS.
0004 // Author: Jerome Brunet <jbrunet@baylibre.com>
0005 
0006 #include <linux/clk.h>
0007 #include <linux/module.h>
0008 #include <linux/of_platform.h>
0009 #include <linux/regmap.h>
0010 #include <sound/soc.h>
0011 #include <sound/soc-dai.h>
0012 #include <sound/pcm_params.h>
0013 #include <sound/pcm_iec958.h>
0014 
0015 /*
0016  * NOTE:
0017  * The meaning of bits SPDIFOUT_CTRL0_XXX_SEL is actually the opposite
0018  * of what the documentation says. Manual control on V, U and C bits is
0019  * applied when the related sel bits are cleared
0020  */
0021 
0022 #define SPDIFOUT_STAT           0x00
0023 #define SPDIFOUT_GAIN0          0x04
0024 #define SPDIFOUT_GAIN1          0x08
0025 #define SPDIFOUT_CTRL0          0x0c
0026 #define  SPDIFOUT_CTRL0_EN      BIT(31)
0027 #define  SPDIFOUT_CTRL0_RST_OUT     BIT(29)
0028 #define  SPDIFOUT_CTRL0_RST_IN      BIT(28)
0029 #define  SPDIFOUT_CTRL0_USEL        BIT(26)
0030 #define  SPDIFOUT_CTRL0_USET        BIT(25)
0031 #define  SPDIFOUT_CTRL0_CHSTS_SEL   BIT(24)
0032 #define  SPDIFOUT_CTRL0_DATA_SEL    BIT(20)
0033 #define  SPDIFOUT_CTRL0_MSB_FIRST   BIT(19)
0034 #define  SPDIFOUT_CTRL0_VSEL        BIT(18)
0035 #define  SPDIFOUT_CTRL0_VSET        BIT(17)
0036 #define  SPDIFOUT_CTRL0_MASK_MASK   GENMASK(11, 4)
0037 #define  SPDIFOUT_CTRL0_MASK(x)     ((x) << 4)
0038 #define SPDIFOUT_CTRL1          0x10
0039 #define  SPDIFOUT_CTRL1_MSB_POS_MASK    GENMASK(12, 8)
0040 #define  SPDIFOUT_CTRL1_MSB_POS(x)  ((x) << 8)
0041 #define  SPDIFOUT_CTRL1_TYPE_MASK   GENMASK(6, 4)
0042 #define  SPDIFOUT_CTRL1_TYPE(x)     ((x) << 4)
0043 #define SPDIFOUT_PREAMB         0x14
0044 #define SPDIFOUT_SWAP           0x18
0045 #define SPDIFOUT_CHSTS0         0x1c
0046 #define SPDIFOUT_CHSTS1         0x20
0047 #define SPDIFOUT_CHSTS2         0x24
0048 #define SPDIFOUT_CHSTS3         0x28
0049 #define SPDIFOUT_CHSTS4         0x2c
0050 #define SPDIFOUT_CHSTS5         0x30
0051 #define SPDIFOUT_CHSTS6         0x34
0052 #define SPDIFOUT_CHSTS7         0x38
0053 #define SPDIFOUT_CHSTS8         0x3c
0054 #define SPDIFOUT_CHSTS9         0x40
0055 #define SPDIFOUT_CHSTSA         0x44
0056 #define SPDIFOUT_CHSTSB         0x48
0057 #define SPDIFOUT_MUTE_VAL       0x4c
0058 
0059 struct axg_spdifout {
0060     struct regmap *map;
0061     struct clk *mclk;
0062     struct clk *pclk;
0063 };
0064 
0065 static void axg_spdifout_enable(struct regmap *map)
0066 {
0067     /* Apply both reset */
0068     regmap_update_bits(map, SPDIFOUT_CTRL0,
0069                SPDIFOUT_CTRL0_RST_OUT | SPDIFOUT_CTRL0_RST_IN,
0070                0);
0071 
0072     /* Clear out reset before in reset */
0073     regmap_update_bits(map, SPDIFOUT_CTRL0,
0074                SPDIFOUT_CTRL0_RST_OUT, SPDIFOUT_CTRL0_RST_OUT);
0075     regmap_update_bits(map, SPDIFOUT_CTRL0,
0076                SPDIFOUT_CTRL0_RST_IN,  SPDIFOUT_CTRL0_RST_IN);
0077 
0078     /* Enable spdifout */
0079     regmap_update_bits(map, SPDIFOUT_CTRL0, SPDIFOUT_CTRL0_EN,
0080                SPDIFOUT_CTRL0_EN);
0081 }
0082 
0083 static void axg_spdifout_disable(struct regmap *map)
0084 {
0085     regmap_update_bits(map, SPDIFOUT_CTRL0, SPDIFOUT_CTRL0_EN, 0);
0086 }
0087 
0088 static int axg_spdifout_trigger(struct snd_pcm_substream *substream, int cmd,
0089                 struct snd_soc_dai *dai)
0090 {
0091     struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);
0092 
0093     switch (cmd) {
0094     case SNDRV_PCM_TRIGGER_START:
0095     case SNDRV_PCM_TRIGGER_RESUME:
0096     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0097         axg_spdifout_enable(priv->map);
0098         return 0;
0099 
0100     case SNDRV_PCM_TRIGGER_STOP:
0101     case SNDRV_PCM_TRIGGER_SUSPEND:
0102     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0103         axg_spdifout_disable(priv->map);
0104         return 0;
0105 
0106     default:
0107         return -EINVAL;
0108     }
0109 }
0110 
0111 static int axg_spdifout_mute(struct snd_soc_dai *dai, int mute, int direction)
0112 {
0113     struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);
0114 
0115     /* Use spdif valid bit to perform digital mute */
0116     regmap_update_bits(priv->map, SPDIFOUT_CTRL0, SPDIFOUT_CTRL0_VSET,
0117                mute ? SPDIFOUT_CTRL0_VSET : 0);
0118 
0119     return 0;
0120 }
0121 
0122 static int axg_spdifout_sample_fmt(struct snd_pcm_hw_params *params,
0123                    struct snd_soc_dai *dai)
0124 {
0125     struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);
0126     unsigned int val;
0127 
0128     /* Set the samples spdifout will pull from the FIFO */
0129     switch (params_channels(params)) {
0130     case 1:
0131         val = SPDIFOUT_CTRL0_MASK(0x1);
0132         break;
0133     case 2:
0134         val = SPDIFOUT_CTRL0_MASK(0x3);
0135         break;
0136     default:
0137         dev_err(dai->dev, "too many channels for spdif dai: %u\n",
0138             params_channels(params));
0139         return -EINVAL;
0140     }
0141 
0142     regmap_update_bits(priv->map, SPDIFOUT_CTRL0,
0143                SPDIFOUT_CTRL0_MASK_MASK, val);
0144 
0145     /* FIFO data are arranged in chunks of 64bits */
0146     switch (params_physical_width(params)) {
0147     case 8:
0148         /* 8 samples of 8 bits */
0149         val = SPDIFOUT_CTRL1_TYPE(0);
0150         break;
0151     case 16:
0152         /* 4 samples of 16 bits - right justified */
0153         val = SPDIFOUT_CTRL1_TYPE(2);
0154         break;
0155     case 32:
0156         /* 2 samples of 32 bits - right justified */
0157         val = SPDIFOUT_CTRL1_TYPE(4);
0158         break;
0159     default:
0160         dev_err(dai->dev, "Unsupported physical width: %u\n",
0161             params_physical_width(params));
0162         return -EINVAL;
0163     }
0164 
0165     /* Position of the MSB in FIFO samples */
0166     val |= SPDIFOUT_CTRL1_MSB_POS(params_width(params) - 1);
0167 
0168     regmap_update_bits(priv->map, SPDIFOUT_CTRL1,
0169                SPDIFOUT_CTRL1_MSB_POS_MASK |
0170                SPDIFOUT_CTRL1_TYPE_MASK, val);
0171 
0172     regmap_update_bits(priv->map, SPDIFOUT_CTRL0,
0173                SPDIFOUT_CTRL0_MSB_FIRST | SPDIFOUT_CTRL0_DATA_SEL,
0174                0);
0175 
0176     return 0;
0177 }
0178 
0179 static int axg_spdifout_set_chsts(struct snd_pcm_hw_params *params,
0180                   struct snd_soc_dai *dai)
0181 {
0182     struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);
0183     unsigned int offset;
0184     int ret;
0185     u8 cs[4];
0186     u32 val;
0187 
0188     ret = snd_pcm_create_iec958_consumer_hw_params(params, cs, 4);
0189     if (ret < 0) {
0190         dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",
0191             ret);
0192         return ret;
0193     }
0194     val = cs[0] | cs[1] << 8 | cs[2] << 16 | cs[3] << 24;
0195 
0196     /* Setup channel status A bits [31 - 0]*/
0197     regmap_write(priv->map, SPDIFOUT_CHSTS0, val);
0198 
0199     /* Clear channel status A bits [191 - 32] */
0200     for (offset = SPDIFOUT_CHSTS1; offset <= SPDIFOUT_CHSTS5;
0201          offset += regmap_get_reg_stride(priv->map))
0202         regmap_write(priv->map, offset, 0);
0203 
0204     /* Setup channel status B bits [31 - 0]*/
0205     regmap_write(priv->map, SPDIFOUT_CHSTS6, val);
0206 
0207     /* Clear channel status B bits [191 - 32] */
0208     for (offset = SPDIFOUT_CHSTS7; offset <= SPDIFOUT_CHSTSB;
0209          offset += regmap_get_reg_stride(priv->map))
0210         regmap_write(priv->map, offset, 0);
0211 
0212     return 0;
0213 }
0214 
0215 static int axg_spdifout_hw_params(struct snd_pcm_substream *substream,
0216                   struct snd_pcm_hw_params *params,
0217                   struct snd_soc_dai *dai)
0218 {
0219     struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);
0220     unsigned int rate = params_rate(params);
0221     int ret;
0222 
0223     /* 2 * 32bits per subframe * 2 channels = 128 */
0224     ret = clk_set_rate(priv->mclk, rate * 128);
0225     if (ret) {
0226         dev_err(dai->dev, "failed to set spdif clock\n");
0227         return ret;
0228     }
0229 
0230     ret = axg_spdifout_sample_fmt(params, dai);
0231     if (ret) {
0232         dev_err(dai->dev, "failed to setup sample format\n");
0233         return ret;
0234     }
0235 
0236     ret = axg_spdifout_set_chsts(params, dai);
0237     if (ret) {
0238         dev_err(dai->dev, "failed to setup channel status words\n");
0239         return ret;
0240     }
0241 
0242     return 0;
0243 }
0244 
0245 static int axg_spdifout_startup(struct snd_pcm_substream *substream,
0246                 struct snd_soc_dai *dai)
0247 {
0248     struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);
0249     int ret;
0250 
0251     /* Clock the spdif output block */
0252     ret = clk_prepare_enable(priv->pclk);
0253     if (ret) {
0254         dev_err(dai->dev, "failed to enable pclk\n");
0255         return ret;
0256     }
0257 
0258     /* Make sure the block is initially stopped */
0259     axg_spdifout_disable(priv->map);
0260 
0261     /* Insert data from bit 27 lsb first */
0262     regmap_update_bits(priv->map, SPDIFOUT_CTRL0,
0263                SPDIFOUT_CTRL0_MSB_FIRST | SPDIFOUT_CTRL0_DATA_SEL,
0264                0);
0265 
0266     /* Manual control of V, C and U, U = 0 */
0267     regmap_update_bits(priv->map, SPDIFOUT_CTRL0,
0268                SPDIFOUT_CTRL0_CHSTS_SEL | SPDIFOUT_CTRL0_VSEL |
0269                SPDIFOUT_CTRL0_USEL | SPDIFOUT_CTRL0_USET,
0270                0);
0271 
0272     /* Static SWAP configuration ATM */
0273     regmap_write(priv->map, SPDIFOUT_SWAP, 0x10);
0274 
0275     return 0;
0276 }
0277 
0278 static void axg_spdifout_shutdown(struct snd_pcm_substream *substream,
0279                   struct snd_soc_dai *dai)
0280 {
0281     struct axg_spdifout *priv = snd_soc_dai_get_drvdata(dai);
0282 
0283     clk_disable_unprepare(priv->pclk);
0284 }
0285 
0286 static const struct snd_soc_dai_ops axg_spdifout_ops = {
0287     .trigger    = axg_spdifout_trigger,
0288     .mute_stream    = axg_spdifout_mute,
0289     .hw_params  = axg_spdifout_hw_params,
0290     .startup    = axg_spdifout_startup,
0291     .shutdown   = axg_spdifout_shutdown,
0292     .no_capture_mute = 1,
0293 };
0294 
0295 static struct snd_soc_dai_driver axg_spdifout_dai_drv[] = {
0296     {
0297         .name = "SPDIF Output",
0298         .playback = {
0299             .stream_name    = "Playback",
0300             .channels_min   = 1,
0301             .channels_max   = 2,
0302             .rates      = (SNDRV_PCM_RATE_32000  |
0303                        SNDRV_PCM_RATE_44100  |
0304                        SNDRV_PCM_RATE_48000  |
0305                        SNDRV_PCM_RATE_88200  |
0306                        SNDRV_PCM_RATE_96000  |
0307                        SNDRV_PCM_RATE_176400 |
0308                        SNDRV_PCM_RATE_192000),
0309             .formats    = (SNDRV_PCM_FMTBIT_S8     |
0310                        SNDRV_PCM_FMTBIT_S16_LE |
0311                        SNDRV_PCM_FMTBIT_S20_LE |
0312                        SNDRV_PCM_FMTBIT_S24_LE),
0313         },
0314         .ops = &axg_spdifout_ops,
0315     },
0316 };
0317 
0318 static const char * const spdifout_sel_texts[] = {
0319     "IN 0", "IN 1", "IN 2",
0320 };
0321 
0322 static SOC_ENUM_SINGLE_DECL(axg_spdifout_sel_enum, SPDIFOUT_CTRL1, 24,
0323                 spdifout_sel_texts);
0324 
0325 static const struct snd_kcontrol_new axg_spdifout_in_mux =
0326     SOC_DAPM_ENUM("Input Source", axg_spdifout_sel_enum);
0327 
0328 static const struct snd_soc_dapm_widget axg_spdifout_dapm_widgets[] = {
0329     SND_SOC_DAPM_AIF_IN("IN 0", NULL, 0, SND_SOC_NOPM, 0, 0),
0330     SND_SOC_DAPM_AIF_IN("IN 1", NULL, 0, SND_SOC_NOPM, 0, 0),
0331     SND_SOC_DAPM_AIF_IN("IN 2", NULL, 0, SND_SOC_NOPM, 0, 0),
0332     SND_SOC_DAPM_MUX("SRC SEL", SND_SOC_NOPM, 0, 0, &axg_spdifout_in_mux),
0333 };
0334 
0335 static const struct snd_soc_dapm_route axg_spdifout_dapm_routes[] = {
0336     { "SRC SEL", "IN 0", "IN 0" },
0337     { "SRC SEL", "IN 1", "IN 1" },
0338     { "SRC SEL", "IN 2", "IN 2" },
0339     { "Playback", NULL, "SRC SEL" },
0340 };
0341 
0342 static const struct snd_kcontrol_new axg_spdifout_controls[] = {
0343     SOC_DOUBLE("Playback Volume", SPDIFOUT_GAIN0,  0,  8, 255, 0),
0344     SOC_DOUBLE("Playback Switch", SPDIFOUT_CTRL0, 22, 21, 1, 1),
0345     SOC_SINGLE("Playback Gain Enable Switch",
0346            SPDIFOUT_CTRL1, 26, 1, 0),
0347     SOC_SINGLE("Playback Channels Mix Switch",
0348            SPDIFOUT_CTRL0, 23, 1, 0),
0349 };
0350 
0351 static int axg_spdifout_set_bias_level(struct snd_soc_component *component,
0352                        enum snd_soc_bias_level level)
0353 {
0354     struct axg_spdifout *priv = snd_soc_component_get_drvdata(component);
0355     enum snd_soc_bias_level now =
0356         snd_soc_component_get_bias_level(component);
0357     int ret = 0;
0358 
0359     switch (level) {
0360     case SND_SOC_BIAS_PREPARE:
0361         if (now == SND_SOC_BIAS_STANDBY)
0362             ret = clk_prepare_enable(priv->mclk);
0363         break;
0364 
0365     case SND_SOC_BIAS_STANDBY:
0366         if (now == SND_SOC_BIAS_PREPARE)
0367             clk_disable_unprepare(priv->mclk);
0368         break;
0369 
0370     case SND_SOC_BIAS_OFF:
0371     case SND_SOC_BIAS_ON:
0372         break;
0373     }
0374 
0375     return ret;
0376 }
0377 
0378 static const struct snd_soc_component_driver axg_spdifout_component_drv = {
0379     .controls       = axg_spdifout_controls,
0380     .num_controls       = ARRAY_SIZE(axg_spdifout_controls),
0381     .dapm_widgets       = axg_spdifout_dapm_widgets,
0382     .num_dapm_widgets   = ARRAY_SIZE(axg_spdifout_dapm_widgets),
0383     .dapm_routes        = axg_spdifout_dapm_routes,
0384     .num_dapm_routes    = ARRAY_SIZE(axg_spdifout_dapm_routes),
0385     .set_bias_level     = axg_spdifout_set_bias_level,
0386     .legacy_dai_naming  = 1,
0387 };
0388 
0389 static const struct regmap_config axg_spdifout_regmap_cfg = {
0390     .reg_bits   = 32,
0391     .val_bits   = 32,
0392     .reg_stride = 4,
0393     .max_register   = SPDIFOUT_MUTE_VAL,
0394 };
0395 
0396 static const struct of_device_id axg_spdifout_of_match[] = {
0397     { .compatible = "amlogic,axg-spdifout", },
0398     {}
0399 };
0400 MODULE_DEVICE_TABLE(of, axg_spdifout_of_match);
0401 
0402 static int axg_spdifout_probe(struct platform_device *pdev)
0403 {
0404     struct device *dev = &pdev->dev;
0405     struct axg_spdifout *priv;
0406     void __iomem *regs;
0407 
0408     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0409     if (!priv)
0410         return -ENOMEM;
0411     platform_set_drvdata(pdev, priv);
0412 
0413     regs = devm_platform_ioremap_resource(pdev, 0);
0414     if (IS_ERR(regs))
0415         return PTR_ERR(regs);
0416 
0417     priv->map = devm_regmap_init_mmio(dev, regs, &axg_spdifout_regmap_cfg);
0418     if (IS_ERR(priv->map)) {
0419         dev_err(dev, "failed to init regmap: %ld\n",
0420             PTR_ERR(priv->map));
0421         return PTR_ERR(priv->map);
0422     }
0423 
0424     priv->pclk = devm_clk_get(dev, "pclk");
0425     if (IS_ERR(priv->pclk))
0426         return dev_err_probe(dev, PTR_ERR(priv->pclk), "failed to get pclk\n");
0427 
0428     priv->mclk = devm_clk_get(dev, "mclk");
0429     if (IS_ERR(priv->mclk))
0430         return dev_err_probe(dev, PTR_ERR(priv->mclk), "failed to get mclk\n");
0431 
0432     return devm_snd_soc_register_component(dev, &axg_spdifout_component_drv,
0433             axg_spdifout_dai_drv, ARRAY_SIZE(axg_spdifout_dai_drv));
0434 }
0435 
0436 static struct platform_driver axg_spdifout_pdrv = {
0437     .probe = axg_spdifout_probe,
0438     .driver = {
0439         .name = "axg-spdifout",
0440         .of_match_table = axg_spdifout_of_match,
0441     },
0442 };
0443 module_platform_driver(axg_spdifout_pdrv);
0444 
0445 MODULE_DESCRIPTION("Amlogic AXG SPDIF Output driver");
0446 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
0447 MODULE_LICENSE("GPL v2");