[PATCH v2 0/15] Patches to update for rockchip i2s

These patches fixup or update for rockchip i2s.
Changes in v2: - split property trcm into single 'trcm-sync-tx-only' and 'trcm-sync-rx-only' suggested by Nicolas. - split property trcm into single 'trcm-sync-tx-only' and 'trcm-sync-rx-only' suggested by Nicolas. - drop change-id
Sugar Zhang (13): ASoC: rockchip: i2s: Add support for set bclk ratio ASoC: rockchip: i2s: Fixup clk div error ASoC: rockchip: i2s: Improve dma data transfer efficiency ASoC: rockchip: i2s: Fix regmap_ops hang ASoC: rockchip: i2s: Fix concurrency between tx/rx ASoC: rockchip: i2s: Reset the controller if soft reset failed ASoC: dt-bindings: rockchip: Document reset property for i2s ASoC: rockchip: i2s: Add property to specify play/cap capability ASoC: dt-bindings: rockchip: i2s: Document property for playback/capture ASoC: rockchip: i2s: Add compatible for more SoCs ASoC: dt-bindings: rockchip: Add compatible strings for more SoCs ASoC: rockchip: i2s: Add support for frame inversion ASoC: dt-bindings: rockchip: i2s: Document property TRCM
Xiaotan Luo (1): ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B
Xing Zheng (1): ASoC: rockchip: i2s: Add support for TRCM property
.../devicetree/bindings/sound/rockchip-i2s.yaml | 29 ++++ sound/soc/rockchip/rockchip_i2s.c | 161 +++++++++++++++++---- sound/soc/rockchip/rockchip_i2s.h | 10 +- 3 files changed, 164 insertions(+), 36 deletions(-)

This patch adds support for set bclk ratio from machine driver.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index c7dc350..c9d5c52 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -49,6 +49,7 @@ struct rk_i2s_dev { bool rx_start; bool is_master_mode; const struct rk_i2s_pins *pins; + unsigned int bclk_ratio; };
static int i2s_runtime_suspend(struct device *dev) @@ -278,7 +279,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
if (i2s->is_master_mode) { mclk_rate = clk_get_rate(i2s->mclk); - bclk_rate = 2 * 32 * params_rate(params); + bclk_rate = i2s->bclk_ratio * params_rate(params); if (bclk_rate == 0 || mclk_rate % bclk_rate) return -EINVAL;
@@ -413,6 +414,16 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, return ret; }
+static int rockchip_i2s_set_bclk_ratio(struct snd_soc_dai *dai, + unsigned int ratio) +{ + struct rk_i2s_dev *i2s = to_info(dai); + + i2s->bclk_ratio = ratio; + + return 0; +} + static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { @@ -441,6 +452,7 @@ static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)
static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { .hw_params = rockchip_i2s_hw_params, + .set_bclk_ratio = rockchip_i2s_set_bclk_ratio, .set_sysclk = rockchip_i2s_set_sysclk, .set_fmt = rockchip_i2s_set_fmt, .trigger = rockchip_i2s_trigger, @@ -638,6 +650,8 @@ static int rockchip_i2s_probe(struct platform_device *pdev) i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; i2s->capture_dma_data.maxburst = 4;
+ i2s->bclk_ratio = 64; + dev_set_drvdata(&pdev->dev, i2s);
pm_runtime_enable(&pdev->dev);

MCLK maybe not precise as required because of PLL, but which still can be used and no side effect. so, using DIV_ROUND_CLOSEST instead div.
e.g.
set mclk to 11289600 Hz, but get 11289598 Hz.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index c9d5c52..05fce2c 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -280,10 +280,10 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, if (i2s->is_master_mode) { mclk_rate = clk_get_rate(i2s->mclk); bclk_rate = i2s->bclk_ratio * params_rate(params); - if (bclk_rate == 0 || mclk_rate % bclk_rate) + if (!bclk_rate) return -EINVAL;
- div_bclk = mclk_rate / bclk_rate; + div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); div_lrck = bclk_rate / params_rate(params); regmap_update_bits(i2s->regmap, I2S_CKR, I2S_CKR_MDIV_MASK,

This patch changes dma data burst from 4 to 8 to improve data transfer efficiency.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 05fce2c..2e0047d 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -644,11 +644,11 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
i2s->playback_dma_data.addr = res->start + I2S_TXDR; i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - i2s->playback_dma_data.maxburst = 4; + i2s->playback_dma_data.maxburst = 8;
i2s->capture_dma_data.addr = res->start + I2S_RXDR; i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - i2s->capture_dma_data.maxburst = 4; + i2s->capture_dma_data.maxburst = 8;
i2s->bclk_ratio = 64;

API 'set_fmt' maybe called when PD is off, in the situation, any register access will hang the system. so, enable PD before r/w register.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 2e0047d..90877e8 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -187,7 +187,9 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, { struct rk_i2s_dev *i2s = to_info(cpu_dai); unsigned int mask = 0, val = 0; + int ret = 0;
+ pm_runtime_get_sync(cpu_dai->dev); mask = I2S_CKR_MSS_MASK; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: @@ -200,7 +202,8 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, i2s->is_master_mode = false; break; default: - return -EINVAL; + ret = -EINVAL; + goto err_pm_put; }
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val); @@ -214,7 +217,8 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, val = I2S_CKR_CKP_POS; break; default: - return -EINVAL; + ret = -EINVAL; + goto err_pm_put; }
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val); @@ -237,7 +241,8 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1); break; default: - return -EINVAL; + ret = -EINVAL; + goto err_pm_put; }
regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val); @@ -260,12 +265,16 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1); break; default: - return -EINVAL; + ret = -EINVAL; + goto err_pm_put; }
regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
- return 0; +err_pm_put: + pm_runtime_put(cpu_dai->dev); + + return ret; }
static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,

