forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4
kernel/sound/soc/rockchip/rockchip_pdm.c
....@@ -1,17 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Rockchip PDM ALSA SoC Digital Audio Interface(DAI) driver
34 *
45 * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
5
- *
6
- * This software is licensed under the terms of the GNU General Public
7
- * License version 2, as published by the Free Software Foundation, and
8
- * may be copied, distributed, and modified under those terms.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
156 */
167
178 #include <linux/module.h>
....@@ -29,20 +20,23 @@
2920 #include "rockchip_pdm.h"
3021
3122 #define PDM_DMA_BURST_SIZE (8) /* size * width: 8*4 = 32 bytes */
32
-#define PDM_SIGNOFF_CLK_RATE (100000000)
23
+#define PDM_SIGNOFF_CLK_100M (100000000)
24
+#define PDM_SIGNOFF_CLK_300M (300000000)
3325 #define PDM_PATH_MAX (4)
34
-#define CLK_PPM_MIN (-1000)
35
-#define CLK_PPM_MAX (1000)
3626 #define PDM_DEFAULT_RATE (48000)
3727 #define PDM_START_DELAY_MS_DEFAULT (20)
3828 #define PDM_START_DELAY_MS_MIN (0)
3929 #define PDM_START_DELAY_MS_MAX (1000)
4030 #define PDM_FILTER_DELAY_MS_MIN (20)
4131 #define PDM_FILTER_DELAY_MS_MAX (1000)
32
+#define PDM_CLK_SHIFT_PPM_MAX (1000000) /* 1 ppm */
33
+#define CLK_PPM_MIN (-1000)
34
+#define CLK_PPM_MAX (1000)
4235
4336 enum rk_pdm_version {
37
+ RK_PDM_RK3229,
4438 RK_PDM_RK3308,
45
- RK_PDM_RK3328,
39
+ RK_PDM_RK3588,
4640 RK_PDM_RV1126,
4741 };
4842
....@@ -101,9 +95,10 @@
10195 };
10296
10397 static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr,
104
- unsigned int *clk_src, unsigned int *clk_out)
98
+ unsigned int *clk_src, unsigned int *clk_out,
99
+ unsigned int signoff)
105100 {
106
- unsigned int i, count, clk, div, rate;
101
+ unsigned int i, count, clk, div, rate, delta;
107102
108103 clk = 0;
109104 if (!sr)
....@@ -122,7 +117,9 @@
122117 break;
123118 }
124119 rate = clk_round_rate(pdm->clk, clkref[i].clk);
125
- if (rate != clkref[i].clk)
120
+ delta = clkref[i].clk / PDM_CLK_SHIFT_PPM_MAX;
121
+ if (rate < clkref[i].clk - delta ||
122
+ rate > clkref[i].clk + delta)
126123 continue;
127124 clk = clkref[i].clk;
128125 *clk_src = clkref[i].clk;
....@@ -131,7 +128,7 @@
131128 }
132129
133130 if (!clk) {
134
- clk = clk_round_rate(pdm->clk, PDM_SIGNOFF_CLK_RATE);
131
+ clk = clk_round_rate(pdm->clk, signoff);
135132 *clk_src = clk;
136133 }
137134 return clk;
....@@ -207,22 +204,35 @@
207204 return snd_soc_dai_get_drvdata(dai);
208205 }
209206
210
-static void rockchip_pdm_drop_fifo(struct rk_pdm_dev *pdm)
211
-{
212
- int cnt, val, i;
213
-
214
- /* drop the dirty data */
215
- regmap_read(pdm->regmap, PDM_FIFO_CTRL, &cnt);
216
- for (i = 0; i < PDM_FIFO_CNT(cnt); i++)
217
- regmap_read(pdm->regmap, PDM_RXFIFO_DATA, &val);
218
-}
219
-
220207 static void rockchip_pdm_rxctrl(struct rk_pdm_dev *pdm, int on)
221208 {
209
+ unsigned long flags;
210
+
222211 if (on) {
223
- rockchip_pdm_drop_fifo(pdm);
212
+ /* The PDM device need to delete some unused data
213
+ * since the pdm of various manufacturers can not
214
+ * be stable quickly. This is done by commit "ASoC:
215
+ * rockchip: pdm: Fix pop noise in the beginning".
216
+ *
217
+ * But we do not know how many data we delete, this
218
+ * cause channel disorder. For example, we record
219
+ * two channel 24-bit sound, then delete some starting
220
+ * data. Because the deleted starting data is uncertain,
221
+ * the next data may be left or right channel and cause
222
+ * channel disorder.
223
+ *
224
+ * Luckily, we can use the PDM_RX_CLR to fix this.
225
+ * Use the PDM_RX_CLR to clear fifo written data and
226
+ * address, but can not clear the read data and address.
227
+ * In initial state, the read data and address are zero.
228
+ */
229
+ local_irq_save(flags);
230
+ regmap_update_bits(pdm->regmap, PDM_SYSCONFIG,
231
+ PDM_RX_CLR_MASK,
232
+ PDM_RX_CLR_WR);
224233 regmap_update_bits(pdm->regmap, PDM_DMA_CTRL,
225234 PDM_DMA_RD_MSK, PDM_DMA_RD_EN);
235
+ local_irq_restore(flags);
226236 } else {
227237 regmap_update_bits(pdm->regmap, PDM_DMA_CTRL,
228238 PDM_DMA_RD_MSK, PDM_DMA_RD_DIS);
....@@ -264,18 +274,20 @@
264274 return ret;
265275 }
266276
267
-static int rockchip_pdm_set_samplerate(struct rk_pdm_dev *pdm,
268
- unsigned int samplerate)
277
+static int rockchip_pdm_set_samplerate(struct rk_pdm_dev *pdm, unsigned int samplerate)
269278 {
270
- unsigned int clk_rate, clk_div;
271
- unsigned int clk_src, clk_out = 0;
272
- unsigned int val = 0, div = 0, rate, delta;
279
+
280
+ unsigned int val = 0, div = 0;
281
+ unsigned int clk_rate, clk_div, rate, delta;
282
+ unsigned int clk_src = 0, clk_out = 0, signoff = PDM_SIGNOFF_CLK_100M;
273283 unsigned long m, n;
274284 uint64_t ppm;
275
- int ret;
276285 bool change;
286
+ int ret;
277287
278
- clk_rate = get_pdm_clk(pdm, samplerate, &clk_src, &clk_out);
288
+ if (pdm->version == RK_PDM_RK3588)
289
+ signoff = PDM_SIGNOFF_CLK_300M;
290
+ clk_rate = get_pdm_clk(pdm, samplerate, &clk_src, &clk_out, signoff);
279291 if (!clk_rate)
280292 return -EINVAL;
281293
....@@ -312,6 +324,7 @@
312324 return ret;
313325
314326 if (pdm->version == RK_PDM_RK3308 ||
327
+ pdm->version == RK_PDM_RK3588 ||
315328 pdm->version == RK_PDM_RV1126) {
316329 rational_best_approximation(clk_out, clk_src,
317330 GENMASK(16 - 1, 0),
....@@ -341,7 +354,7 @@
341354 val);
342355 }
343356
344
- if (pdm->version == RK_PDM_RV1126) {
357
+ if (pdm->version == RK_PDM_RK3588 || pdm->version == RK_PDM_RV1126) {
345358 val = get_pdm_cic_ratio(clk_out);
346359 regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CIC_RATIO_MSK, val);
347360 val = samplerate_to_bit(samplerate);
....@@ -351,10 +364,11 @@
351364 val = get_pdm_ds_ratio(samplerate);
352365 regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_DS_RATIO_MSK, val);
353366 }
354
- regmap_update_bits(pdm->regmap, PDM_HPF_CTRL, PDM_HPF_CF_MSK, PDM_HPF_60HZ);
367
+
368
+ regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
369
+ PDM_HPF_CF_MSK, PDM_HPF_60HZ);
355370 regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
356371 PDM_HPF_LE | PDM_HPF_RE, PDM_HPF_LE | PDM_HPF_RE);
357
-
358372 return 0;
359373 }
360374
....@@ -370,7 +384,7 @@
370384
371385 rockchip_pdm_set_samplerate(pdm, params_rate(params));
372386
373
- if (pdm->version != RK_PDM_RK3328)
387
+ if (pdm->version != RK_PDM_RK3229)
374388 regmap_update_bits(pdm->regmap, PDM_CTRL0,
375389 PDM_MODE_MSK, PDM_MODE_LJ);
376390
....@@ -398,13 +412,13 @@
398412 switch (params_channels(params)) {
399413 case 8:
400414 val |= PDM_PATH3_EN;
401
- /* fallthrough */
415
+ fallthrough;
402416 case 6:
403417 val |= PDM_PATH2_EN;
404
- /* fallthrough */
418
+ fallthrough;
405419 case 4:
406420 val |= PDM_PATH1_EN;
407
- /* fallthrough */
421
+ fallthrough;
408422 case 2:
409423 val |= PDM_PATH0_EN;
410424 break;
....@@ -476,51 +490,6 @@
476490 return ret;
477491 }
478492
479
-static int rockchip_pdm_clk_compensation_info(struct snd_kcontrol *kcontrol,
480
- struct snd_ctl_elem_info *uinfo)
481
-{
482
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
483
- uinfo->count = 1;
484
- uinfo->value.integer.min = CLK_PPM_MIN;
485
- uinfo->value.integer.max = CLK_PPM_MAX;
486
- uinfo->value.integer.step = 1;
487
-
488
- return 0;
489
-}
490
-
491
-static int rockchip_pdm_clk_compensation_get(struct snd_kcontrol *kcontrol,
492
- struct snd_ctl_elem_value *ucontrol)
493
-{
494
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
495
- struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
496
-
497
- ucontrol->value.integer.value[0] = pdm->clk_ppm;
498
-
499
- return 0;
500
-}
501
-
502
-static int rockchip_pdm_clk_compensation_put(struct snd_kcontrol *kcontrol,
503
- struct snd_ctl_elem_value *ucontrol)
504
-{
505
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
506
- struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
507
- int ppm = ucontrol->value.integer.value[0];
508
-
509
- if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) ||
510
- (ucontrol->value.integer.value[0] > CLK_PPM_MAX))
511
- return -EINVAL;
512
-
513
- return rockchip_pdm_clk_set_rate(pdm, pdm->clk_root, pdm->clk_root_rate, ppm);
514
-}
515
-
516
-static struct snd_kcontrol_new rockchip_pdm_compensation_control = {
517
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
518
- .name = "PCM Clk Compensation In PPM",
519
- .info = rockchip_pdm_clk_compensation_info,
520
- .get = rockchip_pdm_clk_compensation_get,
521
- .put = rockchip_pdm_clk_compensation_put,
522
-};
523
-
524493 static int rockchip_pdm_start_delay_info(struct snd_kcontrol *kcontrol,
525494 struct snd_ctl_elem_info *uinfo)
526495 {
....@@ -531,7 +500,6 @@
531500 uinfo->value.integer.step = 1;
532501
533502 return 0;
534
-
535503 }
536504
537505 static int rockchip_pdm_start_delay_get(struct snd_kcontrol *kcontrol,
....@@ -615,16 +583,64 @@
615583 },
616584 };
617585
586
+static int rockchip_pdm_clk_compensation_info(struct snd_kcontrol *kcontrol,
587
+ struct snd_ctl_elem_info *uinfo)
588
+{
589
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
590
+ uinfo->count = 1;
591
+ uinfo->value.integer.min = CLK_PPM_MIN;
592
+ uinfo->value.integer.max = CLK_PPM_MAX;
593
+ uinfo->value.integer.step = 1;
594
+
595
+ return 0;
596
+}
597
+
598
+
599
+static int rockchip_pdm_clk_compensation_get(struct snd_kcontrol *kcontrol,
600
+ struct snd_ctl_elem_value *ucontrol)
601
+
602
+{
603
+ struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
604
+ struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
605
+
606
+ ucontrol->value.integer.value[0] = pdm->clk_ppm;
607
+
608
+ return 0;
609
+}
610
+
611
+static int rockchip_pdm_clk_compensation_put(struct snd_kcontrol *kcontrol,
612
+ struct snd_ctl_elem_value *ucontrol)
613
+{
614
+ struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
615
+ struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
616
+
617
+ int ppm = ucontrol->value.integer.value[0];
618
+
619
+ if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) ||
620
+ (ucontrol->value.integer.value[0] > CLK_PPM_MAX))
621
+ return -EINVAL;
622
+
623
+ return rockchip_pdm_clk_set_rate(pdm, pdm->clk_root, pdm->clk_root_rate, ppm);
624
+}
625
+
626
+static struct snd_kcontrol_new rockchip_pdm_compensation_control = {
627
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
628
+ .name = "PDM PCM Clk Compensation In PPM",
629
+ .info = rockchip_pdm_clk_compensation_info,
630
+ .get = rockchip_pdm_clk_compensation_get,
631
+ .put = rockchip_pdm_clk_compensation_put,
632
+
633
+};
634
+
618635 static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai)
619636 {
620637 struct rk_pdm_dev *pdm = to_info(dai);
621638
622639 dai->capture_dma_data = &pdm->capture_dma_data;
623
-
624
- if (pdm->clk_calibrate)
625
- snd_soc_add_dai_controls(dai, &rockchip_pdm_compensation_control, 1);
626640 snd_soc_add_dai_controls(dai, rockchip_pdm_controls,
627641 ARRAY_SIZE(rockchip_pdm_controls));
642
+ if (pdm->clk_calibrate)
643
+ snd_soc_add_dai_controls(dai, &rockchip_pdm_compensation_control, 1);
628644 return 0;
629645 }
630646
....@@ -735,6 +751,7 @@
735751 return ret;
736752 }
737753
754
+ rockchip_pdm_rxctrl(pdm, 0);
738755 regcache_cache_only(pdm->regmap, false);
739756 regcache_mark_dirty(pdm->regmap);
740757 ret = regcache_sync(pdm->regmap);
....@@ -831,31 +848,21 @@
831848 .cache_type = REGCACHE_FLAT,
832849 };
833850
834
-static const struct of_device_id rockchip_pdm_match[] = {
835
-#ifdef CONFIG_CPU_PX30
851
+static const struct of_device_id rockchip_pdm_match[] __maybe_unused = {
852
+ { .compatible = "rockchip,pdm",
853
+ .data = (void *)RK_PDM_RK3229 },
836854 { .compatible = "rockchip,px30-pdm",
837855 .data = (void *)RK_PDM_RK3308 },
838
-#endif
839
-#ifdef CONFIG_CPU_RK1808
840856 { .compatible = "rockchip,rk1808-pdm",
841857 .data = (void *)RK_PDM_RK3308 },
842
-#endif
843
-#ifdef CONFIG_CPU_RK3308
844858 { .compatible = "rockchip,rk3308-pdm",
845859 .data = (void *)RK_PDM_RK3308 },
846
-#endif
847
-#ifdef CONFIG_CPU_RK3328
848
- { .compatible = "rockchip,rk3328-pdm",
849
- .data = (void *)RK_PDM_RK3328 },
850
-#endif
851
-#ifdef CONFIG_CPU_RK3568
852860 { .compatible = "rockchip,rk3568-pdm",
853861 .data = (void *)RK_PDM_RV1126 },
854
-#endif
855
-#ifdef CONFIG_CPU_RV1126
862
+ { .compatible = "rockchip,rk3588-pdm",
863
+ .data = (void *)RK_PDM_RK3588 },
856864 { .compatible = "rockchip,rv1126-pdm",
857865 .data = (void *)RK_PDM_RV1126 },
858
-#endif
859866 {},
860867 };
861868 MODULE_DEVICE_TABLE(of, rockchip_pdm_match);
....@@ -910,8 +917,7 @@
910917 return PTR_ERR(pdm->reset);
911918 }
912919
913
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
914
- regs = devm_ioremap_resource(&pdev->dev, res);
920
+ regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
915921 if (IS_ERR(regs))
916922 return PTR_ERR(regs);
917923
....@@ -927,6 +933,9 @@
927933 pdm->dev = &pdev->dev;
928934 dev_set_drvdata(&pdev->dev, pdm);
929935
936
+ pdm->start_delay_ms = PDM_START_DELAY_MS_DEFAULT;
937
+ pdm->filter_delay_ms = PDM_FILTER_DELAY_MS_MIN;
938
+
930939 pdm->clk_calibrate =
931940 of_property_read_bool(node, "rockchip,mclk-calibrate");
932941 if (pdm->clk_calibrate) {
....@@ -937,9 +946,6 @@
937946 pdm->clk_root_initial_rate = clk_get_rate(pdm->clk_root);
938947 pdm->clk_root_rate = pdm->clk_root_initial_rate;
939948 }
940
-
941
- pdm->start_delay_ms = PDM_START_DELAY_MS_DEFAULT;
942
- pdm->filter_delay_ms = PDM_FILTER_DELAY_MS_MIN;
943949
944950 pdm->clk = devm_clk_get(&pdev->dev, "pdm_clk");
945951 if (IS_ERR(pdm->clk))
....@@ -976,8 +982,10 @@
976982 if (ret != 0 && ret != -ENOENT)
977983 goto err_suspend;
978984
979
- if (of_property_read_bool(node, "rockchip,no-dmaengine"))
985
+ if (of_property_read_bool(node, "rockchip,no-dmaengine")) {
986
+ dev_info(&pdev->dev, "Used for Multi-DAI\n");
980987 return 0;
988
+ }
981989
982990 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
983991 if (ret) {