0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/init.h>
0014 #include <linux/module.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/err.h>
0017 #include <linux/clk.h>
0018 #include <linux/io.h>
0019 #include <linux/slab.h>
0020 #include <linux/pm_runtime.h>
0021 #include <linux/of_device.h>
0022
0023 #include <sound/core.h>
0024 #include <sound/pcm.h>
0025 #include <sound/pcm_params.h>
0026 #include <sound/initval.h>
0027 #include <sound/soc.h>
0028 #include <sound/dmaengine_pcm.h>
0029
0030 #include "omap-dmic.h"
0031 #include "sdma-pcm.h"
0032
0033 struct omap_dmic {
0034 struct device *dev;
0035 void __iomem *io_base;
0036 struct clk *fclk;
0037 struct pm_qos_request pm_qos_req;
0038 int latency;
0039 int fclk_freq;
0040 int out_freq;
0041 int clk_div;
0042 int sysclk;
0043 int threshold;
0044 u32 ch_enabled;
0045 bool active;
0046 struct mutex mutex;
0047
0048 struct snd_dmaengine_dai_dma_data dma_data;
0049 };
0050
0051 static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
0052 {
0053 writel_relaxed(val, dmic->io_base + reg);
0054 }
0055
0056 static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg)
0057 {
0058 return readl_relaxed(dmic->io_base + reg);
0059 }
0060
0061 static inline void omap_dmic_start(struct omap_dmic *dmic)
0062 {
0063 u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
0064
0065
0066 omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_SET_REG,
0067 OMAP_DMIC_DMA_ENABLE);
0068
0069 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl | dmic->ch_enabled);
0070 }
0071
0072 static inline void omap_dmic_stop(struct omap_dmic *dmic)
0073 {
0074 u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
0075 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
0076 ctrl & ~OMAP_DMIC_UP_ENABLE_MASK);
0077
0078
0079 omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_CLR_REG,
0080 OMAP_DMIC_DMA_ENABLE);
0081
0082 }
0083
0084 static inline int dmic_is_enabled(struct omap_dmic *dmic)
0085 {
0086 return omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG) &
0087 OMAP_DMIC_UP_ENABLE_MASK;
0088 }
0089
0090 static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
0091 struct snd_soc_dai *dai)
0092 {
0093 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
0094 int ret = 0;
0095
0096 mutex_lock(&dmic->mutex);
0097
0098 if (!snd_soc_dai_active(dai))
0099 dmic->active = 1;
0100 else
0101 ret = -EBUSY;
0102
0103 mutex_unlock(&dmic->mutex);
0104
0105 return ret;
0106 }
0107
0108 static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
0109 struct snd_soc_dai *dai)
0110 {
0111 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
0112
0113 mutex_lock(&dmic->mutex);
0114
0115 cpu_latency_qos_remove_request(&dmic->pm_qos_req);
0116
0117 if (!snd_soc_dai_active(dai))
0118 dmic->active = 0;
0119
0120 mutex_unlock(&dmic->mutex);
0121 }
0122
0123 static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate)
0124 {
0125 int divider = -EINVAL;
0126
0127
0128
0129
0130
0131 if (sample_rate == 192000) {
0132 if (dmic->fclk_freq == 19200000 && dmic->out_freq == 3840000)
0133 divider = 0x6;
0134 else
0135 dev_err(dmic->dev,
0136 "invalid clock configuration for 192KHz\n");
0137
0138 return divider;
0139 }
0140
0141 switch (dmic->out_freq) {
0142 case 1536000:
0143 if (dmic->fclk_freq != 24576000)
0144 goto div_err;
0145 divider = 0x4;
0146 break;
0147 case 2400000:
0148 switch (dmic->fclk_freq) {
0149 case 12000000:
0150 divider = 0x5;
0151 break;
0152 case 19200000:
0153 divider = 0x0;
0154 break;
0155 case 24000000:
0156 divider = 0x2;
0157 break;
0158 default:
0159 goto div_err;
0160 }
0161 break;
0162 case 3072000:
0163 if (dmic->fclk_freq != 24576000)
0164 goto div_err;
0165 divider = 0x3;
0166 break;
0167 case 3840000:
0168 if (dmic->fclk_freq != 19200000)
0169 goto div_err;
0170 divider = 0x1;
0171 break;
0172 default:
0173 dev_err(dmic->dev, "invalid out frequency: %dHz\n",
0174 dmic->out_freq);
0175 break;
0176 }
0177
0178 return divider;
0179
0180 div_err:
0181 dev_err(dmic->dev, "invalid out frequency %dHz for %dHz input\n",
0182 dmic->out_freq, dmic->fclk_freq);
0183 return -EINVAL;
0184 }
0185
0186 static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
0187 struct snd_pcm_hw_params *params,
0188 struct snd_soc_dai *dai)
0189 {
0190 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
0191 struct snd_dmaengine_dai_dma_data *dma_data;
0192 int channels;
0193
0194 dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
0195 if (dmic->clk_div < 0) {
0196 dev_err(dmic->dev, "no valid divider for %dHz from %dHz\n",
0197 dmic->out_freq, dmic->fclk_freq);
0198 return -EINVAL;
0199 }
0200
0201 dmic->ch_enabled = 0;
0202 channels = params_channels(params);
0203 switch (channels) {
0204 case 6:
0205 dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE;
0206 fallthrough;
0207 case 4:
0208 dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE;
0209 fallthrough;
0210 case 2:
0211 dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE;
0212 break;
0213 default:
0214 dev_err(dmic->dev, "invalid number of legacy channels\n");
0215 return -EINVAL;
0216 }
0217
0218
0219 dma_data = snd_soc_dai_get_dma_data(dai, substream);
0220 dma_data->maxburst = dmic->threshold * channels;
0221 dmic->latency = (OMAP_DMIC_THRES_MAX - dmic->threshold) * USEC_PER_SEC /
0222 params_rate(params);
0223
0224 return 0;
0225 }
0226
0227 static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
0228 struct snd_soc_dai *dai)
0229 {
0230 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
0231 u32 ctrl;
0232
0233 if (cpu_latency_qos_request_active(&dmic->pm_qos_req))
0234 cpu_latency_qos_update_request(&dmic->pm_qos_req,
0235 dmic->latency);
0236
0237
0238 omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
0239
0240 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
0241
0242
0243 ctrl &= ~(OMAP_DMIC_FORMAT | OMAP_DMIC_POLAR_MASK);
0244 ctrl |= (OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
0245 OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
0246
0247
0248 ctrl &= ~OMAP_DMIC_CLK_DIV_MASK;
0249 ctrl |= OMAP_DMIC_CLK_DIV(dmic->clk_div);
0250
0251 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl);
0252
0253 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
0254 ctrl | OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
0255 OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
0256
0257 return 0;
0258 }
0259
0260 static int omap_dmic_dai_trigger(struct snd_pcm_substream *substream,
0261 int cmd, struct snd_soc_dai *dai)
0262 {
0263 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
0264
0265 switch (cmd) {
0266 case SNDRV_PCM_TRIGGER_START:
0267 omap_dmic_start(dmic);
0268 break;
0269 case SNDRV_PCM_TRIGGER_STOP:
0270 omap_dmic_stop(dmic);
0271 break;
0272 default:
0273 break;
0274 }
0275
0276 return 0;
0277 }
0278
0279 static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
0280 unsigned int freq)
0281 {
0282 struct clk *parent_clk, *mux;
0283 char *parent_clk_name;
0284 int ret = 0;
0285
0286 switch (freq) {
0287 case 12000000:
0288 case 19200000:
0289 case 24000000:
0290 case 24576000:
0291 break;
0292 default:
0293 dev_err(dmic->dev, "invalid input frequency: %dHz\n", freq);
0294 dmic->fclk_freq = 0;
0295 return -EINVAL;
0296 }
0297
0298 if (dmic->sysclk == clk_id) {
0299 dmic->fclk_freq = freq;
0300 return 0;
0301 }
0302
0303
0304 if (dmic->active && dmic_is_enabled(dmic)) {
0305 dev_err(dmic->dev, "can't re-parent when DMIC active\n");
0306 return -EBUSY;
0307 }
0308
0309 switch (clk_id) {
0310 case OMAP_DMIC_SYSCLK_PAD_CLKS:
0311 parent_clk_name = "pad_clks_ck";
0312 break;
0313 case OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS:
0314 parent_clk_name = "slimbus_clk";
0315 break;
0316 case OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS:
0317 parent_clk_name = "dmic_sync_mux_ck";
0318 break;
0319 default:
0320 dev_err(dmic->dev, "fclk clk_id (%d) not supported\n", clk_id);
0321 return -EINVAL;
0322 }
0323
0324 parent_clk = clk_get(dmic->dev, parent_clk_name);
0325 if (IS_ERR(parent_clk)) {
0326 dev_err(dmic->dev, "can't get %s\n", parent_clk_name);
0327 return -ENODEV;
0328 }
0329
0330 mux = clk_get_parent(dmic->fclk);
0331 if (IS_ERR(mux)) {
0332 dev_err(dmic->dev, "can't get fck mux parent\n");
0333 clk_put(parent_clk);
0334 return -ENODEV;
0335 }
0336
0337 mutex_lock(&dmic->mutex);
0338 if (dmic->active) {
0339
0340 pm_runtime_put_sync(dmic->dev);
0341 ret = clk_set_parent(mux, parent_clk);
0342 pm_runtime_get_sync(dmic->dev);
0343 } else {
0344 ret = clk_set_parent(mux, parent_clk);
0345 }
0346 mutex_unlock(&dmic->mutex);
0347
0348 if (ret < 0) {
0349 dev_err(dmic->dev, "re-parent failed\n");
0350 goto err_busy;
0351 }
0352
0353 dmic->sysclk = clk_id;
0354 dmic->fclk_freq = freq;
0355
0356 err_busy:
0357 clk_put(mux);
0358 clk_put(parent_clk);
0359
0360 return ret;
0361 }
0362
0363 static int omap_dmic_select_outclk(struct omap_dmic *dmic, int clk_id,
0364 unsigned int freq)
0365 {
0366 int ret = 0;
0367
0368 if (clk_id != OMAP_DMIC_ABE_DMIC_CLK) {
0369 dev_err(dmic->dev, "output clk_id (%d) not supported\n",
0370 clk_id);
0371 return -EINVAL;
0372 }
0373
0374 switch (freq) {
0375 case 1536000:
0376 case 2400000:
0377 case 3072000:
0378 case 3840000:
0379 dmic->out_freq = freq;
0380 break;
0381 default:
0382 dev_err(dmic->dev, "invalid out frequency: %dHz\n", freq);
0383 dmic->out_freq = 0;
0384 ret = -EINVAL;
0385 }
0386
0387 return ret;
0388 }
0389
0390 static int omap_dmic_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
0391 unsigned int freq, int dir)
0392 {
0393 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
0394
0395 if (dir == SND_SOC_CLOCK_IN)
0396 return omap_dmic_select_fclk(dmic, clk_id, freq);
0397 else if (dir == SND_SOC_CLOCK_OUT)
0398 return omap_dmic_select_outclk(dmic, clk_id, freq);
0399
0400 dev_err(dmic->dev, "invalid clock direction (%d)\n", dir);
0401 return -EINVAL;
0402 }
0403
0404 static const struct snd_soc_dai_ops omap_dmic_dai_ops = {
0405 .startup = omap_dmic_dai_startup,
0406 .shutdown = omap_dmic_dai_shutdown,
0407 .hw_params = omap_dmic_dai_hw_params,
0408 .prepare = omap_dmic_dai_prepare,
0409 .trigger = omap_dmic_dai_trigger,
0410 .set_sysclk = omap_dmic_set_dai_sysclk,
0411 };
0412
0413 static int omap_dmic_probe(struct snd_soc_dai *dai)
0414 {
0415 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
0416
0417 pm_runtime_enable(dmic->dev);
0418
0419
0420 pm_runtime_get_sync(dmic->dev);
0421 omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, 0x00);
0422 pm_runtime_put_sync(dmic->dev);
0423
0424
0425 dmic->threshold = OMAP_DMIC_THRES_MAX - 3;
0426
0427 snd_soc_dai_init_dma_data(dai, NULL, &dmic->dma_data);
0428
0429 return 0;
0430 }
0431
0432 static int omap_dmic_remove(struct snd_soc_dai *dai)
0433 {
0434 struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
0435
0436 pm_runtime_disable(dmic->dev);
0437
0438 return 0;
0439 }
0440
0441 static struct snd_soc_dai_driver omap_dmic_dai = {
0442 .name = "omap-dmic",
0443 .probe = omap_dmic_probe,
0444 .remove = omap_dmic_remove,
0445 .capture = {
0446 .channels_min = 2,
0447 .channels_max = 6,
0448 .rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
0449 .formats = SNDRV_PCM_FMTBIT_S32_LE,
0450 .sig_bits = 24,
0451 },
0452 .ops = &omap_dmic_dai_ops,
0453 };
0454
0455 static const struct snd_soc_component_driver omap_dmic_component = {
0456 .name = "omap-dmic",
0457 .legacy_dai_naming = 1,
0458 };
0459
0460 static int asoc_dmic_probe(struct platform_device *pdev)
0461 {
0462 struct omap_dmic *dmic;
0463 struct resource *res;
0464 int ret;
0465
0466 dmic = devm_kzalloc(&pdev->dev, sizeof(struct omap_dmic), GFP_KERNEL);
0467 if (!dmic)
0468 return -ENOMEM;
0469
0470 platform_set_drvdata(pdev, dmic);
0471 dmic->dev = &pdev->dev;
0472 dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS;
0473
0474 mutex_init(&dmic->mutex);
0475
0476 dmic->fclk = devm_clk_get(dmic->dev, "fck");
0477 if (IS_ERR(dmic->fclk)) {
0478 dev_err(dmic->dev, "can't get fck\n");
0479 return -ENODEV;
0480 }
0481
0482 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
0483 if (!res) {
0484 dev_err(dmic->dev, "invalid dma memory resource\n");
0485 return -ENODEV;
0486 }
0487 dmic->dma_data.addr = res->start + OMAP_DMIC_DATA_REG;
0488
0489 dmic->dma_data.filter_data = "up_link";
0490
0491 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
0492 dmic->io_base = devm_ioremap_resource(&pdev->dev, res);
0493 if (IS_ERR(dmic->io_base))
0494 return PTR_ERR(dmic->io_base);
0495
0496
0497 ret = devm_snd_soc_register_component(&pdev->dev,
0498 &omap_dmic_component,
0499 &omap_dmic_dai, 1);
0500 if (ret)
0501 return ret;
0502
0503 ret = sdma_pcm_platform_register(&pdev->dev, NULL, "up_link");
0504 if (ret)
0505 return ret;
0506
0507 return 0;
0508 }
0509
0510 static const struct of_device_id omap_dmic_of_match[] = {
0511 { .compatible = "ti,omap4-dmic", },
0512 { }
0513 };
0514 MODULE_DEVICE_TABLE(of, omap_dmic_of_match);
0515
0516 static struct platform_driver asoc_dmic_driver = {
0517 .driver = {
0518 .name = "omap-dmic",
0519 .of_match_table = omap_dmic_of_match,
0520 },
0521 .probe = asoc_dmic_probe,
0522 };
0523
0524 module_platform_driver(asoc_dmic_driver);
0525
0526 MODULE_ALIAS("platform:omap-dmic");
0527 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
0528 MODULE_DESCRIPTION("OMAP DMIC ASoC Interface");
0529 MODULE_LICENSE("GPL");