[PATCH v4 00/24] Add audio support for the Renesas RZ/G3S SoC
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Hi,
Series enables the audio support for the Renesas RZ/G3S SoC along with runtime PM and suspend to RAM.
Patches: - 01-03/24 - update versaclock3 clock generator driver to support the 5L35023 hardware variant; versaclock3 provides clocks for the audio devices (SSIF, DA7212 codec) - 04-19/24 - add SSIF support for the RZ/G3S SoC; fixes and cleanups were also included - 20-24/24 - add device tree support
Merge strategy, if any: - clock patches (01-03/24) can go the clock tree - audio patches (04-19/24) can go through the audio tree - device tree patches (20-24/24) can go through the Renesas tree
Thank you, Claudiu Beznea
Changes in v4: - added patch 18/24 "ASoC: dt-bindings: renesas,rz-ssi: Remove DMA description" - collected tags - addressed review comments - dropped already integrated patches - the changelog for each patch is detailed within the individual patches
Changes in v3: - use renesas instead of sh in audio patches title - use proper fixes tag for patch "ASoC: renesas: rz-ssi: Terminate all the DMA transactions" - collected tags
Changes in v2: - fixed typos pointed out in the review process - dropped da7213 patches already applied - dropped patch "ASoC: sh: rz-ssi: Use a proper bitmask for clear bits" as requested in the review process
Claudiu Beznea (24): clk: versaclock3: Prepare for the addition of 5L35023 device dt-bindings: clock: versaclock3: Document 5L35023 Versa3 clock generator clk: versaclock3: Add support for the 5L35023 variant ASoC: renesas: rz-ssi: Terminate all the DMA transactions ASoC: renesas: rz-ssi: Use only the proper amount of dividers ASoC: renesas: rz-ssi: Fix typo on SSI_RATES macro comment ASoC: renesas: rz-ssi: Remove pdev member of struct rz_ssi_priv ASoC: renesas: rz-ssi: Remove the rz_ssi_get_dai() function ASoC: renesas: rz-ssi: Remove the first argument of rz_ssi_stream_is_play() ASoC: renesas: rz-ssi: Use readl_poll_timeout_atomic() ASoC: renesas: rz-ssi: Use temporary variable for struct device ASoC: renesas: rz-ssi: Use goto label names that specify their actions ASoC: renesas: rz-ssi: Rely on the ASoC subsystem to runtime resume/suspend the SSI ASoC: renesas: rz-ssi: Enable runtime PM autosuspend support ASoC: renesas: rz-ssi: Add runtime PM support ASoC: renesas: rz-ssi: Issue software reset in hw_params API ASoC: renesas: rz-ssi: Add suspend to RAM support ASoC: dt-bindings: renesas,rz-ssi: Remove DMA description ASoC: dt-bindings: renesas,rz-ssi: Document the Renesas RZ/G3S SoC arm64: dts: renesas: r9a08g045: Add SSI nodes arm64: dts: renesas: rzg3s-smarc-som: Add versa3 clock generator node arm64: dts: renesas: Add da7212 audio codec node arm64: dts: renesas: rzg3s-smarc: Enable SSI3 arm64: dts: renesas: rzg3s-smarc: Add sound card
.../bindings/clock/renesas,5p35023.yaml | 1 + .../bindings/sound/renesas,rz-ssi.yaml | 19 +- arch/arm64/boot/dts/renesas/r9a08g045.dtsi | 94 ++++++++ .../boot/dts/renesas/rzg3s-smarc-som.dtsi | 47 +++- arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi | 63 +++++ drivers/clk/clk-versaclock3.c | 67 ++++-- sound/soc/renesas/rz-ssi.c | 226 +++++++++++------- 7 files changed, 388 insertions(+), 129 deletions(-)
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
The 5P35023 and 5L35035 Versa 3 clock generator variants are different but the versaclock3 driver could be used with small adjustments. The features that are implemented in driver and differs b/w variants are the PLL2 Fvco and clock sel bit for SE2 clock. Adjust the driver to prepare for the addition of 5L35023 device.
Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - none
Changes in v3: - collected tags
Changes in v2: - none
drivers/clk/clk-versaclock3.c | 61 ++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 18 deletions(-)
diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index 76d7ea1964c3..1398d16df5d0 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -78,9 +78,6 @@ #define VC3_PLL1_VCO_MIN 300000000UL #define VC3_PLL1_VCO_MAX 600000000UL
-#define VC3_PLL2_VCO_MIN 400000000UL -#define VC3_PLL2_VCO_MAX 1200000000UL - #define VC3_PLL3_VCO_MIN 300000000UL #define VC3_PLL3_VCO_MAX 800000000UL
@@ -147,9 +144,13 @@ struct vc3_pfd_data { u8 mdiv2_bitmsk; };
+struct vc3_vco { + unsigned long min; + unsigned long max; +}; + struct vc3_pll_data { - unsigned long vco_min; - unsigned long vco_max; + struct vc3_vco vco; u8 num; u8 int_div_msb_offs; u8 int_div_lsb_offs; @@ -166,12 +167,17 @@ struct vc3_div_data { struct vc3_hw_data { struct clk_hw hw; struct regmap *regmap; - const void *data; + void *data;
u32 div_int; u32 div_frc; };
+struct vc3_hw_cfg { + struct vc3_vco pll2_vco; + u32 se2_clk_sel_msk; +}; + static const struct clk_div_table div1_divs[] = { { .val = 0, .div = 1, }, { .val = 1, .div = 4, }, { .val = 2, .div = 5, }, { .val = 3, .div = 6, }, @@ -386,10 +392,10 @@ static long vc3_pll_round_rate(struct clk_hw *hw, unsigned long rate, const struct vc3_pll_data *pll = vc3->data; u64 div_frc;
- if (rate < pll->vco_min) - rate = pll->vco_min; - if (rate > pll->vco_max) - rate = pll->vco_max; + if (rate < pll->vco.min) + rate = pll->vco.min; + if (rate > pll->vco.max) + rate = pll->vco.max;
vc3->div_int = rate / *parent_rate;
@@ -680,8 +686,10 @@ static struct vc3_hw_data clk_pll[] = { .num = VC3_PLL1, .int_div_msb_offs = VC3_PLL1_LOOP_FILTER_N_DIV_MSB, .int_div_lsb_offs = VC3_PLL1_VCO_N_DIVIDER, - .vco_min = VC3_PLL1_VCO_MIN, - .vco_max = VC3_PLL1_VCO_MAX + .vco = { + .min = VC3_PLL1_VCO_MIN, + .max = VC3_PLL1_VCO_MAX + } }, .hw.init = &(struct clk_init_data) { .name = "pll1", @@ -698,8 +706,6 @@ static struct vc3_hw_data clk_pll[] = { .num = VC3_PLL2, .int_div_msb_offs = VC3_PLL2_FB_INT_DIV_MSB, .int_div_lsb_offs = VC3_PLL2_FB_INT_DIV_LSB, - .vco_min = VC3_PLL2_VCO_MIN, - .vco_max = VC3_PLL2_VCO_MAX }, .hw.init = &(struct clk_init_data) { .name = "pll2", @@ -716,8 +722,10 @@ static struct vc3_hw_data clk_pll[] = { .num = VC3_PLL3, .int_div_msb_offs = VC3_PLL3_LOOP_FILTER_N_DIV_MSB, .int_div_lsb_offs = VC3_PLL3_N_DIVIDER, - .vco_min = VC3_PLL3_VCO_MIN, - .vco_max = VC3_PLL3_VCO_MAX + .vco = { + .min = VC3_PLL3_VCO_MIN, + .max = VC3_PLL3_VCO_MAX + } }, .hw.init = &(struct clk_init_data) { .name = "pll3", @@ -901,7 +909,6 @@ static struct vc3_hw_data clk_mux[] = { [VC3_SE2_MUX] = { .data = &(struct vc3_clk_data) { .offs = VC3_SE2_CTRL_REG0, - .bitmsk = VC3_SE2_CTRL_REG0_SE2_CLK_SEL }, .hw.init = &(struct clk_init_data) { .name = "se2_mux", @@ -982,6 +989,7 @@ static int vc3_probe(struct i2c_client *client) { struct device *dev = &client->dev; u8 settings[NUM_CONFIG_REGISTERS]; + const struct vc3_hw_cfg *data; struct regmap *regmap; const char *name; int ret, i; @@ -1029,9 +1037,16 @@ static int vc3_probe(struct i2c_client *client) clk_pfd[i].hw.init->name); }
+ data = i2c_get_match_data(client); + /* Register pll's */ for (i = 0; i < ARRAY_SIZE(clk_pll); i++) { clk_pll[i].regmap = regmap; + if (i == VC3_PLL2) { + struct vc3_pll_data *pll_data = clk_pll[i].data; + + pll_data->vco = data->pll2_vco; + } ret = devm_clk_hw_register(dev, &clk_pll[i].hw); if (ret) return dev_err_probe(dev, ret, "%s failed\n", @@ -1059,6 +1074,11 @@ static int vc3_probe(struct i2c_client *client) /* Register clk muxes */ for (i = 0; i < ARRAY_SIZE(clk_mux); i++) { clk_mux[i].regmap = regmap; + if (i == VC3_SE2_MUX) { + struct vc3_clk_data *clk_data = clk_mux[i].data; + + clk_data->bitmsk = data->se2_clk_sel_msk; + } ret = devm_clk_hw_register(dev, &clk_mux[i].hw); if (ret) return dev_err_probe(dev, ret, "%s failed\n", @@ -1108,8 +1128,13 @@ static int vc3_probe(struct i2c_client *client) return ret; }
+static const struct vc3_hw_cfg vc3_5p = { + .pll2_vco = { .min = 400000000UL, .max = 1200000000UL }, + .se2_clk_sel_msk = BIT(6), +}; + static const struct of_device_id dev_ids[] = { - { .compatible = "renesas,5p35023" }, + { .compatible = "renesas,5p35023", .data = &vc3_5p }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, dev_ids);
Quoting Claudiu (2024-12-10 09:09:30)
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
The 5P35023 and 5L35035 Versa 3 clock generator variants are different but the versaclock3 driver could be used with small adjustments. The features that are implemented in driver and differs b/w variants are the PLL2 Fvco and clock sel bit for SE2 clock. Adjust the driver to prepare for the addition of 5L35023 device.
Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Applied to clk-next
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
There are some differences b/w 5L35023 and 5P35023 Versa3 clock generator variants but the same driver could be used with minimal adjustments. The identified differences are PLL2 Fvco, the clock sel bit for SE2 clock and different default values for some registers.
Acked-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - collected tags
Changes in v2: - collected tags
Documentation/devicetree/bindings/clock/renesas,5p35023.yaml | 1 + 1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/clock/renesas,5p35023.yaml b/Documentation/devicetree/bindings/clock/renesas,5p35023.yaml index 42b6f80613f3..162d38035188 100644 --- a/Documentation/devicetree/bindings/clock/renesas,5p35023.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,5p35023.yaml @@ -31,6 +31,7 @@ description: | properties: compatible: enum: + - renesas,5l35023 - renesas,5p35023
reg:
Quoting Claudiu (2024-12-10 09:09:31)
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
There are some differences b/w 5L35023 and 5P35023 Versa3 clock generator variants but the same driver could be used with minimal adjustments. The identified differences are PLL2 Fvco, the clock sel bit for SE2 clock and different default values for some registers.
Acked-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Applied to clk-next
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Add support for the 5L35023 variant of the Versa 3 clock generator.
Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - collected tags
Changes in v2: - none
drivers/clk/clk-versaclock3.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index 1398d16df5d0..9fe27dace111 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -1133,8 +1133,14 @@ static const struct vc3_hw_cfg vc3_5p = { .se2_clk_sel_msk = BIT(6), };
+static const struct vc3_hw_cfg vc3_5l = { + .pll2_vco = { .min = 30000000UL, .max = 130000000UL }, + .se2_clk_sel_msk = BIT(0), +}; + static const struct of_device_id dev_ids[] = { { .compatible = "renesas,5p35023", .data = &vc3_5p }, + { .compatible = "renesas,5l35023", .data = &vc3_5l }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, dev_ids);
Quoting Claudiu (2024-12-10 09:09:32)
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Add support for the 5L35023 variant of the Versa 3 clock generator.
Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Applied to clk-next
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
The stop trigger invokes rz_ssi_stop() and rz_ssi_stream_quit(). - The purpose of rz_ssi_stop() is to disable TX/RX, terminate DMA transactions, and set the controller to idle. - The purpose of rz_ssi_stream_quit() is to reset the substream-specific software data by setting strm->running and strm->substream appropriately.
The function rz_ssi_is_stream_running() checks if both strm->substream and strm->running are valid and returns true if so. Its implementation is as follows:
static inline bool rz_ssi_is_stream_running(struct rz_ssi_stream *strm) { return strm->substream && strm->running; }
When the controller is configured in full-duplex mode (with both playback and capture active), the rz_ssi_stop() function does not modify the controller settings when called for the first substream in the full-duplex setup. Instead, it simply sets strm->running = 0 and returns if the companion substream is still running. The following code illustrates this:
static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { strm->running = 0;
if (rz_ssi_is_stream_running(&ssi->playback) || rz_ssi_is_stream_running(&ssi->capture)) return 0;
// ... }
The controller settings, along with the DMA termination (for the last stopped substream), are only applied when the last substream in the full-duplex setup is stopped.
While applying the controller settings only when the last substream stops is not problematic, terminating the DMA operations for only one substream causes failures when starting and stopping full-duplex operations multiple times in a loop.
To address this issue, call dmaengine_terminate_async() for both substreams involved in the full-duplex setup when the last substream in the setup is stopped.
Fixes: 4f8cd05a4305 ("ASoC: sh: rz-ssi: Add full duplex support") Cc: stable@vger.kernel.org Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - updated patch description
Changes in v3: - collected tags - use proper fixes commit SHA1 and description - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 6efd017aaa7f..2d8721156099 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -415,8 +415,12 @@ static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
/* Cancel all remaining DMA transactions */ - if (rz_ssi_is_dma_enabled(ssi)) - dmaengine_terminate_async(strm->dma_ch); + if (rz_ssi_is_dma_enabled(ssi)) { + if (ssi->playback.dma_ch) + dmaengine_terminate_async(ssi->playback.dma_ch); + if (ssi->capture.dma_ch) + dmaengine_terminate_async(ssi->capture.dma_ch); + }
rz_ssi_set_idle(ssi);
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
There is no need to populate the ckdv[] with invalid dividers as that part will not be indexed anyway. The ssi->audio_mck/bclk_rate should always be >= 0. While at it, change the ckdv type as u8, as the divider 128 was previously using the s8 sign bit.
Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - changed the ckdv type from s8 to u8 and updated patch description to reflect it
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 2d8721156099..178c915331e9 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -258,8 +258,7 @@ static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi, static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, unsigned int channels) { - static s8 ckdv[16] = { 1, 2, 4, 8, 16, 32, 64, 128, - 6, 12, 24, 48, 96, -1, -1, -1 }; + static u8 ckdv[] = { 1, 2, 4, 8, 16, 32, 64, 128, 6, 12, 24, 48, 96 }; unsigned int channel_bits = 32; /* System Word Length */ unsigned long bclk_rate = rate * channels * channel_bits; unsigned int div;
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
The SSI_RATES macro covers 8KHz-48KHz audio frequencies. Update macro comment to reflect it.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 178c915331e9..35929160a8a5 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -71,7 +71,7 @@ #define PREALLOC_BUFFER (SZ_32K) #define PREALLOC_BUFFER_MAX (SZ_32K)
-#define SSI_RATES SNDRV_PCM_RATE_8000_48000 /* 8k-44.1kHz */ +#define SSI_RATES SNDRV_PCM_RATE_8000_48000 /* 8k-48kHz */ #define SSI_FMTS SNDRV_PCM_FMTBIT_S16_LE #define SSI_CHAN_MIN 2 #define SSI_CHAN_MAX 2
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Remove the pdev member of struct rz_ssi_priv as it is not used.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 35929160a8a5..b24c323ee05f 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -99,7 +99,6 @@ struct rz_ssi_stream {
struct rz_ssi_priv { void __iomem *base; - struct platform_device *pdev; struct reset_control *rstc; struct device *dev; struct clk *sfr_clk; @@ -1043,7 +1042,6 @@ static int rz_ssi_probe(struct platform_device *pdev) if (!ssi) return -ENOMEM;
- ssi->pdev = pdev; ssi->dev = &pdev->dev; ssi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(ssi->base))
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Remove the rz_ssi_get_dai() function and use directly the snd_soc_rtd_to_cpu() where needed or the struct device pointer embedded in the struct rz_ssi_priv objects.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags - updated patch description
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index b24c323ee05f..e2e172d8e9db 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -162,14 +162,6 @@ static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg, writel(val, (priv->base + reg)); }
-static inline struct snd_soc_dai * -rz_ssi_get_dai(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - - return snd_soc_rtd_to_cpu(rtd, 0); -} - static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream) { @@ -243,15 +235,15 @@ static void rz_ssi_stream_init(struct rz_ssi_stream *strm, static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { - struct snd_soc_dai *dai = rz_ssi_get_dai(strm->substream); + struct device *dev = ssi->dev;
rz_ssi_set_substream(strm, NULL);
if (strm->oerr_num > 0) - dev_info(dai->dev, "overrun = %d\n", strm->oerr_num); + dev_info(dev, "overrun = %d\n", strm->oerr_num);
if (strm->uerr_num > 0) - dev_info(dai->dev, "underrun = %d\n", strm->uerr_num); + dev_info(dev, "underrun = %d\n", strm->uerr_num); }
static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, @@ -988,7 +980,8 @@ static int rz_ssi_pcm_open(struct snd_soc_component *component, static snd_pcm_uframes_t rz_ssi_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_dai *dai = rz_ssi_get_dai(substream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0); struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
The first argument of the rz_ssi_stream_is_play() is not used. Remove it.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - fixed typos in patch title and description - collected tags
sound/soc/renesas/rz-ssi.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index e2e172d8e9db..1a98f6b3e6a7 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -162,8 +162,7 @@ static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg, writel(val, (priv->base + reg)); }
-static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi, - struct snd_pcm_substream *substream) +static inline bool rz_ssi_stream_is_play(struct snd_pcm_substream *substream) { return substream->stream == SNDRV_PCM_STREAM_PLAYBACK; } @@ -337,7 +336,7 @@ static void rz_ssi_set_idle(struct rz_ssi_priv *ssi)
static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { - bool is_play = rz_ssi_stream_is_play(ssi, strm->substream); + bool is_play = rz_ssi_stream_is_play(strm->substream); bool is_full_duplex; u32 ssicr, ssifcr;
@@ -674,7 +673,7 @@ static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi, */ return 0;
- dir = rz_ssi_stream_is_play(ssi, substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; + dir = rz_ssi_stream_is_play(substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
/* Always transfer 1 period */ amount = runtime->period_size; @@ -800,7 +799,7 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, if (ssi->dma_rt) { bool is_playback;
- is_playback = rz_ssi_stream_is_play(ssi, substream); + is_playback = rz_ssi_stream_is_play(substream); ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, is_playback); /* Fallback to pio */
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Use readl_poll_timeout_atomic() instead of hardcoding something similar. While at it replace dev_info() with dev_warn_ratelimited() as the rz_ssi_set_idle() can also be called from IRQ context and if the SSI idle is not properly set this is at least a warning for user.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 1a98f6b3e6a7..03d409d3070c 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -9,6 +9,7 @@ #include <linux/clk.h> #include <linux/dmaengine.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/reset.h> @@ -307,7 +308,8 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
static void rz_ssi_set_idle(struct rz_ssi_priv *ssi) { - int timeout; + u32 tmp; + int ret;
/* Disable irqs */ rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN | @@ -320,15 +322,9 @@ static void rz_ssi_set_idle(struct rz_ssi_priv *ssi) SSISR_RUIRQ), 0);
/* Wait for idle */ - timeout = 100; - while (--timeout) { - if (rz_ssi_reg_readl(ssi, SSISR) & SSISR_IIRQ) - break; - udelay(1); - } - - if (!timeout) - dev_info(ssi->dev, "timeout waiting for SSI idle\n"); + ret = readl_poll_timeout_atomic(ssi->base + SSISR, tmp, (tmp & SSISR_IIRQ), 1, 100); + if (ret) + dev_warn_ratelimited(ssi->dev, "timeout waiting for SSI idle\n");
/* Hold FIFOs in reset */ rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_FIFO_RST);
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Use a temporary variable for the struct device pointers to avoid dereferencing.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 62 +++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 31 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 03d409d3070c..74632e2482f8 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -1021,36 +1021,37 @@ static const struct snd_soc_component_driver rz_ssi_soc_component = {
static int rz_ssi_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct rz_ssi_priv *ssi; struct clk *audio_clk; struct resource *res; int ret;
- ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); + ssi = devm_kzalloc(dev, sizeof(*ssi), GFP_KERNEL); if (!ssi) return -ENOMEM;
- ssi->dev = &pdev->dev; + ssi->dev = dev; ssi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(ssi->base)) return PTR_ERR(ssi->base);
ssi->phys = res->start; - ssi->clk = devm_clk_get(&pdev->dev, "ssi"); + ssi->clk = devm_clk_get(dev, "ssi"); if (IS_ERR(ssi->clk)) return PTR_ERR(ssi->clk);
- ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr"); + ssi->sfr_clk = devm_clk_get(dev, "ssi_sfr"); if (IS_ERR(ssi->sfr_clk)) return PTR_ERR(ssi->sfr_clk);
- audio_clk = devm_clk_get(&pdev->dev, "audio_clk1"); + audio_clk = devm_clk_get(dev, "audio_clk1"); if (IS_ERR(audio_clk)) return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), "no audio clk1");
ssi->audio_clk_1 = clk_get_rate(audio_clk); - audio_clk = devm_clk_get(&pdev->dev, "audio_clk2"); + audio_clk = devm_clk_get(dev, "audio_clk2"); if (IS_ERR(audio_clk)) return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk), "no audio clk2"); @@ -1063,13 +1064,13 @@ static int rz_ssi_probe(struct platform_device *pdev) ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
/* Detect DMA support */ - ret = rz_ssi_dma_request(ssi, &pdev->dev); + ret = rz_ssi_dma_request(ssi, dev); if (ret < 0) { - dev_warn(&pdev->dev, "DMA not available, using PIO\n"); + dev_warn(dev, "DMA not available, using PIO\n"); ssi->playback.transfer = rz_ssi_pio_send; ssi->capture.transfer = rz_ssi_pio_recv; } else { - dev_info(&pdev->dev, "DMA enabled"); + dev_info(dev, "DMA enabled"); ssi->playback.transfer = rz_ssi_dma_transfer; ssi->capture.transfer = rz_ssi_dma_transfer; } @@ -1078,7 +1079,7 @@ static int rz_ssi_probe(struct platform_device *pdev) ssi->capture.priv = ssi;
spin_lock_init(&ssi->lock); - dev_set_drvdata(&pdev->dev, ssi); + dev_set_drvdata(dev, ssi);
/* Error Interrupt */ ssi->irq_int = platform_get_irq_byname(pdev, "int_req"); @@ -1087,12 +1088,11 @@ static int rz_ssi_probe(struct platform_device *pdev) return ssi->irq_int; }
- ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt, - 0, dev_name(&pdev->dev), ssi); + ret = devm_request_irq(dev, ssi->irq_int, &rz_ssi_interrupt, + 0, dev_name(dev), ssi); if (ret < 0) { rz_ssi_release_dma_channels(ssi); - return dev_err_probe(&pdev->dev, ret, - "irq request error (int_req)\n"); + return dev_err_probe(dev, ret, "irq request error (int_req)\n"); }
if (!rz_ssi_is_dma_enabled(ssi)) { @@ -1104,11 +1104,11 @@ static int rz_ssi_probe(struct platform_device *pdev) if (ssi->irq_rt < 0) return ssi->irq_rt;
- ret = devm_request_irq(&pdev->dev, ssi->irq_rt, + ret = devm_request_irq(dev, ssi->irq_rt, &rz_ssi_interrupt, 0, - dev_name(&pdev->dev), ssi); + dev_name(dev), ssi); if (ret < 0) - return dev_err_probe(&pdev->dev, ret, + return dev_err_probe(dev, ret, "irq request error (dma_rt)\n"); } else { if (ssi->irq_tx < 0) @@ -1117,50 +1117,50 @@ static int rz_ssi_probe(struct platform_device *pdev) if (ssi->irq_rx < 0) return ssi->irq_rx;
- ret = devm_request_irq(&pdev->dev, ssi->irq_tx, + ret = devm_request_irq(dev, ssi->irq_tx, &rz_ssi_interrupt, 0, - dev_name(&pdev->dev), ssi); + dev_name(dev), ssi); if (ret < 0) - return dev_err_probe(&pdev->dev, ret, + return dev_err_probe(dev, ret, "irq request error (dma_tx)\n");
- ret = devm_request_irq(&pdev->dev, ssi->irq_rx, + ret = devm_request_irq(dev, ssi->irq_rx, &rz_ssi_interrupt, 0, - dev_name(&pdev->dev), ssi); + dev_name(dev), ssi); if (ret < 0) - return dev_err_probe(&pdev->dev, ret, + return dev_err_probe(dev, ret, "irq request error (dma_rx)\n"); } }
- ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + ssi->rstc = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(ssi->rstc)) { ret = PTR_ERR(ssi->rstc); goto err_reset; }
reset_control_deassert(ssi->rstc); - pm_runtime_enable(&pdev->dev); - ret = pm_runtime_resume_and_get(&pdev->dev); + pm_runtime_enable(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) { - dev_err(&pdev->dev, "pm_runtime_resume_and_get failed\n"); + dev_err(dev, "pm_runtime_resume_and_get failed\n"); goto err_pm; }
- ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component, + ret = devm_snd_soc_register_component(dev, &rz_ssi_soc_component, rz_ssi_soc_dai, ARRAY_SIZE(rz_ssi_soc_dai)); if (ret < 0) { - dev_err(&pdev->dev, "failed to register snd component\n"); + dev_err(dev, "failed to register snd component\n"); goto err_snd_soc; }
return 0;
err_snd_soc: - pm_runtime_put(ssi->dev); + pm_runtime_put(dev); err_pm: - pm_runtime_disable(ssi->dev); + pm_runtime_disable(dev); reset_control_assert(ssi->rstc); err_reset: rz_ssi_release_dma_channels(ssi);
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Use goto label names that specify their action. In this way we can have a better understanding of what is the action associated with the label by just reading the label name.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 74632e2482f8..209b5b8827e5 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -1084,15 +1084,15 @@ static int rz_ssi_probe(struct platform_device *pdev) /* Error Interrupt */ ssi->irq_int = platform_get_irq_byname(pdev, "int_req"); if (ssi->irq_int < 0) { - rz_ssi_release_dma_channels(ssi); - return ssi->irq_int; + ret = ssi->irq_int; + goto err_release_dma_chs; }
ret = devm_request_irq(dev, ssi->irq_int, &rz_ssi_interrupt, 0, dev_name(dev), ssi); if (ret < 0) { - rz_ssi_release_dma_channels(ssi); - return dev_err_probe(dev, ret, "irq request error (int_req)\n"); + dev_err_probe(dev, ret, "irq request error (int_req)\n"); + goto err_release_dma_chs; }
if (!rz_ssi_is_dma_enabled(ssi)) { @@ -1136,7 +1136,7 @@ static int rz_ssi_probe(struct platform_device *pdev) ssi->rstc = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(ssi->rstc)) { ret = PTR_ERR(ssi->rstc); - goto err_reset; + goto err_release_dma_chs; }
reset_control_deassert(ssi->rstc); @@ -1152,17 +1152,17 @@ static int rz_ssi_probe(struct platform_device *pdev) ARRAY_SIZE(rz_ssi_soc_dai)); if (ret < 0) { dev_err(dev, "failed to register snd component\n"); - goto err_snd_soc; + goto err_pm_put; }
return 0;
-err_snd_soc: +err_pm_put: pm_runtime_put(dev); err_pm: pm_runtime_disable(dev); reset_control_assert(ssi->rstc); -err_reset: +err_release_dma_chs: rz_ssi_release_dma_channels(ssi);
return ret;
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
The ASoC subsystem takes care of runtime resume/suspend the audio devices when needed. Just enable the runtime PM on the SSI driver and let the subsystem runtime resume/suspend it. While at it use directly the devm_pm_runtime_enable().
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 209b5b8827e5..878158344f88 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -1140,11 +1140,10 @@ static int rz_ssi_probe(struct platform_device *pdev) }
reset_control_deassert(ssi->rstc); - pm_runtime_enable(dev); - ret = pm_runtime_resume_and_get(dev); + ret = devm_pm_runtime_enable(dev); if (ret < 0) { - dev_err(dev, "pm_runtime_resume_and_get failed\n"); - goto err_pm; + dev_err(dev, "Failed to enable runtime PM!\n"); + goto err_reset; }
ret = devm_snd_soc_register_component(dev, &rz_ssi_soc_component, @@ -1152,15 +1151,12 @@ static int rz_ssi_probe(struct platform_device *pdev) ARRAY_SIZE(rz_ssi_soc_dai)); if (ret < 0) { dev_err(dev, "failed to register snd component\n"); - goto err_pm_put; + goto err_reset; }
return 0;
-err_pm_put: - pm_runtime_put(dev); -err_pm: - pm_runtime_disable(dev); +err_reset: reset_control_assert(ssi->rstc); err_release_dma_chs: rz_ssi_release_dma_channels(ssi); @@ -1174,8 +1170,6 @@ static void rz_ssi_remove(struct platform_device *pdev)
rz_ssi_release_dma_channels(ssi);
- pm_runtime_put(ssi->dev); - pm_runtime_disable(ssi->dev); reset_control_assert(ssi->rstc); }
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Enable runtime PM autosuspend support. The chosen autosuspend delay is zero for immediate autosuspend. In case there are users that need a different autosuspend delay, it can be adjusted through sysfs.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 878158344f88..eebf2d647ef2 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -1140,6 +1140,9 @@ static int rz_ssi_probe(struct platform_device *pdev) }
reset_control_deassert(ssi->rstc); + /* Default 0 for power saving. Can be overridden via sysfs. */ + pm_runtime_set_autosuspend_delay(dev, 0); + pm_runtime_use_autosuspend(dev); ret = devm_pm_runtime_enable(dev); if (ret < 0) { dev_err(dev, "Failed to enable runtime PM!\n");
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Add runtime PM support to the ssi driver. This assert/de-assert the reset lines on runtime suspend/resume. Along with it the de-assertion of the reset line from probe function was removed as it is not necessary anymore.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index eebf2d647ef2..34c2e22b5a67 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -1139,14 +1139,13 @@ static int rz_ssi_probe(struct platform_device *pdev) goto err_release_dma_chs; }
- reset_control_deassert(ssi->rstc); /* Default 0 for power saving. Can be overridden via sysfs. */ pm_runtime_set_autosuspend_delay(dev, 0); pm_runtime_use_autosuspend(dev); ret = devm_pm_runtime_enable(dev); if (ret < 0) { dev_err(dev, "Failed to enable runtime PM!\n"); - goto err_reset; + goto err_release_dma_chs; }
ret = devm_snd_soc_register_component(dev, &rz_ssi_soc_component, @@ -1154,13 +1153,11 @@ static int rz_ssi_probe(struct platform_device *pdev) ARRAY_SIZE(rz_ssi_soc_dai)); if (ret < 0) { dev_err(dev, "failed to register snd component\n"); - goto err_reset; + goto err_release_dma_chs; }
return 0;
-err_reset: - reset_control_assert(ssi->rstc); err_release_dma_chs: rz_ssi_release_dma_channels(ssi);
@@ -1182,10 +1179,29 @@ static const struct of_device_id rz_ssi_of_match[] = { }; MODULE_DEVICE_TABLE(of, rz_ssi_of_match);
+static int rz_ssi_runtime_suspend(struct device *dev) +{ + struct rz_ssi_priv *ssi = dev_get_drvdata(dev); + + return reset_control_assert(ssi->rstc); +} + +static int rz_ssi_runtime_resume(struct device *dev) +{ + struct rz_ssi_priv *ssi = dev_get_drvdata(dev); + + return reset_control_deassert(ssi->rstc); +} + +static const struct dev_pm_ops rz_ssi_pm_ops = { + RUNTIME_PM_OPS(rz_ssi_runtime_suspend, rz_ssi_runtime_resume, NULL) +}; + static struct platform_driver rz_ssi_driver = { .driver = { .name = "rz-ssi-pcm-audio", .of_match_table = rz_ssi_of_match, + .pm = pm_ptr(&rz_ssi_pm_ops), }, .probe = rz_ssi_probe, .remove = rz_ssi_remove,
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
The code initially issued software reset on SNDRV_PCM_TRIGGER_START action only before starting the first stream. This can be easily moved to hw_params() as the action is similar to setting the clocks. Moreover, according to the hardware manual (Table 35.7 Bits Initialized by Software Reset of the SSIFCR.SSIRST Bit) the software reset action acts also on the clock dividers bits. Due to this issue the software reset in hw_params() before configuring the clock dividers. This also simplifies the code in trigger API.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags - use rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST); in rz_ssi_swreset() as suggested in the review process
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 34c2e22b5a67..486822d79458 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -388,6 +388,15 @@ static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) return 0; }
+static int rz_ssi_swreset(struct rz_ssi_priv *ssi) +{ + u32 tmp; + + rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST); + rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0); + return readl_poll_timeout_atomic(ssi->base + SSIFCR, tmp, !(tmp & SSIFCR_SSIRST), 1, 5); +} + static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { strm->running = 0; @@ -782,14 +791,6 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
switch (cmd) { case SNDRV_PCM_TRIGGER_START: - /* Soft Reset */ - if (!rz_ssi_is_stream_running(&ssi->playback) && - !rz_ssi_is_stream_running(&ssi->capture)) { - rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST); - rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0); - udelay(5); - } - rz_ssi_stream_init(strm, substream);
if (ssi->dma_rt) { @@ -914,6 +915,7 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; unsigned int channels = params_channels(params); unsigned int rate = params_rate(params); + int ret;
if (sample_bits != 16) { dev_err(ssi->dev, "Unsupported sample width: %d\n", @@ -940,6 +942,10 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, rz_ssi_cache_hw_params(ssi, rate, channels, strm->sample_width, sample_bits);
+ ret = rz_ssi_swreset(ssi); + if (ret) + return ret; + return rz_ssi_clk_setup(ssi, rate, channels); }
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
The SSIF-2 IP is available on the Renesas RZ/G3S SoC. The Renesas RZ/G3S SoC supports a power-saving mode where power to most of the SoC components is turned off. Add suspend/resume support to the SSIF-2 driver to support this power-saving mode.
On SNDRV_PCM_TRIGGER_SUSPEND trigger the SSI is stopped (the stream user pointer is left untouched to avoid breaking user space and the dma buffer pointer is set to zero), on SNDRV_PCM_TRIGGER_RESUME software reset is issued for the SSIF-2 IP and the clocks are re-configured.
Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - none
Changes in v3: - s/sh/renesas in patch title
Changes in v2: - none
sound/soc/renesas/rz-ssi.c | 46 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c index 486822d79458..d48e2e7356b6 100644 --- a/sound/soc/renesas/rz-ssi.c +++ b/sound/soc/renesas/rz-ssi.c @@ -782,6 +782,32 @@ static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev) return -ENODEV; }
+static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi) +{ + int ret; + + if (rz_ssi_is_stream_running(&ssi->playback) || + rz_ssi_is_stream_running(&ssi->capture)) + return 0; + + ret = rz_ssi_swreset(ssi); + if (ret) + return ret; + + return rz_ssi_clk_setup(ssi, ssi->hw_params_cache.rate, + ssi->hw_params_cache.channels); +} + +static void rz_ssi_streams_suspend(struct rz_ssi_priv *ssi) +{ + if (rz_ssi_is_stream_running(&ssi->playback) || + rz_ssi_is_stream_running(&ssi->capture)) + return; + + ssi->playback.dma_buffer_pos = 0; + ssi->capture.dma_buffer_pos = 0; +} + static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -790,8 +816,16 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, int ret = 0, i, num_transfer = 1;
switch (cmd) { + case SNDRV_PCM_TRIGGER_RESUME: + ret = rz_ssi_trigger_resume(ssi); + if (ret) + return ret; + + fallthrough; + case SNDRV_PCM_TRIGGER_START: - rz_ssi_stream_init(strm, substream); + if (cmd == SNDRV_PCM_TRIGGER_START) + rz_ssi_stream_init(strm, substream);
if (ssi->dma_rt) { bool is_playback; @@ -819,6 +853,12 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
ret = rz_ssi_start(ssi, strm); break; + + case SNDRV_PCM_TRIGGER_SUSPEND: + rz_ssi_stop(ssi, strm); + rz_ssi_streams_suspend(ssi); + break; + case SNDRV_PCM_TRIGGER_STOP: rz_ssi_stop(ssi, strm); rz_ssi_stream_quit(ssi, strm); @@ -958,7 +998,8 @@ static const struct snd_soc_dai_ops rz_ssi_dai_ops = { static const struct snd_pcm_hardware rz_ssi_pcm_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_RESUME, .buffer_bytes_max = PREALLOC_BUFFER, .period_bytes_min = 32, .period_bytes_max = 8192, @@ -1201,6 +1242,7 @@ static int rz_ssi_runtime_resume(struct device *dev)
static const struct dev_pm_ops rz_ssi_pm_ops = { RUNTIME_PM_OPS(rz_ssi_runtime_suspend, rz_ssi_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) };
static struct platform_driver rz_ssi_driver = {
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Remove the DMA description, as it duplicates content from ../dma/renesas,rz-dma.yaml. Additionally, remove the MID/RID examples mentioned in the dropped description (this information is already documented in the hardware manual).
Suggested-by: Geert Uytterhoeven geert@linux-m68k.org Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - none; this patch is new
.../bindings/sound/renesas,rz-ssi.yaml | 18 ------------------ 1 file changed, 18 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml index f4610eaed1e1..5b42eec864f8 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml @@ -57,24 +57,6 @@ properties: dmas: minItems: 1 maxItems: 2 - description: - The first cell represents a phandle to dmac. - The second cell specifies the encoded MID/RID values of the SSI port - connected to the DMA client and the slave channel configuration - parameters. - bits[0:9] - Specifies MID/RID value of a SSI channel as below - MID/RID value of SSI rx0 = 0x256 - MID/RID value of SSI tx0 = 0x255 - MID/RID value of SSI rx1 = 0x25a - MID/RID value of SSI tx1 = 0x259 - MID/RID value of SSI rt2 = 0x25f - MID/RID value of SSI rx3 = 0x262 - MID/RID value of SSI tx3 = 0x261 - bit[10] - HIEN = 1, Detects a request in response to the rising edge - of the signal - bit[11] - LVL = 0, Detects based on the edge - bits[12:14] - AM = 2, Bus cycle mode - bit[15] - TM = 0, Single transfer mode
dma-names: oneOf:
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
The SSI IP variant present on the Renesas RZ/G3S SoC is similar to the one found on the Renesas RZ/G2{UL, L, LC} SoCs. Add documentation for it.
Acked-by: Krzysztof Kozlowski krzysztof.kozlowski@linaro.org Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - none
Changes in v3: - none
Changes in v2: - collected tags
Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml | 1 + 1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml index 5b42eec864f8..e4cdbf2202b9 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml @@ -19,6 +19,7 @@ properties: - renesas,r9a07g043-ssi # RZ/G2UL and RZ/Five - renesas,r9a07g044-ssi # RZ/G2{L,LC} - renesas,r9a07g054-ssi # RZ/V2L + - renesas,r9a08g045-ssi # RZ/G3S - const: renesas,rz-ssi
reg:
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Add DT nodes for the SSI IPs available on the Renesas RZ/G3S SoC. Along with it external audio clocks were added. Board device tree could use it and update the frequencies.
Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - s/audio-clk1/audio1-clk - s/audio-clk2/audio2-clk - dropped status for the audio clock nodes - collected tags
Changes in v3: - none
Changes in v2: - none
arch/arm64/boot/dts/renesas/r9a08g045.dtsi | 94 ++++++++++++++++++++++ 1 file changed, 94 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi index be8a0a768c65..0e06a4b96c64 100644 --- a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi +++ b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi @@ -14,6 +14,20 @@ / { #address-cells = <2>; #size-cells = <2>;
+ audio_clk1: audio1-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by boards that provide it. */ + clock-frequency = <0>; + }; + + audio_clk2: audio2-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by boards that provide it. */ + clock-frequency = <0>; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -187,6 +201,86 @@ i2c3: i2c@10090c00 { status = "disabled"; };
+ ssi0: ssi@100a8000 { + compatible = "renesas,r9a08g045-ssi", + "renesas,rz-ssi"; + reg = <0 0x100a8000 0 0x400>; + interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 241 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 242 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "int_req", "dma_rx", "dma_tx"; + clocks = <&cpg CPG_MOD R9A08G045_SSI0_PCLK2>, + <&cpg CPG_MOD R9A08G045_SSI0_PCLK_SFR>, + <&audio_clk1>, <&audio_clk2>; + clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; + resets = <&cpg R9A08G045_SSI0_RST_M2_REG>; + dmas = <&dmac 0x2665>, <&dmac 0x2666>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + ssi1: ssi@100a8400 { + compatible = "renesas,r9a08g045-ssi", + "renesas,rz-ssi"; + reg = <0 0x100a8400 0 0x400>; + interrupts = <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 244 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 245 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "int_req", "dma_rx", "dma_tx"; + clocks = <&cpg CPG_MOD R9A08G045_SSI1_PCLK2>, + <&cpg CPG_MOD R9A08G045_SSI1_PCLK_SFR>, + <&audio_clk1>, <&audio_clk2>; + clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; + resets = <&cpg R9A08G045_SSI1_RST_M2_REG>; + dmas = <&dmac 0x2669>, <&dmac 0x266a>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + ssi2: ssi@100a8800 { + compatible = "renesas,r9a08g045-ssi", + "renesas,rz-ssi"; + reg = <0 0x100a8800 0 0x400>; + interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 247 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 248 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "int_req", "dma_rx", "dma_tx"; + clocks = <&cpg CPG_MOD R9A08G045_SSI2_PCLK2>, + <&cpg CPG_MOD R9A08G045_SSI2_PCLK_SFR>, + <&audio_clk1>, <&audio_clk2>; + clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; + resets = <&cpg R9A08G045_SSI2_RST_M2_REG>; + dmas = <&dmac 0x266d>, <&dmac 0x266e>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + ssi3: ssi@100a8c00 { + compatible = "renesas,r9a08g045-ssi", + "renesas,rz-ssi"; + reg = <0 0x100a8c00 0 0x400>; + interrupts = <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 250 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 251 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "int_req", "dma_rx", "dma_tx"; + clocks = <&cpg CPG_MOD R9A08G045_SSI3_PCLK2>, + <&cpg CPG_MOD R9A08G045_SSI3_PCLK_SFR>, + <&audio_clk1>, <&audio_clk2>; + clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2"; + resets = <&cpg R9A08G045_SSI3_RST_M2_REG>; + dmas = <&dmac 0x2671>, <&dmac 0x2672>; + dma-names = "tx", "rx"; + power-domains = <&cpg>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + cpg: clock-controller@11010000 { compatible = "renesas,r9a08g045-cpg"; reg = <0 0x11010000 0 0x10000>;
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Add versa3 clock generator node. It provides the clocks for the Ethernet PHY, PCIe, audio devices.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Reviewed-by: Biju Das biju.das.jz@bp.renesas.com Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - none
Changes in v2: - none
.../boot/dts/renesas/rzg3s-smarc-som.dtsi | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi index 2ed01d391554..6e58d47d85b0 100644 --- a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi @@ -92,6 +92,12 @@ vcc_sdhi2: regulator2 { gpios = <&pinctrl RZG2L_GPIO(8, 1) GPIO_ACTIVE_HIGH>; enable-active-high; }; + + x3_clk: x3-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + }; };
#if SW_CONFIG3 == SW_ON @@ -152,6 +158,30 @@ &extal_clk {
&i2c1 { status = "okay"; + + versa3: clock-generator@68 { + compatible = "renesas,5l35023"; + reg = <0x68>; + clocks = <&x3_clk>; + #clock-cells = <1>; + assigned-clocks = <&versa3 0>, + <&versa3 1>, + <&versa3 2>, + <&versa3 3>, + <&versa3 4>, + <&versa3 5>; + assigned-clock-rates = <24000000>, + <12288000>, + <11289600>, + <25000000>, + <100000000>, + <100000000>; + renesas,settings = [ + 80 00 11 19 4c 42 dc 2f 06 7d 20 1a 5f 1e f2 27 + 00 40 00 00 00 00 00 00 06 0c 19 02 3f f0 90 86 + a0 80 30 30 9c + ]; + }; };
#if SW_CONFIG2 == SW_ON
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Add the da7212 audio codec node. Along with it regulators nodes were reworked to be able to re-use them on da7212.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags - dropped #address-cells, #size-cells - moved #sound-dai-cells after clock names to align with the documentation example
Changes in v3: - none
Changes in v2: - none
.../boot/dts/renesas/rzg3s-smarc-som.dtsi | 17 ++++++++++----- arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi | 21 +++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi index 6e58d47d85b0..5ee9dac4aebb 100644 --- a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi @@ -63,7 +63,6 @@ vcc_sdhi0: regulator0 { enable-active-high; };
-#if SW_CONFIG2 == SW_ON vccq_sdhi0: regulator1 { compatible = "regulator-gpio"; regulator-name = "SDHI0 VccQ"; @@ -73,8 +72,8 @@ vccq_sdhi0: regulator1 { gpios-states = <1>; states = <3300000 1>, <1800000 0>; }; -#else - reg_1p8v: regulator1 { + + reg_1p8v: regulator2 { compatible = "regulator-fixed"; regulator-name = "fixed-1.8V"; regulator-min-microvolt = <1800000>; @@ -82,9 +81,17 @@ reg_1p8v: regulator1 { regulator-boot-on; regulator-always-on; }; -#endif
- vcc_sdhi2: regulator2 { + reg_3p3v: regulator3 { + compatible = "regulator-fixed"; + regulator-name = "fixed-3.3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + vcc_sdhi2: regulator4 { compatible = "regulator-fixed"; regulator-name = "SDHI2 Vcc"; regulator-min-microvolt = <3300000>; diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi index ee19c4155750..899d88467d79 100644 --- a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi @@ -68,6 +68,27 @@ &i2c0 { status = "okay";
clock-frequency = <1000000>; + + da7212: codec@1a { + compatible = "dlg,da7212"; + reg = <0x1a>; + + clocks = <&versa3 1>; + clock-names = "mclk"; + + #sound-dai-cells = <0>; + + dlg,micbias1-lvl = <2500>; + dlg,micbias2-lvl = <2500>; + dlg,dmic-data-sel = "lrise_rfall"; + dlg,dmic-samplephase = "between_clkedge"; + dlg,dmic-clkrate = <3000000>; + + VDDA-supply = <®_1p8v>; + VDDSP-supply = <®_3p3v>; + VDDMIC-supply = <®_3p3v>; + VDDIO-supply = <®_1p8v>; + }; };
&i2c1 {
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Enable SSI3.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags - dropped status for audio_clk2
Changes in v3: - none
Changes in v2: - none
arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi index 899d88467d79..1944468a2961 100644 --- a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi @@ -64,6 +64,10 @@ vccq_sdhi1: regulator-vccq-sdhi1 { }; };
+&audio_clk2 { + clock-frequency = <12288000>; +}; + &i2c0 { status = "okay";
@@ -105,6 +109,11 @@ power-monitor@44 { };
&pinctrl { + audio_clock_pins: audio-clock { + pins = "AUDIO_CLK1", "AUDIO_CLK2"; + input-enable; + }; + key-1-gpio-hog { gpio-hog; gpios = <RZG2L_GPIO(18, 0) GPIO_ACTIVE_LOW>; @@ -162,6 +171,13 @@ cd { pinmux = <RZG2L_PORT_PINMUX(0, 2, 1)>; /* SD1_CD */ }; }; + + ssi3_pins: ssi3 { + pinmux = <RZG2L_PORT_PINMUX(18, 2, 8)>, /* BCK */ + <RZG2L_PORT_PINMUX(18, 3, 8)>, /* RCK */ + <RZG2L_PORT_PINMUX(18, 4, 8)>, /* TXD */ + <RZG2L_PORT_PINMUX(18, 5, 8)>; /* RXD */ + }; };
&scif0 { @@ -182,3 +198,12 @@ &sdhi1 { max-frequency = <125000000>; status = "okay"; }; + +&ssi3 { + clocks = <&cpg CPG_MOD R9A08G045_SSI3_PCLK2>, + <&cpg CPG_MOD R9A08G045_SSI3_PCLK_SFR>, + <&versa3 2>, <&audio_clk2>; + pinctrl-names = "default"; + pinctrl-0 = <&ssi3_pins>, <&audio_clock_pins>; + status = "okay"; +};
From: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com
Add sound card with SSI3 as CPU DAI and DA7212 as codec DAI.
Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Signed-off-by: Claudiu Beznea claudiu.beznea.uj@bp.renesas.com ---
Changes in v4: - collected tags
Changes in v3: - none
Changes in v2: - none
arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi index 1944468a2961..5329f3461990 100644 --- a/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi +++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc.dtsi @@ -44,6 +44,23 @@ key-3 { }; };
+ snd_rzg3s: sound { + compatible = "simple-audio-card"; + simple-audio-card,format = "i2s"; + simple-audio-card,bitclock-master = <&cpu_dai>; + simple-audio-card,frame-master = <&cpu_dai>; + simple-audio-card,mclk-fs = <256>; + + cpu_dai: simple-audio-card,cpu { + sound-dai = <&ssi3>; + }; + + codec_dai: simple-audio-card,codec { + sound-dai = <&da7212>; + clocks = <&versa3 1>; + }; + }; + vcc_sdhi1: regulator-vcc-sdhi1 { compatible = "regulator-fixed"; regulator-name = "SDHI1 Vcc";
participants (2)
-
Claudiu
-
Stephen Boyd