This patch adds lock to fix comcurrency between tx/rx to fix 'rockchip-i2s ff070000.i2s; fail to clear'
Considering the situation;
tx stream rx stream | | | disable enable | | reset
After this patch:
lock | tx stream | enable | unlock -------- --------- lock | rx stream | disable | reset | unlock
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 90877e8..0ba728f 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -15,6 +15,7 @@ #include <linux/clk.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/spinlock.h> #include <sound/pcm_params.h> #include <sound/dmaengine_pcm.h>
@@ -52,6 +53,9 @@ struct rk_i2s_dev { unsigned int bclk_ratio; };
+/* tx/rx ctrl lock */ +static DEFINE_SPINLOCK(lock); + static int i2s_runtime_suspend(struct device *dev) { struct rk_i2s_dev *i2s = dev_get_drvdata(dev); @@ -93,6 +97,7 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) unsigned int val = 0; int retry = 10;
+ spin_lock(&lock); if (on) { regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); @@ -133,6 +138,7 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) } } } + spin_unlock(&lock); }
static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) @@ -140,6 +146,7 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) unsigned int val = 0; int retry = 10;
+ spin_lock(&lock); if (on) { regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); @@ -180,6 +187,7 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) } } } + spin_unlock(&lock); }
static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,

This patch brings i2s back to normal by resetting i2s m/h when the soft reset failed.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 0ba728f..78321ee 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -15,6 +15,7 @@ #include <linux/clk.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/reset.h> #include <linux/spinlock.h> #include <sound/pcm_params.h> #include <sound/dmaengine_pcm.h> @@ -40,6 +41,8 @@ struct rk_i2s_dev {
struct regmap *regmap; struct regmap *grf; + struct reset_control *reset_m; + struct reset_control *reset_h;
/* * Used to indicate the tx/rx status. @@ -92,6 +95,20 @@ static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai) return snd_soc_dai_get_drvdata(dai); }
+static void rockchip_i2s_reset(struct rk_i2s_dev *i2s) +{ + dev_warn(i2s->dev, "Reset controller.\n"); + + reset_control_assert(i2s->reset_m); + reset_control_assert(i2s->reset_h); + udelay(1); + reset_control_deassert(i2s->reset_m); + reset_control_deassert(i2s->reset_h); + + regcache_mark_dirty(i2s->regmap); + regcache_sync(i2s->regmap); +} + static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) { unsigned int val = 0; @@ -132,7 +149,7 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) regmap_read(i2s->regmap, I2S_CLR, &val); retry--; if (!retry) { - dev_warn(i2s->dev, "fail to clear\n"); + rockchip_i2s_reset(i2s); break; } } @@ -181,7 +198,7 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) regmap_read(i2s->regmap, I2S_CLR, &val); retry--; if (!retry) { - dev_warn(i2s->dev, "fail to clear\n"); + rockchip_i2s_reset(i2s); break; } } @@ -629,6 +646,14 @@ static int rockchip_i2s_probe(struct platform_device *pdev) i2s->pins = of_id->data; }
+ i2s->reset_m = devm_reset_control_get_optional(&pdev->dev, "reset-m"); + if (IS_ERR(i2s->reset_m)) + return PTR_ERR(i2s->reset_m); + + i2s->reset_h = devm_reset_control_get_optional(&pdev->dev, "reset-h"); + if (IS_ERR(i2s->reset_h)) + return PTR_ERR(i2s->reset_h); + /* try to prepare related clocks */ i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk"); if (IS_ERR(i2s->hclk)) {

