forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4
kernel/sound/soc/rockchip/rockchip_i2s_tdm.c
....@@ -27,6 +27,7 @@
2727 #include <sound/dmaengine_pcm.h>
2828
2929 #include "rockchip_i2s_tdm.h"
30
+#include "rockchip_dlp.h"
3031
3132 #define DRV_NAME "rockchip-i2s-tdm"
3233
....@@ -266,7 +267,7 @@
266267 writeq(val, addr);
267268 break;
268269 }
269
- /* fallthrough */
270
+ fallthrough;
270271 default:
271272 local_irq_save(flags);
272273 writel(BIT(tx_offset) | (BIT(tx_offset) << 16),
....@@ -328,7 +329,7 @@
328329 writeq(val, addr);
329330 break;
330331 }
331
- /* fallthrough */
332
+ fallthrough;
332333 default:
333334 local_irq_save(flags);
334335 writel((BIT(tx_offset) << 16),
....@@ -395,6 +396,12 @@
395396 default:
396397 return -EINVAL;
397398 }
399
+
400
+ regmap_update_bits(i2s_tdm->regmap, I2S_CLR, clr, clr);
401
+ ret = regmap_read_poll_timeout_atomic(i2s_tdm->regmap, I2S_CLR, val,
402
+ !(val & clr), 10, 100);
403
+ if (ret == 0)
404
+ return 0;
398405
399406 /*
400407 * Workaround for FIFO clear on SLAVE mode:
....@@ -654,6 +661,19 @@
654661 case SND_SOC_DAIFMT_CBM_CFM:
655662 val = I2S_CKR_MSS_SLAVE;
656663 i2s_tdm->is_master_mode = false;
664
+ /*
665
+ * TRCM require TX/RX enabled at the same time, or need the one
666
+ * which provide clk enabled at first for master mode.
667
+ *
668
+ * It is quite a different for slave mode which does not have
669
+ * these restrictions, because the BCLK / LRCK are provided by
670
+ * external master devices.
671
+ *
672
+ * So, we just set the right clk path value on TRCM register on
673
+ * stage probe and then drop the trcm value to make TX / RX work
674
+ * independently.
675
+ */
676
+ i2s_tdm->clk_trcm = 0;
657677 break;
658678 default:
659679 ret = -EINVAL;
....@@ -924,13 +944,26 @@
924944 switch (i2s_tdm->clk_trcm) {
925945 case I2S_CKR_TRCM_TXONLY:
926946 parent = clk_get_parent(i2s_tdm->mclk_tx);
947
+ /*
948
+ * API clk_has_parent is not available yet on GKI, so we
949
+ * use clk_set_parent directly and ignore the ret value.
950
+ * if the API has addressed on GKI, should remove it.
951
+ */
952
+#ifdef CONFIG_NO_GKI
927953 if (clk_has_parent(i2s_tdm->mclk_rx, parent))
928954 ret = clk_set_parent(i2s_tdm->mclk_rx, parent);
955
+#else
956
+ clk_set_parent(i2s_tdm->mclk_rx, parent);
957
+#endif
929958 break;
930959 case I2S_CKR_TRCM_RXONLY:
931960 parent = clk_get_parent(i2s_tdm->mclk_rx);
961
+#ifdef CONFIG_NO_GKI
932962 if (clk_has_parent(i2s_tdm->mclk_tx, parent))
933963 ret = clk_set_parent(i2s_tdm->mclk_tx, parent);
964
+#else
965
+ clk_set_parent(i2s_tdm->mclk_tx, parent);
966
+#endif
934967 break;
935968 }
936969
....@@ -1789,6 +1822,12 @@
17891822 #ifdef CONFIG_CPU_RK3568
17901823 { .compatible = "rockchip,rk3568-i2s-tdm", .data = &rk3568_i2s_soc_data },
17911824 #endif
1825
+#ifdef CONFIG_CPU_RK3588
1826
+ { .compatible = "rockchip,rk3588-i2s-tdm", },
1827
+#endif
1828
+#ifdef CONFIG_CPU_RV1106
1829
+ { .compatible = "rockchip,rv1106-i2s-tdm", },
1830
+#endif
17921831 #ifdef CONFIG_CPU_RV1126
17931832 { .compatible = "rockchip,rv1126-i2s-tdm", .data = &rv1126_i2s_soc_data },
17941833 #endif
....@@ -1998,6 +2037,28 @@
19982037 return rockchip_i2s_tdm_path_prepare(i2s_tdm, np, 1);
19992038 }
20002039
2040
+static int rockchip_i2s_tdm_get_fifo_count(struct device *dev, int stream)
2041
+{
2042
+ struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(dev);
2043
+ int val = 0;
2044
+
2045
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2046
+ regmap_read(i2s_tdm->regmap, I2S_TXFIFOLR, &val);
2047
+ else
2048
+ regmap_read(i2s_tdm->regmap, I2S_RXFIFOLR, &val);
2049
+
2050
+ val = ((val & I2S_FIFOLR_TFL3_MASK) >> I2S_FIFOLR_TFL3_SHIFT) +
2051
+ ((val & I2S_FIFOLR_TFL2_MASK) >> I2S_FIFOLR_TFL2_SHIFT) +
2052
+ ((val & I2S_FIFOLR_TFL1_MASK) >> I2S_FIFOLR_TFL1_SHIFT) +
2053
+ ((val & I2S_FIFOLR_TFL0_MASK) >> I2S_FIFOLR_TFL0_SHIFT);
2054
+
2055
+ return val;
2056
+}
2057
+
2058
+static const struct snd_dlp_config dconfig = {
2059
+ .get_fifo_count = rockchip_i2s_tdm_get_fifo_count,
2060
+};
2061
+
20012062 static irqreturn_t rockchip_i2s_tdm_isr(int irq, void *devid)
20022063 {
20032064 struct rk_i2s_tdm_dev *i2s_tdm = (struct rk_i2s_tdm_dev *)devid;
....@@ -2050,7 +2111,7 @@
20502111 i2s_tdm->dev = &pdev->dev;
20512112
20522113 of_id = of_match_device(rockchip_i2s_tdm_match, &pdev->dev);
2053
- if (!of_id || !of_id->data)
2114
+ if (!of_id)
20542115 return -EINVAL;
20552116
20562117 spin_lock_init(&i2s_tdm->lock);
....@@ -2170,7 +2231,7 @@
21702231 if (IS_ERR(i2s_tdm->regmap))
21712232 return PTR_ERR(i2s_tdm->regmap);
21722233
2173
- irq = platform_get_irq(pdev, 0);
2234
+ irq = platform_get_irq_optional(pdev, 0);
21742235 if (irq > 0) {
21752236 ret = devm_request_irq(&pdev->dev, irq, rockchip_i2s_tdm_isr,
21762237 IRQF_SHARED, node->name, i2s_tdm);
....@@ -2264,7 +2325,11 @@
22642325 return 0;
22652326 }
22662327
2267
- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
2328
+ if (of_property_read_bool(node, "rockchip,digital-loopback"))
2329
+ ret = devm_snd_dmaengine_dlp_register(&pdev->dev, &dconfig);
2330
+ else
2331
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
2332
+
22682333 if (ret) {
22692334 dev_err(&pdev->dev, "Could not register PCM\n");
22702335 return ret;