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/gpio/consumer.h>
0007 #include <linux/of_platform.h>
0008 #include <linux/module.h>
0009 #include <sound/soc.h>
0010 
0011 struct es7241_clock_mode {
0012     unsigned int rate_min;
0013     unsigned int rate_max;
0014     unsigned int *slv_mfs;
0015     unsigned int slv_mfs_num;
0016     unsigned int mst_mfs;
0017     unsigned int mst_m0:1;
0018     unsigned int mst_m1:1;
0019 };
0020 
0021 struct es7241_chip {
0022     const struct es7241_clock_mode *modes;
0023     unsigned int mode_num;
0024 };
0025 
0026 struct es7241_data {
0027     struct gpio_desc *reset;
0028     struct gpio_desc *m0;
0029     struct gpio_desc *m1;
0030     unsigned int fmt;
0031     unsigned int mclk;
0032     bool is_consumer;
0033     const struct es7241_chip *chip;
0034 };
0035 
0036 static void es7241_set_mode(struct es7241_data *priv,  int m0, int m1)
0037 {
0038     /* put the device in reset */
0039     gpiod_set_value_cansleep(priv->reset, 0);
0040 
0041     /* set the mode */
0042     gpiod_set_value_cansleep(priv->m0, m0);
0043     gpiod_set_value_cansleep(priv->m1, m1);
0044 
0045     /* take the device out of reset - datasheet does not specify a delay */
0046     gpiod_set_value_cansleep(priv->reset, 1);
0047 }
0048 
0049 static int es7241_set_consumer_mode(struct es7241_data *priv,
0050                     const struct es7241_clock_mode *mode,
0051                     unsigned int mfs)
0052 {
0053     int j;
0054 
0055     if (!mfs)
0056         goto out_ok;
0057 
0058     for (j = 0; j < mode->slv_mfs_num; j++) {
0059         if (mode->slv_mfs[j] == mfs)
0060             goto out_ok;
0061     }
0062 
0063     return -EINVAL;
0064 
0065 out_ok:
0066     es7241_set_mode(priv, 1, 1);
0067     return 0;
0068 }
0069 
0070 static int es7241_set_provider_mode(struct es7241_data *priv,
0071                     const struct es7241_clock_mode *mode,
0072                     unsigned int mfs)
0073 {
0074     /*
0075      * We can't really set clock ratio, if the mclk/lrclk is different
0076      * from what we provide, then error out
0077      */
0078     if (mfs && mfs != mode->mst_mfs)
0079         return -EINVAL;
0080 
0081     es7241_set_mode(priv, mode->mst_m0, mode->mst_m1);
0082 
0083     return 0;
0084 }
0085 
0086 static int es7241_hw_params(struct snd_pcm_substream *substream,
0087                 struct snd_pcm_hw_params *params,
0088                 struct snd_soc_dai *dai)
0089 {
0090     struct es7241_data *priv = snd_soc_dai_get_drvdata(dai);
0091     unsigned int rate = params_rate(params);
0092     unsigned int mfs = priv->mclk / rate;
0093     int i;
0094 
0095     for (i = 0; i < priv->chip->mode_num; i++) {
0096         const struct es7241_clock_mode *mode = &priv->chip->modes[i];
0097 
0098         if (rate < mode->rate_min || rate >= mode->rate_max)
0099             continue;
0100 
0101         if (priv->is_consumer)
0102             return es7241_set_consumer_mode(priv, mode, mfs);
0103         else
0104             return es7241_set_provider_mode(priv, mode, mfs);
0105     }
0106 
0107     /* should not happen */
0108     dev_err(dai->dev, "unsupported rate: %u\n", rate);
0109     return -EINVAL;
0110 }
0111 
0112 static int es7241_set_sysclk(struct snd_soc_dai *dai, int clk_id,
0113                  unsigned int freq, int dir)
0114 {
0115     struct es7241_data *priv = snd_soc_dai_get_drvdata(dai);
0116 
0117     if (dir == SND_SOC_CLOCK_IN && clk_id == 0) {
0118         priv->mclk = freq;
0119         return 0;
0120     }
0121 
0122     return -ENOTSUPP;
0123 }
0124 
0125 static int es7241_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0126 {
0127     struct es7241_data *priv = snd_soc_dai_get_drvdata(dai);
0128 
0129     if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
0130         dev_err(dai->dev, "Unsupported dai clock inversion\n");
0131         return -EINVAL;
0132     }
0133 
0134     if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != priv->fmt) {
0135         dev_err(dai->dev, "Invalid dai format\n");
0136         return -EINVAL;
0137     }
0138 
0139     switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
0140     case SND_SOC_DAIFMT_CBC_CFC:
0141         priv->is_consumer = true;
0142         break;
0143     case SND_SOC_DAIFMT_CBP_CFP:
0144         priv->is_consumer = false;
0145         break;
0146 
0147     default:
0148         dev_err(dai->dev, "Unsupported clock configuration\n");
0149         return -EINVAL;
0150     }
0151 
0152     return 0;
0153 }
0154 
0155 static const struct snd_soc_dai_ops es7241_dai_ops = {
0156     .set_fmt    = es7241_set_fmt,
0157     .hw_params  = es7241_hw_params,
0158     .set_sysclk = es7241_set_sysclk,
0159 };
0160 
0161 static struct snd_soc_dai_driver es7241_dai = {
0162     .name = "es7241-hifi",
0163     .capture = {
0164         .stream_name = "Capture",
0165         .channels_min = 2,
0166         .channels_max = 2,
0167         .rates = SNDRV_PCM_RATE_8000_192000,
0168         .formats = (SNDRV_PCM_FMTBIT_S16_LE  |
0169                 SNDRV_PCM_FMTBIT_S24_3LE |
0170                 SNDRV_PCM_FMTBIT_S24_LE),
0171     },
0172     .ops = &es7241_dai_ops,
0173 };
0174 
0175 static const struct es7241_clock_mode es7241_modes[] = {
0176     {
0177         /* Single speed mode */
0178         .rate_min = 8000,
0179         .rate_max = 50000,
0180         .slv_mfs = (unsigned int[]) { 256, 384, 512, 768, 1024 },
0181         .slv_mfs_num = 5,
0182         .mst_mfs = 256,
0183         .mst_m0 = 0,
0184         .mst_m1 = 0,
0185     }, {
0186         /* Double speed mode */
0187         .rate_min = 50000,
0188         .rate_max = 100000,
0189         .slv_mfs = (unsigned int[]) { 128, 192 },
0190         .slv_mfs_num = 2,
0191         .mst_mfs = 128,
0192         .mst_m0 = 1,
0193         .mst_m1 = 0,
0194     }, {
0195         /* Quad speed mode */
0196         .rate_min = 100000,
0197         .rate_max = 200000,
0198         .slv_mfs = (unsigned int[]) { 64 },
0199         .slv_mfs_num = 1,
0200         .mst_mfs = 64,
0201         .mst_m0 = 0,
0202         .mst_m1 = 1,
0203     },
0204 };
0205 
0206 static const struct es7241_chip es7241_chip __maybe_unused = {
0207     .modes = es7241_modes,
0208     .mode_num = ARRAY_SIZE(es7241_modes),
0209 };
0210 
0211 static const struct snd_soc_dapm_widget es7241_dapm_widgets[] = {
0212     SND_SOC_DAPM_INPUT("AINL"),
0213     SND_SOC_DAPM_INPUT("AINR"),
0214     SND_SOC_DAPM_DAC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
0215     SND_SOC_DAPM_REGULATOR_SUPPLY("VDDP", 0, 0),
0216     SND_SOC_DAPM_REGULATOR_SUPPLY("VDDD", 0, 0),
0217     SND_SOC_DAPM_REGULATOR_SUPPLY("VDDA", 0, 0),
0218 };
0219 
0220 static const struct snd_soc_dapm_route es7241_dapm_routes[] = {
0221     { "ADC", NULL, "AINL", },
0222     { "ADC", NULL, "AINR", },
0223     { "ADC", NULL, "VDDA", },
0224     { "Capture", NULL, "VDDP", },
0225     { "Capture", NULL, "VDDD", },
0226 };
0227 
0228 static const struct snd_soc_component_driver es7241_component_driver = {
0229     .dapm_widgets       = es7241_dapm_widgets,
0230     .num_dapm_widgets   = ARRAY_SIZE(es7241_dapm_widgets),
0231     .dapm_routes        = es7241_dapm_routes,
0232     .num_dapm_routes    = ARRAY_SIZE(es7241_dapm_routes),
0233     .idle_bias_on       = 1,
0234     .endianness     = 1,
0235 };
0236 
0237 static void es7241_parse_fmt(struct device *dev, struct es7241_data *priv)
0238 {
0239     bool is_leftj;
0240 
0241     /*
0242      * The format is given by a pull resistor on the SDOUT pin:
0243      * pull-up for i2s, pull-down for left justified.
0244      */
0245     is_leftj = of_property_read_bool(dev->of_node,
0246                      "everest,sdout-pull-down");
0247     if (is_leftj)
0248         priv->fmt = SND_SOC_DAIFMT_LEFT_J;
0249     else
0250         priv->fmt = SND_SOC_DAIFMT_I2S;
0251 }
0252 
0253 static int es7241_probe(struct platform_device *pdev)
0254 {
0255     struct device *dev = &pdev->dev;
0256     struct es7241_data *priv;
0257 
0258     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0259     if (!priv)
0260         return -ENOMEM;
0261     platform_set_drvdata(pdev, priv);
0262 
0263     priv->chip = of_device_get_match_data(dev);
0264     if (!priv->chip) {
0265         dev_err(dev, "failed to match device\n");
0266         return -ENODEV;
0267     }
0268 
0269     es7241_parse_fmt(dev, priv);
0270 
0271     priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
0272     if (IS_ERR(priv->reset))
0273         return dev_err_probe(dev, PTR_ERR(priv->reset),
0274                      "Failed to get 'reset' gpio");
0275 
0276     priv->m0 = devm_gpiod_get_optional(dev, "m0", GPIOD_OUT_LOW);
0277     if (IS_ERR(priv->m0))
0278         return dev_err_probe(dev, PTR_ERR(priv->m0),
0279                      "Failed to get 'm0' gpio");
0280 
0281     priv->m1 = devm_gpiod_get_optional(dev, "m1", GPIOD_OUT_LOW);
0282     if (IS_ERR(priv->m1))
0283         return dev_err_probe(dev, PTR_ERR(priv->m1),
0284                      "Failed to get 'm1' gpio");
0285 
0286     return devm_snd_soc_register_component(&pdev->dev,
0287                       &es7241_component_driver,
0288                       &es7241_dai, 1);
0289 }
0290 
0291 #ifdef CONFIG_OF
0292 static const struct of_device_id es7241_ids[] = {
0293     { .compatible = "everest,es7241", .data = &es7241_chip },
0294     { }
0295 };
0296 MODULE_DEVICE_TABLE(of, es7241_ids);
0297 #endif
0298 
0299 static struct platform_driver es7241_driver = {
0300     .driver = {
0301         .name = "es7241",
0302         .of_match_table = of_match_ptr(es7241_ids),
0303     },
0304     .probe = es7241_probe,
0305 };
0306 
0307 module_platform_driver(es7241_driver);
0308 
0309 MODULE_DESCRIPTION("ASoC ES7241 audio codec driver");
0310 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
0311 MODULE_LICENSE("GPL");