This patch documents reset property for i2s.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml index 245895b..9f9cc48 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml @@ -61,6 +61,14 @@ properties: power-domains: maxItems: 1
+ reset-names: + items: + - const: reset-m + - const: reset-h + + resets: + maxItems: 2 + rockchip,capture-channels: $ref: /schemas/types.yaml#/definitions/uint32 default: 2

On Tue, 24 Aug 2021 17:17:54 +0800, Sugar Zhang wrote:
This patch documents reset property for i2s.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com
Changes in v2: None
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 8 ++++++++ 1 file changed, 8 insertions(+)
Reviewed-by: Rob Herring robh@kernel.org

From: Xiaotan Luo lxt@rock-chips.com
- DSP_A: PCM delay 1 bit mode, L data MSB after FRM LRC - DSP_B: PCM no delay mode, L data MSB during FRM LRC
Signed-off-by: Xiaotan Luo lxt@rock-chips.com Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 78321ee..15e2690 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -259,12 +259,12 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, case SND_SOC_DAIFMT_I2S: val = I2S_TXCR_IBM_NORMAL; break; - case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ - val = I2S_TXCR_TFS_PCM; - break; - case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ + case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */ val = I2S_TXCR_TFS_PCM | I2S_TXCR_PBM_MODE(1); break; + case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */ + val = I2S_TXCR_TFS_PCM; + break; default: ret = -EINVAL; goto err_pm_put; @@ -283,12 +283,12 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, case SND_SOC_DAIFMT_I2S: val = I2S_RXCR_IBM_NORMAL; break; - case SND_SOC_DAIFMT_DSP_A: /* PCM no delay mode */ - val = I2S_RXCR_TFS_PCM; - break; - case SND_SOC_DAIFMT_DSP_B: /* PCM delay 1 mode */ + case SND_SOC_DAIFMT_DSP_A: /* PCM delay 1 bit mode */ val = I2S_RXCR_TFS_PCM | I2S_RXCR_PBM_MODE(1); break; + case SND_SOC_DAIFMT_DSP_B: /* PCM no delay mode */ + val = I2S_RXCR_TFS_PCM; + break; default: ret = -EINVAL; goto err_pm_put;

- 'rockchip,playback-only': support playback only. - 'rockchip,capture-only': support capture only.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 15e2690..90580dc 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -720,6 +720,11 @@ static int rockchip_i2s_probe(struct platform_device *pdev) soc_dai->capture.channels_max = val; }
+ if (of_property_read_bool(node, "rockchip,playback-only")) + soc_dai->capture.channels_min = 0; + else if (of_property_read_bool(node, "rockchip,capture-only")) + soc_dai->playback.channels_min = 0; + ret = devm_snd_soc_register_component(&pdev->dev, &rockchip_i2s_component, soc_dai, 1);

