ARM: s3c64xx: bring back notes from removed debug-macro.S
[linux-2.6-microblaze.git] / sound / soc / rockchip / rockchip_pdm.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Rockchip PDM ALSA SoC Digital Audio Interface(DAI)  driver
4  *
5  * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
6  */
7
8 #include <linux/module.h>
9 #include <linux/clk.h>
10 #include <linux/of.h>
11 #include <linux/of_device.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/rational.h>
14 #include <linux/regmap.h>
15 #include <linux/reset.h>
16 #include <sound/dmaengine_pcm.h>
17 #include <sound/pcm_params.h>
18
19 #include "rockchip_pdm.h"
20
21 #define PDM_DMA_BURST_SIZE      (8) /* size * width: 8*4 = 32 bytes */
22 #define PDM_SIGNOFF_CLK_RATE    (100000000)
23
24 enum rk_pdm_version {
25         RK_PDM_RK3229,
26         RK_PDM_RK3308,
27 };
28
29 struct rk_pdm_dev {
30         struct device *dev;
31         struct clk *clk;
32         struct clk *hclk;
33         struct regmap *regmap;
34         struct snd_dmaengine_dai_dma_data capture_dma_data;
35         struct reset_control *reset;
36         enum rk_pdm_version version;
37 };
38
39 struct rk_pdm_clkref {
40         unsigned int sr;
41         unsigned int clk;
42         unsigned int clk_out;
43 };
44
45 struct rk_pdm_ds_ratio {
46         unsigned int ratio;
47         unsigned int sr;
48 };
49
50 static struct rk_pdm_clkref clkref[] = {
51         { 8000, 40960000, 2048000 },
52         { 11025, 56448000, 2822400 },
53         { 12000, 61440000, 3072000 },
54         { 8000, 98304000, 2048000 },
55         { 12000, 98304000, 3072000 },
56 };
57
58 static struct rk_pdm_ds_ratio ds_ratio[] = {
59         { 0, 192000 },
60         { 0, 176400 },
61         { 0, 128000 },
62         { 1, 96000 },
63         { 1, 88200 },
64         { 1, 64000 },
65         { 2, 48000 },
66         { 2, 44100 },
67         { 2, 32000 },
68         { 3, 24000 },
69         { 3, 22050 },
70         { 3, 16000 },
71         { 4, 12000 },
72         { 4, 11025 },
73         { 4, 8000 },
74 };
75
76 static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr,
77                                 unsigned int *clk_src, unsigned int *clk_out)
78 {
79         unsigned int i, count, clk, div, rate;
80
81         clk = 0;
82         if (!sr)
83                 return clk;
84
85         count = ARRAY_SIZE(clkref);
86         for (i = 0; i < count; i++) {
87                 if (sr % clkref[i].sr)
88                         continue;
89                 div = sr / clkref[i].sr;
90                 if ((div & (div - 1)) == 0) {
91                         *clk_out = clkref[i].clk_out;
92                         rate = clk_round_rate(pdm->clk, clkref[i].clk);
93                         if (rate != clkref[i].clk)
94                                 continue;
95                         clk = clkref[i].clk;
96                         *clk_src = clkref[i].clk;
97                         break;
98                 }
99         }
100
101         if (!clk) {
102                 clk = clk_round_rate(pdm->clk, PDM_SIGNOFF_CLK_RATE);
103                 *clk_src = clk;
104         }
105         return clk;
106 }
107
108 static unsigned int get_pdm_ds_ratio(unsigned int sr)
109 {
110         unsigned int i, count, ratio;
111
112         ratio = 0;
113         if (!sr)
114                 return ratio;
115
116         count = ARRAY_SIZE(ds_ratio);
117         for (i = 0; i < count; i++) {
118                 if (sr == ds_ratio[i].sr)
119                         ratio = ds_ratio[i].ratio;
120         }
121         return ratio;
122 }
123
124 static inline struct rk_pdm_dev *to_info(struct snd_soc_dai *dai)
125 {
126         return snd_soc_dai_get_drvdata(dai);
127 }
128
129 static void rockchip_pdm_rxctrl(struct rk_pdm_dev *pdm, int on)
130 {
131         if (on) {
132                 regmap_update_bits(pdm->regmap, PDM_DMA_CTRL,
133                                    PDM_DMA_RD_MSK, PDM_DMA_RD_EN);
134                 regmap_update_bits(pdm->regmap, PDM_SYSCONFIG,
135                                    PDM_RX_MASK, PDM_RX_START);
136         } else {
137                 regmap_update_bits(pdm->regmap, PDM_DMA_CTRL,
138                                    PDM_DMA_RD_MSK, PDM_DMA_RD_DIS);
139                 regmap_update_bits(pdm->regmap, PDM_SYSCONFIG,
140                                    PDM_RX_MASK | PDM_RX_CLR_MASK,
141                                    PDM_RX_STOP | PDM_RX_CLR_WR);
142         }
143 }
144
145 static int rockchip_pdm_hw_params(struct snd_pcm_substream *substream,
146                                   struct snd_pcm_hw_params *params,
147                                   struct snd_soc_dai *dai)
148 {
149         struct rk_pdm_dev *pdm = to_info(dai);
150         unsigned int val = 0;
151         unsigned int clk_rate, clk_div, samplerate;
152         unsigned int clk_src, clk_out = 0;
153         unsigned long m, n;
154         bool change;
155         int ret;
156
157         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
158                 return 0;
159
160         samplerate = params_rate(params);
161         clk_rate = get_pdm_clk(pdm, samplerate, &clk_src, &clk_out);
162         if (!clk_rate)
163                 return -EINVAL;
164
165         ret = clk_set_rate(pdm->clk, clk_src);
166         if (ret)
167                 return -EINVAL;
168
169         if (pdm->version == RK_PDM_RK3308) {
170                 rational_best_approximation(clk_out, clk_src,
171                                             GENMASK(16 - 1, 0),
172                                             GENMASK(16 - 1, 0),
173                                             &m, &n);
174
175                 val = (m << PDM_FD_NUMERATOR_SFT) |
176                         (n << PDM_FD_DENOMINATOR_SFT);
177                 regmap_update_bits_check(pdm->regmap, PDM_CTRL1,
178                                          PDM_FD_NUMERATOR_MSK |
179                                          PDM_FD_DENOMINATOR_MSK,
180                                          val, &change);
181                 if (change) {
182                         reset_control_assert(pdm->reset);
183                         reset_control_deassert(pdm->reset);
184                         rockchip_pdm_rxctrl(pdm, 0);
185                 }
186                 clk_div = n / m;
187                 if (clk_div >= 40)
188                         val = PDM_CLK_FD_RATIO_40;
189                 else if (clk_div <= 35)
190                         val = PDM_CLK_FD_RATIO_35;
191                 else
192                         return -EINVAL;
193                 regmap_update_bits(pdm->regmap, PDM_CLK_CTRL,
194                                    PDM_CLK_FD_RATIO_MSK,
195                                    val);
196         }
197         val = get_pdm_ds_ratio(samplerate);
198         regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_DS_RATIO_MSK, val);
199         regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
200                            PDM_HPF_CF_MSK, PDM_HPF_60HZ);
201         regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
202                            PDM_HPF_LE | PDM_HPF_RE, PDM_HPF_LE | PDM_HPF_RE);
203         regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CLK_EN, PDM_CLK_EN);
204         if (pdm->version != RK_PDM_RK3229)
205                 regmap_update_bits(pdm->regmap, PDM_CTRL0,
206                                    PDM_MODE_MSK, PDM_MODE_LJ);
207
208         val = 0;
209         switch (params_format(params)) {
210         case SNDRV_PCM_FORMAT_S8:
211                 val |= PDM_VDW(8);
212                 break;
213         case SNDRV_PCM_FORMAT_S16_LE:
214                 val |= PDM_VDW(16);
215                 break;
216         case SNDRV_PCM_FORMAT_S20_3LE:
217                 val |= PDM_VDW(20);
218                 break;
219         case SNDRV_PCM_FORMAT_S24_LE:
220                 val |= PDM_VDW(24);
221                 break;
222         case SNDRV_PCM_FORMAT_S32_LE:
223                 val |= PDM_VDW(32);
224                 break;
225         default:
226                 return -EINVAL;
227         }
228
229         switch (params_channels(params)) {
230         case 8:
231                 val |= PDM_PATH3_EN;
232                 /* fallthrough */
233         case 6:
234                 val |= PDM_PATH2_EN;
235                 /* fallthrough */
236         case 4:
237                 val |= PDM_PATH1_EN;
238                 /* fallthrough */
239         case 2:
240                 val |= PDM_PATH0_EN;
241                 break;
242         default:
243                 dev_err(pdm->dev, "invalid channel: %d\n",
244                         params_channels(params));
245                 return -EINVAL;
246         }
247
248         regmap_update_bits(pdm->regmap, PDM_CTRL0,
249                            PDM_PATH_MSK | PDM_VDW_MSK,
250                            val);
251         /* all channels share the single FIFO */
252         regmap_update_bits(pdm->regmap, PDM_DMA_CTRL, PDM_DMA_RDL_MSK,
253                            PDM_DMA_RDL(8 * params_channels(params)));
254
255         return 0;
256 }
257
258 static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai,
259                                 unsigned int fmt)
260 {
261         struct rk_pdm_dev *pdm = to_info(cpu_dai);
262         unsigned int mask = 0, val = 0;
263
264         mask = PDM_CKP_MSK;
265         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
266         case SND_SOC_DAIFMT_NB_NF:
267                 val = PDM_CKP_NORMAL;
268                 break;
269         case SND_SOC_DAIFMT_IB_NF:
270                 val = PDM_CKP_INVERTED;
271                 break;
272         default:
273                 return -EINVAL;
274         }
275
276         pm_runtime_get_sync(cpu_dai->dev);
277         regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, mask, val);
278         pm_runtime_put(cpu_dai->dev);
279
280         return 0;
281 }
282
283 static int rockchip_pdm_trigger(struct snd_pcm_substream *substream, int cmd,
284                                 struct snd_soc_dai *dai)
285 {
286         struct rk_pdm_dev *pdm = to_info(dai);
287         int ret = 0;
288
289         switch (cmd) {
290         case SNDRV_PCM_TRIGGER_START:
291         case SNDRV_PCM_TRIGGER_RESUME:
292         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
293                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
294                         rockchip_pdm_rxctrl(pdm, 1);
295                 break;
296         case SNDRV_PCM_TRIGGER_SUSPEND:
297         case SNDRV_PCM_TRIGGER_STOP:
298         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
299                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
300                         rockchip_pdm_rxctrl(pdm, 0);
301                 break;
302         default:
303                 ret = -EINVAL;
304                 break;
305         }
306
307         return ret;
308 }
309
310 static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai)
311 {
312         struct rk_pdm_dev *pdm = to_info(dai);
313
314         dai->capture_dma_data = &pdm->capture_dma_data;
315
316         return 0;
317 }
318
319 static const struct snd_soc_dai_ops rockchip_pdm_dai_ops = {
320         .set_fmt = rockchip_pdm_set_fmt,
321         .trigger = rockchip_pdm_trigger,
322         .hw_params = rockchip_pdm_hw_params,
323 };
324
325 #define ROCKCHIP_PDM_RATES SNDRV_PCM_RATE_8000_192000
326 #define ROCKCHIP_PDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
327                               SNDRV_PCM_FMTBIT_S20_3LE | \
328                               SNDRV_PCM_FMTBIT_S24_LE | \
329                               SNDRV_PCM_FMTBIT_S32_LE)
330
331 static struct snd_soc_dai_driver rockchip_pdm_dai = {
332         .probe = rockchip_pdm_dai_probe,
333         .capture = {
334                 .stream_name = "Capture",
335                 .channels_min = 2,
336                 .channels_max = 8,
337                 .rates = ROCKCHIP_PDM_RATES,
338                 .formats = ROCKCHIP_PDM_FORMATS,
339         },
340         .ops = &rockchip_pdm_dai_ops,
341         .symmetric_rates = 1,
342 };
343
344 static const struct snd_soc_component_driver rockchip_pdm_component = {
345         .name = "rockchip-pdm",
346 };
347
348 static int rockchip_pdm_runtime_suspend(struct device *dev)
349 {
350         struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
351
352         clk_disable_unprepare(pdm->clk);
353         clk_disable_unprepare(pdm->hclk);
354
355         return 0;
356 }
357
358 static int rockchip_pdm_runtime_resume(struct device *dev)
359 {
360         struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
361         int ret;
362
363         ret = clk_prepare_enable(pdm->clk);
364         if (ret) {
365                 dev_err(pdm->dev, "clock enable failed %d\n", ret);
366                 return ret;
367         }
368
369         ret = clk_prepare_enable(pdm->hclk);
370         if (ret) {
371                 dev_err(pdm->dev, "hclock enable failed %d\n", ret);
372                 return ret;
373         }
374
375         return 0;
376 }
377
378 static bool rockchip_pdm_wr_reg(struct device *dev, unsigned int reg)
379 {
380         switch (reg) {
381         case PDM_SYSCONFIG:
382         case PDM_CTRL0:
383         case PDM_CTRL1:
384         case PDM_CLK_CTRL:
385         case PDM_HPF_CTRL:
386         case PDM_FIFO_CTRL:
387         case PDM_DMA_CTRL:
388         case PDM_INT_EN:
389         case PDM_INT_CLR:
390         case PDM_DATA_VALID:
391                 return true;
392         default:
393                 return false;
394         }
395 }
396
397 static bool rockchip_pdm_rd_reg(struct device *dev, unsigned int reg)
398 {
399         switch (reg) {
400         case PDM_SYSCONFIG:
401         case PDM_CTRL0:
402         case PDM_CTRL1:
403         case PDM_CLK_CTRL:
404         case PDM_HPF_CTRL:
405         case PDM_FIFO_CTRL:
406         case PDM_DMA_CTRL:
407         case PDM_INT_EN:
408         case PDM_INT_CLR:
409         case PDM_INT_ST:
410         case PDM_DATA_VALID:
411         case PDM_RXFIFO_DATA:
412         case PDM_VERSION:
413                 return true;
414         default:
415                 return false;
416         }
417 }
418
419 static bool rockchip_pdm_volatile_reg(struct device *dev, unsigned int reg)
420 {
421         switch (reg) {
422         case PDM_SYSCONFIG:
423         case PDM_FIFO_CTRL:
424         case PDM_INT_CLR:
425         case PDM_INT_ST:
426         case PDM_RXFIFO_DATA:
427                 return true;
428         default:
429                 return false;
430         }
431 }
432
433 static bool rockchip_pdm_precious_reg(struct device *dev, unsigned int reg)
434 {
435         switch (reg) {
436         case PDM_RXFIFO_DATA:
437                 return true;
438         default:
439                 return false;
440         }
441 }
442
443 static const struct reg_default rockchip_pdm_reg_defaults[] = {
444         {0x04, 0x78000017},
445         {0x08, 0x0bb8ea60},
446         {0x18, 0x0000001f},
447 };
448
449 static const struct regmap_config rockchip_pdm_regmap_config = {
450         .reg_bits = 32,
451         .reg_stride = 4,
452         .val_bits = 32,
453         .max_register = PDM_VERSION,
454         .reg_defaults = rockchip_pdm_reg_defaults,
455         .num_reg_defaults = ARRAY_SIZE(rockchip_pdm_reg_defaults),
456         .writeable_reg = rockchip_pdm_wr_reg,
457         .readable_reg = rockchip_pdm_rd_reg,
458         .volatile_reg = rockchip_pdm_volatile_reg,
459         .precious_reg = rockchip_pdm_precious_reg,
460         .cache_type = REGCACHE_FLAT,
461 };
462
463 static const struct of_device_id rockchip_pdm_match[] = {
464         { .compatible = "rockchip,pdm",
465           .data = (void *)RK_PDM_RK3229 },
466         { .compatible = "rockchip,px30-pdm",
467           .data = (void *)RK_PDM_RK3308 },
468         { .compatible = "rockchip,rk1808-pdm",
469           .data = (void *)RK_PDM_RK3308 },
470         { .compatible = "rockchip,rk3308-pdm",
471           .data = (void *)RK_PDM_RK3308 },
472         {},
473 };
474 MODULE_DEVICE_TABLE(of, rockchip_pdm_match);
475
476 static int rockchip_pdm_probe(struct platform_device *pdev)
477 {
478         const struct of_device_id *match;
479         struct rk_pdm_dev *pdm;
480         struct resource *res;
481         void __iomem *regs;
482         int ret;
483
484         pdm = devm_kzalloc(&pdev->dev, sizeof(*pdm), GFP_KERNEL);
485         if (!pdm)
486                 return -ENOMEM;
487
488         match = of_match_device(rockchip_pdm_match, &pdev->dev);
489         if (match)
490                 pdm->version = (enum rk_pdm_version)match->data;
491
492         if (pdm->version == RK_PDM_RK3308) {
493                 pdm->reset = devm_reset_control_get(&pdev->dev, "pdm-m");
494                 if (IS_ERR(pdm->reset))
495                         return PTR_ERR(pdm->reset);
496         }
497
498         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
499         regs = devm_ioremap_resource(&pdev->dev, res);
500         if (IS_ERR(regs))
501                 return PTR_ERR(regs);
502
503         pdm->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
504                                             &rockchip_pdm_regmap_config);
505         if (IS_ERR(pdm->regmap))
506                 return PTR_ERR(pdm->regmap);
507
508         pdm->capture_dma_data.addr = res->start + PDM_RXFIFO_DATA;
509         pdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
510         pdm->capture_dma_data.maxburst = PDM_DMA_BURST_SIZE;
511
512         pdm->dev = &pdev->dev;
513         dev_set_drvdata(&pdev->dev, pdm);
514
515         pdm->clk = devm_clk_get(&pdev->dev, "pdm_clk");
516         if (IS_ERR(pdm->clk))
517                 return PTR_ERR(pdm->clk);
518
519         pdm->hclk = devm_clk_get(&pdev->dev, "pdm_hclk");
520         if (IS_ERR(pdm->hclk))
521                 return PTR_ERR(pdm->hclk);
522
523         ret = clk_prepare_enable(pdm->hclk);
524         if (ret)
525                 return ret;
526
527         pm_runtime_enable(&pdev->dev);
528         if (!pm_runtime_enabled(&pdev->dev)) {
529                 ret = rockchip_pdm_runtime_resume(&pdev->dev);
530                 if (ret)
531                         goto err_pm_disable;
532         }
533
534         ret = devm_snd_soc_register_component(&pdev->dev,
535                                               &rockchip_pdm_component,
536                                               &rockchip_pdm_dai, 1);
537
538         if (ret) {
539                 dev_err(&pdev->dev, "could not register dai: %d\n", ret);
540                 goto err_suspend;
541         }
542
543         rockchip_pdm_rxctrl(pdm, 0);
544         ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
545         if (ret) {
546                 dev_err(&pdev->dev, "could not register pcm: %d\n", ret);
547                 goto err_suspend;
548         }
549
550         return 0;
551
552 err_suspend:
553         if (!pm_runtime_status_suspended(&pdev->dev))
554                 rockchip_pdm_runtime_suspend(&pdev->dev);
555 err_pm_disable:
556         pm_runtime_disable(&pdev->dev);
557
558         clk_disable_unprepare(pdm->hclk);
559
560         return ret;
561 }
562
563 static int rockchip_pdm_remove(struct platform_device *pdev)
564 {
565         struct rk_pdm_dev *pdm = dev_get_drvdata(&pdev->dev);
566
567         pm_runtime_disable(&pdev->dev);
568         if (!pm_runtime_status_suspended(&pdev->dev))
569                 rockchip_pdm_runtime_suspend(&pdev->dev);
570
571         clk_disable_unprepare(pdm->clk);
572         clk_disable_unprepare(pdm->hclk);
573
574         return 0;
575 }
576
577 #ifdef CONFIG_PM_SLEEP
578 static int rockchip_pdm_suspend(struct device *dev)
579 {
580         struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
581
582         regcache_mark_dirty(pdm->regmap);
583
584         return 0;
585 }
586
587 static int rockchip_pdm_resume(struct device *dev)
588 {
589         struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
590         int ret;
591
592         ret = pm_runtime_get_sync(dev);
593         if (ret < 0) {
594                 pm_runtime_put(dev);
595                 return ret;
596         }
597
598         ret = regcache_sync(pdm->regmap);
599
600         pm_runtime_put(dev);
601
602         return ret;
603 }
604 #endif
605
606 static const struct dev_pm_ops rockchip_pdm_pm_ops = {
607         SET_RUNTIME_PM_OPS(rockchip_pdm_runtime_suspend,
608                            rockchip_pdm_runtime_resume, NULL)
609         SET_SYSTEM_SLEEP_PM_OPS(rockchip_pdm_suspend, rockchip_pdm_resume)
610 };
611
612 static struct platform_driver rockchip_pdm_driver = {
613         .probe  = rockchip_pdm_probe,
614         .remove = rockchip_pdm_remove,
615         .driver = {
616                 .name = "rockchip-pdm",
617                 .of_match_table = of_match_ptr(rockchip_pdm_match),
618                 .pm = &rockchip_pdm_pm_ops,
619         },
620 };
621
622 module_platform_driver(rockchip_pdm_driver);
623
624 MODULE_AUTHOR("Sugar <sugar.zhang@rock-chips.com>");
625 MODULE_DESCRIPTION("Rockchip PDM Controller Driver");
626 MODULE_LICENSE("GPL v2");