GNU Linux-libre 6.1.91-gnu
[releases.git] / sound / soc / sunxi / sun50i-dmic.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 //
3 // This driver supports the DMIC in Allwinner's H6 SoCs.
4 //
5 // Copyright 2021 Ban Tao <fengzheng923@gmail.com>
6
7 #include <linux/clk.h>
8 #include <linux/device.h>
9 #include <linux/of_device.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/reset.h>
14 #include <sound/dmaengine_pcm.h>
15 #include <sound/pcm_params.h>
16 #include <sound/soc.h>
17
18 #define SUN50I_DMIC_EN_CTL                      (0x00)
19         #define SUN50I_DMIC_EN_CTL_GLOBE                        BIT(8)
20         #define SUN50I_DMIC_EN_CTL_CHAN(v)                      ((v) << 0)
21         #define SUN50I_DMIC_EN_CTL_CHAN_MASK                    GENMASK(7, 0)
22 #define SUN50I_DMIC_SR                          (0x04)
23         #define SUN50I_DMIC_SR_SAMPLE_RATE(v)                   ((v) << 0)
24         #define SUN50I_DMIC_SR_SAMPLE_RATE_MASK                 GENMASK(2, 0)
25 #define SUN50I_DMIC_CTL                         (0x08)
26         #define SUN50I_DMIC_CTL_OVERSAMPLE_RATE                 BIT(0)
27 #define SUN50I_DMIC_DATA                        (0x10)
28 #define SUN50I_DMIC_INTC                        (0x14)
29         #define SUN50I_DMIC_FIFO_DRQ_EN                         BIT(2)
30 #define SUN50I_DMIC_INT_STA                     (0x18)
31         #define SUN50I_DMIC_INT_STA_OVERRUN_IRQ_PENDING         BIT(1)
32         #define SUN50I_DMIC_INT_STA_DATA_IRQ_PENDING            BIT(0)
33 #define SUN50I_DMIC_RXFIFO_CTL                  (0x1c)
34         #define SUN50I_DMIC_RXFIFO_CTL_FLUSH                    BIT(31)
35         #define SUN50I_DMIC_RXFIFO_CTL_MODE_MASK                BIT(9)
36         #define SUN50I_DMIC_RXFIFO_CTL_MODE_LSB                 (0 << 9)
37         #define SUN50I_DMIC_RXFIFO_CTL_MODE_MSB                 (1 << 9)
38         #define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK              BIT(8)
39         #define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16                (0 << 8)
40         #define SUN50I_DMIC_RXFIFO_CTL_SAMPLE_24                (1 << 8)
41 #define SUN50I_DMIC_CH_NUM                      (0x24)
42         #define SUN50I_DMIC_CH_NUM_N(v)                         ((v) << 0)
43         #define SUN50I_DMIC_CH_NUM_N_MASK                       GENMASK(2, 0)
44 #define SUN50I_DMIC_CNT                         (0x2c)
45         #define SUN50I_DMIC_CNT_N                               (1 << 0)
46 #define SUN50I_DMIC_HPF_CTRL                    (0x38)
47 #define SUN50I_DMIC_VERSION                     (0x50)
48
49 struct sun50i_dmic_dev {
50         struct clk *dmic_clk;
51         struct clk *bus_clk;
52         struct reset_control *rst;
53         struct regmap *regmap;
54         struct snd_dmaengine_dai_dma_data dma_params_rx;
55 };
56
57 struct dmic_rate {
58         unsigned int samplerate;
59         unsigned int rate_bit;
60 };
61
62 static const struct dmic_rate dmic_rate_s[] = {
63         {48000, 0x0},
64         {44100, 0x0},
65         {32000, 0x1},
66         {24000, 0x2},
67         {22050, 0x2},
68         {16000, 0x3},
69         {12000, 0x4},
70         {11025, 0x4},
71         {8000,  0x5},
72 };
73
74 static int sun50i_dmic_startup(struct snd_pcm_substream *substream,
75                                struct snd_soc_dai *cpu_dai)
76 {
77         struct snd_soc_pcm_runtime *rtd = substream->private_data;
78         struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
79
80         /* only support capture */
81         if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
82                 return -EINVAL;
83
84         regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL,
85                         SUN50I_DMIC_RXFIFO_CTL_FLUSH,
86                         SUN50I_DMIC_RXFIFO_CTL_FLUSH);
87         regmap_write(host->regmap, SUN50I_DMIC_CNT, SUN50I_DMIC_CNT_N);
88
89         return 0;
90 }
91
92 static int sun50i_dmic_hw_params(struct snd_pcm_substream *substream,
93                                  struct snd_pcm_hw_params *params,
94                                  struct snd_soc_dai *cpu_dai)
95 {
96         int i = 0;
97         unsigned long rate = params_rate(params);
98         unsigned int mclk = 0;
99         unsigned int channels = params_channels(params);
100         unsigned int chan_en = (1 << channels) - 1;
101         struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(cpu_dai);
102
103         /* DMIC num is N+1 */
104         regmap_update_bits(host->regmap, SUN50I_DMIC_CH_NUM,
105                            SUN50I_DMIC_CH_NUM_N_MASK,
106                            SUN50I_DMIC_CH_NUM_N(channels - 1));
107         regmap_write(host->regmap, SUN50I_DMIC_HPF_CTRL, chan_en);
108         regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL,
109                            SUN50I_DMIC_EN_CTL_CHAN_MASK,
110                            SUN50I_DMIC_EN_CTL_CHAN(chan_en));
111
112         switch (params_format(params)) {
113         case SNDRV_PCM_FORMAT_S16_LE:
114                 regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL,
115                                    SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK,
116                                    SUN50I_DMIC_RXFIFO_CTL_SAMPLE_16);
117                 break;
118         case SNDRV_PCM_FORMAT_S24_LE:
119                 regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL,
120                                    SUN50I_DMIC_RXFIFO_CTL_SAMPLE_MASK,
121                                    SUN50I_DMIC_RXFIFO_CTL_SAMPLE_24);
122                 break;
123         default:
124                 dev_err(cpu_dai->dev, "Invalid format!\n");
125                 return -EINVAL;
126         }
127         /* The hardware supports FIFO mode 1 for 24-bit samples */
128         regmap_update_bits(host->regmap, SUN50I_DMIC_RXFIFO_CTL,
129                            SUN50I_DMIC_RXFIFO_CTL_MODE_MASK,
130                            SUN50I_DMIC_RXFIFO_CTL_MODE_MSB);
131
132         switch (rate) {
133         case 11025:
134         case 22050:
135         case 44100:
136                 mclk = 22579200;
137                 break;
138         case 8000:
139         case 12000:
140         case 16000:
141         case 24000:
142         case 32000:
143         case 48000:
144                 mclk = 24576000;
145                 break;
146         default:
147                 dev_err(cpu_dai->dev, "Invalid rate!\n");
148                 return -EINVAL;
149         }
150
151         if (clk_set_rate(host->dmic_clk, mclk)) {
152                 dev_err(cpu_dai->dev, "mclk : %u not support\n", mclk);
153                 return -EINVAL;
154         }
155
156         for (i = 0; i < ARRAY_SIZE(dmic_rate_s); i++) {
157                 if (dmic_rate_s[i].samplerate == rate) {
158                         regmap_update_bits(host->regmap, SUN50I_DMIC_SR,
159                                            SUN50I_DMIC_SR_SAMPLE_RATE_MASK,
160                                            SUN50I_DMIC_SR_SAMPLE_RATE(dmic_rate_s[i].rate_bit));
161                         break;
162                 }
163         }
164
165         switch (params_physical_width(params)) {
166         case 16:
167                 host->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
168                 break;
169         case 32:
170                 host->dma_params_rx.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
171                 break;
172         default:
173                 dev_err(cpu_dai->dev, "Unsupported physical sample width: %d\n",
174                         params_physical_width(params));
175                 return -EINVAL;
176         }
177
178         /* oversamplerate adjust */
179         if (params_rate(params) >= 24000)
180                 regmap_update_bits(host->regmap, SUN50I_DMIC_CTL,
181                                    SUN50I_DMIC_CTL_OVERSAMPLE_RATE,
182                                    SUN50I_DMIC_CTL_OVERSAMPLE_RATE);
183         else
184                 regmap_update_bits(host->regmap, SUN50I_DMIC_CTL,
185                                    SUN50I_DMIC_CTL_OVERSAMPLE_RATE, 0);
186
187         return 0;
188 }
189
190 static int sun50i_dmic_trigger(struct snd_pcm_substream *substream, int cmd,
191                                struct snd_soc_dai *dai)
192 {
193         int ret = 0;
194         struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(dai);
195
196         if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
197                 return -EINVAL;
198
199         switch (cmd) {
200         case SNDRV_PCM_TRIGGER_START:
201         case SNDRV_PCM_TRIGGER_RESUME:
202         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
203                 /* DRQ ENABLE */
204                 regmap_update_bits(host->regmap, SUN50I_DMIC_INTC,
205                                    SUN50I_DMIC_FIFO_DRQ_EN,
206                                    SUN50I_DMIC_FIFO_DRQ_EN);
207                 /* Global enable */
208                 regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL,
209                                    SUN50I_DMIC_EN_CTL_GLOBE,
210                                    SUN50I_DMIC_EN_CTL_GLOBE);
211                 break;
212         case SNDRV_PCM_TRIGGER_STOP:
213         case SNDRV_PCM_TRIGGER_SUSPEND:
214         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
215                 /* DRQ DISABLE */
216                 regmap_update_bits(host->regmap, SUN50I_DMIC_INTC,
217                                    SUN50I_DMIC_FIFO_DRQ_EN, 0);
218                 /* Global disable */
219                 regmap_update_bits(host->regmap, SUN50I_DMIC_EN_CTL,
220                                    SUN50I_DMIC_EN_CTL_GLOBE, 0);
221                 break;
222         default:
223                 ret = -EINVAL;
224                 break;
225         }
226         return ret;
227 }
228
229 static int sun50i_dmic_soc_dai_probe(struct snd_soc_dai *dai)
230 {
231         struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(dai);
232
233         snd_soc_dai_init_dma_data(dai, NULL, &host->dma_params_rx);
234
235         return 0;
236 }
237
238 static const struct snd_soc_dai_ops sun50i_dmic_dai_ops = {
239         .startup        = sun50i_dmic_startup,
240         .trigger        = sun50i_dmic_trigger,
241         .hw_params      = sun50i_dmic_hw_params,
242 };
243
244 static const struct regmap_config sun50i_dmic_regmap_config = {
245         .reg_bits = 32,
246         .reg_stride = 4,
247         .val_bits = 32,
248         .max_register = SUN50I_DMIC_VERSION,
249         .cache_type = REGCACHE_NONE,
250 };
251
252 #define SUN50I_DMIC_RATES (SNDRV_PCM_RATE_8000_48000)
253 #define SUN50I_DMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
254
255 static struct snd_soc_dai_driver sun50i_dmic_dai = {
256         .capture = {
257                 .channels_min = 1,
258                 .channels_max = 8,
259                 .rates = SUN50I_DMIC_RATES,
260                 .formats = SUN50I_DMIC_FORMATS,
261                 .sig_bits = 21,
262         },
263         .probe = sun50i_dmic_soc_dai_probe,
264         .ops = &sun50i_dmic_dai_ops,
265         .name = "dmic",
266 };
267
268 static const struct of_device_id sun50i_dmic_of_match[] = {
269         {
270                 .compatible = "allwinner,sun50i-h6-dmic",
271         },
272         { /* sentinel */ }
273 };
274 MODULE_DEVICE_TABLE(of, sun50i_dmic_of_match);
275
276 static const struct snd_soc_component_driver sun50i_dmic_component = {
277         .name           = "sun50i-dmic",
278 };
279
280 static int sun50i_dmic_runtime_suspend(struct device *dev)
281 {
282         struct sun50i_dmic_dev *host  = dev_get_drvdata(dev);
283
284         clk_disable_unprepare(host->dmic_clk);
285         clk_disable_unprepare(host->bus_clk);
286
287         return 0;
288 }
289
290 static int sun50i_dmic_runtime_resume(struct device *dev)
291 {
292         struct sun50i_dmic_dev *host  = dev_get_drvdata(dev);
293         int ret;
294
295         ret = clk_prepare_enable(host->dmic_clk);
296         if (ret)
297                 return ret;
298
299         ret = clk_prepare_enable(host->bus_clk);
300         if (ret) {
301                 clk_disable_unprepare(host->dmic_clk);
302                 return ret;
303         }
304
305         return 0;
306 }
307
308 static int sun50i_dmic_probe(struct platform_device *pdev)
309 {
310         struct sun50i_dmic_dev *host;
311         struct resource *res;
312         int ret;
313         void __iomem *base;
314
315         host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
316         if (!host)
317                 return -ENOMEM;
318
319         /* Get the addresses */
320         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
321         base = devm_ioremap_resource(&pdev->dev, res);
322         if (IS_ERR(base))
323                 return dev_err_probe(&pdev->dev, PTR_ERR(base),
324                                      "get resource failed.\n");
325
326         host->regmap = devm_regmap_init_mmio(&pdev->dev, base,
327                                              &sun50i_dmic_regmap_config);
328
329         /* Clocks */
330         host->bus_clk = devm_clk_get(&pdev->dev, "bus");
331         if (IS_ERR(host->bus_clk))
332                 return dev_err_probe(&pdev->dev, PTR_ERR(host->bus_clk),
333                                      "failed to get bus clock.\n");
334
335         host->dmic_clk = devm_clk_get(&pdev->dev, "mod");
336         if (IS_ERR(host->dmic_clk))
337                 return dev_err_probe(&pdev->dev, PTR_ERR(host->dmic_clk),
338                                      "failed to get dmic clock.\n");
339
340         host->dma_params_rx.addr = res->start + SUN50I_DMIC_DATA;
341         host->dma_params_rx.maxburst = 8;
342
343         platform_set_drvdata(pdev, host);
344
345         host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
346         if (IS_ERR(host->rst))
347                 return dev_err_probe(&pdev->dev, PTR_ERR(host->rst),
348                                      "Failed to get reset.\n");
349         reset_control_deassert(host->rst);
350
351         ret = devm_snd_soc_register_component(&pdev->dev, &sun50i_dmic_component,
352                                               &sun50i_dmic_dai, 1);
353         if (ret)
354                 return dev_err_probe(&pdev->dev, ret,
355                                      "failed to register component.\n");
356
357         pm_runtime_enable(&pdev->dev);
358         if (!pm_runtime_enabled(&pdev->dev)) {
359                 ret = sun50i_dmic_runtime_resume(&pdev->dev);
360                 if (ret)
361                         goto err_disable_runtime_pm;
362         }
363
364         ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
365         if (ret)
366                 goto err_suspend;
367
368         return 0;
369 err_suspend:
370         if (!pm_runtime_status_suspended(&pdev->dev))
371                 sun50i_dmic_runtime_suspend(&pdev->dev);
372 err_disable_runtime_pm:
373         pm_runtime_disable(&pdev->dev);
374         return ret;
375 }
376
377 static int sun50i_dmic_remove(struct platform_device *pdev)
378 {
379         pm_runtime_disable(&pdev->dev);
380         if (!pm_runtime_status_suspended(&pdev->dev))
381                 sun50i_dmic_runtime_suspend(&pdev->dev);
382
383         return 0;
384 }
385
386 static const struct dev_pm_ops sun50i_dmic_pm = {
387         SET_RUNTIME_PM_OPS(sun50i_dmic_runtime_suspend,
388                            sun50i_dmic_runtime_resume, NULL)
389 };
390
391 static struct platform_driver sun50i_dmic_driver = {
392         .driver         = {
393                 .name   = "sun50i-dmic",
394                 .of_match_table = of_match_ptr(sun50i_dmic_of_match),
395                 .pm     = &sun50i_dmic_pm,
396         },
397         .probe          = sun50i_dmic_probe,
398         .remove         = sun50i_dmic_remove,
399 };
400
401 module_platform_driver(sun50i_dmic_driver);
402
403 MODULE_DESCRIPTION("Allwinner sun50i DMIC SoC Interface");
404 MODULE_AUTHOR("Ban Tao <fengzheng923@gmail.com>");
405 MODULE_LICENSE("GPL");
406 MODULE_ALIAS("platform:sun50i-dmic");