This patch documents property for playback-only and capture-only.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml index 9f9cc48..005b6e6 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml @@ -81,6 +81,16 @@ properties: description: Max playback channels, if not set, 8 channels default.
+ rockchip,capture-only: + type: boolean + description: + Specify that the controller has capture only capability. + + rockchip,playback-only: + type: boolean + description: + Specify that the controller has playback only capability. + rockchip,grf: $ref: /schemas/types.yaml#/definitions/phandle description:

On Tue, Aug 24, 2021 at 05:17:57PM +0800, Sugar Zhang wrote:
This patch documents property for playback-only and capture-only.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com
Changes in v2: None
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml index 9f9cc48..005b6e6 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml @@ -81,6 +81,16 @@ properties: description: Max playback channels, if not set, 8 channels default.
- rockchip,capture-only:
- type: boolean
- description:
Specify that the controller has capture only capability.
- rockchip,playback-only:
- type: boolean
- description:
Specify that the controller has playback only capability.
In the Rockchip TDM-I2S binding[1], these were dropped. Perhaps comment there why they are needed.
Rob
[1] https://lore.kernel.org/lkml/20210820182731.29370-1-frattaroli.nicolas@gmail...

Hi Rob,
On 2021/8/25 1:06, Rob Herring wrote:
On Tue, Aug 24, 2021 at 05:17:57PM +0800, Sugar Zhang wrote:
This patch documents property for playback-only and capture-only.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com
Changes in v2: None
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml index 9f9cc48..005b6e6 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml @@ -81,6 +81,16 @@ properties: description: Max playback channels, if not set, 8 channels default.
- rockchip,capture-only:
- type: boolean
- description:
Specify that the controller has capture only capability.
- rockchip,playback-only:
- type: boolean
- description:
Specify that the controller has playback only capability.
In the Rockchip TDM-I2S binding[1], these were dropped. Perhaps comment there why they are needed.
It was used to specify the controller capatiblity, some controller has capture or playback only.
maybe we can implement it by judge property 'dma-names'. such as:
of_property_for_each_string(np, "dma-names", dma_names, name)
if (!strcmp(name, "tx"))
has capture capability...
if (!strcmp(name, "rx"))
has capture capability...
will do in v3.
Rob
[1] https://lore.kernel.org/lkml/20210820182731.29370-1-frattaroli.nicolas@gmail...

This patch adds more compatible strings for SoCs.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 90580dc..8898ba4 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -613,10 +613,20 @@ static const struct rk_i2s_pins rk3399_i2s_pins = { };
static const struct of_device_id rockchip_i2s_match[] __maybe_unused = { + { .compatible = "rockchip,px30-i2s", }, + { .compatible = "rockchip,rk1808-i2s", }, + { .compatible = "rockchip,rk3036-i2s", }, { .compatible = "rockchip,rk3066-i2s", }, + { .compatible = "rockchip,rk3128-i2s", }, { .compatible = "rockchip,rk3188-i2s", }, + { .compatible = "rockchip,rk3228-i2s", }, { .compatible = "rockchip,rk3288-i2s", }, + { .compatible = "rockchip,rk3308-i2s", }, + { .compatible = "rockchip,rk3328-i2s", }, + { .compatible = "rockchip,rk3366-i2s", }, + { .compatible = "rockchip,rk3368-i2s", }, { .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins }, + { .compatible = "rockchip,rv1126-i2s", }, {}, };

This patch adds compatible strings for more SoCs.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml index 005b6e6..11e911a 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml @@ -20,7 +20,9 @@ properties: - items: - enum: - rockchip,px30-i2s + - rockchip,rk1808-i2s - rockchip,rk3036-i2s + - rockchip,rk3128-i2s - rockchip,rk3188-i2s - rockchip,rk3228-i2s - rockchip,rk3288-i2s @@ -29,6 +31,7 @@ properties: - rockchip,rk3366-i2s - rockchip,rk3368-i2s - rockchip,rk3399-i2s + - rockchip,rv1126-i2s - const: rockchip,rk3066-i2s
reg:

