forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/sound/soc/rockchip/rockchip_pdm.c
....@@ -10,6 +10,7 @@
1010 #include <linux/clk/rockchip.h>
1111 #include <linux/of.h>
1212 #include <linux/of_device.h>
13
+#include <linux/pinctrl/consumer.h>
1314 #include <linux/pm_runtime.h>
1415 #include <linux/rational.h>
1516 #include <linux/regmap.h>
....@@ -30,8 +31,10 @@
3031 #define PDM_FILTER_DELAY_MS_MIN (20)
3132 #define PDM_FILTER_DELAY_MS_MAX (1000)
3233 #define PDM_CLK_SHIFT_PPM_MAX (1000000) /* 1 ppm */
33
-#define CLK_PPM_MIN (-1000)
34
-#define CLK_PPM_MAX (1000)
34
+#define CLK_PPM_MIN (-1000)
35
+#define CLK_PPM_MAX (1000)
36
+
37
+#define QUIRK_ALWAYS_ON BIT(0)
3538
3639 enum rk_pdm_version {
3740 RK_PDM_RK3229,
....@@ -48,11 +51,14 @@
4851 struct regmap *regmap;
4952 struct snd_dmaengine_dai_dma_data capture_dma_data;
5053 struct reset_control *reset;
54
+ struct pinctrl *pinctrl;
55
+ struct pinctrl_state *clk_state;
5156 unsigned int start_delay_ms;
5257 unsigned int filter_delay_ms;
5358 enum rk_pdm_version version;
5459 unsigned int clk_root_rate;
5560 unsigned int clk_root_initial_rate;
61
+ unsigned int quirks;
5662 int clk_ppm;
5763 bool clk_calibrate;
5864 };
....@@ -92,6 +98,16 @@
9298 { 4, 12000 },
9399 { 4, 11025 },
94100 { 4, 8000 },
101
+};
102
+
103
+static const struct pdm_of_quirks {
104
+ char *quirk;
105
+ int id;
106
+} of_quirks[] = {
107
+ {
108
+ .quirk = "rockchip,always-on",
109
+ .id = QUIRK_ALWAYS_ON,
110
+ },
95111 };
96112
97113 static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr,
....@@ -505,8 +521,8 @@
505521 static int rockchip_pdm_start_delay_get(struct snd_kcontrol *kcontrol,
506522 struct snd_ctl_elem_value *ucontrol)
507523 {
508
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
509
- struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
524
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
525
+ struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component);
510526
511527 ucontrol->value.integer.value[0] = pdm->start_delay_ms;
512528
....@@ -516,8 +532,8 @@
516532 static int rockchip_pdm_start_delay_put(struct snd_kcontrol *kcontrol,
517533 struct snd_ctl_elem_value *ucontrol)
518534 {
519
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
520
- struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
535
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
536
+ struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component);
521537
522538 if ((ucontrol->value.integer.value[0] < PDM_START_DELAY_MS_MIN) ||
523539 (ucontrol->value.integer.value[0] > PDM_START_DELAY_MS_MAX))
....@@ -543,8 +559,8 @@
543559 static int rockchip_pdm_filter_delay_get(struct snd_kcontrol *kcontrol,
544560 struct snd_ctl_elem_value *ucontrol)
545561 {
546
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
547
- struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
562
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
563
+ struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component);
548564
549565 ucontrol->value.integer.value[0] = pdm->filter_delay_ms;
550566
....@@ -554,8 +570,8 @@
554570 static int rockchip_pdm_filter_delay_put(struct snd_kcontrol *kcontrol,
555571 struct snd_ctl_elem_value *ucontrol)
556572 {
557
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
558
- struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
573
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
574
+ struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component);
559575
560576 if ((ucontrol->value.integer.value[0] < PDM_FILTER_DELAY_MS_MIN) ||
561577 (ucontrol->value.integer.value[0] > PDM_FILTER_DELAY_MS_MAX))
....@@ -566,7 +582,31 @@
566582 return 1;
567583 }
568584
585
+static const char * const rpaths_text[] = {
586
+ "From SDI0", "From SDI1", "From SDI2", "From SDI3" };
587
+
588
+static SOC_ENUM_SINGLE_DECL(rpath3_enum, PDM_CLK_CTRL, 14, rpaths_text);
589
+static SOC_ENUM_SINGLE_DECL(rpath2_enum, PDM_CLK_CTRL, 12, rpaths_text);
590
+static SOC_ENUM_SINGLE_DECL(rpath1_enum, PDM_CLK_CTRL, 10, rpaths_text);
591
+static SOC_ENUM_SINGLE_DECL(rpath0_enum, PDM_CLK_CTRL, 8, rpaths_text);
592
+
593
+static const char * const hpf_cutoff_text[] = {
594
+ "3.79Hz", "60Hz", "243Hz", "493Hz",
595
+};
596
+
597
+static SOC_ENUM_SINGLE_DECL(hpf_cutoff_enum, PDM_HPF_CTRL,
598
+ 0, hpf_cutoff_text);
599
+
569600 static const struct snd_kcontrol_new rockchip_pdm_controls[] = {
601
+ SOC_ENUM("Receive PATH3 Source Select", rpath3_enum),
602
+ SOC_ENUM("Receive PATH2 Source Select", rpath2_enum),
603
+ SOC_ENUM("Receive PATH1 Source Select", rpath1_enum),
604
+ SOC_ENUM("Receive PATH0 Source Select", rpath0_enum),
605
+
606
+ SOC_ENUM("HPF Cutoff", hpf_cutoff_enum),
607
+ SOC_SINGLE("HPFL Switch", PDM_HPF_CTRL, 3, 1, 0),
608
+ SOC_SINGLE("HPFR Switch", PDM_HPF_CTRL, 2, 1, 0),
609
+
570610 {
571611 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
572612 .name = "PDM Start Delay Ms",
....@@ -600,8 +640,8 @@
600640 struct snd_ctl_elem_value *ucontrol)
601641
602642 {
603
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
604
- struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
643
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
644
+ struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component);
605645
606646 ucontrol->value.integer.value[0] = pdm->clk_ppm;
607647
....@@ -611,8 +651,8 @@
611651 static int rockchip_pdm_clk_compensation_put(struct snd_kcontrol *kcontrol,
612652 struct snd_ctl_elem_value *ucontrol)
613653 {
614
- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
615
- struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
654
+ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
655
+ struct rk_pdm_dev *pdm = snd_soc_component_get_drvdata(component);
616656
617657 int ppm = ucontrol->value.integer.value[0];
618658
....@@ -637,10 +677,12 @@
637677 struct rk_pdm_dev *pdm = to_info(dai);
638678
639679 dai->capture_dma_data = &pdm->capture_dma_data;
640
- snd_soc_add_dai_controls(dai, rockchip_pdm_controls,
641
- ARRAY_SIZE(rockchip_pdm_controls));
680
+
642681 if (pdm->clk_calibrate)
643
- snd_soc_add_dai_controls(dai, &rockchip_pdm_compensation_control, 1);
682
+ snd_soc_add_component_controls(dai->component,
683
+ &rockchip_pdm_compensation_control,
684
+ 1);
685
+
644686 return 0;
645687 }
646688
....@@ -721,7 +763,34 @@
721763
722764 static const struct snd_soc_component_driver rockchip_pdm_component = {
723765 .name = "rockchip-pdm",
766
+ .controls = rockchip_pdm_controls,
767
+ .num_controls = ARRAY_SIZE(rockchip_pdm_controls),
724768 };
769
+
770
+static int rockchip_pdm_pinctrl_select_clk_state(struct device *dev)
771
+{
772
+ struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
773
+
774
+ if (IS_ERR_OR_NULL(pdm->pinctrl) || !pdm->clk_state)
775
+ return 0;
776
+
777
+ /*
778
+ * A necessary delay to make sure the correct
779
+ * frac div has been applied when resume from
780
+ * power down.
781
+ */
782
+ udelay(10);
783
+
784
+ /*
785
+ * Must disable the clk to avoid clk glitch
786
+ * when pinctrl switch from gpio to pdm clk.
787
+ */
788
+ clk_disable_unprepare(pdm->clk);
789
+ pinctrl_select_state(pdm->pinctrl, pdm->clk_state);
790
+ clk_prepare_enable(pdm->clk);
791
+
792
+ return 0;
793
+}
725794
726795 static int rockchip_pdm_runtime_suspend(struct device *dev)
727796 {
....@@ -730,6 +799,8 @@
730799 regcache_cache_only(pdm->regmap, true);
731800 clk_disable_unprepare(pdm->clk);
732801 clk_disable_unprepare(pdm->hclk);
802
+
803
+ pinctrl_pm_select_idle_state(dev);
733804
734805 return 0;
735806 }
....@@ -740,26 +811,31 @@
740811 int ret;
741812
742813 ret = clk_prepare_enable(pdm->clk);
743
- if (ret) {
744
- dev_err(pdm->dev, "clock enable failed %d\n", ret);
745
- return ret;
746
- }
814
+ if (ret)
815
+ goto err_clk;
747816
748817 ret = clk_prepare_enable(pdm->hclk);
749
- if (ret) {
750
- dev_err(pdm->dev, "hclock enable failed %d\n", ret);
751
- return ret;
752
- }
818
+ if (ret)
819
+ goto err_hclk;
753820
754
- rockchip_pdm_rxctrl(pdm, 0);
755821 regcache_cache_only(pdm->regmap, false);
756822 regcache_mark_dirty(pdm->regmap);
757823 ret = regcache_sync(pdm->regmap);
758
- if (ret) {
759
- clk_disable_unprepare(pdm->clk);
760
- clk_disable_unprepare(pdm->hclk);
761
- }
824
+ if (ret)
825
+ goto err_regmap;
826
+
827
+ rockchip_pdm_rxctrl(pdm, 0);
828
+
829
+ rockchip_pdm_pinctrl_select_clk_state(dev);
830
+
762831 return 0;
832
+
833
+err_regmap:
834
+ clk_disable_unprepare(pdm->hclk);
835
+err_hclk:
836
+ clk_disable_unprepare(pdm->clk);
837
+err_clk:
838
+ return ret;
763839 }
764840
765841 static bool rockchip_pdm_wr_reg(struct device *dev, unsigned int reg)
....@@ -894,6 +970,29 @@
894970 return 0;
895971 }
896972
973
+static int rockchip_pdm_keep_clk_always_on(struct rk_pdm_dev *pdm)
974
+{
975
+ pm_runtime_forbid(pdm->dev);
976
+
977
+ dev_info(pdm->dev, "CLK-ALWAYS-ON: samplerate: %d\n", PDM_DEFAULT_RATE);
978
+
979
+ return 0;
980
+}
981
+
982
+static int rockchip_pdm_parse_quirks(struct rk_pdm_dev *pdm)
983
+{
984
+ int ret = 0, i = 0;
985
+
986
+ for (i = 0; i < ARRAY_SIZE(of_quirks); i++)
987
+ if (device_property_read_bool(pdm->dev, of_quirks[i].quirk))
988
+ pdm->quirks |= of_quirks[i].id;
989
+
990
+ if (pdm->quirks & QUIRK_ALWAYS_ON)
991
+ ret = rockchip_pdm_keep_clk_always_on(pdm);
992
+
993
+ return ret;
994
+}
995
+
897996 static int rockchip_pdm_probe(struct platform_device *pdev)
898997 {
899998 struct device_node *node = pdev->dev.of_node;
....@@ -933,6 +1032,15 @@
9331032 pdm->dev = &pdev->dev;
9341033 dev_set_drvdata(&pdev->dev, pdm);
9351034
1035
+ pdm->pinctrl = devm_pinctrl_get(&pdev->dev);
1036
+ if (!IS_ERR_OR_NULL(pdm->pinctrl)) {
1037
+ pdm->clk_state = pinctrl_lookup_state(pdm->pinctrl, "clk");
1038
+ if (IS_ERR(pdm->clk_state)) {
1039
+ pdm->clk_state = NULL;
1040
+ dev_dbg(pdm->dev, "Have no clk pinctrl state\n");
1041
+ }
1042
+ }
1043
+
9361044 pdm->start_delay_ms = PDM_START_DELAY_MS_DEFAULT;
9371045 pdm->filter_delay_ms = PDM_FILTER_DELAY_MS_MIN;
9381046
....@@ -959,6 +1067,27 @@
9591067 if (ret)
9601068 return ret;
9611069
1070
+ rockchip_pdm_set_samplerate(pdm, PDM_DEFAULT_RATE);
1071
+ rockchip_pdm_rxctrl(pdm, 0);
1072
+
1073
+ ret = rockchip_pdm_path_parse(pdm, node);
1074
+ if (ret != 0 && ret != -ENOENT)
1075
+ goto err_clk;
1076
+
1077
+ ret = rockchip_pdm_parse_quirks(pdm);
1078
+ if (ret)
1079
+ goto err_clk;
1080
+
1081
+ /*
1082
+ * MUST: after pm_runtime_enable step, any register R/W
1083
+ * should be wrapped with pm_runtime_get_sync/put.
1084
+ *
1085
+ * Another approach is to enable the regcache true to
1086
+ * avoid access HW registers.
1087
+ *
1088
+ * Alternatively, performing the registers R/W before
1089
+ * pm_runtime_enable is also a good option.
1090
+ */
9621091 pm_runtime_enable(&pdev->dev);
9631092 if (!pm_runtime_enabled(&pdev->dev)) {
9641093 ret = rockchip_pdm_runtime_resume(&pdev->dev);
....@@ -975,13 +1104,6 @@
9751104 goto err_suspend;
9761105 }
9771106
978
- rockchip_pdm_set_samplerate(pdm, PDM_DEFAULT_RATE);
979
- rockchip_pdm_rxctrl(pdm, 0);
980
-
981
- ret = rockchip_pdm_path_parse(pdm, node);
982
- if (ret != 0 && ret != -ENOENT)
983
- goto err_suspend;
984
-
9851107 if (of_property_read_bool(node, "rockchip,no-dmaengine")) {
9861108 dev_info(&pdev->dev, "Used for Multi-DAI\n");
9871109 return 0;
....@@ -993,6 +1115,8 @@
9931115 goto err_suspend;
9941116 }
9951117
1118
+ clk_disable_unprepare(pdm->hclk);
1119
+
9961120 return 0;
9971121
9981122 err_suspend:
....@@ -1000,7 +1124,7 @@
10001124 rockchip_pdm_runtime_suspend(&pdev->dev);
10011125 err_pm_disable:
10021126 pm_runtime_disable(&pdev->dev);
1003
-
1127
+err_clk:
10041128 clk_disable_unprepare(pdm->hclk);
10051129
10061130 return ret;
....@@ -1008,14 +1132,9 @@
10081132
10091133 static int rockchip_pdm_remove(struct platform_device *pdev)
10101134 {
1011
- struct rk_pdm_dev *pdm = dev_get_drvdata(&pdev->dev);
1012
-
10131135 pm_runtime_disable(&pdev->dev);
10141136 if (!pm_runtime_status_suspended(&pdev->dev))
10151137 rockchip_pdm_runtime_suspend(&pdev->dev);
1016
-
1017
- clk_disable_unprepare(pdm->clk);
1018
- clk_disable_unprepare(pdm->hclk);
10191138
10201139 return 0;
10211140 }