On Tue, 24 Aug 2021 17:18:51 +0800, Sugar Zhang wrote:
This patch adds compatible strings for more SoCs.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com
Changes in v2: None
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 3 +++ 1 file changed, 3 insertions(+)
Acked-by: Rob Herring robh@kernel.org

This patch adds support for frame inversion.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: None
sound/soc/rockchip/rockchip_i2s.c | 20 +++++++++++++++++--- sound/soc/rockchip/rockchip_i2s.h | 10 ++++++---- 2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 8898ba4..84884ce 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -233,13 +233,27 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
- mask = I2S_CKR_CKP_MASK; + mask = I2S_CKR_CKP_MASK | I2S_CKR_TLP_MASK | I2S_CKR_RLP_MASK; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: - val = I2S_CKR_CKP_NEG; + val = I2S_CKR_CKP_NORMAL | + I2S_CKR_TLP_NORMAL | + I2S_CKR_RLP_NORMAL; + break; + case SND_SOC_DAIFMT_NB_IF: + val = I2S_CKR_CKP_NORMAL | + I2S_CKR_TLP_INVERTED | + I2S_CKR_RLP_INVERTED; break; case SND_SOC_DAIFMT_IB_NF: - val = I2S_CKR_CKP_POS; + val = I2S_CKR_CKP_INVERTED | + I2S_CKR_TLP_NORMAL | + I2S_CKR_RLP_NORMAL; + break; + case SND_SOC_DAIFMT_IB_IF: + val = I2S_CKR_CKP_INVERTED | + I2S_CKR_TLP_INVERTED | + I2S_CKR_RLP_INVERTED; break; default: ret = -EINVAL; diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h index fcaae24..251851b 100644 --- a/sound/soc/rockchip/rockchip_i2s.h +++ b/sound/soc/rockchip/rockchip_i2s.h @@ -88,15 +88,17 @@ #define I2S_CKR_MSS_SLAVE (1 << I2S_CKR_MSS_SHIFT) #define I2S_CKR_MSS_MASK (1 << I2S_CKR_MSS_SHIFT) #define I2S_CKR_CKP_SHIFT 26 -#define I2S_CKR_CKP_NEG (0 << I2S_CKR_CKP_SHIFT) -#define I2S_CKR_CKP_POS (1 << I2S_CKR_CKP_SHIFT) +#define I2S_CKR_CKP_NORMAL (0 << I2S_CKR_CKP_SHIFT) +#define I2S_CKR_CKP_INVERTED (1 << I2S_CKR_CKP_SHIFT) #define I2S_CKR_CKP_MASK (1 << I2S_CKR_CKP_SHIFT) #define I2S_CKR_RLP_SHIFT 25 #define I2S_CKR_RLP_NORMAL (0 << I2S_CKR_RLP_SHIFT) -#define I2S_CKR_RLP_OPPSITE (1 << I2S_CKR_RLP_SHIFT) +#define I2S_CKR_RLP_INVERTED (1 << I2S_CKR_RLP_SHIFT) +#define I2S_CKR_RLP_MASK (1 << I2S_CKR_RLP_SHIFT) #define I2S_CKR_TLP_SHIFT 24 #define I2S_CKR_TLP_NORMAL (0 << I2S_CKR_TLP_SHIFT) -#define I2S_CKR_TLP_OPPSITE (1 << I2S_CKR_TLP_SHIFT) +#define I2S_CKR_TLP_INVERTED (1 << I2S_CKR_TLP_SHIFT) +#define I2S_CKR_TLP_MASK (1 << I2S_CKR_TLP_SHIFT) #define I2S_CKR_MDIV_SHIFT 16 #define I2S_CKR_MDIV(x) ((x - 1) << I2S_CKR_MDIV_SHIFT) #define I2S_CKR_MDIV_MASK (0xff << I2S_CKR_MDIV_SHIFT)

From: Xing Zheng zhengxing@rock-chips.com
If there is only one lrck (tx or rx) by hardware, we need to use 'rockchip,trcm-sync-tx-only/rx-only' to specify which lrck can be used.
Signed-off-by: Xing Zheng zhengxing@rock-chips.com Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: - split property trcm into single 'trcm-sync-tx-only' and 'trcm-sync-rx-only' suggested by Nicolas.
sound/soc/rockchip/rockchip_i2s.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 84884ce..cd9e069 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -25,6 +25,10 @@
#define DRV_NAME "rockchip-i2s"
+#define TRCM_TXRX 0 +#define TRCM_TX 1 +#define TRCM_RX 2 + struct rk_i2s_pins { u32 reg_offset; u32 shift; @@ -321,7 +325,6 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct rk_i2s_dev *i2s = to_info(dai); - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); unsigned int val = 0; unsigned int mclk_rate, bclk_rate, div_bclk, div_lrck;
@@ -421,13 +424,6 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, I2S_DMACR_RDL(16));
- val = I2S_CKR_TRCM_TXRX; - if (dai->driver->symmetric_rate && rtd->dai_link->symmetric_rate) - val = I2S_CKR_TRCM_TXONLY; - - regmap_update_bits(i2s->regmap, I2S_CKR, - I2S_CKR_TRCM_MASK, - val); return 0; }
@@ -531,7 +527,6 @@ static struct snd_soc_dai_driver rockchip_i2s_dai = { SNDRV_PCM_FMTBIT_S32_LE), }, .ops = &rockchip_i2s_dai_ops, - .symmetric_rate = 1, };
static const struct snd_soc_component_driver rockchip_i2s_component = { @@ -652,6 +647,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev) struct snd_soc_dai_driver *soc_dai; struct resource *res; void __iomem *regs; + unsigned int clk_trcm; int ret; int val;
@@ -749,6 +745,22 @@ static int rockchip_i2s_probe(struct platform_device *pdev) else if (of_property_read_bool(node, "rockchip,capture-only")) soc_dai->playback.channels_min = 0;
+ clk_trcm = TRCM_TXRX; + if (of_property_read_bool(node, "rockchip,trcm-sync-tx-only")) + clk_trcm = TRCM_TX; + if (of_property_read_bool(node, "rockchip,trcm-sync-rx-only")) { + if (clk_trcm) { + dev_err(i2s->dev, "invalid trcm-sync configuration\n"); + return -EINVAL; + } + clk_trcm = TRCM_RX; + } + if (clk_trcm != TRCM_TXRX) + soc_dai->symmetric_rate = 1; + + regmap_update_bits(i2s->regmap, I2S_CKR, + I2S_CKR_TRCM_MASK, I2S_CKR_TRCM(clk_trcm)); + ret = devm_snd_soc_register_component(&pdev->dev, &rockchip_i2s_component, soc_dai, 1);

This patch documents property 'rockchip,trcm-sync-tx-only/rx-only' which is used to specify the lrck.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com ---
Changes in v2: - split property trcm into single 'trcm-sync-tx-only' and 'trcm-sync-rx-only' suggested by Nicolas. - drop change-id
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml index 11e911a..20f3237 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml @@ -101,6 +101,14 @@ properties: Required property for controllers which support multi channel playback/capture.
+ rockchip,trcm-sync-tx-only: + type: boolean + description: Use TX LRCK for both TX and RX. + + rockchip,trcm-sync-rx-only: + type: boolean + description: Use RX LRCK for both TX and RX. + "#sound-dai-cells": const: 0

On Tue, 24 Aug 2021 17:18:54 +0800, Sugar Zhang wrote:
This patch documents property 'rockchip,trcm-sync-tx-only/rx-only' which is used to specify the lrck.
Signed-off-by: Sugar Zhang sugar.zhang@rock-chips.com
Changes in v2:
- split property trcm into single 'trcm-sync-tx-only' and 'trcm-sync-rx-only' suggested by Nicolas.
- drop change-id
Documentation/devicetree/bindings/sound/rockchip-i2s.yaml | 8 ++++++++ 1 file changed, 8 insertions(+)
Reviewed-by: Rob Herring robh@kernel.org
participants (2)
-
Rob Herring
-
Sugar Zhang