All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC
@ 2022-04-20 21:34 Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 01/24] ASoC: dt-bindings: Document RZ/G2L bindings Lad Prabhakar
                   ` (24 more replies)
  0 siblings, 25 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

Hi All,

This patch series adds sound support to Renesas RZ/G2L SoC and enables
SSI and codec on Renesas RZ/G2L SMARC EVK.

All the patches have been cherry picked from v5.18-rc3.

Sound support patches were already sent earlier as part of bulk series
[0], but due to some review comments the patches were rejected, now that
the driver is fixed upstream, re-sending the series with all the fixes.

[0] https://patchwork.kernel.org/project/cip-dev/cover/
20211229101530.22783-1-prabhakar.mahadev-lad.rj@bp.renesas.com/

Cheers,
Prabhakar

Biju Das (16):
  ASoC: dt-bindings: Document RZ/G2L bindings
  ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support
  ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel
    configuration parameter
  ASoC: sh: Add RZ/G2L SSIF-2 driver
  ASoC: sh: rz-ssi: Add SSI DMAC support
  ASoC: sh: rz-ssi: Fix dereference of noderef expression warning
  ASoC: sh: rz-ssi: Fix wrong operator used issue
  ASoC: sh: rz-ssi: Improve error handling in rz_ssi_dma_request
    function
  arm64: dts: renesas: r9a07g044: Add external audio clock nodes
  arm64: dts: renesas: r9a07g044: Add SSI support
  arm64: dts: renesas: r9a07g044: Add DMA support to SSI
  arm64: dts: renesas: rzg2l-smarc: Add WM8978 sound codec
  arm64: dts: renesas: rzg2l-smarc: Enable audio
  arm64: dts: renesas: rzg2l-smarc: Add Mic routing
  arm64: defconfig: Enable SOUND_SOC_RZ
  arm64: defconfig: Enable SND_SOC_WM8978

Heiner Kallweit (1):
  ASoC: sh: rz-ssi: Check return value of pm_runtime_resume_and_get()

Lad Prabhakar (7):
  ASoC: sh: rz-ssi: Drop calling rz_ssi_pio_recv() recursively
  ASoC: sh: rz-ssi: Make the data structures available before
    registering the handlers
  ASoC: sh: rz-ssi: Drop ssi parameter from rz_ssi_stream_init()
  ASoC: sh: rz-ssi: Make return type of rz_ssi_stream_is_valid() to bool
  ASoC: sh: rz-ssi: Use a do-while loop in rz_ssi_pio_recv()
  ASoC: sh: rz-ssi: Add rz_ssi_set_substream() helper function
  ASoC: sh: rz-ssi: Remove duplicate macros

 .../bindings/sound/renesas,rz-ssi.yaml        |  118 ++
 arch/arm64/boot/dts/renesas/r9a07g044.dtsi    |   98 ++
 arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi  |   79 ++
 arch/arm64/configs/defconfig                  |    2 +
 sound/soc/sh/Kconfig                          |    6 +
 sound/soc/sh/Makefile                         |    4 +
 sound/soc/sh/rz-ssi.c                         | 1078 +++++++++++++++++
 7 files changed, 1385 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
 create mode 100644 sound/soc/sh/rz-ssi.c

-- 
2.17.1



^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 01/24] ASoC: dt-bindings: Document RZ/G2L bindings
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 02/24] ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support Lad Prabhakar
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 2b761f476f3a6e0a212c8c88e7855f66edb177e0 upstream.

Document RZ/G2L ASoC serial sound interface bindings.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20210719134040.7964-2-biju.das.jz@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 .../bindings/sound/renesas,rz-ssi.yaml        | 85 +++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml

diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
new file mode 100644
index 000000000000..891f381ee5b8
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/renesas,rz-ssi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L ASoC Sound Serial Interface (SSIF-2)
+
+maintainers:
+  - Biju Das <biju.das.jz@bp.renesas.com>
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - renesas,r9a07g044-ssi  # RZ/G2{L,LC}
+      - const: renesas,rz-ssi
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 4
+
+  interrupt-names:
+    items:
+      - const: int_req
+      - const: dma_rx
+      - const: dma_tx
+      - const: dma_rt
+
+  clocks:
+    maxItems: 4
+
+  clock-names:
+    items:
+      - const: ssi
+      - const: ssi_sfr
+      - const: audio_clk1
+      - const: audio_clk2
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  '#sound-dai-cells':
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - interrupt-names
+  - clocks
+  - clock-names
+  - resets
+  - '#sound-dai-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/r9a07g044-cpg.h>
+
+    ssi0: ssi@10049c00 {
+        compatible = "renesas,r9a07g044-ssi",
+                     "renesas,rz-ssi";
+            reg = <0x10049c00 0x400>;
+            interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
+                         <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
+                         <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>;
+            interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
+            clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
+                     <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
+                     <&audio_clk1>,
+                     <&audio_clk2>;
+            clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
+            power-domains = <&cpg>;
+            resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
+            #sound-dai-cells = <0>;
+    };
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 02/24] ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 01/24] ASoC: dt-bindings: Document RZ/G2L bindings Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 03/24] ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel configuration parameter Lad Prabhakar
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 5df6dfbb6de815ba3a75c788a916865212fd5221 upstream.

Document DMA support in binding document.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20210719134040.7964-7-biju.das.jz@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 .../devicetree/bindings/sound/renesas,rz-ssi.yaml | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
index 891f381ee5b8..471937cb8d05 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
+++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
@@ -45,6 +45,18 @@ properties:
   resets:
     maxItems: 1
 
+  dmas:
+    minItems: 1
+    maxItems: 2
+
+  dma-names:
+    oneOf:
+      - items:
+          - const: tx
+          - const: rx
+      - items:
+          - const: rt
+
   '#sound-dai-cells':
     const: 0
 
@@ -81,5 +93,8 @@ examples:
             clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
             power-domains = <&cpg>;
             resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
+            dmas = <&dmac 0x255>,
+                   <&dmac 0x256>;
+            dma-names = "tx", "rx";
             #sound-dai-cells = <0>;
     };
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 03/24] ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel configuration parameter
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 01/24] ASoC: dt-bindings: Document RZ/G2L bindings Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 02/24] ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-21  8:32   ` Pavel Machek
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver Lad Prabhakar
                   ` (21 subsequent siblings)
  24 siblings, 1 reply; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit bed0b1c1e88a27b76c74584128cadebc6fa58622 upstream.

The DMAC on RZ/G2L has specific slave channel configuration
parameters for SSI.
This patch updates the dmas description and example node to include
the encoded slave channel configuration.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210813091156.10700-3-biju.das.jz@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 .../bindings/sound/renesas,rz-ssi.yaml        | 22 +++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
index 471937cb8d05..414ff8035a4e 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
+++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
@@ -48,6 +48,24 @@ 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:
@@ -93,8 +111,8 @@ examples:
             clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
             power-domains = <&cpg>;
             resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
-            dmas = <&dmac 0x255>,
-                   <&dmac 0x256>;
+            dmas = <&dmac 0x2655>,
+                   <&dmac 0x2656>;
             dma-names = "tx", "rx";
             #sound-dai-cells = <0>;
     };
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (2 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 03/24] ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel configuration parameter Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-21  1:12   ` nobuhiro1.iwamatsu
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 05/24] ASoC: sh: rz-ssi: Add SSI DMAC support Lad Prabhakar
                   ` (20 subsequent siblings)
  24 siblings, 1 reply; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 03e786bd43410fa93e5d2459f7a43e90ff0ae801 upstream.

Add serial sound interface(SSIF-2) driver support for
RZ/G2L SoC.

Based on the work done by Chris Brandt for RZ/A SSI driver.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210813091156.10700-2-biju.das.jz@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
[PL: Dropped using modern terminology]
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/Kconfig  |   6 +
 sound/soc/sh/Makefile |   4 +
 sound/soc/sh/rz-ssi.c | 871 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 881 insertions(+)
 create mode 100644 sound/soc/sh/rz-ssi.c

diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index ef8a29b9f641..f19bd15c0900 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -44,6 +44,12 @@ config SND_SOC_RCAR
 	help
 	  This option enables R-Car SRU/SCU/SSIU/SSI sound support
 
+config SND_SOC_RZ
+	tristate "RZ/G2L series SSIF-2 support"
+	depends on ARCH_R9A07G044 || COMPILE_TEST
+	help
+	  This option enables RZ/G2L SSIF-2 sound support.
+
 ##
 ## Boards
 ##
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index 51bd7c81671c..f6fd79948f6a 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -22,3 +22,7 @@ snd-soc-migor-objs		:= migor.o
 
 obj-$(CONFIG_SND_SH7760_AC97)	+= snd-soc-sh7760-ac97.o
 obj-$(CONFIG_SND_SIU_MIGOR)	+= snd-soc-migor.o
+
+# RZ/G2L
+snd-soc-rz-ssi-objs		:= rz-ssi.o
+obj-$(CONFIG_SND_SOC_RZ)	+= snd-soc-rz-ssi.o
diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
new file mode 100644
index 000000000000..7e0d3a4485e3
--- /dev/null
+++ b/sound/soc/sh/rz-ssi.c
@@ -0,0 +1,871 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Renesas RZ/G2L ASoC Serial Sound Interface (SSIF-2) Driver
+//
+// Copyright (C) 2021 Renesas Electronics Corp.
+// Copyright (C) 2019 Chris Brandt.
+//
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <sound/soc.h>
+
+/* REGISTER OFFSET */
+#define SSICR			0x000
+#define SSISR			0x004
+#define SSIFCR			0x010
+#define SSIFSR			0x014
+#define SSIFTDR			0x018
+#define SSIFRDR			0x01c
+#define SSIOFR			0x020
+#define SSISCR			0x024
+
+/* SSI REGISTER BITS */
+#define SSICR_DWL(x)		(((x) & 0x7) << 19)
+#define SSICR_SWL(x)		(((x) & 0x7) << 16)
+#define SSICR_MST		BIT(14)
+#define SSICR_CKDV(x)		(((x) & 0xf) << 4)
+
+#define SSICR_CKS		BIT(30)
+#define SSICR_TUIEN		BIT(29)
+#define SSICR_TOIEN		BIT(28)
+#define SSICR_RUIEN		BIT(27)
+#define SSICR_ROIEN		BIT(26)
+#define SSICR_MST		BIT(14)
+#define SSICR_BCKP		BIT(13)
+#define SSICR_LRCKP		BIT(12)
+#define SSICR_CKDV(x)		(((x) & 0xf) << 4)
+#define SSICR_TEN		BIT(1)
+#define SSICR_REN		BIT(0)
+
+#define SSISR_TUIRQ		BIT(29)
+#define SSISR_TOIRQ		BIT(28)
+#define SSISR_RUIRQ		BIT(27)
+#define SSISR_ROIRQ		BIT(26)
+#define SSISR_IIRQ		BIT(25)
+
+#define SSIFCR_AUCKE		BIT(31)
+#define SSIFCR_SSIRST		BIT(16)
+#define SSIFCR_TIE		BIT(3)
+#define SSIFCR_RIE		BIT(2)
+#define SSIFCR_TFRST		BIT(1)
+#define SSIFCR_RFRST		BIT(0)
+
+#define SSIFSR_TDC_MASK		0x3f
+#define SSIFSR_TDC_SHIFT	24
+#define SSIFSR_RDC_MASK		0x3f
+#define SSIFSR_RDC_SHIFT	8
+
+#define SSIFSR_TDC(x)		(((x) & 0x1f) << 24)
+#define SSIFSR_TDE		BIT(16)
+#define SSIFSR_RDC(x)		(((x) & 0x1f) << 8)
+#define SSIFSR_RDF		BIT(0)
+
+#define SSIOFR_LRCONT		BIT(8)
+
+#define SSISCR_TDES(x)		(((x) & 0x1f) << 8)
+#define SSISCR_RDFS(x)		(((x) & 0x1f) << 0)
+
+/* Pre allocated buffers sizes */
+#define PREALLOC_BUFFER		(SZ_32K)
+#define PREALLOC_BUFFER_MAX	(SZ_32K)
+
+#define SSI_RATES		SNDRV_PCM_RATE_8000_48000 /* 8k-44.1kHz */
+#define SSI_FMTS		SNDRV_PCM_FMTBIT_S16_LE
+#define SSI_CHAN_MIN		2
+#define SSI_CHAN_MAX		2
+#define SSI_FIFO_DEPTH		32
+
+struct rz_ssi_priv;
+
+struct rz_ssi_stream {
+	struct rz_ssi_priv *priv;
+	struct snd_pcm_substream *substream;
+	int fifo_sample_size;	/* sample capacity of SSI FIFO */
+	int period_counter;	/* for keeping track of periods transferred */
+	int sample_width;
+	int buffer_pos;		/* current frame position in the buffer */
+	int running;		/* 0=stopped, 1=running */
+
+	int uerr_num;
+	int oerr_num;
+
+	int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm);
+};
+
+struct rz_ssi_priv {
+	void __iomem *base;
+	struct platform_device *pdev;
+	struct reset_control *rstc;
+	struct device *dev;
+	struct clk *sfr_clk;
+	struct clk *clk;
+
+	int irq_int;
+	int irq_tx;
+	int irq_rx;
+
+	spinlock_t lock;
+
+	/*
+	 * The SSI supports full-duplex transmission and reception.
+	 * However, if an error occurs, channel reset (both transmission
+	 * and reception reset) is required.
+	 * So it is better to use as half-duplex (playing and recording
+	 * should be done on separate channels).
+	 */
+	struct rz_ssi_stream playback;
+	struct rz_ssi_stream capture;
+
+	/* clock */
+	unsigned long audio_mck;
+	unsigned long audio_clk_1;
+	unsigned long audio_clk_2;
+
+	bool lrckp_fsync_fall;	/* LR clock polarity (SSICR.LRCKP) */
+	bool bckp_rise;	/* Bit clock polarity (SSICR.BCKP) */
+};
+
+static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data)
+{
+	writel(data, (priv->base + reg));
+}
+
+static u32 rz_ssi_reg_readl(struct rz_ssi_priv *priv, uint reg)
+{
+	return readl(priv->base + reg);
+}
+
+static void rz_ssi_reg_mask_setl(struct rz_ssi_priv __iomem *priv, uint reg,
+				 u32 bclr, u32 bset)
+{
+	u32 val;
+
+	val = readl(priv->base + reg);
+	val = (val & ~bclr) | bset;
+	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 = asoc_substream_to_rtd(substream);
+
+	return asoc_rtd_to_cpu(rtd, 0);
+}
+
+static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi,
+					 struct snd_pcm_substream *substream)
+{
+	return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+}
+
+static inline struct rz_ssi_stream *
+rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
+{
+	struct rz_ssi_stream *stream = &ssi->playback;
+
+	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+		stream = &ssi->capture;
+
+	return stream;
+}
+
+static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
+				  struct rz_ssi_stream *strm)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&ssi->lock, flags);
+	ret = !!(strm->substream && strm->substream->runtime);
+	spin_unlock_irqrestore(&ssi->lock, flags);
+
+	return ret;
+}
+
+static int rz_ssi_stream_init(struct rz_ssi_priv *ssi,
+			      struct rz_ssi_stream *strm,
+			      struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	strm->substream = substream;
+	strm->sample_width = samples_to_bytes(runtime, 1);
+	strm->period_counter = 0;
+	strm->buffer_pos = 0;
+
+	strm->oerr_num = 0;
+	strm->uerr_num = 0;
+	strm->running = 0;
+
+	/* fifo init */
+	strm->fifo_sample_size = SSI_FIFO_DEPTH;
+
+	return 0;
+}
+
+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);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ssi->lock, flags);
+	strm->substream = NULL;
+	spin_unlock_irqrestore(&ssi->lock, flags);
+
+	if (strm->oerr_num > 0)
+		dev_info(dai->dev, "overrun = %d\n", strm->oerr_num);
+
+	if (strm->uerr_num > 0)
+		dev_info(dai->dev, "underrun = %d\n", strm->uerr_num);
+}
+
+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 };
+	unsigned int channel_bits = 32;	/* System Word Length */
+	unsigned long bclk_rate = rate * channels * channel_bits;
+	unsigned int div;
+	unsigned int i;
+	u32 ssicr = 0;
+	u32 clk_ckdv;
+
+	/* Clear AUCKE so we can set MST */
+	rz_ssi_reg_writel(ssi, SSIFCR, 0);
+
+	/* Continue to output LRCK pin even when idle */
+	rz_ssi_reg_writel(ssi, SSIOFR, SSIOFR_LRCONT);
+	if (ssi->audio_clk_1 && ssi->audio_clk_2) {
+		if (ssi->audio_clk_1 % bclk_rate)
+			ssi->audio_mck = ssi->audio_clk_2;
+		else
+			ssi->audio_mck = ssi->audio_clk_1;
+	}
+
+	/* Clock setting */
+	ssicr |= SSICR_MST;
+	if (ssi->audio_mck == ssi->audio_clk_1)
+		ssicr |= SSICR_CKS;
+	if (ssi->bckp_rise)
+		ssicr |= SSICR_BCKP;
+	if (ssi->lrckp_fsync_fall)
+		ssicr |= SSICR_LRCKP;
+
+	/* Determine the clock divider */
+	clk_ckdv = 0;
+	div = ssi->audio_mck / bclk_rate;
+	/* try to find an match */
+	for (i = 0; i < ARRAY_SIZE(ckdv); i++) {
+		if (ckdv[i] == div) {
+			clk_ckdv = i;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(ckdv)) {
+		dev_err(ssi->dev, "Rate not divisible by audio clock source\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * DWL: Data Word Length = 16 bits
+	 * SWL: System Word Length = 32 bits
+	 */
+	ssicr |= SSICR_CKDV(clk_ckdv);
+	ssicr |= SSICR_DWL(1) | SSICR_SWL(3);
+	rz_ssi_reg_writel(ssi, SSICR, ssicr);
+	rz_ssi_reg_writel(ssi, SSIFCR,
+			  (SSIFCR_AUCKE | SSIFCR_TFRST | SSIFCR_RFRST));
+
+	return 0;
+}
+
+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);
+	u32 ssicr, ssifcr;
+
+	ssicr = rz_ssi_reg_readl(ssi, SSICR);
+	ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF;
+
+	/* FIFO interrupt thresholds */
+	rz_ssi_reg_writel(ssi, SSISCR,
+			  SSISCR_TDES(strm->fifo_sample_size / 2 - 1) |
+			  SSISCR_RDFS(0));
+
+	/* enable IRQ */
+	if (is_play) {
+		ssicr |= SSICR_TUIEN | SSICR_TOIEN;
+		ssifcr |= SSIFCR_TIE | SSIFCR_RFRST;
+	} else {
+		ssicr |= SSICR_RUIEN | SSICR_ROIEN;
+		ssifcr |= SSIFCR_RIE | SSIFCR_TFRST;
+	}
+
+	rz_ssi_reg_writel(ssi, SSICR, ssicr);
+	rz_ssi_reg_writel(ssi, SSIFCR, ssifcr);
+
+	/* Clear all error flags */
+	rz_ssi_reg_mask_setl(ssi, SSISR,
+			     (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
+			      SSISR_RUIRQ), 0);
+
+	strm->running = 1;
+	ssicr |= is_play ? SSICR_TEN : SSICR_REN;
+	rz_ssi_reg_writel(ssi, SSICR, ssicr);
+
+	return 0;
+}
+
+static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+	int timeout;
+
+	strm->running = 0;
+
+	/* Disable TX/RX */
+	rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
+
+	/* Disable irqs */
+	rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN |
+			     SSICR_RUIEN | SSICR_ROIEN, 0);
+	rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0);
+
+	/* Clear all error flags */
+	rz_ssi_reg_mask_setl(ssi, SSISR,
+			     (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
+			      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");
+
+	/* Hold FIFOs in reset */
+	rz_ssi_reg_mask_setl(ssi, SSIFCR, 0,
+			     SSIFCR_TFRST | SSIFCR_RFRST);
+
+	return 0;
+}
+
+static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames)
+{
+	struct snd_pcm_substream *substream = strm->substream;
+	struct snd_pcm_runtime *runtime;
+	int current_period;
+
+	if (!strm->running || !substream || !substream->runtime)
+		return;
+
+	runtime = substream->runtime;
+	strm->buffer_pos += frames;
+	WARN_ON(strm->buffer_pos > runtime->buffer_size);
+
+	/* ring buffer */
+	if (strm->buffer_pos == runtime->buffer_size)
+		strm->buffer_pos = 0;
+
+	current_period = strm->buffer_pos / runtime->period_size;
+	if (strm->period_counter != current_period) {
+		snd_pcm_period_elapsed(strm->substream);
+		strm->period_counter = current_period;
+	}
+}
+
+static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+	struct snd_pcm_substream *substream = strm->substream;
+	struct snd_pcm_runtime *runtime;
+	u16 *buf;
+	int fifo_samples;
+	int frames_left;
+	int samples = 0;
+	int i;
+
+	if (!rz_ssi_stream_is_valid(ssi, strm))
+		return -EINVAL;
+
+	runtime = substream->runtime;
+	/* frames left in this period */
+	frames_left = runtime->period_size - (strm->buffer_pos %
+					      runtime->period_size);
+	if (frames_left == 0)
+		frames_left = runtime->period_size;
+
+	/* Samples in RX FIFO */
+	fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
+			SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
+
+	/* Only read full frames at a time */
+	while (frames_left && (fifo_samples >= runtime->channels)) {
+		samples += runtime->channels;
+		fifo_samples -= runtime->channels;
+		frames_left--;
+	}
+
+	/* not enough samples yet */
+	if (samples == 0)
+		return 0;
+
+	/* calculate new buffer index */
+	buf = (u16 *)(runtime->dma_area);
+	buf += strm->buffer_pos * runtime->channels;
+
+	/* Note, only supports 16-bit samples */
+	for (i = 0; i < samples; i++)
+		*buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
+
+	rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
+	rz_ssi_pointer_update(strm, samples / runtime->channels);
+
+	/*
+	 * If we finished this period, but there are more samples in
+	 * the RX FIFO, call this function again
+	 */
+	if (frames_left == 0 && fifo_samples >= runtime->channels)
+		rz_ssi_pio_recv(ssi, strm);
+
+	return 0;
+}
+
+static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
+{
+	struct snd_pcm_substream *substream = strm->substream;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int sample_space;
+	int samples = 0;
+	int frames_left;
+	int i;
+	u32 ssifsr;
+	u16 *buf;
+
+	if (!rz_ssi_stream_is_valid(ssi, strm))
+		return -EINVAL;
+
+	/* frames left in this period */
+	frames_left = runtime->period_size - (strm->buffer_pos %
+					      runtime->period_size);
+	if (frames_left == 0)
+		frames_left = runtime->period_size;
+
+	sample_space = strm->fifo_sample_size;
+	ssifsr = rz_ssi_reg_readl(ssi, SSIFSR);
+	sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) & SSIFSR_TDC_MASK;
+
+	/* Only add full frames at a time */
+	while (frames_left && (sample_space >= runtime->channels)) {
+		samples += runtime->channels;
+		sample_space -= runtime->channels;
+		frames_left--;
+	}
+
+	/* no space to send anything right now */
+	if (samples == 0)
+		return 0;
+
+	/* calculate new buffer index */
+	buf = (u16 *)(runtime->dma_area);
+	buf += strm->buffer_pos * runtime->channels;
+
+	/* Note, only supports 16-bit samples */
+	for (i = 0; i < samples; i++)
+		rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16));
+
+	rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_TDE, 0);
+	rz_ssi_pointer_update(strm, samples / runtime->channels);
+
+	return 0;
+}
+
+static irqreturn_t rz_ssi_interrupt(int irq, void *data)
+{
+	struct rz_ssi_stream *strm = NULL;
+	struct rz_ssi_priv *ssi = data;
+	u32 ssisr = rz_ssi_reg_readl(ssi, SSISR);
+
+	if (ssi->playback.substream)
+		strm = &ssi->playback;
+	else if (ssi->capture.substream)
+		strm = &ssi->capture;
+	else
+		return IRQ_HANDLED; /* Left over TX/RX interrupt */
+
+	if (irq == ssi->irq_int) { /* error or idle */
+		if (ssisr & SSISR_TUIRQ)
+			strm->uerr_num++;
+		if (ssisr & SSISR_TOIRQ)
+			strm->oerr_num++;
+		if (ssisr & SSISR_RUIRQ)
+			strm->uerr_num++;
+		if (ssisr & SSISR_ROIRQ)
+			strm->oerr_num++;
+
+		if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ |
+			     SSISR_ROIRQ)) {
+			/* Error handling */
+			/* You must reset (stop/restart) after each interrupt */
+			rz_ssi_stop(ssi, strm);
+
+			/* Clear all flags */
+			rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ |
+					     SSISR_TUIRQ | SSISR_ROIRQ |
+					     SSISR_RUIRQ, 0);
+
+			/* Add/remove more data */
+			strm->transfer(ssi, strm);
+
+			/* Resume */
+			rz_ssi_start(ssi, strm);
+		}
+	}
+
+	if (!strm->running)
+		return IRQ_HANDLED;
+
+	/* tx data empty */
+	if (irq == ssi->irq_tx)
+		strm->transfer(ssi, &ssi->playback);
+
+	/* rx data full */
+	if (irq == ssi->irq_rx) {
+		strm->transfer(ssi, &ssi->capture);
+		rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+			      struct snd_soc_dai *dai)
+{
+	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+	struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
+	int ret = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* Soft Reset */
+		rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST);
+		rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0);
+		udelay(5);
+
+		ret = rz_ssi_stream_init(ssi, strm, substream);
+		if (ret)
+			goto done;
+
+		ret = strm->transfer(ssi, strm);
+		if (ret)
+			goto done;
+
+		ret = rz_ssi_start(ssi, strm);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		rz_ssi_stop(ssi, strm);
+		rz_ssi_stream_quit(ssi, strm);
+		break;
+	}
+
+done:
+	return ret;
+}
+
+static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		dev_err(ssi->dev, "Codec should be clk and frame consumer\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * set clock polarity
+	 *
+	 * "normal" BCLK = Signal is available at rising edge of BCLK
+	 * "normal" FSYNC = (I2S) Left ch starts with falling FSYNC edge
+	 */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		ssi->bckp_rise = false;
+		ssi->lrckp_fsync_fall = false;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		ssi->bckp_rise = false;
+		ssi->lrckp_fsync_fall = true;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		ssi->bckp_rise = true;
+		ssi->lrckp_fsync_fall = false;
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		ssi->bckp_rise = true;
+		ssi->lrckp_fsync_fall = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* only i2s support */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	default:
+		dev_err(ssi->dev, "Only I2S mode is supported.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+	unsigned int sample_bits = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
+	unsigned int channels = params_channels(params);
+
+	if (sample_bits != 16) {
+		dev_err(ssi->dev, "Unsupported sample width: %d\n",
+			sample_bits);
+		return -EINVAL;
+	}
+
+	if (channels != 2) {
+		dev_err(ssi->dev, "Number of channels not matched: %d\n",
+			channels);
+		return -EINVAL;
+	}
+
+	return rz_ssi_clk_setup(ssi, params_rate(params),
+				params_channels(params));
+}
+
+static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
+	.trigger	= rz_ssi_dai_trigger,
+	.set_fmt	= rz_ssi_dai_set_fmt,
+	.hw_params	= rz_ssi_dai_hw_params,
+};
+
+static const struct snd_pcm_hardware rz_ssi_pcm_hardware = {
+	.info			= SNDRV_PCM_INFO_INTERLEAVED	|
+				  SNDRV_PCM_INFO_MMAP		|
+				  SNDRV_PCM_INFO_MMAP_VALID,
+	.buffer_bytes_max	= PREALLOC_BUFFER,
+	.period_bytes_min	= 32,
+	.period_bytes_max	= 8192,
+	.channels_min		= SSI_CHAN_MIN,
+	.channels_max		= SSI_CHAN_MAX,
+	.periods_min		= 1,
+	.periods_max		= 32,
+	.fifo_size		= 32 * 2,
+};
+
+static int rz_ssi_pcm_open(struct snd_soc_component *component,
+			   struct snd_pcm_substream *substream)
+{
+	snd_soc_set_runtime_hwparams(substream, &rz_ssi_pcm_hardware);
+
+	return snd_pcm_hw_constraint_integer(substream->runtime,
+					    SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+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 rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+	struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
+
+	return strm->buffer_pos;
+}
+
+static int rz_ssi_pcm_new(struct snd_soc_component *component,
+			  struct snd_soc_pcm_runtime *rtd)
+{
+	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
+				       rtd->card->snd_card->dev,
+				       PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
+	return 0;
+}
+
+static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
+	{
+		.name			= "rz-ssi-dai",
+		.playback = {
+			.rates		= SSI_RATES,
+			.formats	= SSI_FMTS,
+			.channels_min	= SSI_CHAN_MIN,
+			.channels_max	= SSI_CHAN_MAX,
+		},
+		.capture = {
+			.rates		= SSI_RATES,
+			.formats	= SSI_FMTS,
+			.channels_min	= SSI_CHAN_MIN,
+			.channels_max	= SSI_CHAN_MAX,
+		},
+		.ops = &rz_ssi_dai_ops,
+	},
+};
+
+static const struct snd_soc_component_driver rz_ssi_soc_component = {
+	.name		= "rz-ssi",
+	.open		= rz_ssi_pcm_open,
+	.pointer	= rz_ssi_pcm_pointer,
+	.pcm_construct	= rz_ssi_pcm_new,
+};
+
+static int rz_ssi_probe(struct platform_device *pdev)
+{
+	struct rz_ssi_priv *ssi;
+	struct clk *audio_clk;
+	int ret;
+
+	ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL);
+	if (!ssi)
+		return -ENOMEM;
+
+	ssi->pdev = pdev;
+	ssi->dev = &pdev->dev;
+	ssi->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(ssi->base))
+		return PTR_ERR(ssi->base);
+
+	ssi->clk = devm_clk_get(&pdev->dev, "ssi");
+	if (IS_ERR(ssi->clk))
+		return PTR_ERR(ssi->clk);
+
+	ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr");
+	if (IS_ERR(ssi->sfr_clk))
+		return PTR_ERR(ssi->sfr_clk);
+
+	audio_clk = devm_clk_get(&pdev->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");
+	if (IS_ERR(audio_clk))
+		return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk),
+				     "no audio clk2");
+
+	ssi->audio_clk_2 = clk_get_rate(audio_clk);
+	if (!(ssi->audio_clk_1 || ssi->audio_clk_2))
+		return dev_err_probe(&pdev->dev, -EINVAL,
+				     "no audio clk1 or audio clk2");
+
+	ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
+
+	ssi->playback.transfer = rz_ssi_pio_send;
+	ssi->capture.transfer = rz_ssi_pio_recv;
+	ssi->playback.priv = ssi;
+	ssi->capture.priv = ssi;
+
+	/* Error Interrupt */
+	ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
+	if (ssi->irq_int < 0)
+		return dev_err_probe(&pdev->dev, -ENODEV,
+				     "Unable to get SSI int_req IRQ\n");
+
+	ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt,
+			       0, dev_name(&pdev->dev), ssi);
+	if (ret < 0)
+		return dev_err_probe(&pdev->dev, ret,
+				     "irq request error (int_req)\n");
+
+	/* Tx and Rx interrupts (pio only) */
+	ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx");
+	if (ssi->irq_tx < 0)
+		return dev_err_probe(&pdev->dev, -ENODEV,
+				     "Unable to get SSI dma_tx IRQ\n");
+
+	ret = devm_request_irq(&pdev->dev, ssi->irq_tx, &rz_ssi_interrupt, 0,
+			       dev_name(&pdev->dev), ssi);
+	if (ret < 0)
+		return dev_err_probe(&pdev->dev, ret,
+				     "irq request error (dma_tx)\n");
+
+	ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx");
+	if (ssi->irq_rx < 0)
+		return dev_err_probe(&pdev->dev, -ENODEV,
+				     "Unable to get SSI dma_rx IRQ\n");
+
+	ret = devm_request_irq(&pdev->dev, ssi->irq_rx, &rz_ssi_interrupt, 0,
+			       dev_name(&pdev->dev), ssi);
+	if (ret < 0)
+		return dev_err_probe(&pdev->dev, ret,
+				     "irq request error (dma_rx)\n");
+
+	ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+	if (IS_ERR(ssi->rstc))
+		return PTR_ERR(ssi->rstc);
+
+	reset_control_deassert(ssi->rstc);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_resume_and_get(&pdev->dev);
+
+	spin_lock_init(&ssi->lock);
+	dev_set_drvdata(&pdev->dev, ssi);
+	ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component,
+					      rz_ssi_soc_dai,
+					      ARRAY_SIZE(rz_ssi_soc_dai));
+	if (ret < 0) {
+		pm_runtime_put(ssi->dev);
+		pm_runtime_disable(ssi->dev);
+		reset_control_assert(ssi->rstc);
+		dev_err(&pdev->dev, "failed to register snd component\n");
+	}
+
+	return ret;
+}
+
+static int rz_ssi_remove(struct platform_device *pdev)
+{
+	struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
+
+	pm_runtime_put(ssi->dev);
+	pm_runtime_disable(ssi->dev);
+	reset_control_assert(ssi->rstc);
+
+	return 0;
+}
+
+static const struct of_device_id rz_ssi_of_match[] = {
+	{ .compatible = "renesas,rz-ssi", },
+	{/* Sentinel */},
+};
+MODULE_DEVICE_TABLE(of, rz_ssi_of_match);
+
+static struct platform_driver rz_ssi_driver = {
+	.driver	= {
+		.name	= "rz-ssi-pcm-audio",
+		.of_match_table = rz_ssi_of_match,
+	},
+	.probe		= rz_ssi_probe,
+	.remove		= rz_ssi_remove,
+};
+
+module_platform_driver(rz_ssi_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas RZ/G2L ASoC Serial Sound Interface Driver");
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 05/24] ASoC: sh: rz-ssi: Add SSI DMAC support
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (3 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-21  8:33   ` Pavel Machek
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 06/24] ASoC: sh: rz-ssi: Fix dereference of noderef expression warning Lad Prabhakar
                   ` (19 subsequent siblings)
  24 siblings, 1 reply; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 26ac471c5354583cf4fe0e42537a2c6b84d6d74e upstream.

Add SSI DMAC support to RZ/G2L SoC.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210813091156.10700-4-biju.das.jz@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 256 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 224 insertions(+), 32 deletions(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index 7e0d3a4485e3..4e702b7d5b49 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -7,6 +7,7 @@
 //
 
 #include <linux/clk.h>
+#include <linux/dmaengine.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
@@ -86,6 +87,7 @@ struct rz_ssi_stream {
 	struct rz_ssi_priv *priv;
 	struct snd_pcm_substream *substream;
 	int fifo_sample_size;	/* sample capacity of SSI FIFO */
+	int dma_buffer_pos;	/* The address for the next DMA descriptor */
 	int period_counter;	/* for keeping track of periods transferred */
 	int sample_width;
 	int buffer_pos;		/* current frame position in the buffer */
@@ -94,6 +96,8 @@ struct rz_ssi_stream {
 	int uerr_num;
 	int oerr_num;
 
+	struct dma_chan *dma_ch;
+
 	int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm);
 };
 
@@ -105,6 +109,7 @@ struct rz_ssi_priv {
 	struct clk *sfr_clk;
 	struct clk *clk;
 
+	phys_addr_t phys;
 	int irq_int;
 	int irq_tx;
 	int irq_rx;
@@ -128,8 +133,11 @@ struct rz_ssi_priv {
 
 	bool lrckp_fsync_fall;	/* LR clock polarity (SSICR.LRCKP) */
 	bool bckp_rise;	/* Bit clock polarity (SSICR.BCKP) */
+	bool dma_rt;
 };
 
+static void rz_ssi_dma_complete(void *data);
+
 static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data)
 {
 	writel(data, (priv->base + reg));
@@ -175,6 +183,11 @@ rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
 	return stream;
 }
 
+static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi)
+{
+	return (ssi->playback.dma_ch || ssi->capture.dma_ch);
+}
+
 static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
 				  struct rz_ssi_stream *strm)
 {
@@ -196,6 +209,7 @@ static int rz_ssi_stream_init(struct rz_ssi_priv *ssi,
 
 	strm->substream = substream;
 	strm->sample_width = samples_to_bytes(runtime, 1);
+	strm->dma_buffer_pos = 0;
 	strm->period_counter = 0;
 	strm->buffer_pos = 0;
 
@@ -297,9 +311,12 @@ static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
 	ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF;
 
 	/* FIFO interrupt thresholds */
-	rz_ssi_reg_writel(ssi, SSISCR,
-			  SSISCR_TDES(strm->fifo_sample_size / 2 - 1) |
-			  SSISCR_RDFS(0));
+	if (rz_ssi_is_dma_enabled(ssi))
+		rz_ssi_reg_writel(ssi, SSISCR, 0);
+	else
+		rz_ssi_reg_writel(ssi, SSISCR,
+				  SSISCR_TDES(strm->fifo_sample_size / 2 - 1) |
+				  SSISCR_RDFS(0));
 
 	/* enable IRQ */
 	if (is_play) {
@@ -334,6 +351,10 @@ static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
 	/* Disable TX/RX */
 	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);
+
 	/* Disable irqs */
 	rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN |
 			     SSICR_RUIEN | SSICR_ROIEN, 0);
@@ -549,12 +570,143 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi,
+				   struct dma_chan *dma_ch, bool is_play)
+{
+	struct dma_slave_config cfg;
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+	cfg.dst_addr = ssi->phys + SSIFTDR;
+	cfg.src_addr = ssi->phys + SSIFRDR;
+	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+
+	return dmaengine_slave_config(dma_ch, &cfg);
+}
+
+static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi,
+			       struct rz_ssi_stream *strm)
+{
+	struct snd_pcm_substream *substream = strm->substream;
+	struct dma_async_tx_descriptor *desc;
+	struct snd_pcm_runtime *runtime;
+	enum dma_transfer_direction dir;
+	u32 dma_paddr, dma_size;
+	int amount;
+
+	if (!rz_ssi_stream_is_valid(ssi, strm))
+		return -EINVAL;
+
+	runtime = substream->runtime;
+	if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+		/*
+		 * Stream is ending, so do not queue up any more DMA
+		 * transfers otherwise we play partial sound clips
+		 * because we can't shut off the DMA quick enough.
+		 */
+		return 0;
+
+	dir = rz_ssi_stream_is_play(ssi, substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+
+	/* Always transfer 1 period */
+	amount = runtime->period_size;
+
+	/* DMA physical address and size */
+	dma_paddr = runtime->dma_addr + frames_to_bytes(runtime,
+							strm->dma_buffer_pos);
+	dma_size = frames_to_bytes(runtime, amount);
+	desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size,
+					   dir,
+					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n");
+		return -ENOMEM;
+	}
+
+	desc->callback = rz_ssi_dma_complete;
+	desc->callback_param = strm;
+
+	if (dmaengine_submit(desc) < 0) {
+		dev_err(ssi->dev, "dmaengine_submit() fail\n");
+		return -EIO;
+	}
+
+	/* Update DMA pointer */
+	strm->dma_buffer_pos += amount;
+	if (strm->dma_buffer_pos >= runtime->buffer_size)
+		strm->dma_buffer_pos = 0;
+
+	/* Start DMA */
+	dma_async_issue_pending(strm->dma_ch);
+
+	return 0;
+}
+
+static void rz_ssi_dma_complete(void *data)
+{
+	struct rz_ssi_stream *strm = (struct rz_ssi_stream *)data;
+
+	if (!strm->running || !strm->substream || !strm->substream->runtime)
+		return;
+
+	/* Note that next DMA transaction has probably already started */
+	rz_ssi_pointer_update(strm, strm->substream->runtime->period_size);
+
+	/* Queue up another DMA transaction */
+	rz_ssi_dma_transfer(strm->priv, strm);
+}
+
+static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi)
+{
+	if (ssi->playback.dma_ch) {
+		dma_release_channel(ssi->playback.dma_ch);
+		ssi->playback.dma_ch = NULL;
+		if (ssi->dma_rt)
+			ssi->dma_rt = false;
+	}
+
+	if (ssi->capture.dma_ch) {
+		dma_release_channel(ssi->capture.dma_ch);
+		ssi->capture.dma_ch = NULL;
+	}
+}
+
+static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev)
+{
+	ssi->playback.dma_ch = dma_request_chan(dev, "tx");
+	ssi->capture.dma_ch = dma_request_chan(dev, "rx");
+	if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) {
+		ssi->playback.dma_ch = dma_request_chan(dev, "rt");
+		if (!ssi->playback.dma_ch)
+			goto no_dma;
+
+		ssi->dma_rt = true;
+	}
+
+	if (ssi->playback.dma_ch &&
+	    (rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, true) < 0))
+		goto no_dma;
+
+	if (ssi->capture.dma_ch &&
+	    (rz_ssi_dma_slave_config(ssi, ssi->capture.dma_ch, false) < 0))
+		goto no_dma;
+
+	return 0;
+
+no_dma:
+	rz_ssi_release_dma_channels(ssi);
+
+	return -ENODEV;
+}
+
 static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 			      struct snd_soc_dai *dai)
 {
 	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
 	struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
-	int ret = 0;
+	int ret = 0, i, num_transfer = 1;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -567,9 +719,29 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 		if (ret)
 			goto done;
 
-		ret = strm->transfer(ssi, strm);
-		if (ret)
-			goto done;
+		if (ssi->dma_rt) {
+			bool is_playback;
+
+			is_playback = rz_ssi_stream_is_play(ssi, substream);
+			ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch,
+						      is_playback);
+			/* Fallback to pio */
+			if (ret < 0) {
+				ssi->playback.transfer = rz_ssi_pio_send;
+				ssi->capture.transfer = rz_ssi_pio_recv;
+				rz_ssi_release_dma_channels(ssi);
+			}
+		}
+
+		/* For DMA, queue up multiple DMA descriptors */
+		if (rz_ssi_is_dma_enabled(ssi))
+			num_transfer = 4;
+
+		for (i = 0; i < num_transfer; i++) {
+			ret = strm->transfer(ssi, strm);
+			if (ret)
+				goto done;
+		}
 
 		ret = rz_ssi_start(ssi, strm);
 		break;
@@ -737,6 +909,7 @@ static int rz_ssi_probe(struct platform_device *pdev)
 {
 	struct rz_ssi_priv *ssi;
 	struct clk *audio_clk;
+	struct resource *res;
 	int ret;
 
 	ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL);
@@ -745,10 +918,11 @@ static int rz_ssi_probe(struct platform_device *pdev)
 
 	ssi->pdev = pdev;
 	ssi->dev = &pdev->dev;
-	ssi->base = devm_platform_ioremap_resource(pdev, 0);
+	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");
 	if (IS_ERR(ssi->clk))
 		return PTR_ERR(ssi->clk);
@@ -775,8 +949,18 @@ static int rz_ssi_probe(struct platform_device *pdev)
 
 	ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
 
-	ssi->playback.transfer = rz_ssi_pio_send;
-	ssi->capture.transfer = rz_ssi_pio_recv;
+	/* Detect DMA support */
+	ret = rz_ssi_dma_request(ssi, &pdev->dev);
+	if (ret < 0) {
+		dev_warn(&pdev->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");
+		ssi->playback.transfer = rz_ssi_dma_transfer;
+		ssi->capture.transfer = rz_ssi_dma_transfer;
+	}
+
 	ssi->playback.priv = ssi;
 	ssi->capture.priv = ssi;
 
@@ -792,28 +976,32 @@ static int rz_ssi_probe(struct platform_device *pdev)
 		return dev_err_probe(&pdev->dev, ret,
 				     "irq request error (int_req)\n");
 
-	/* Tx and Rx interrupts (pio only) */
-	ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx");
-	if (ssi->irq_tx < 0)
-		return dev_err_probe(&pdev->dev, -ENODEV,
-				     "Unable to get SSI dma_tx IRQ\n");
-
-	ret = devm_request_irq(&pdev->dev, ssi->irq_tx, &rz_ssi_interrupt, 0,
-			       dev_name(&pdev->dev), ssi);
-	if (ret < 0)
-		return dev_err_probe(&pdev->dev, ret,
-				     "irq request error (dma_tx)\n");
-
-	ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx");
-	if (ssi->irq_rx < 0)
-		return dev_err_probe(&pdev->dev, -ENODEV,
-				     "Unable to get SSI dma_rx IRQ\n");
-
-	ret = devm_request_irq(&pdev->dev, ssi->irq_rx, &rz_ssi_interrupt, 0,
-			       dev_name(&pdev->dev), ssi);
-	if (ret < 0)
-		return dev_err_probe(&pdev->dev, ret,
-				     "irq request error (dma_rx)\n");
+	if (!rz_ssi_is_dma_enabled(ssi)) {
+		/* Tx and Rx interrupts (pio only) */
+		ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx");
+		if (ssi->irq_tx < 0)
+			return dev_err_probe(&pdev->dev, -ENODEV,
+					     "Unable to get SSI dma_tx IRQ\n");
+
+		ret = devm_request_irq(&pdev->dev, ssi->irq_tx,
+				       &rz_ssi_interrupt, 0,
+				       dev_name(&pdev->dev), ssi);
+		if (ret < 0)
+			return dev_err_probe(&pdev->dev, ret,
+					     "irq request error (dma_tx)\n");
+
+		ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx");
+		if (ssi->irq_rx < 0)
+			return dev_err_probe(&pdev->dev, -ENODEV,
+					     "Unable to get SSI dma_rx IRQ\n");
+
+		ret = devm_request_irq(&pdev->dev, ssi->irq_rx,
+				       &rz_ssi_interrupt, 0,
+				       dev_name(&pdev->dev), ssi);
+		if (ret < 0)
+			return dev_err_probe(&pdev->dev, ret,
+					     "irq request error (dma_rx)\n");
+	}
 
 	ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
 	if (IS_ERR(ssi->rstc))
@@ -829,6 +1017,8 @@ static int rz_ssi_probe(struct platform_device *pdev)
 					      rz_ssi_soc_dai,
 					      ARRAY_SIZE(rz_ssi_soc_dai));
 	if (ret < 0) {
+		rz_ssi_release_dma_channels(ssi);
+
 		pm_runtime_put(ssi->dev);
 		pm_runtime_disable(ssi->dev);
 		reset_control_assert(ssi->rstc);
@@ -842,6 +1032,8 @@ static int rz_ssi_remove(struct platform_device *pdev)
 {
 	struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
 
+	rz_ssi_release_dma_channels(ssi);
+
 	pm_runtime_put(ssi->dev);
 	pm_runtime_disable(ssi->dev);
 	reset_control_assert(ssi->rstc);
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 06/24] ASoC: sh: rz-ssi: Fix dereference of noderef expression warning
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (4 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 05/24] ASoC: sh: rz-ssi: Add SSI DMAC support Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 07/24] ASoC: sh: rz-ssi: Fix wrong operator used issue Lad Prabhakar
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit d40dfb860ad72a32b9c2aeae739a2725f8ce011a upstream.

Fix following sparse warning:
sound/soc/sh/rz-ssi.c:156:15: sparse: warning: dereference of
noderef expression

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reported-by: kernel test robot <lkp@intel.com>
Link: https://lore.kernel.org/r/20210816132049.28128-1-biju.das.jz@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index 4e702b7d5b49..d96c1bea047c 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -148,7 +148,7 @@ static u32 rz_ssi_reg_readl(struct rz_ssi_priv *priv, uint reg)
 	return readl(priv->base + reg);
 }
 
-static void rz_ssi_reg_mask_setl(struct rz_ssi_priv __iomem *priv, uint reg,
+static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg,
 				 u32 bclr, u32 bset)
 {
 	u32 val;
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 07/24] ASoC: sh: rz-ssi: Fix wrong operator used issue
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (5 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 06/24] ASoC: sh: rz-ssi: Fix dereference of noderef expression warning Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 08/24] ASoC: sh: rz-ssi: Improve error handling in rz_ssi_dma_request function Lad Prabhakar
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 1b5d1d3a2f77250707225509cadc17997bab4353 upstream.

Fix wrong operator used issue reported by Coverity by replacing |
operator with & operator.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reported-by: Colin Ian King <colin.king@canonical.com>
Link: https://lore.kernel.org/r/20210816182336.29959-1-biju.das.jz@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index d96c1bea047c..341815476244 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -368,7 +368,7 @@ static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
 	/* Wait for idle */
 	timeout = 100;
 	while (--timeout) {
-		if (rz_ssi_reg_readl(ssi, SSISR) | SSISR_IIRQ)
+		if (rz_ssi_reg_readl(ssi, SSISR) & SSISR_IIRQ)
 			break;
 		udelay(1);
 	}
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 08/24] ASoC: sh: rz-ssi: Improve error handling in rz_ssi_dma_request function
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (6 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 07/24] ASoC: sh: rz-ssi: Fix wrong operator used issue Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 09/24] ASoC: sh: rz-ssi: Check return value of pm_runtime_resume_and_get() Lad Prabhakar
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 4b14f17912052a6963580dfba04781cfe6ccba02 upstream.

dma_request_chan() returns error pointer in case of failures, but
the rz_ssi_dma_request() checked for NULL pointer instead.

This patch fixes the issue by checking for ERR_PTR() instead of
NULL and sets the DMA pointers to NULL in error case so that ssi
can fallback to PIO mode.

Fixes: 26ac471c5354 ("ASoC: sh: rz-ssi: Add SSI DMAC support")
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210818101450.15948-1-biju.das.jz@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index 341815476244..89c7e5e4cbf6 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -185,7 +185,7 @@ rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
 
 static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi)
 {
-	return (ssi->playback.dma_ch || ssi->capture.dma_ch);
+	return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch));
 }
 
 static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
@@ -676,15 +676,26 @@ static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi)
 static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev)
 {
 	ssi->playback.dma_ch = dma_request_chan(dev, "tx");
+	if (IS_ERR(ssi->playback.dma_ch))
+		ssi->playback.dma_ch = NULL;
+
 	ssi->capture.dma_ch = dma_request_chan(dev, "rx");
+	if (IS_ERR(ssi->capture.dma_ch))
+		ssi->capture.dma_ch = NULL;
+
 	if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) {
 		ssi->playback.dma_ch = dma_request_chan(dev, "rt");
-		if (!ssi->playback.dma_ch)
+		if (IS_ERR(ssi->playback.dma_ch)) {
+			ssi->playback.dma_ch = NULL;
 			goto no_dma;
+		}
 
 		ssi->dma_rt = true;
 	}
 
+	if (!rz_ssi_is_dma_enabled(ssi))
+		goto no_dma;
+
 	if (ssi->playback.dma_ch &&
 	    (rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch, true) < 0))
 		goto no_dma;
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 09/24] ASoC: sh: rz-ssi: Check return value of pm_runtime_resume_and_get()
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (7 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 08/24] ASoC: sh: rz-ssi: Improve error handling in rz_ssi_dma_request function Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 10/24] ASoC: sh: rz-ssi: Drop calling rz_ssi_pio_recv() recursively Lad Prabhakar
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Heiner Kallweit <hkallweit1@gmail.com>

commit f04b4fb47d83b110a5b007fb2eddea862cfeb151 upstream.

The return value of pm_runtime_resume_and_get() needs to be checked to
avoid a usage count imbalance in the error case. This fix is basically
the same as 92c959bae2e5 ("reset: renesas: Fix Runtime PM usage"),
and the last step before pm_runtime_resume_and_get() can be annotated
as __must_check.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Link: https://lore.kernel.org/r/9fed506d-b780-55cd-45a4-9bd2407c910f@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index 89c7e5e4cbf6..e8ca3a90264d 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -1020,7 +1020,12 @@ static int rz_ssi_probe(struct platform_device *pdev)
 
 	reset_control_deassert(ssi->rstc);
 	pm_runtime_enable(&pdev->dev);
-	pm_runtime_resume_and_get(&pdev->dev);
+	ret = pm_runtime_resume_and_get(&pdev->dev);
+	if (ret < 0) {
+		pm_runtime_disable(ssi->dev);
+		reset_control_assert(ssi->rstc);
+		return dev_err_probe(ssi->dev, ret, "pm_runtime_resume_and_get failed\n");
+	}
 
 	spin_lock_init(&ssi->lock);
 	dev_set_drvdata(&pdev->dev, ssi);
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 10/24] ASoC: sh: rz-ssi: Drop calling rz_ssi_pio_recv() recursively
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (8 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 09/24] ASoC: sh: rz-ssi: Check return value of pm_runtime_resume_and_get() Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 11/24] ASoC: sh: rz-ssi: Make the data structures available before registering the handlers Lad Prabhakar
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

commit 6570f991582e32b7992601d0497c61962a2c5dcc upstream.

Instead of recursively calling rz_ssi_pio_recv() use a while loop
to read the samples from RX fifo.

This also fixes an issue where the return value of rz_ssi_pio_recv()
was ignored when called recursively.

Fixes: 03e786bd4341 ("ASoC: sh: Add RZ/G2L SSIF-2 driver")
Reported-by: Pavel Machek <pavel@denx.de>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20220110094711.8574-2-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 68 ++++++++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 33 deletions(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index e8ca3a90264d..77dd7455b7fa 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -411,54 +411,56 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
 {
 	struct snd_pcm_substream *substream = strm->substream;
 	struct snd_pcm_runtime *runtime;
+	bool done = false;
 	u16 *buf;
 	int fifo_samples;
 	int frames_left;
-	int samples = 0;
+	int samples;
 	int i;
 
 	if (!rz_ssi_stream_is_valid(ssi, strm))
 		return -EINVAL;
 
 	runtime = substream->runtime;
-	/* frames left in this period */
-	frames_left = runtime->period_size - (strm->buffer_pos %
-					      runtime->period_size);
-	if (frames_left == 0)
-		frames_left = runtime->period_size;
 
-	/* Samples in RX FIFO */
-	fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
-			SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
-
-	/* Only read full frames at a time */
-	while (frames_left && (fifo_samples >= runtime->channels)) {
-		samples += runtime->channels;
-		fifo_samples -= runtime->channels;
-		frames_left--;
-	}
+	while (!done) {
+		/* frames left in this period */
+		frames_left = runtime->period_size -
+			      (strm->buffer_pos % runtime->period_size);
+		if (!frames_left)
+			frames_left = runtime->period_size;
+
+		/* Samples in RX FIFO */
+		fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
+				SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
+
+		/* Only read full frames at a time */
+		samples = 0;
+		while (frames_left && (fifo_samples >= runtime->channels)) {
+			samples += runtime->channels;
+			fifo_samples -= runtime->channels;
+			frames_left--;
+		}
 
-	/* not enough samples yet */
-	if (samples == 0)
-		return 0;
+		/* not enough samples yet */
+		if (!samples)
+			break;
 
-	/* calculate new buffer index */
-	buf = (u16 *)(runtime->dma_area);
-	buf += strm->buffer_pos * runtime->channels;
+		/* calculate new buffer index */
+		buf = (u16 *)(runtime->dma_area);
+		buf += strm->buffer_pos * runtime->channels;
 
-	/* Note, only supports 16-bit samples */
-	for (i = 0; i < samples; i++)
-		*buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
+		/* Note, only supports 16-bit samples */
+		for (i = 0; i < samples; i++)
+			*buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
 
-	rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
-	rz_ssi_pointer_update(strm, samples / runtime->channels);
+		rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
+		rz_ssi_pointer_update(strm, samples / runtime->channels);
 
-	/*
-	 * If we finished this period, but there are more samples in
-	 * the RX FIFO, call this function again
-	 */
-	if (frames_left == 0 && fifo_samples >= runtime->channels)
-		rz_ssi_pio_recv(ssi, strm);
+		/* check if there are no more samples in the RX FIFO */
+		if (!(!frames_left && fifo_samples >= runtime->channels))
+			done = true;
+	}
 
 	return 0;
 }
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 11/24] ASoC: sh: rz-ssi: Make the data structures available before registering the handlers
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (9 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 10/24] ASoC: sh: rz-ssi: Drop calling rz_ssi_pio_recv() recursively Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 12/24] ASoC: sh: rz-ssi: Drop ssi parameter from rz_ssi_stream_init() Lad Prabhakar
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

commit 0788785c78342d422f93b1c9831c2b2b7f137937 upstream.

Initialize the spinlock and make the data structures available before
registering the interrupt handlers.

Reported-by: Pavel Machek <pavel@denx.de>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20220110094711.8574-3-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index 77dd7455b7fa..9f0d6d7f08c6 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -977,6 +977,9 @@ static int rz_ssi_probe(struct platform_device *pdev)
 	ssi->playback.priv = ssi;
 	ssi->capture.priv = ssi;
 
+	spin_lock_init(&ssi->lock);
+	dev_set_drvdata(&pdev->dev, ssi);
+
 	/* Error Interrupt */
 	ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
 	if (ssi->irq_int < 0)
@@ -1029,8 +1032,6 @@ static int rz_ssi_probe(struct platform_device *pdev)
 		return dev_err_probe(ssi->dev, ret, "pm_runtime_resume_and_get failed\n");
 	}
 
-	spin_lock_init(&ssi->lock);
-	dev_set_drvdata(&pdev->dev, ssi);
 	ret = devm_snd_soc_register_component(&pdev->dev, &rz_ssi_soc_component,
 					      rz_ssi_soc_dai,
 					      ARRAY_SIZE(rz_ssi_soc_dai));
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 12/24] ASoC: sh: rz-ssi: Drop ssi parameter from rz_ssi_stream_init()
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (10 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 11/24] ASoC: sh: rz-ssi: Make the data structures available before registering the handlers Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 13/24] ASoC: sh: rz-ssi: Make return type of rz_ssi_stream_is_valid() to bool Lad Prabhakar
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

commit 4f78f3c970f131a179fd135806a9b693fa606beb upstream.

ssi parameter is unused in rz_ssi_stream_init() so just drop it.

While at it, change the return type of rz_ssi_stream_init() to void
instead of int.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20220110094711.8574-4-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index 9f0d6d7f08c6..e77307f38494 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -201,9 +201,8 @@ static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
 	return ret;
 }
 
-static int rz_ssi_stream_init(struct rz_ssi_priv *ssi,
-			      struct rz_ssi_stream *strm,
-			      struct snd_pcm_substream *substream)
+static void rz_ssi_stream_init(struct rz_ssi_stream *strm,
+			       struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
@@ -219,8 +218,6 @@ static int rz_ssi_stream_init(struct rz_ssi_priv *ssi,
 
 	/* fifo init */
 	strm->fifo_sample_size = SSI_FIFO_DEPTH;
-
-	return 0;
 }
 
 static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi,
@@ -728,9 +725,7 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 		rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0);
 		udelay(5);
 
-		ret = rz_ssi_stream_init(ssi, strm, substream);
-		if (ret)
-			goto done;
+		rz_ssi_stream_init(strm, substream);
 
 		if (ssi->dma_rt) {
 			bool is_playback;
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 13/24] ASoC: sh: rz-ssi: Make return type of rz_ssi_stream_is_valid() to bool
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (11 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 12/24] ASoC: sh: rz-ssi: Drop ssi parameter from rz_ssi_stream_init() Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 14/24] ASoC: sh: rz-ssi: Use a do-while loop in rz_ssi_pio_recv() Lad Prabhakar
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

commit e42c903e8bf400728c4ae1f922169b4d28b72efa upstream.

rz_ssi_stream_is_valid() never returns an int, it returns the result of
a condition which is either true or false.

While at it, drop "!!" as the expression is boolean.

Reported-by: Pavel Machek <pavel@denx.de>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20220110094711.8574-5-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index e77307f38494..8b0d921a2a9e 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -188,14 +188,14 @@ static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi)
 	return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch));
 }
 
-static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
-				  struct rz_ssi_stream *strm)
+static bool rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
+				   struct rz_ssi_stream *strm)
 {
 	unsigned long flags;
-	int ret;
+	bool ret;
 
 	spin_lock_irqsave(&ssi->lock, flags);
-	ret = !!(strm->substream && strm->substream->runtime);
+	ret = strm->substream && strm->substream->runtime;
 	spin_unlock_irqrestore(&ssi->lock, flags);
 
 	return ret;
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 14/24] ASoC: sh: rz-ssi: Use a do-while loop in rz_ssi_pio_recv()
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (12 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 13/24] ASoC: sh: rz-ssi: Make return type of rz_ssi_stream_is_valid() to bool Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 15/24] ASoC: sh: rz-ssi: Add rz_ssi_set_substream() helper function Lad Prabhakar
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

commit 7276d3f329c633340f3c539ce35ed254d2fe467b upstream.

Use a do-while loop while reading the samples from RX FIFO. The "done"
flag was only changed as an outcome of the last if-statement (last step)
in this entire procedure. This patch moves the condition from if
statement to while and drops the "done" variable for readability.

While at it, also drop the unneeded parentheses around runtime->dma_area.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20220125132457.14984-2-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index 8b0d921a2a9e..b88161fedbea 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -408,7 +408,6 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
 {
 	struct snd_pcm_substream *substream = strm->substream;
 	struct snd_pcm_runtime *runtime;
-	bool done = false;
 	u16 *buf;
 	int fifo_samples;
 	int frames_left;
@@ -420,7 +419,7 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
 
 	runtime = substream->runtime;
 
-	while (!done) {
+	do {
 		/* frames left in this period */
 		frames_left = runtime->period_size -
 			      (strm->buffer_pos % runtime->period_size);
@@ -444,7 +443,7 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
 			break;
 
 		/* calculate new buffer index */
-		buf = (u16 *)(runtime->dma_area);
+		buf = (u16 *)runtime->dma_area;
 		buf += strm->buffer_pos * runtime->channels;
 
 		/* Note, only supports 16-bit samples */
@@ -453,11 +452,7 @@ static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
 
 		rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
 		rz_ssi_pointer_update(strm, samples / runtime->channels);
-
-		/* check if there are no more samples in the RX FIFO */
-		if (!(!frames_left && fifo_samples >= runtime->channels))
-			done = true;
-	}
+	} while (!frames_left && fifo_samples >= runtime->channels);
 
 	return 0;
 }
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 15/24] ASoC: sh: rz-ssi: Add rz_ssi_set_substream() helper function
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (13 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 14/24] ASoC: sh: rz-ssi: Use a do-while loop in rz_ssi_pio_recv() Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 16/24] ASoC: sh: rz-ssi: Remove duplicate macros Lad Prabhakar
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

commit 962ff7ecb60b684fe15b135ccbe07628b8bb522a  upstream.

A copy of substream pointer is stored in priv structure during
rz_ssi_dai_trigger() callback ie in SNDRV_PCM_TRIGGER_START case
and the pointer is assigned to NULL in case of SNDRV_PCM_TRIGGER_STOP.

The driver used the locks only in rz_ssi_stream_is_valid() and assigned
the local substream pointer to NULL in rz_ssi_dai_trigger() callback but
never locked it while making a local copy.

This patch adds the rz_ssi_set_substream() helper function to set the
substream pointer with locks acquired and replaces the instances of
setting the local substream pointer with the rz_ssi_set_substream()
function.

Reported-by: Pavel Machek <pavel@denx.de>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20220125132457.14984-3-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index b88161fedbea..73f053c8235a 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -188,6 +188,17 @@ static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi)
 	return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch));
 }
 
+static void rz_ssi_set_substream(struct rz_ssi_stream *strm,
+				 struct snd_pcm_substream *substream)
+{
+	struct rz_ssi_priv *ssi = strm->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ssi->lock, flags);
+	strm->substream = substream;
+	spin_unlock_irqrestore(&ssi->lock, flags);
+}
+
 static bool rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
 				   struct rz_ssi_stream *strm)
 {
@@ -206,7 +217,7 @@ static void rz_ssi_stream_init(struct rz_ssi_stream *strm,
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	strm->substream = substream;
+	rz_ssi_set_substream(strm, substream);
 	strm->sample_width = samples_to_bytes(runtime, 1);
 	strm->dma_buffer_pos = 0;
 	strm->period_counter = 0;
@@ -224,11 +235,8 @@ 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);
-	unsigned long flags;
 
-	spin_lock_irqsave(&ssi->lock, flags);
-	strm->substream = NULL;
-	spin_unlock_irqrestore(&ssi->lock, flags);
+	rz_ssi_set_substream(strm, NULL);
 
 	if (strm->oerr_num > 0)
 		dev_info(dai->dev, "overrun = %d\n", strm->oerr_num);
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 16/24] ASoC: sh: rz-ssi: Remove duplicate macros
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (14 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 15/24] ASoC: sh: rz-ssi: Add rz_ssi_set_substream() helper function Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 17/24] arm64: dts: renesas: r9a07g044: Add external audio clock nodes Lad Prabhakar
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

commit acfa1e2c2ff5cd7fb7948b0c5c2057acd9dceb14 upstream.

Remove SSICR_MST and SSICR_CKDV macros which are defined more than once.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20220125132457.14984-4-prabhakar.mahadev-lad.rj@bp.renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 sound/soc/sh/rz-ssi.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
index 73f053c8235a..7a9de98b7857 100644
--- a/sound/soc/sh/rz-ssi.c
+++ b/sound/soc/sh/rz-ssi.c
@@ -28,8 +28,6 @@
 /* SSI REGISTER BITS */
 #define SSICR_DWL(x)		(((x) & 0x7) << 19)
 #define SSICR_SWL(x)		(((x) & 0x7) << 16)
-#define SSICR_MST		BIT(14)
-#define SSICR_CKDV(x)		(((x) & 0xf) << 4)
 
 #define SSICR_CKS		BIT(30)
 #define SSICR_TUIEN		BIT(29)
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 17/24] arm64: dts: renesas: r9a07g044: Add external audio clock nodes
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (15 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 16/24] ASoC: sh: rz-ssi: Remove duplicate macros Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 18/24] arm64: dts: renesas: r9a07g044: Add SSI support Lad Prabhakar
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 6f48272f11b1863e652530b7171a54fc9b24e275 upstream.

Add external audio clocks nodes to RZ/G2L (a.k.a R9A07G044) SoC DTSI.

The external audio clocks are configured as 0 Hz fixed frequency clocks by
default. Boards that provide audio clocks should override them.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210814135526.15561-2-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 arch/arm64/boot/dts/renesas/r9a07g044.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
index 6ff3f81334cf..2acf5e57930a 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
@@ -13,6 +13,20 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	audio_clk1: audio_clk1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by boards that provide it */
+		clock-frequency = <0>;
+	};
+
+	audio_clk2: audio_clk2 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by boards that provide it */
+		clock-frequency = <0>;
+	};
+
 	/* External CAN clock - to be overridden by boards that provide it */
 	can_clk: can {
 		compatible = "fixed-clock";
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 18/24] arm64: dts: renesas: r9a07g044: Add SSI support
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (16 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 17/24] arm64: dts: renesas: r9a07g044: Add external audio clock nodes Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 19/24] arm64: dts: renesas: r9a07g044: Add DMA support to SSI Lad Prabhakar
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 92a341315afc9cc8e015fa201610d8dd73db4a01 upstream.

Add SSI{0,1,2,3} nodes to RZ/G2L SoC DTSI.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210814135526.15561-3-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
[PL: Manually applied the changes]
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 arch/arm64/boot/dts/renesas/r9a07g044.dtsi | 76 ++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
index 2acf5e57930a..1f3bcc1945f2 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
@@ -124,6 +124,82 @@
 		#size-cells = <2>;
 		ranges;
 
+		ssi0: ssi@10049c00 {
+			compatible = "renesas,r9a07g044-ssi",
+				     "renesas,rz-ssi";
+			reg = <0 0x10049c00 0 0x400>;
+			interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
+			clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
+				 <&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
+				 <&audio_clk1>, <&audio_clk2>;
+			clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
+			resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
+			power-domains = <&cpg>;
+			#sound-dai-cells = <0>;
+			status = "disabled";
+		};
+
+		ssi1: ssi@1004a000 {
+			compatible = "renesas,r9a07g044-ssi",
+				     "renesas,rz-ssi";
+			reg = <0 0x1004a000 0 0x400>;
+			interrupts = <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 331 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 332 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 333 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
+			clocks = <&cpg CPG_MOD R9A07G044_SSI1_PCLK2>,
+				 <&cpg CPG_MOD R9A07G044_SSI1_PCLK_SFR>,
+				 <&audio_clk1>, <&audio_clk2>;
+			clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
+			resets = <&cpg R9A07G044_SSI1_RST_M2_REG>;
+			power-domains = <&cpg>;
+			#sound-dai-cells = <0>;
+			status = "disabled";
+		};
+
+		ssi2: ssi@1004a400 {
+			compatible = "renesas,r9a07g044-ssi",
+				     "renesas,rz-ssi";
+			reg = <0 0x1004a400 0 0x400>;
+			interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 335 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 336 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 337 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
+			clocks = <&cpg CPG_MOD R9A07G044_SSI2_PCLK2>,
+				 <&cpg CPG_MOD R9A07G044_SSI2_PCLK_SFR>,
+				 <&audio_clk1>, <&audio_clk2>;
+			clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
+			resets = <&cpg R9A07G044_SSI2_RST_M2_REG>;
+			power-domains = <&cpg>;
+			#sound-dai-cells = <0>;
+			status = "disabled";
+		};
+
+		ssi3: ssi@1004a800 {
+			compatible = "renesas,r9a07g044-ssi",
+				     "renesas,rz-ssi";
+			reg = <0 0x1004a800 0 0x400>;
+			interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 339 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 341 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
+			clocks = <&cpg CPG_MOD R9A07G044_SSI3_PCLK2>,
+				 <&cpg CPG_MOD R9A07G044_SSI3_PCLK_SFR>,
+				 <&audio_clk1>, <&audio_clk2>;
+			clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
+			resets = <&cpg R9A07G044_SSI3_RST_M2_REG>;
+			power-domains = <&cpg>;
+			#sound-dai-cells = <0>;
+			status = "disabled";
+		};
+
 		spi0: spi@1004ac00 {
 			compatible = "renesas,r9a07g044-rspi", "renesas,rspi-rz";
 			reg = <0 0x1004ac00 0 0x400>;
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 19/24] arm64: dts: renesas: r9a07g044: Add DMA support to SSI
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (17 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 18/24] arm64: dts: renesas: r9a07g044: Add SSI support Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 20/24] arm64: dts: renesas: rzg2l-smarc: Add WM8978 sound codec Lad Prabhakar
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 89fe8d246a26a1a60e658a58e5099a90e4d56f6f upstream.

Add dmac phandles to SSI nodes to support DMA operation.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210921084605.16250-2-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 arch/arm64/boot/dts/renesas/r9a07g044.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
index 1f3bcc1945f2..3859337989b7 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
@@ -138,6 +138,8 @@
 				 <&audio_clk1>, <&audio_clk2>;
 			clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
 			resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
+			dmas = <&dmac 0x2655>, <&dmac 0x2656>;
+			dma-names = "tx", "rx";
 			power-domains = <&cpg>;
 			#sound-dai-cells = <0>;
 			status = "disabled";
@@ -157,6 +159,8 @@
 				 <&audio_clk1>, <&audio_clk2>;
 			clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
 			resets = <&cpg R9A07G044_SSI1_RST_M2_REG>;
+			dmas = <&dmac 0x2659>, <&dmac 0x265a>;
+			dma-names = "tx", "rx";
 			power-domains = <&cpg>;
 			#sound-dai-cells = <0>;
 			status = "disabled";
@@ -176,6 +180,8 @@
 				 <&audio_clk1>, <&audio_clk2>;
 			clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
 			resets = <&cpg R9A07G044_SSI2_RST_M2_REG>;
+			dmas = <&dmac 0x265f>;
+			dma-names = "rt";
 			power-domains = <&cpg>;
 			#sound-dai-cells = <0>;
 			status = "disabled";
@@ -195,6 +201,8 @@
 				 <&audio_clk1>, <&audio_clk2>;
 			clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
 			resets = <&cpg R9A07G044_SSI3_RST_M2_REG>;
+			dmas = <&dmac 0x2661>, <&dmac 0x2662>;
+			dma-names = "tx", "rx";
 			power-domains = <&cpg>;
 			#sound-dai-cells = <0>;
 			status = "disabled";
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 20/24] arm64: dts: renesas: rzg2l-smarc: Add WM8978 sound codec
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (18 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 19/24] arm64: dts: renesas: r9a07g044: Add DMA support to SSI Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 21/24] arm64: dts: renesas: rzg2l-smarc: Enable audio Lad Prabhakar
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 1c8da81cc452075a21d4654f88264df8e8e89676 upstream.

Add WM8978 sound codec node to RZ/G2L SMARC EVK.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210921084605.16250-3-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
index 994fc0dc1516..549cee1733c7 100644
--- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
@@ -88,8 +88,15 @@
 &i2c3 {
 	pinctrl-0 = <&i2c3_pins>;
 	pinctrl-names = "default";
+	clock-frequency = <400000>;
 
 	status = "okay";
+
+	wm8978: codec@1a {
+		compatible = "wlf,wm8978";
+		#sound-dai-cells = <0>;
+		reg = <0x1a>;
+	};
 };
 
 &ohci0 {
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 21/24] arm64: dts: renesas: rzg2l-smarc: Enable audio
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (19 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 20/24] arm64: dts: renesas: rzg2l-smarc: Add WM8978 sound codec Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-21 11:15   ` Pavel Machek
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 22/24] arm64: dts: renesas: rzg2l-smarc: Add Mic routing Lad Prabhakar
                   ` (3 subsequent siblings)
  24 siblings, 1 reply; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit e396d6103343ff95874444bd8a67f031eafe0e38 upstream.

Enable audio on RZ/G2L SMARC EVK by linking SSI0 with WM8978
audio CODEC.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210921084605.16250-4-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
[PL: Manually applied the changes]
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi | 66 ++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
index 549cee1733c7..4bffd6b4c837 100644
--- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
@@ -8,6 +8,19 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/pinctrl/rzg2l-pinctrl.h>
 
+/*
+ * SSI-WM8978
+ *
+ * This command is required when Playback/Capture
+ *
+ *	amixer cset name='Left Input Mixer L2 Switch' on
+ *	amixer cset name='Right Input Mixer R2 Switch' on
+ *	amixer cset name='Headphone Playback Volume' 100
+ *	amixer cset name='PCM Volume' 100%
+ *	amixer cset name='Input PGA Volume' 25
+ *
+ */
+
 /* comment the #define statement to disable SCIF2 (SER0) on PMOD1 (CN7) */
 #define PMOD1_SER0	1
 
@@ -24,6 +37,29 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	audio_mclock: audio_mclock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <11289600>;
+	};
+
+	snd_rzg2l: 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 = <&ssi0>;
+		};
+
+		codec_dai: simple-audio-card,codec {
+			clocks = <&audio_mclock>;
+			sound-dai = <&wm8978>;
+		};
+	};
+
 	usb0_vbus_otg: regulator-usb0-vbus-otg {
 		compatible = "regulator-fixed";
 
@@ -43,6 +79,14 @@
 	};
 };
 
+&audio_clk1{
+	clock-frequency = <11289600>;
+};
+
+&audio_clk2{
+	clock-frequency = <12288000>;
+};
+
 &canfd {
 	pinctrl-0 = <&can0_pins &can1_pins>;
 	pinctrl-names = "default";
@@ -113,6 +157,9 @@
 };
 
 &pinctrl {
+	pinctrl-0 = <&sound_clk_pins>;
+	pinctrl-names = "default";
+
 	can0_pins: can0 {
 		pinmux = <RZG2L_PORT_PINMUX(10, 1, 2)>, /* TX */
 			 <RZG2L_PORT_PINMUX(11, 0, 2)>; /* RX */
@@ -205,6 +252,11 @@
 		};
 	};
 
+	sound_clk_pins: sound_clk {
+		pins = "AUDIO_CLK1", "AUDIO_CLK2";
+		input-enable;
+	};
+
 	spi1_pins: spi1 {
 		pinmux = <RZG2L_PORT_PINMUX(44, 0, 1)>, /* CK */
 			 <RZG2L_PORT_PINMUX(44, 1, 1)>, /* MOSI */
@@ -212,6 +264,13 @@
 			 <RZG2L_PORT_PINMUX(44, 3, 1)>; /* SSL */
 	};
 
+	ssi0_pins: ssi0 {
+		pinmux = <RZG2L_PORT_PINMUX(45, 0, 1)>, /* BCK */
+			 <RZG2L_PORT_PINMUX(45, 1, 1)>, /* RCK */
+			 <RZG2L_PORT_PINMUX(45, 2, 1)>, /* TXD */
+			 <RZG2L_PORT_PINMUX(45, 3, 1)>; /* RXD */
+	};
+
 	usb0_pins: usb0 {
 		pinmux = <RZG2L_PORT_PINMUX(4, 0, 1)>, /* VBUS */
 			 <RZG2L_PORT_PINMUX(5, 0, 1)>, /* OVC */
@@ -267,6 +326,13 @@
 	status = "okay";
 };
 
+&ssi0 {
+	pinctrl-0 = <&ssi0_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
 &usb2_phy0 {
 	pinctrl-0 = <&usb0_pins>;
 	pinctrl-names = "default";
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 22/24] arm64: dts: renesas: rzg2l-smarc: Add Mic routing
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (20 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 21/24] arm64: dts: renesas: rzg2l-smarc: Enable audio Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 23/24] arm64: defconfig: Enable SOUND_SOC_RZ Lad Prabhakar
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 87b1e27af4c1e3422bb2189b5f8f72075e841d6f upstream.

Add audio routing for Mic with bias to reduce noise when doing
audio capture.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
Link: https://lore.kernel.org/r/20210921084605.16250-5-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
index 4bffd6b4c837..6f2a8bdfa225 100644
--- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
@@ -50,6 +50,12 @@
 		simple-audio-card,frame-master = <&cpu_dai>;
 		simple-audio-card,mclk-fs = <256>;
 
+		simple-audio-card,widgets = "Microphone", "Microphone Jack";
+		simple-audio-card,routing =
+			    "L2", "Mic Bias",
+			    "R2", "Mic Bias",
+			    "Mic Bias", "Microphone Jack";
+
 		cpu_dai: simple-audio-card,cpu {
 			sound-dai = <&ssi0>;
 		};
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 23/24] arm64: defconfig: Enable SOUND_SOC_RZ
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (21 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 22/24] arm64: dts: renesas: rzg2l-smarc: Add Mic routing Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 24/24] arm64: defconfig: Enable SND_SOC_WM8978 Lad Prabhakar
  2022-04-21  3:25 ` [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC nobuhiro1.iwamatsu
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit be15aa5cc14f94b520c13ab3540fdf7e735bff47 upstream.

Enable sound driver support for Renesas RZ/G2L based platforms.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20210920093905.10878-2-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
[PL: Manually applied the changes]
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 54cd7f1430d7..97a62dd4f01f 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -708,6 +708,7 @@ CONFIG_SND_SOC_ROCKCHIP_RT5645=m
 CONFIG_SND_SOC_RK3399_GRU_SOUND=m
 CONFIG_SND_SOC_SAMSUNG=y
 CONFIG_SND_SOC_RCAR=m
+CONFIG_SND_SOC_RZ=m
 CONFIG_SND_SUN4I_SPDIF=m
 CONFIG_SND_SOC_TEGRA=m
 CONFIG_SND_SOC_TEGRA210_AHUB=m
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 5.10.y-cip 24/24] arm64: defconfig: Enable SND_SOC_WM8978
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (22 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 23/24] arm64: defconfig: Enable SOUND_SOC_RZ Lad Prabhakar
@ 2022-04-20 21:34 ` Lad Prabhakar
  2022-04-21  3:25 ` [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC nobuhiro1.iwamatsu
  24 siblings, 0 replies; 39+ messages in thread
From: Lad Prabhakar @ 2022-04-20 21:34 UTC (permalink / raw)
  To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek; +Cc: Biju Das

From: Biju Das <biju.das.jz@bp.renesas.com>

commit 3c158ec884d8d75526594c888997cabc3223f521 upstream.

WM8978 audio CODEC is supported on RZ/G2L SMARC EVK.
Enable it on arm64 defconfig as module.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Link: https://lore.kernel.org/r/20210920093905.10878-1-biju.das.jz@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
[PL: Manually applied the changes]
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 97a62dd4f01f..0957b725eb1b 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -724,6 +724,7 @@ CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
 CONFIG_SND_SOC_TAS571X=m
 CONFIG_SND_SOC_WCD934X=m
 CONFIG_SND_SOC_WM8904=m
+CONFIG_SND_SOC_WM8978=m
 CONFIG_SND_SOC_WSA881X=m
 CONFIG_SND_SIMPLE_CARD=m
 CONFIG_SND_AUDIO_GRAPH_CARD=m
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* RE: [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver Lad Prabhakar
@ 2022-04-21  1:12   ` nobuhiro1.iwamatsu
  2022-04-21 10:50     ` Prabhakar Mahadev Lad
  0 siblings, 1 reply; 39+ messages in thread
From: nobuhiro1.iwamatsu @ 2022-04-21  1:12 UTC (permalink / raw)
  To: prabhakar.mahadev-lad.rj, cip-dev, pavel; +Cc: biju.das.jz

Hi Lad,

> -----Original Message-----
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Sent: Thursday, April 21, 2022 6:34 AM
> To: cip-dev@lists.cip-project.org; iwamatsu nobuhiro(岩松 信洋 □SWC◯A
> CT) <nobuhiro1.iwamatsu@toshiba.co.jp>; Pavel Machek
> <pavel@denx.de>
> Cc: Biju Das <biju.das.jz@bp.renesas.com>
> Subject: [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver
> 
> From: Biju Das <biju.das.jz@bp.renesas.com>
> 
> commit 03e786bd43410fa93e5d2459f7a43e90ff0ae801 upstream.
> 
> Add serial sound interface(SSIF-2) driver support for RZ/G2L SoC.
> 
> Based on the work done by Chris Brandt for RZ/A SSI driver.
> 
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Link:
> https://lore.kernel.org/r/20210813091156.10700-2-biju.das.jz@bp.renesas.co
> m
> Signed-off-by: Mark Brown <broonie@kernel.org>
> [PL: Dropped using modern terminology]
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> ---
>  sound/soc/sh/Kconfig  |   6 +
>  sound/soc/sh/Makefile |   4 +
>  sound/soc/sh/rz-ssi.c | 871
> ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 881 insertions(+)
>  create mode 100644 sound/soc/sh/rz-ssi.c
> 
> diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index
> ef8a29b9f641..f19bd15c0900 100644
> --- a/sound/soc/sh/Kconfig
> +++ b/sound/soc/sh/Kconfig
> @@ -44,6 +44,12 @@ config SND_SOC_RCAR
>  	help
>  	  This option enables R-Car SRU/SCU/SSIU/SSI sound support
> 
> +config SND_SOC_RZ
> +	tristate "RZ/G2L series SSIF-2 support"
> +	depends on ARCH_R9A07G044 || COMPILE_TEST
> +	help
> +	  This option enables RZ/G2L SSIF-2 sound support.
> +
>  ##
>  ## Boards
>  ##
> diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile index
> 51bd7c81671c..f6fd79948f6a 100644
> --- a/sound/soc/sh/Makefile
> +++ b/sound/soc/sh/Makefile
> @@ -22,3 +22,7 @@ snd-soc-migor-objs		:= migor.o
> 
>  obj-$(CONFIG_SND_SH7760_AC97)	+= snd-soc-sh7760-ac97.o
>  obj-$(CONFIG_SND_SIU_MIGOR)	+= snd-soc-migor.o
> +
> +# RZ/G2L
> +snd-soc-rz-ssi-objs		:= rz-ssi.o
> +obj-$(CONFIG_SND_SOC_RZ)	+= snd-soc-rz-ssi.o
> diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c new file mode
> 100644 index 000000000000..7e0d3a4485e3
> --- /dev/null
> +++ b/sound/soc/sh/rz-ssi.c
> @@ -0,0 +1,871 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// Renesas RZ/G2L ASoC Serial Sound Interface (SSIF-2) Driver // //
> +Copyright (C) 2021 Renesas Electronics Corp.
> +// Copyright (C) 2019 Chris Brandt.
> +//
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/reset.h>
> +#include <sound/soc.h>
> +
> +/* REGISTER OFFSET */
> +#define SSICR			0x000
> +#define SSISR			0x004
> +#define SSIFCR			0x010
> +#define SSIFSR			0x014
> +#define SSIFTDR			0x018
> +#define SSIFRDR			0x01c
> +#define SSIOFR			0x020
> +#define SSISCR			0x024
> +
> +/* SSI REGISTER BITS */
> +#define SSICR_DWL(x)		(((x) & 0x7) << 19)
> +#define SSICR_SWL(x)		(((x) & 0x7) << 16)
> +#define SSICR_MST		BIT(14)
> +#define SSICR_CKDV(x)		(((x) & 0xf) << 4)
> +
> +#define SSICR_CKS		BIT(30)
> +#define SSICR_TUIEN		BIT(29)
> +#define SSICR_TOIEN		BIT(28)
> +#define SSICR_RUIEN		BIT(27)
> +#define SSICR_ROIEN		BIT(26)
> +#define SSICR_MST		BIT(14)
> +#define SSICR_BCKP		BIT(13)
> +#define SSICR_LRCKP		BIT(12)
> +#define SSICR_CKDV(x)		(((x) & 0xf) << 4)
> +#define SSICR_TEN		BIT(1)
> +#define SSICR_REN		BIT(0)
> +
> +#define SSISR_TUIRQ		BIT(29)
> +#define SSISR_TOIRQ		BIT(28)
> +#define SSISR_RUIRQ		BIT(27)
> +#define SSISR_ROIRQ		BIT(26)
> +#define SSISR_IIRQ		BIT(25)
> +
> +#define SSIFCR_AUCKE		BIT(31)
> +#define SSIFCR_SSIRST		BIT(16)
> +#define SSIFCR_TIE		BIT(3)
> +#define SSIFCR_RIE		BIT(2)
> +#define SSIFCR_TFRST		BIT(1)
> +#define SSIFCR_RFRST		BIT(0)
> +
> +#define SSIFSR_TDC_MASK		0x3f
> +#define SSIFSR_TDC_SHIFT	24
> +#define SSIFSR_RDC_MASK		0x3f
> +#define SSIFSR_RDC_SHIFT	8
> +
> +#define SSIFSR_TDC(x)		(((x) & 0x1f) << 24)

This is not used. 
If you use it, you can use SSIFSR_TDC_SHIFT and SSIFSR_TDC_MASK.

> +#define SSIFSR_TDE		BIT(16)
> +#define SSIFSR_RDC(x)		(((x) & 0x1f) << 8)

Same above.

> +#define SSIFSR_RDF		BIT(0)
> +
> +#define SSIOFR_LRCONT		BIT(8)
> +
> +#define SSISCR_TDES(x)		(((x) & 0x1f) << 8)
> +#define SSISCR_RDFS(x)		(((x) & 0x1f) << 0)
> +
> +/* Pre allocated buffers sizes */
> +#define PREALLOC_BUFFER		(SZ_32K)
> +#define PREALLOC_BUFFER_MAX	(SZ_32K)
> +
> +#define SSI_RATES		SNDRV_PCM_RATE_8000_48000 /*
> 8k-44.1kHz */
> +#define SSI_FMTS		SNDRV_PCM_FMTBIT_S16_LE
> +#define SSI_CHAN_MIN		2
> +#define SSI_CHAN_MAX		2
> +#define SSI_FIFO_DEPTH		32
> +
> +struct rz_ssi_priv;
> +
> +struct rz_ssi_stream {
> +	struct rz_ssi_priv *priv;
> +	struct snd_pcm_substream *substream;
> +	int fifo_sample_size;	/* sample capacity of SSI FIFO */
> +	int period_counter;	/* for keeping track of periods transferred */
> +	int sample_width;
> +	int buffer_pos;		/* current frame position in the buffer */
> +	int running;		/* 0=stopped, 1=running */
> +
> +	int uerr_num;
> +	int oerr_num;
> +
> +	int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm);
> +};
> +
> +struct rz_ssi_priv {
> +	void __iomem *base;
> +	struct platform_device *pdev;
> +	struct reset_control *rstc;
> +	struct device *dev;
> +	struct clk *sfr_clk;
> +	struct clk *clk;
> +
> +	int irq_int;
> +	int irq_tx;
> +	int irq_rx;
> +
> +	spinlock_t lock;
> +
> +	/*
> +	 * The SSI supports full-duplex transmission and reception.
> +	 * However, if an error occurs, channel reset (both transmission
> +	 * and reception reset) is required.
> +	 * So it is better to use as half-duplex (playing and recording
> +	 * should be done on separate channels).
> +	 */
> +	struct rz_ssi_stream playback;
> +	struct rz_ssi_stream capture;
> +
> +	/* clock */
> +	unsigned long audio_mck;
> +	unsigned long audio_clk_1;
> +	unsigned long audio_clk_2;
> +
> +	bool lrckp_fsync_fall;	/* LR clock polarity (SSICR.LRCKP) */
> +	bool bckp_rise;	/* Bit clock polarity (SSICR.BCKP) */
> +};
> +
> +static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32
> +data) {
> +	writel(data, (priv->base + reg));
> +}
> +
> +static u32 rz_ssi_reg_readl(struct rz_ssi_priv *priv, uint reg) {
> +	return readl(priv->base + reg);
> +}
> +
> +static void rz_ssi_reg_mask_setl(struct rz_ssi_priv __iomem *priv, uint reg,
> +				 u32 bclr, u32 bset)
> +{
> +	u32 val;
> +
> +	val = readl(priv->base + reg);
> +	val = (val & ~bclr) | bset;
> +	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 =
> asoc_substream_to_rtd(substream);
> +
> +	return asoc_rtd_to_cpu(rtd, 0);
> +}
> +
> +static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi,
> +					 struct snd_pcm_substream
> *substream) {
> +	return substream->stream == SNDRV_PCM_STREAM_PLAYBACK; }
> +
> +static inline struct rz_ssi_stream *
> +rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream
> +*substream) {
> +	struct rz_ssi_stream *stream = &ssi->playback;
> +
> +	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
> +		stream = &ssi->capture;
> +
> +	return stream;
> +}
> +
> +static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
> +				  struct rz_ssi_stream *strm)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&ssi->lock, flags);
> +	ret = !!(strm->substream && strm->substream->runtime);
> +	spin_unlock_irqrestore(&ssi->lock, flags);
> +
> +	return ret;
> +}
> +
> +static int rz_ssi_stream_init(struct rz_ssi_priv *ssi,
> +			      struct rz_ssi_stream *strm,
> +			      struct snd_pcm_substream *substream) {
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +
> +	strm->substream = substream;
> +	strm->sample_width = samples_to_bytes(runtime, 1);
> +	strm->period_counter = 0;
> +	strm->buffer_pos = 0;
> +
> +	strm->oerr_num = 0;
> +	strm->uerr_num = 0;
> +	strm->running = 0;
> +
> +	/* fifo init */
> +	strm->fifo_sample_size = SSI_FIFO_DEPTH;
> +
> +	return 0;
> +}
> +
> +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);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&ssi->lock, flags);
> +	strm->substream = NULL;
> +	spin_unlock_irqrestore(&ssi->lock, flags);
> +
> +	if (strm->oerr_num > 0)
> +		dev_info(dai->dev, "overrun = %d\n", strm->oerr_num);
> +
> +	if (strm->uerr_num > 0)
> +		dev_info(dai->dev, "underrun = %d\n", strm->uerr_num); }
> +
> +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 };
> +	unsigned int channel_bits = 32;	/* System Word Length */
> +	unsigned long bclk_rate = rate * channels * channel_bits;
> +	unsigned int div;
> +	unsigned int i;
> +	u32 ssicr = 0;
> +	u32 clk_ckdv;
> +
> +	/* Clear AUCKE so we can set MST */
> +	rz_ssi_reg_writel(ssi, SSIFCR, 0);
> +
> +	/* Continue to output LRCK pin even when idle */
> +	rz_ssi_reg_writel(ssi, SSIOFR, SSIOFR_LRCONT);
> +	if (ssi->audio_clk_1 && ssi->audio_clk_2) {
> +		if (ssi->audio_clk_1 % bclk_rate)
> +			ssi->audio_mck = ssi->audio_clk_2;
> +		else
> +			ssi->audio_mck = ssi->audio_clk_1;
> +	}
> +
> +	/* Clock setting */
> +	ssicr |= SSICR_MST;
> +	if (ssi->audio_mck == ssi->audio_clk_1)
> +		ssicr |= SSICR_CKS;
> +	if (ssi->bckp_rise)
> +		ssicr |= SSICR_BCKP;
> +	if (ssi->lrckp_fsync_fall)
> +		ssicr |= SSICR_LRCKP;
> +
> +	/* Determine the clock divider */
> +	clk_ckdv = 0;
> +	div = ssi->audio_mck / bclk_rate;
> +	/* try to find an match */
> +	for (i = 0; i < ARRAY_SIZE(ckdv); i++) {
> +		if (ckdv[i] == div) {
> +			clk_ckdv = i;
> +			break;
> +		}
> +	}
> +
> +	if (i == ARRAY_SIZE(ckdv)) {
> +		dev_err(ssi->dev, "Rate not divisible by audio clock
> source\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * DWL: Data Word Length = 16 bits
> +	 * SWL: System Word Length = 32 bits
> +	 */
> +	ssicr |= SSICR_CKDV(clk_ckdv);
> +	ssicr |= SSICR_DWL(1) | SSICR_SWL(3);
> +	rz_ssi_reg_writel(ssi, SSICR, ssicr);
> +	rz_ssi_reg_writel(ssi, SSIFCR,
> +			  (SSIFCR_AUCKE | SSIFCR_TFRST |
> SSIFCR_RFRST));
> +
> +	return 0;
> +}
> +
> +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);
> +	u32 ssicr, ssifcr;
> +
> +	ssicr = rz_ssi_reg_readl(ssi, SSICR);
> +	ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF;
> +
> +	/* FIFO interrupt thresholds */
> +	rz_ssi_reg_writel(ssi, SSISCR,
> +			  SSISCR_TDES(strm->fifo_sample_size / 2 - 1) |
> +			  SSISCR_RDFS(0));
> +
> +	/* enable IRQ */
> +	if (is_play) {
> +		ssicr |= SSICR_TUIEN | SSICR_TOIEN;
> +		ssifcr |= SSIFCR_TIE | SSIFCR_RFRST;
> +	} else {
> +		ssicr |= SSICR_RUIEN | SSICR_ROIEN;
> +		ssifcr |= SSIFCR_RIE | SSIFCR_TFRST;
> +	}
> +
> +	rz_ssi_reg_writel(ssi, SSICR, ssicr);
> +	rz_ssi_reg_writel(ssi, SSIFCR, ssifcr);
> +
> +	/* Clear all error flags */
> +	rz_ssi_reg_mask_setl(ssi, SSISR,
> +			     (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
> +			      SSISR_RUIRQ), 0);
> +
> +	strm->running = 1;
> +	ssicr |= is_play ? SSICR_TEN : SSICR_REN;
> +	rz_ssi_reg_writel(ssi, SSICR, ssicr);
> +
> +	return 0;
> +}
> +
> +static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream
> +*strm) {
> +	int timeout;
> +
> +	strm->running = 0;
> +
> +	/* Disable TX/RX */
> +	rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
> +
> +	/* Disable irqs */
> +	rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN |
> +			     SSICR_RUIEN | SSICR_ROIEN, 0);
> +	rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0);
> +
> +	/* Clear all error flags */
> +	rz_ssi_reg_mask_setl(ssi, SSISR,
> +			     (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
> +			      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");
> +
> +	/* Hold FIFOs in reset */
> +	rz_ssi_reg_mask_setl(ssi, SSIFCR, 0,
> +			     SSIFCR_TFRST | SSIFCR_RFRST);
> +
> +	return 0;
> +}
> +
> +static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int
> +frames) {
> +	struct snd_pcm_substream *substream = strm->substream;
> +	struct snd_pcm_runtime *runtime;
> +	int current_period;
> +
> +	if (!strm->running || !substream || !substream->runtime)
> +		return;
> +
> +	runtime = substream->runtime;
> +	strm->buffer_pos += frames;
> +	WARN_ON(strm->buffer_pos > runtime->buffer_size);
> +
> +	/* ring buffer */
> +	if (strm->buffer_pos == runtime->buffer_size)
> +		strm->buffer_pos = 0;
> +
> +	current_period = strm->buffer_pos / runtime->period_size;
> +	if (strm->period_counter != current_period) {
> +		snd_pcm_period_elapsed(strm->substream);
> +		strm->period_counter = current_period;
> +	}
> +}
> +
> +static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct
> +rz_ssi_stream *strm) {
> +	struct snd_pcm_substream *substream = strm->substream;
> +	struct snd_pcm_runtime *runtime;
> +	u16 *buf;
> +	int fifo_samples;
> +	int frames_left;
> +	int samples = 0;
> +	int i;


Please use reverse christmas tree order.

> +
> +	if (!rz_ssi_stream_is_valid(ssi, strm))
> +		return -EINVAL;
> +
> +	runtime = substream->runtime;
> +	/* frames left in this period */
> +	frames_left = runtime->period_size - (strm->buffer_pos %
> +					      runtime->period_size);
> +	if (frames_left == 0)
> +		frames_left = runtime->period_size;
> +
> +	/* Samples in RX FIFO */
> +	fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
> +			SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
> +
> +	/* Only read full frames at a time */
> +	while (frames_left && (fifo_samples >= runtime->channels)) {
> +		samples += runtime->channels;
> +		fifo_samples -= runtime->channels;
> +		frames_left--;
> +	}
> +
> +	/* not enough samples yet */
> +	if (samples == 0)
> +		return 0;
> +
> +	/* calculate new buffer index */
> +	buf = (u16 *)(runtime->dma_area);
> +	buf += strm->buffer_pos * runtime->channels;
> +
> +	/* Note, only supports 16-bit samples */
> +	for (i = 0; i < samples; i++)
> +		*buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
> +
> +	rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
> +	rz_ssi_pointer_update(strm, samples / runtime->channels);
> +
> +	/*
> +	 * If we finished this period, but there are more samples in
> +	 * the RX FIFO, call this function again
> +	 */
> +	if (frames_left == 0 && fifo_samples >= runtime->channels)
> +		rz_ssi_pio_recv(ssi, strm);
> +
> +	return 0;
> +}
> +
> +static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct
> +rz_ssi_stream *strm) {
> +	struct snd_pcm_substream *substream = strm->substream;
> +	struct snd_pcm_runtime *runtime = substream->runtime;
> +	int sample_space;
> +	int samples = 0;
> +	int frames_left;
> +	int i;
> +	u32 ssifsr;
> +	u16 *buf;

Please use reverse christmas tree order.

> +
> +	if (!rz_ssi_stream_is_valid(ssi, strm))
> +		return -EINVAL;
> +
> +	/* frames left in this period */
> +	frames_left = runtime->period_size - (strm->buffer_pos %
> +					      runtime->period_size);
> +	if (frames_left == 0)
> +		frames_left = runtime->period_size;
> +
> +	sample_space = strm->fifo_sample_size;
> +	ssifsr = rz_ssi_reg_readl(ssi, SSIFSR);
> +	sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) &
> SSIFSR_TDC_MASK;
> +
> +	/* Only add full frames at a time */
> +	while (frames_left && (sample_space >= runtime->channels)) {
> +		samples += runtime->channels;
> +		sample_space -= runtime->channels;
> +		frames_left--;
> +	}
> +
> +	/* no space to send anything right now */
> +	if (samples == 0)
> +		return 0;
> +
> +	/* calculate new buffer index */
> +	buf = (u16 *)(runtime->dma_area);
> +	buf += strm->buffer_pos * runtime->channels;
> +
> +	/* Note, only supports 16-bit samples */
> +	for (i = 0; i < samples; i++)
> +		rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16));
> +
> +	rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_TDE, 0);
> +	rz_ssi_pointer_update(strm, samples / runtime->channels);
> +
> +	return 0;
> +}
> +
> +static irqreturn_t rz_ssi_interrupt(int irq, void *data) {
> +	struct rz_ssi_stream *strm = NULL;
> +	struct rz_ssi_priv *ssi = data;
> +	u32 ssisr = rz_ssi_reg_readl(ssi, SSISR);
> +
> +	if (ssi->playback.substream)
> +		strm = &ssi->playback;
> +	else if (ssi->capture.substream)
> +		strm = &ssi->capture;
> +	else
> +		return IRQ_HANDLED; /* Left over TX/RX interrupt */
> +
> +	if (irq == ssi->irq_int) { /* error or idle */
> +		if (ssisr & SSISR_TUIRQ)
> +			strm->uerr_num++;
> +		if (ssisr & SSISR_TOIRQ)
> +			strm->oerr_num++;
> +		if (ssisr & SSISR_RUIRQ)
> +			strm->uerr_num++;
> +		if (ssisr & SSISR_ROIRQ)
> +			strm->oerr_num++;
> +
> +		if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ |
> +			     SSISR_ROIRQ)) {
> +			/* Error handling */
> +			/* You must reset (stop/restart) after each interrupt */
> +			rz_ssi_stop(ssi, strm);
> +
> +			/* Clear all flags */
> +			rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ |
> +					     SSISR_TUIRQ | SSISR_ROIRQ |
> +					     SSISR_RUIRQ, 0);
> +
> +			/* Add/remove more data */
> +			strm->transfer(ssi, strm);
> +
> +			/* Resume */
> +			rz_ssi_start(ssi, strm);
> +		}
> +	}
> +
> +	if (!strm->running)
> +		return IRQ_HANDLED;
> +
> +	/* tx data empty */
> +	if (irq == ssi->irq_tx)
> +		strm->transfer(ssi, &ssi->playback);
> +
> +	/* rx data full */
> +	if (irq == ssi->irq_rx) {
> +		strm->transfer(ssi, &ssi->capture);
> +		rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int
> cmd,
> +			      struct snd_soc_dai *dai)
> +{
> +	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
> +	struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
> +	int ret = 0;
> +
> +	switch (cmd) {
> +	case SNDRV_PCM_TRIGGER_START:
> +		/* Soft Reset */
> +		rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST);
> +		rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0);
> +		udelay(5);
> +
> +		ret = rz_ssi_stream_init(ssi, strm, substream);
> +		if (ret)
> +			goto done;
> +
> +		ret = strm->transfer(ssi, strm);
> +		if (ret)
> +			goto done;
> +
> +		ret = rz_ssi_start(ssi, strm);
> +		break;
> +	case SNDRV_PCM_TRIGGER_STOP:
> +		rz_ssi_stop(ssi, strm);
> +		rz_ssi_stream_quit(ssi, strm);
> +		break;
> +	}
> +
> +done:
> +	return ret;
> +}
> +
> +static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int
> +fmt) {
> +	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
> +
> +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> +	case SND_SOC_DAIFMT_CBS_CFS:
> +		break;
> +	default:
> +		dev_err(ssi->dev, "Codec should be clk and frame
> consumer\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * set clock polarity
> +	 *
> +	 * "normal" BCLK = Signal is available at rising edge of BCLK
> +	 * "normal" FSYNC = (I2S) Left ch starts with falling FSYNC edge
> +	 */
> +	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> +	case SND_SOC_DAIFMT_NB_NF:
> +		ssi->bckp_rise = false;
> +		ssi->lrckp_fsync_fall = false;
> +		break;
> +	case SND_SOC_DAIFMT_NB_IF:
> +		ssi->bckp_rise = false;
> +		ssi->lrckp_fsync_fall = true;
> +		break;
> +	case SND_SOC_DAIFMT_IB_NF:
> +		ssi->bckp_rise = true;
> +		ssi->lrckp_fsync_fall = false;
> +		break;
> +	case SND_SOC_DAIFMT_IB_IF:
> +		ssi->bckp_rise = true;
> +		ssi->lrckp_fsync_fall = true;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	/* only i2s support */
> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	case SND_SOC_DAIFMT_I2S:
> +		break;
> +	default:
> +		dev_err(ssi->dev, "Only I2S mode is supported.\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
> +				struct snd_pcm_hw_params *params,
> +				struct snd_soc_dai *dai)
> +{
> +	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
> +	unsigned int sample_bits = hw_param_interval(params,
> +
> 	SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
> +	unsigned int channels = params_channels(params);
> +
> +	if (sample_bits != 16) {
> +		dev_err(ssi->dev, "Unsupported sample width: %d\n",
> +			sample_bits);
> +		return -EINVAL;
> +	}
> +
> +	if (channels != 2) {
> +		dev_err(ssi->dev, "Number of channels not matched: %d\n",
> +			channels);
> +		return -EINVAL;
> +	}
> +
> +	return rz_ssi_clk_setup(ssi, params_rate(params),
> +				params_channels(params));
> +}
> +
> +static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
> +	.trigger	= rz_ssi_dai_trigger,
> +	.set_fmt	= rz_ssi_dai_set_fmt,
> +	.hw_params	= rz_ssi_dai_hw_params,
> +};
> +
> +static const struct snd_pcm_hardware rz_ssi_pcm_hardware = {
> +	.info			= SNDRV_PCM_INFO_INTERLEAVED	|
> +				  SNDRV_PCM_INFO_MMAP		|
> +				  SNDRV_PCM_INFO_MMAP_VALID,
> +	.buffer_bytes_max	= PREALLOC_BUFFER,
> +	.period_bytes_min	= 32,
> +	.period_bytes_max	= 8192,
> +	.channels_min		= SSI_CHAN_MIN,
> +	.channels_max		= SSI_CHAN_MAX,
> +	.periods_min		= 1,
> +	.periods_max		= 32,
> +	.fifo_size		= 32 * 2,
> +};
> +
> +static int rz_ssi_pcm_open(struct snd_soc_component *component,
> +			   struct snd_pcm_substream *substream) {
> +	snd_soc_set_runtime_hwparams(substream,
> &rz_ssi_pcm_hardware);
> +
> +	return snd_pcm_hw_constraint_integer(substream->runtime,
> +
> SNDRV_PCM_HW_PARAM_PERIODS);
> +}
> +
> +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 rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
> +	struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
> +
> +	return strm->buffer_pos;
> +}
> +
> +static int rz_ssi_pcm_new(struct snd_soc_component *component,
> +			  struct snd_soc_pcm_runtime *rtd)
> +{
> +	snd_pcm_set_managed_buffer_all(rtd->pcm,
> SNDRV_DMA_TYPE_DEV,
> +				       rtd->card->snd_card->dev,
> +				       PREALLOC_BUFFER,
> PREALLOC_BUFFER_MAX);
> +	return 0;
> +}
> +
> +static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
> +	{
> +		.name			= "rz-ssi-dai",
> +		.playback = {
> +			.rates		= SSI_RATES,
> +			.formats	= SSI_FMTS,
> +			.channels_min	= SSI_CHAN_MIN,
> +			.channels_max	= SSI_CHAN_MAX,
> +		},
> +		.capture = {
> +			.rates		= SSI_RATES,
> +			.formats	= SSI_FMTS,
> +			.channels_min	= SSI_CHAN_MIN,
> +			.channels_max	= SSI_CHAN_MAX,
> +		},
> +		.ops = &rz_ssi_dai_ops,
> +	},
> +};
> +
> +static const struct snd_soc_component_driver rz_ssi_soc_component = {
> +	.name		= "rz-ssi",
> +	.open		= rz_ssi_pcm_open,
> +	.pointer	= rz_ssi_pcm_pointer,
> +	.pcm_construct	= rz_ssi_pcm_new,
> +};
> +
> +static int rz_ssi_probe(struct platform_device *pdev) {
> +	struct rz_ssi_priv *ssi;
> +	struct clk *audio_clk;
> +	int ret;
> +
> +	ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL);
> +	if (!ssi)
> +		return -ENOMEM;
> +
> +	ssi->pdev = pdev;
> +	ssi->dev = &pdev->dev;
> +	ssi->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(ssi->base))
> +		return PTR_ERR(ssi->base);
> +
> +	ssi->clk = devm_clk_get(&pdev->dev, "ssi");
> +	if (IS_ERR(ssi->clk))
> +		return PTR_ERR(ssi->clk);
> +
> +	ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr");
> +	if (IS_ERR(ssi->sfr_clk))
> +		return PTR_ERR(ssi->sfr_clk);
> +
> +	audio_clk = devm_clk_get(&pdev->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");
> +	if (IS_ERR(audio_clk))
> +		return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk),
> +				     "no audio clk2");
> +
> +	ssi->audio_clk_2 = clk_get_rate(audio_clk);
> +	if (!(ssi->audio_clk_1 || ssi->audio_clk_2))
> +		return dev_err_probe(&pdev->dev, -EINVAL,
> +				     "no audio clk1 or audio clk2");
> +
> +	ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 :
> +ssi->audio_clk_2;
> +
> +	ssi->playback.transfer = rz_ssi_pio_send;
> +	ssi->capture.transfer = rz_ssi_pio_recv;
> +	ssi->playback.priv = ssi;
> +	ssi->capture.priv = ssi;
> +
> +	/* Error Interrupt */
> +	ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
> +	if (ssi->irq_int < 0)
> +		return dev_err_probe(&pdev->dev, -ENODEV,
> +				     "Unable to get SSI int_req IRQ\n");
> +
> +	ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt,
> +			       0, dev_name(&pdev->dev), ssi);
> +	if (ret < 0)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "irq request error (int_req)\n");
> +
> +	/* Tx and Rx interrupts (pio only) */
> +	ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx");
> +	if (ssi->irq_tx < 0)
> +		return dev_err_probe(&pdev->dev, -ENODEV,
> +				     "Unable to get SSI dma_tx IRQ\n");
> +
> +	ret = devm_request_irq(&pdev->dev, ssi->irq_tx, &rz_ssi_interrupt,
> 0,
> +			       dev_name(&pdev->dev), ssi);
> +	if (ret < 0)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "irq request error (dma_tx)\n");
> +
> +	ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx");
> +	if (ssi->irq_rx < 0)
> +		return dev_err_probe(&pdev->dev, -ENODEV,
> +				     "Unable to get SSI dma_rx IRQ\n");
> +
> +	ret = devm_request_irq(&pdev->dev, ssi->irq_rx, &rz_ssi_interrupt,
> 0,
> +			       dev_name(&pdev->dev), ssi);
> +	if (ret < 0)
> +		return dev_err_probe(&pdev->dev, ret,
> +				     "irq request error (dma_rx)\n");
> +
> +	ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
> +	if (IS_ERR(ssi->rstc))
> +		return PTR_ERR(ssi->rstc);
> +
> +	reset_control_deassert(ssi->rstc);
> +	pm_runtime_enable(&pdev->dev);
> +	pm_runtime_resume_and_get(&pdev->dev);
> +
> +	spin_lock_init(&ssi->lock);
> +	dev_set_drvdata(&pdev->dev, ssi);
> +	ret = devm_snd_soc_register_component(&pdev->dev,
> &rz_ssi_soc_component,
> +					      rz_ssi_soc_dai,
> +
> ARRAY_SIZE(rz_ssi_soc_dai));
> +	if (ret < 0) {
> +		pm_runtime_put(ssi->dev);
> +		pm_runtime_disable(ssi->dev);
> +		reset_control_assert(ssi->rstc);
> +		dev_err(&pdev->dev, "failed to register snd component\n");
> +	}
> +
> +	return ret;
> +}
> +
> +static int rz_ssi_remove(struct platform_device *pdev) {
> +	struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
> +
> +	pm_runtime_put(ssi->dev);
> +	pm_runtime_disable(ssi->dev);
> +	reset_control_assert(ssi->rstc);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id rz_ssi_of_match[] = {
> +	{ .compatible = "renesas,rz-ssi", },
> +	{/* Sentinel */},
> +};
> +MODULE_DEVICE_TABLE(of, rz_ssi_of_match);
> +
> +static struct platform_driver rz_ssi_driver = {
> +	.driver	= {
> +		.name	= "rz-ssi-pcm-audio",
> +		.of_match_table = rz_ssi_of_match,
> +	},
> +	.probe		= rz_ssi_probe,
> +	.remove		= rz_ssi_remove,
> +};
> +
> +module_platform_driver(rz_ssi_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Renesas RZ/G2L ASoC Serial Sound Interface
> +Driver"); MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
> --
> 2.17.1

Best regards,
  Nobuhiro



^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC
  2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
                   ` (23 preceding siblings ...)
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 24/24] arm64: defconfig: Enable SND_SOC_WM8978 Lad Prabhakar
@ 2022-04-21  3:25 ` nobuhiro1.iwamatsu
  2022-04-21 11:17   ` Pavel Machek
  2022-04-25  5:52   ` Prabhakar Mahadev Lad
  24 siblings, 2 replies; 39+ messages in thread
From: nobuhiro1.iwamatsu @ 2022-04-21  3:25 UTC (permalink / raw)
  To: prabhakar.mahadev-lad.rj, cip-dev, pavel; +Cc: biju.das.jz

Hi all,

> -----Original Message-----
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Sent: Thursday, April 21, 2022 6:34 AM
> To: cip-dev@lists.cip-project.org; iwamatsu nobuhiro(岩松 信洋 □SWC◯A
> CT) <nobuhiro1.iwamatsu@toshiba.co.jp>; Pavel Machek
> <pavel@denx.de>
> Cc: Biju Das <biju.das.jz@bp.renesas.com>
> Subject: [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC
> 
> Hi All,
> 
> This patch series adds sound support to Renesas RZ/G2L SoC and enables SSI
> and codec on Renesas RZ/G2L SMARC EVK.
> 
> All the patches have been cherry picked from v5.18-rc3.
> 
> Sound support patches were already sent earlier as part of bulk series [0], but
> due to some review comments the patches were rejected, now that the driver is
> fixed upstream, re-sending the series with all the fixes.
> 
> [0] https://patchwork.kernel.org/project/cip-dev/cover/
> 20211229101530.22783-1-prabhakar.mahadev-lad.rj@bp.renesas.com/

Looks good to me. 
I am testing on https://gitlab.com/cip-project/cip-kernel/linux-cip/-/pipelines/521117833.
I can merge it if there are no other comments and test is successful.

> 
> Cheers,
> Prabhakar
> 

Best regards,
  Nobuhiro

> Biju Das (16):
>   ASoC: dt-bindings: Document RZ/G2L bindings
>   ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support
>   ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel
>     configuration parameter
>   ASoC: sh: Add RZ/G2L SSIF-2 driver
>   ASoC: sh: rz-ssi: Add SSI DMAC support
>   ASoC: sh: rz-ssi: Fix dereference of noderef expression warning
>   ASoC: sh: rz-ssi: Fix wrong operator used issue
>   ASoC: sh: rz-ssi: Improve error handling in rz_ssi_dma_request
>     function
>   arm64: dts: renesas: r9a07g044: Add external audio clock nodes
>   arm64: dts: renesas: r9a07g044: Add SSI support
>   arm64: dts: renesas: r9a07g044: Add DMA support to SSI
>   arm64: dts: renesas: rzg2l-smarc: Add WM8978 sound codec
>   arm64: dts: renesas: rzg2l-smarc: Enable audio
>   arm64: dts: renesas: rzg2l-smarc: Add Mic routing
>   arm64: defconfig: Enable SOUND_SOC_RZ
>   arm64: defconfig: Enable SND_SOC_WM8978
> 
> Heiner Kallweit (1):
>   ASoC: sh: rz-ssi: Check return value of pm_runtime_resume_and_get()
> 
> Lad Prabhakar (7):
>   ASoC: sh: rz-ssi: Drop calling rz_ssi_pio_recv() recursively
>   ASoC: sh: rz-ssi: Make the data structures available before
>     registering the handlers
>   ASoC: sh: rz-ssi: Drop ssi parameter from rz_ssi_stream_init()
>   ASoC: sh: rz-ssi: Make return type of rz_ssi_stream_is_valid() to bool
>   ASoC: sh: rz-ssi: Use a do-while loop in rz_ssi_pio_recv()
>   ASoC: sh: rz-ssi: Add rz_ssi_set_substream() helper function
>   ASoC: sh: rz-ssi: Remove duplicate macros
> 
>  .../bindings/sound/renesas,rz-ssi.yaml        |  118 ++
>  arch/arm64/boot/dts/renesas/r9a07g044.dtsi    |   98 ++
>  arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi  |   79 ++
>  arch/arm64/configs/defconfig                  |    2 +
>  sound/soc/sh/Kconfig                          |    6 +
>  sound/soc/sh/Makefile                         |    4 +
>  sound/soc/sh/rz-ssi.c                         | 1078
> +++++++++++++++++
>  7 files changed, 1385 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
>  create mode 100644 sound/soc/sh/rz-ssi.c
> 
> --
> 2.17.1

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 5.10.y-cip 03/24] ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel configuration parameter
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 03/24] ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel configuration parameter Lad Prabhakar
@ 2022-04-21  8:32   ` Pavel Machek
  2022-04-21 10:55     ` Prabhakar Mahadev Lad
  0 siblings, 1 reply; 39+ messages in thread
From: Pavel Machek @ 2022-04-21  8:32 UTC (permalink / raw)
  To: Lad Prabhakar; +Cc: cip-dev, Nobuhiro Iwamatsu, Pavel Machek, Biju Das

[-- Attachment #1: Type: text/plain, Size: 1100 bytes --]

Hi!

>  .../bindings/sound/renesas,rz-ssi.yaml        | 22 +++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
> index 471937cb8d05..414ff8035a4e 100644
> --- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
> +++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
> @@ -48,6 +48,24 @@ properties:
>    dmas:
>      minItems: 1
>      maxItems: 2
> +    description:
> +      The first cell represents a phandle to dmac

I would not mind . at the end of the sentence, to be consistent with
the next paragraph, but that's really a nitpicking.

> +      The second cell specifies the encoded MID/RID values of the SSI port
> +      connected to the DMA client and the slave channel configuration
> +      parameters.

Best regards,
								Pavel
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 5.10.y-cip 05/24] ASoC: sh: rz-ssi: Add SSI DMAC support
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 05/24] ASoC: sh: rz-ssi: Add SSI DMAC support Lad Prabhakar
@ 2022-04-21  8:33   ` Pavel Machek
  2022-04-21 11:02     ` Prabhakar Mahadev Lad
  0 siblings, 1 reply; 39+ messages in thread
From: Pavel Machek @ 2022-04-21  8:33 UTC (permalink / raw)
  To: Lad Prabhakar; +Cc: cip-dev, Nobuhiro Iwamatsu, Pavel Machek, Biju Das

[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]

Hi!

> @@ -775,8 +949,18 @@ static int rz_ssi_probe(struct platform_device *pdev)
>  
>  	ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
>  
> -	ssi->playback.transfer = rz_ssi_pio_send;
> -	ssi->capture.transfer = rz_ssi_pio_recv;
> +	/* Detect DMA support */
> +	ret = rz_ssi_dma_request(ssi, &pdev->dev);
> +	if (ret < 0) {
> +		dev_warn(&pdev->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");
> +		ssi->playback.transfer = rz_ssi_dma_transfer;
> +		ssi->capture.transfer = rz_ssi_dma_transfer;
> +	}
> +
>  	ssi->playback.priv = ssi;
>  	ssi->capture.priv = ssi;
>  

AFAICT rz_ssi_dma_request() allocates resources and
rz_ssi_release_dma_channels() is needed to free them if we fail.

But in most failure paths below, that's not done, with one exception:

> @@ -829,6 +1017,8 @@ static int rz_ssi_probe(struct platform_device *pdev)
>  					      rz_ssi_soc_dai,
>  					      ARRAY_SIZE(rz_ssi_soc_dai));
>  	if (ret < 0) {
> +		rz_ssi_release_dma_channels(ssi);
> +
>  		pm_runtime_put(ssi->dev);
>  		pm_runtime_disable(ssi->dev);
>  		reset_control_assert(ssi->rstc);

Best regards,
								Pavel
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver
  2022-04-21  1:12   ` nobuhiro1.iwamatsu
@ 2022-04-21 10:50     ` Prabhakar Mahadev Lad
  2022-04-21 11:02       ` Pavel Machek
  0 siblings, 1 reply; 39+ messages in thread
From: Prabhakar Mahadev Lad @ 2022-04-21 10:50 UTC (permalink / raw)
  To: nobuhiro1.iwamatsu, cip-dev, pavel; +Cc: Biju Das

Hi Nobuhiro,

Thank you for the review.

> -----Original Message-----
> From: nobuhiro1.iwamatsu@toshiba.co.jp <nobuhiro1.iwamatsu@toshiba.co.jp>
> Sent: 21 April 2022 02:12
> To: Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>; cip-
> dev@lists.cip-project.org; pavel@denx.de
> Cc: Biju Das <biju.das.jz@bp.renesas.com>
> Subject: RE: [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver
> 
> Hi Lad,
> 
> > -----Original Message-----
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > Sent: Thursday, April 21, 2022 6:34 AM
> > To: cip-dev@lists.cip-project.org; iwamatsu nobuhiro(岩松 信洋 □SWC◯
> A
> > CT) <nobuhiro1.iwamatsu@toshiba.co.jp>; Pavel Machek <pavel@denx.de>
> > Cc: Biju Das <biju.das.jz@bp.renesas.com>
> > Subject: [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver
> >
> > From: Biju Das <biju.das.jz@bp.renesas.com>
> >
> > commit 03e786bd43410fa93e5d2459f7a43e90ff0ae801 upstream.
> >
> > Add serial sound interface(SSIF-2) driver support for RZ/G2L SoC.
> >
> > Based on the work done by Chris Brandt for RZ/A SSI driver.
> >
> > Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
> > Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > Link:
> > https://jpn01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flore
> > .kernel.org%2Fr%2F20210813091156.10700-2-biju.das.jz%40bp.renesas.co&a
> > mp;data=05%7C01%7Cprabhakar.mahadev-lad.rj%40bp.renesas.com%7Cc04d969d
> > 9c0d44303be708da233402c4%7C53d82571da1947e49cb4625a166a4a2a%7C0%7C0%7C
> > 637861003542900587%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjo
> > iV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=j%2F
> > 49Jn9UomcKR6Muv0IOAII11j6my86H%2BvYVQ1McGaY%3D&amp;reserved=0
> > m
> > Signed-off-by: Mark Brown <broonie@kernel.org>
> > [PL: Dropped using modern terminology]
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > ---
> >  sound/soc/sh/Kconfig  |   6 +
> >  sound/soc/sh/Makefile |   4 +
> >  sound/soc/sh/rz-ssi.c | 871
> > ++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 881 insertions(+)
> >  create mode 100644 sound/soc/sh/rz-ssi.c
> >
> > diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index
> > ef8a29b9f641..f19bd15c0900 100644
> > --- a/sound/soc/sh/Kconfig
> > +++ b/sound/soc/sh/Kconfig
> > @@ -44,6 +44,12 @@ config SND_SOC_RCAR
> >  	help
> >  	  This option enables R-Car SRU/SCU/SSIU/SSI sound support
> >
> > +config SND_SOC_RZ
> > +	tristate "RZ/G2L series SSIF-2 support"
> > +	depends on ARCH_R9A07G044 || COMPILE_TEST
> > +	help
> > +	  This option enables RZ/G2L SSIF-2 sound support.
> > +
> >  ##
> >  ## Boards
> >  ##
> > diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile index
> > 51bd7c81671c..f6fd79948f6a 100644
> > --- a/sound/soc/sh/Makefile
> > +++ b/sound/soc/sh/Makefile
> > @@ -22,3 +22,7 @@ snd-soc-migor-objs		:= migor.o
> >
> >  obj-$(CONFIG_SND_SH7760_AC97)	+= snd-soc-sh7760-ac97.o
> >  obj-$(CONFIG_SND_SIU_MIGOR)	+= snd-soc-migor.o
> > +
> > +# RZ/G2L
> > +snd-soc-rz-ssi-objs		:= rz-ssi.o
> > +obj-$(CONFIG_SND_SOC_RZ)	+= snd-soc-rz-ssi.o
> > diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c new file
> > mode
> > 100644 index 000000000000..7e0d3a4485e3
> > --- /dev/null
> > +++ b/sound/soc/sh/rz-ssi.c
> > @@ -0,0 +1,871 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Renesas RZ/G2L ASoC Serial Sound Interface (SSIF-2) Driver // //
> > +Copyright (C) 2021 Renesas Electronics Corp.
> > +// Copyright (C) 2019 Chris Brandt.
> > +//
> > +
> > +#include <linux/clk.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of_device.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/reset.h>
> > +#include <sound/soc.h>
> > +
> > +/* REGISTER OFFSET */
> > +#define SSICR			0x000
> > +#define SSISR			0x004
> > +#define SSIFCR			0x010
> > +#define SSIFSR			0x014
> > +#define SSIFTDR			0x018
> > +#define SSIFRDR			0x01c
> > +#define SSIOFR			0x020
> > +#define SSISCR			0x024
> > +
> > +/* SSI REGISTER BITS */
> > +#define SSICR_DWL(x)		(((x) & 0x7) << 19)
> > +#define SSICR_SWL(x)		(((x) & 0x7) << 16)
> > +#define SSICR_MST		BIT(14)
> > +#define SSICR_CKDV(x)		(((x) & 0xf) << 4)
> > +
> > +#define SSICR_CKS		BIT(30)
> > +#define SSICR_TUIEN		BIT(29)
> > +#define SSICR_TOIEN		BIT(28)
> > +#define SSICR_RUIEN		BIT(27)
> > +#define SSICR_ROIEN		BIT(26)
> > +#define SSICR_MST		BIT(14)
> > +#define SSICR_BCKP		BIT(13)
> > +#define SSICR_LRCKP		BIT(12)
> > +#define SSICR_CKDV(x)		(((x) & 0xf) << 4)
> > +#define SSICR_TEN		BIT(1)
> > +#define SSICR_REN		BIT(0)
> > +
> > +#define SSISR_TUIRQ		BIT(29)
> > +#define SSISR_TOIRQ		BIT(28)
> > +#define SSISR_RUIRQ		BIT(27)
> > +#define SSISR_ROIRQ		BIT(26)
> > +#define SSISR_IIRQ		BIT(25)
> > +
> > +#define SSIFCR_AUCKE		BIT(31)
> > +#define SSIFCR_SSIRST		BIT(16)
> > +#define SSIFCR_TIE		BIT(3)
> > +#define SSIFCR_RIE		BIT(2)
> > +#define SSIFCR_TFRST		BIT(1)
> > +#define SSIFCR_RFRST		BIT(0)
> > +
> > +#define SSIFSR_TDC_MASK		0x3f
> > +#define SSIFSR_TDC_SHIFT	24
> > +#define SSIFSR_RDC_MASK		0x3f
> > +#define SSIFSR_RDC_SHIFT	8
> > +
> > +#define SSIFSR_TDC(x)		(((x) & 0x1f) << 24)
> 
> This is not used.
> If you use it, you can use SSIFSR_TDC_SHIFT and SSIFSR_TDC_MASK.
> 
> > +#define SSIFSR_TDE		BIT(16)
> > +#define SSIFSR_RDC(x)		(((x) & 0x1f) << 8)
> 
> Same above.
> 
> > +#define SSIFSR_RDF		BIT(0)
> > +
> > +#define SSIOFR_LRCONT		BIT(8)
> > +
> > +#define SSISCR_TDES(x)		(((x) & 0x1f) << 8)
> > +#define SSISCR_RDFS(x)		(((x) & 0x1f) << 0)
> > +
> > +/* Pre allocated buffers sizes */
> > +#define PREALLOC_BUFFER		(SZ_32K)
> > +#define PREALLOC_BUFFER_MAX	(SZ_32K)
> > +
> > +#define SSI_RATES		SNDRV_PCM_RATE_8000_48000 /*
> > 8k-44.1kHz */
> > +#define SSI_FMTS		SNDRV_PCM_FMTBIT_S16_LE
> > +#define SSI_CHAN_MIN		2
> > +#define SSI_CHAN_MAX		2
> > +#define SSI_FIFO_DEPTH		32
> > +
> > +struct rz_ssi_priv;
> > +
> > +struct rz_ssi_stream {
> > +	struct rz_ssi_priv *priv;
> > +	struct snd_pcm_substream *substream;
> > +	int fifo_sample_size;	/* sample capacity of SSI FIFO */
> > +	int period_counter;	/* for keeping track of periods transferred
> */
> > +	int sample_width;
> > +	int buffer_pos;		/* current frame position in the buffer */
> > +	int running;		/* 0=stopped, 1=running */
> > +
> > +	int uerr_num;
> > +	int oerr_num;
> > +
> > +	int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream
> > +*strm); };
> > +
> > +struct rz_ssi_priv {
> > +	void __iomem *base;
> > +	struct platform_device *pdev;
> > +	struct reset_control *rstc;
> > +	struct device *dev;
> > +	struct clk *sfr_clk;
> > +	struct clk *clk;
> > +
> > +	int irq_int;
> > +	int irq_tx;
> > +	int irq_rx;
> > +
> > +	spinlock_t lock;
> > +
> > +	/*
> > +	 * The SSI supports full-duplex transmission and reception.
> > +	 * However, if an error occurs, channel reset (both transmission
> > +	 * and reception reset) is required.
> > +	 * So it is better to use as half-duplex (playing and recording
> > +	 * should be done on separate channels).
> > +	 */
> > +	struct rz_ssi_stream playback;
> > +	struct rz_ssi_stream capture;
> > +
> > +	/* clock */
> > +	unsigned long audio_mck;
> > +	unsigned long audio_clk_1;
> > +	unsigned long audio_clk_2;
> > +
> > +	bool lrckp_fsync_fall;	/* LR clock polarity (SSICR.LRCKP) */
> > +	bool bckp_rise;	/* Bit clock polarity (SSICR.BCKP) */
> > +};
> > +
> > +static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32
> > +data) {
> > +	writel(data, (priv->base + reg));
> > +}
> > +
> > +static u32 rz_ssi_reg_readl(struct rz_ssi_priv *priv, uint reg) {
> > +	return readl(priv->base + reg);
> > +}
> > +
> > +static void rz_ssi_reg_mask_setl(struct rz_ssi_priv __iomem *priv, uint
> reg,
> > +				 u32 bclr, u32 bset)
> > +{
> > +	u32 val;
> > +
> > +	val = readl(priv->base + reg);
> > +	val = (val & ~bclr) | bset;
> > +	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 =
> > asoc_substream_to_rtd(substream);
> > +
> > +	return asoc_rtd_to_cpu(rtd, 0);
> > +}
> > +
> > +static inline bool rz_ssi_stream_is_play(struct rz_ssi_priv *ssi,
> > +					 struct snd_pcm_substream
> > *substream) {
> > +	return substream->stream == SNDRV_PCM_STREAM_PLAYBACK; }
> > +
> > +static inline struct rz_ssi_stream *
> > +rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream
> > +*substream) {
> > +	struct rz_ssi_stream *stream = &ssi->playback;
> > +
> > +	if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
> > +		stream = &ssi->capture;
> > +
> > +	return stream;
> > +}
> > +
> > +static int rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi,
> > +				  struct rz_ssi_stream *strm)
> > +{
> > +	unsigned long flags;
> > +	int ret;
> > +
> > +	spin_lock_irqsave(&ssi->lock, flags);
> > +	ret = !!(strm->substream && strm->substream->runtime);
> > +	spin_unlock_irqrestore(&ssi->lock, flags);
> > +
> > +	return ret;
> > +}
> > +
> > +static int rz_ssi_stream_init(struct rz_ssi_priv *ssi,
> > +			      struct rz_ssi_stream *strm,
> > +			      struct snd_pcm_substream *substream) {
> > +	struct snd_pcm_runtime *runtime = substream->runtime;
> > +
> > +	strm->substream = substream;
> > +	strm->sample_width = samples_to_bytes(runtime, 1);
> > +	strm->period_counter = 0;
> > +	strm->buffer_pos = 0;
> > +
> > +	strm->oerr_num = 0;
> > +	strm->uerr_num = 0;
> > +	strm->running = 0;
> > +
> > +	/* fifo init */
> > +	strm->fifo_sample_size = SSI_FIFO_DEPTH;
> > +
> > +	return 0;
> > +}
> > +
> > +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);
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&ssi->lock, flags);
> > +	strm->substream = NULL;
> > +	spin_unlock_irqrestore(&ssi->lock, flags);
> > +
> > +	if (strm->oerr_num > 0)
> > +		dev_info(dai->dev, "overrun = %d\n", strm->oerr_num);
> > +
> > +	if (strm->uerr_num > 0)
> > +		dev_info(dai->dev, "underrun = %d\n", strm->uerr_num); }
> > +
> > +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 };
> > +	unsigned int channel_bits = 32;	/* System Word Length */
> > +	unsigned long bclk_rate = rate * channels * channel_bits;
> > +	unsigned int div;
> > +	unsigned int i;
> > +	u32 ssicr = 0;
> > +	u32 clk_ckdv;
> > +
> > +	/* Clear AUCKE so we can set MST */
> > +	rz_ssi_reg_writel(ssi, SSIFCR, 0);
> > +
> > +	/* Continue to output LRCK pin even when idle */
> > +	rz_ssi_reg_writel(ssi, SSIOFR, SSIOFR_LRCONT);
> > +	if (ssi->audio_clk_1 && ssi->audio_clk_2) {
> > +		if (ssi->audio_clk_1 % bclk_rate)
> > +			ssi->audio_mck = ssi->audio_clk_2;
> > +		else
> > +			ssi->audio_mck = ssi->audio_clk_1;
> > +	}
> > +
> > +	/* Clock setting */
> > +	ssicr |= SSICR_MST;
> > +	if (ssi->audio_mck == ssi->audio_clk_1)
> > +		ssicr |= SSICR_CKS;
> > +	if (ssi->bckp_rise)
> > +		ssicr |= SSICR_BCKP;
> > +	if (ssi->lrckp_fsync_fall)
> > +		ssicr |= SSICR_LRCKP;
> > +
> > +	/* Determine the clock divider */
> > +	clk_ckdv = 0;
> > +	div = ssi->audio_mck / bclk_rate;
> > +	/* try to find an match */
> > +	for (i = 0; i < ARRAY_SIZE(ckdv); i++) {
> > +		if (ckdv[i] == div) {
> > +			clk_ckdv = i;
> > +			break;
> > +		}
> > +	}
> > +
> > +	if (i == ARRAY_SIZE(ckdv)) {
> > +		dev_err(ssi->dev, "Rate not divisible by audio clock
> > source\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	/*
> > +	 * DWL: Data Word Length = 16 bits
> > +	 * SWL: System Word Length = 32 bits
> > +	 */
> > +	ssicr |= SSICR_CKDV(clk_ckdv);
> > +	ssicr |= SSICR_DWL(1) | SSICR_SWL(3);
> > +	rz_ssi_reg_writel(ssi, SSICR, ssicr);
> > +	rz_ssi_reg_writel(ssi, SSIFCR,
> > +			  (SSIFCR_AUCKE | SSIFCR_TFRST |
> > SSIFCR_RFRST));
> > +
> > +	return 0;
> > +}
> > +
> > +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);
> > +	u32 ssicr, ssifcr;
> > +
> > +	ssicr = rz_ssi_reg_readl(ssi, SSICR);
> > +	ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF;
> > +
> > +	/* FIFO interrupt thresholds */
> > +	rz_ssi_reg_writel(ssi, SSISCR,
> > +			  SSISCR_TDES(strm->fifo_sample_size / 2 - 1) |
> > +			  SSISCR_RDFS(0));
> > +
> > +	/* enable IRQ */
> > +	if (is_play) {
> > +		ssicr |= SSICR_TUIEN | SSICR_TOIEN;
> > +		ssifcr |= SSIFCR_TIE | SSIFCR_RFRST;
> > +	} else {
> > +		ssicr |= SSICR_RUIEN | SSICR_ROIEN;
> > +		ssifcr |= SSIFCR_RIE | SSIFCR_TFRST;
> > +	}
> > +
> > +	rz_ssi_reg_writel(ssi, SSICR, ssicr);
> > +	rz_ssi_reg_writel(ssi, SSIFCR, ssifcr);
> > +
> > +	/* Clear all error flags */
> > +	rz_ssi_reg_mask_setl(ssi, SSISR,
> > +			     (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
> > +			      SSISR_RUIRQ), 0);
> > +
> > +	strm->running = 1;
> > +	ssicr |= is_play ? SSICR_TEN : SSICR_REN;
> > +	rz_ssi_reg_writel(ssi, SSICR, ssicr);
> > +
> > +	return 0;
> > +}
> > +
> > +static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream
> > +*strm) {
> > +	int timeout;
> > +
> > +	strm->running = 0;
> > +
> > +	/* Disable TX/RX */
> > +	rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
> > +
> > +	/* Disable irqs */
> > +	rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN |
> > +			     SSICR_RUIEN | SSICR_ROIEN, 0);
> > +	rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0);
> > +
> > +	/* Clear all error flags */
> > +	rz_ssi_reg_mask_setl(ssi, SSISR,
> > +			     (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ |
> > +			      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");
> > +
> > +	/* Hold FIFOs in reset */
> > +	rz_ssi_reg_mask_setl(ssi, SSIFCR, 0,
> > +			     SSIFCR_TFRST | SSIFCR_RFRST);
> > +
> > +	return 0;
> > +}
> > +
> > +static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int
> > +frames) {
> > +	struct snd_pcm_substream *substream = strm->substream;
> > +	struct snd_pcm_runtime *runtime;
> > +	int current_period;
> > +
> > +	if (!strm->running || !substream || !substream->runtime)
> > +		return;
> > +
> > +	runtime = substream->runtime;
> > +	strm->buffer_pos += frames;
> > +	WARN_ON(strm->buffer_pos > runtime->buffer_size);
> > +
> > +	/* ring buffer */
> > +	if (strm->buffer_pos == runtime->buffer_size)
> > +		strm->buffer_pos = 0;
> > +
> > +	current_period = strm->buffer_pos / runtime->period_size;
> > +	if (strm->period_counter != current_period) {
> > +		snd_pcm_period_elapsed(strm->substream);
> > +		strm->period_counter = current_period;
> > +	}
> > +}
> > +
> > +static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct
> > +rz_ssi_stream *strm) {
> > +	struct snd_pcm_substream *substream = strm->substream;
> > +	struct snd_pcm_runtime *runtime;
> > +	u16 *buf;
> > +	int fifo_samples;
> > +	int frames_left;
> > +	int samples = 0;
> > +	int i;
> 
> 
> Please use reverse christmas tree order.
> 
Sure will keep that in mind.

> > +
> > +	if (!rz_ssi_stream_is_valid(ssi, strm))
> > +		return -EINVAL;
> > +
> > +	runtime = substream->runtime;
> > +	/* frames left in this period */
> > +	frames_left = runtime->period_size - (strm->buffer_pos %
> > +					      runtime->period_size);
> > +	if (frames_left == 0)
> > +		frames_left = runtime->period_size;
> > +
> > +	/* Samples in RX FIFO */
> > +	fifo_samples = (rz_ssi_reg_readl(ssi, SSIFSR) >>
> > +			SSIFSR_RDC_SHIFT) & SSIFSR_RDC_MASK;
> > +
> > +	/* Only read full frames at a time */
> > +	while (frames_left && (fifo_samples >= runtime->channels)) {
> > +		samples += runtime->channels;
> > +		fifo_samples -= runtime->channels;
> > +		frames_left--;
> > +	}
> > +
> > +	/* not enough samples yet */
> > +	if (samples == 0)
> > +		return 0;
> > +
> > +	/* calculate new buffer index */
> > +	buf = (u16 *)(runtime->dma_area);
> > +	buf += strm->buffer_pos * runtime->channels;
> > +
> > +	/* Note, only supports 16-bit samples */
> > +	for (i = 0; i < samples; i++)
> > +		*buf++ = (u16)(rz_ssi_reg_readl(ssi, SSIFRDR) >> 16);
> > +
> > +	rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
> > +	rz_ssi_pointer_update(strm, samples / runtime->channels);
> > +
> > +	/*
> > +	 * If we finished this period, but there are more samples in
> > +	 * the RX FIFO, call this function again
> > +	 */
> > +	if (frames_left == 0 && fifo_samples >= runtime->channels)
> > +		rz_ssi_pio_recv(ssi, strm);
> > +
> > +	return 0;
> > +}
> > +
> > +static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct
> > +rz_ssi_stream *strm) {
> > +	struct snd_pcm_substream *substream = strm->substream;
> > +	struct snd_pcm_runtime *runtime = substream->runtime;
> > +	int sample_space;
> > +	int samples = 0;
> > +	int frames_left;
> > +	int i;
> > +	u32 ssifsr;
> > +	u16 *buf;
> 
> Please use reverse christmas tree order.
> 
Ditto.

Cheers,
Prabhakar

> > +
> > +	if (!rz_ssi_stream_is_valid(ssi, strm))
> > +		return -EINVAL;
> > +
> > +	/* frames left in this period */
> > +	frames_left = runtime->period_size - (strm->buffer_pos %
> > +					      runtime->period_size);
> > +	if (frames_left == 0)
> > +		frames_left = runtime->period_size;
> > +
> > +	sample_space = strm->fifo_sample_size;
> > +	ssifsr = rz_ssi_reg_readl(ssi, SSIFSR);
> > +	sample_space -= (ssifsr >> SSIFSR_TDC_SHIFT) &
> > SSIFSR_TDC_MASK;
> > +
> > +	/* Only add full frames at a time */
> > +	while (frames_left && (sample_space >= runtime->channels)) {
> > +		samples += runtime->channels;
> > +		sample_space -= runtime->channels;
> > +		frames_left--;
> > +	}
> > +
> > +	/* no space to send anything right now */
> > +	if (samples == 0)
> > +		return 0;
> > +
> > +	/* calculate new buffer index */
> > +	buf = (u16 *)(runtime->dma_area);
> > +	buf += strm->buffer_pos * runtime->channels;
> > +
> > +	/* Note, only supports 16-bit samples */
> > +	for (i = 0; i < samples; i++)
> > +		rz_ssi_reg_writel(ssi, SSIFTDR, ((u32)(*buf++) << 16));
> > +
> > +	rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_TDE, 0);
> > +	rz_ssi_pointer_update(strm, samples / runtime->channels);
> > +
> > +	return 0;
> > +}
> > +
> > +static irqreturn_t rz_ssi_interrupt(int irq, void *data) {
> > +	struct rz_ssi_stream *strm = NULL;
> > +	struct rz_ssi_priv *ssi = data;
> > +	u32 ssisr = rz_ssi_reg_readl(ssi, SSISR);
> > +
> > +	if (ssi->playback.substream)
> > +		strm = &ssi->playback;
> > +	else if (ssi->capture.substream)
> > +		strm = &ssi->capture;
> > +	else
> > +		return IRQ_HANDLED; /* Left over TX/RX interrupt */
> > +
> > +	if (irq == ssi->irq_int) { /* error or idle */
> > +		if (ssisr & SSISR_TUIRQ)
> > +			strm->uerr_num++;
> > +		if (ssisr & SSISR_TOIRQ)
> > +			strm->oerr_num++;
> > +		if (ssisr & SSISR_RUIRQ)
> > +			strm->uerr_num++;
> > +		if (ssisr & SSISR_ROIRQ)
> > +			strm->oerr_num++;
> > +
> > +		if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ |
> > +			     SSISR_ROIRQ)) {
> > +			/* Error handling */
> > +			/* You must reset (stop/restart) after each interrupt */
> > +			rz_ssi_stop(ssi, strm);
> > +
> > +			/* Clear all flags */
> > +			rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ |
> > +					     SSISR_TUIRQ | SSISR_ROIRQ |
> > +					     SSISR_RUIRQ, 0);
> > +
> > +			/* Add/remove more data */
> > +			strm->transfer(ssi, strm);
> > +
> > +			/* Resume */
> > +			rz_ssi_start(ssi, strm);
> > +		}
> > +	}
> > +
> > +	if (!strm->running)
> > +		return IRQ_HANDLED;
> > +
> > +	/* tx data empty */
> > +	if (irq == ssi->irq_tx)
> > +		strm->transfer(ssi, &ssi->playback);
> > +
> > +	/* rx data full */
> > +	if (irq == ssi->irq_rx) {
> > +		strm->transfer(ssi, &ssi->capture);
> > +		rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0);
> > +	}
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream,
> > +int
> > cmd,
> > +			      struct snd_soc_dai *dai)
> > +{
> > +	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
> > +	struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
> > +	int ret = 0;
> > +
> > +	switch (cmd) {
> > +	case SNDRV_PCM_TRIGGER_START:
> > +		/* Soft Reset */
> > +		rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST);
> > +		rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0);
> > +		udelay(5);
> > +
> > +		ret = rz_ssi_stream_init(ssi, strm, substream);
> > +		if (ret)
> > +			goto done;
> > +
> > +		ret = strm->transfer(ssi, strm);
> > +		if (ret)
> > +			goto done;
> > +
> > +		ret = rz_ssi_start(ssi, strm);
> > +		break;
> > +	case SNDRV_PCM_TRIGGER_STOP:
> > +		rz_ssi_stop(ssi, strm);
> > +		rz_ssi_stream_quit(ssi, strm);
> > +		break;
> > +	}
> > +
> > +done:
> > +	return ret;
> > +}
> > +
> > +static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int
> > +fmt) {
> > +	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
> > +
> > +	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
> > +	case SND_SOC_DAIFMT_CBS_CFS:
> > +		break;
> > +	default:
> > +		dev_err(ssi->dev, "Codec should be clk and frame
> > consumer\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	/*
> > +	 * set clock polarity
> > +	 *
> > +	 * "normal" BCLK = Signal is available at rising edge of BCLK
> > +	 * "normal" FSYNC = (I2S) Left ch starts with falling FSYNC edge
> > +	 */
> > +	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
> > +	case SND_SOC_DAIFMT_NB_NF:
> > +		ssi->bckp_rise = false;
> > +		ssi->lrckp_fsync_fall = false;
> > +		break;
> > +	case SND_SOC_DAIFMT_NB_IF:
> > +		ssi->bckp_rise = false;
> > +		ssi->lrckp_fsync_fall = true;
> > +		break;
> > +	case SND_SOC_DAIFMT_IB_NF:
> > +		ssi->bckp_rise = true;
> > +		ssi->lrckp_fsync_fall = false;
> > +		break;
> > +	case SND_SOC_DAIFMT_IB_IF:
> > +		ssi->bckp_rise = true;
> > +		ssi->lrckp_fsync_fall = true;
> > +		break;
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* only i2s support */
> > +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> > +	case SND_SOC_DAIFMT_I2S:
> > +		break;
> > +	default:
> > +		dev_err(ssi->dev, "Only I2S mode is supported.\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
> > +				struct snd_pcm_hw_params *params,
> > +				struct snd_soc_dai *dai)
> > +{
> > +	struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
> > +	unsigned int sample_bits = hw_param_interval(params,
> > +
> > 	SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
> > +	unsigned int channels = params_channels(params);
> > +
> > +	if (sample_bits != 16) {
> > +		dev_err(ssi->dev, "Unsupported sample width: %d\n",
> > +			sample_bits);
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (channels != 2) {
> > +		dev_err(ssi->dev, "Number of channels not matched: %d\n",
> > +			channels);
> > +		return -EINVAL;
> > +	}
> > +
> > +	return rz_ssi_clk_setup(ssi, params_rate(params),
> > +				params_channels(params));
> > +}
> > +
> > +static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
> > +	.trigger	= rz_ssi_dai_trigger,
> > +	.set_fmt	= rz_ssi_dai_set_fmt,
> > +	.hw_params	= rz_ssi_dai_hw_params,
> > +};
> > +
> > +static const struct snd_pcm_hardware rz_ssi_pcm_hardware = {
> > +	.info			= SNDRV_PCM_INFO_INTERLEAVED	|
> > +				  SNDRV_PCM_INFO_MMAP		|
> > +				  SNDRV_PCM_INFO_MMAP_VALID,
> > +	.buffer_bytes_max	= PREALLOC_BUFFER,
> > +	.period_bytes_min	= 32,
> > +	.period_bytes_max	= 8192,
> > +	.channels_min		= SSI_CHAN_MIN,
> > +	.channels_max		= SSI_CHAN_MAX,
> > +	.periods_min		= 1,
> > +	.periods_max		= 32,
> > +	.fifo_size		= 32 * 2,
> > +};
> > +
> > +static int rz_ssi_pcm_open(struct snd_soc_component *component,
> > +			   struct snd_pcm_substream *substream) {
> > +	snd_soc_set_runtime_hwparams(substream,
> > &rz_ssi_pcm_hardware);
> > +
> > +	return snd_pcm_hw_constraint_integer(substream->runtime,
> > +
> > SNDRV_PCM_HW_PARAM_PERIODS);
> > +}
> > +
> > +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 rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
> > +	struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
> > +
> > +	return strm->buffer_pos;
> > +}
> > +
> > +static int rz_ssi_pcm_new(struct snd_soc_component *component,
> > +			  struct snd_soc_pcm_runtime *rtd) {
> > +	snd_pcm_set_managed_buffer_all(rtd->pcm,
> > SNDRV_DMA_TYPE_DEV,
> > +				       rtd->card->snd_card->dev,
> > +				       PREALLOC_BUFFER,
> > PREALLOC_BUFFER_MAX);
> > +	return 0;
> > +}
> > +
> > +static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
> > +	{
> > +		.name			= "rz-ssi-dai",
> > +		.playback = {
> > +			.rates		= SSI_RATES,
> > +			.formats	= SSI_FMTS,
> > +			.channels_min	= SSI_CHAN_MIN,
> > +			.channels_max	= SSI_CHAN_MAX,
> > +		},
> > +		.capture = {
> > +			.rates		= SSI_RATES,
> > +			.formats	= SSI_FMTS,
> > +			.channels_min	= SSI_CHAN_MIN,
> > +			.channels_max	= SSI_CHAN_MAX,
> > +		},
> > +		.ops = &rz_ssi_dai_ops,
> > +	},
> > +};
> > +
> > +static const struct snd_soc_component_driver rz_ssi_soc_component = {
> > +	.name		= "rz-ssi",
> > +	.open		= rz_ssi_pcm_open,
> > +	.pointer	= rz_ssi_pcm_pointer,
> > +	.pcm_construct	= rz_ssi_pcm_new,
> > +};
> > +
> > +static int rz_ssi_probe(struct platform_device *pdev) {
> > +	struct rz_ssi_priv *ssi;
> > +	struct clk *audio_clk;
> > +	int ret;
> > +
> > +	ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL);
> > +	if (!ssi)
> > +		return -ENOMEM;
> > +
> > +	ssi->pdev = pdev;
> > +	ssi->dev = &pdev->dev;
> > +	ssi->base = devm_platform_ioremap_resource(pdev, 0);
> > +	if (IS_ERR(ssi->base))
> > +		return PTR_ERR(ssi->base);
> > +
> > +	ssi->clk = devm_clk_get(&pdev->dev, "ssi");
> > +	if (IS_ERR(ssi->clk))
> > +		return PTR_ERR(ssi->clk);
> > +
> > +	ssi->sfr_clk = devm_clk_get(&pdev->dev, "ssi_sfr");
> > +	if (IS_ERR(ssi->sfr_clk))
> > +		return PTR_ERR(ssi->sfr_clk);
> > +
> > +	audio_clk = devm_clk_get(&pdev->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");
> > +	if (IS_ERR(audio_clk))
> > +		return dev_err_probe(&pdev->dev, PTR_ERR(audio_clk),
> > +				     "no audio clk2");
> > +
> > +	ssi->audio_clk_2 = clk_get_rate(audio_clk);
> > +	if (!(ssi->audio_clk_1 || ssi->audio_clk_2))
> > +		return dev_err_probe(&pdev->dev, -EINVAL,
> > +				     "no audio clk1 or audio clk2");
> > +
> > +	ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 :
> > +ssi->audio_clk_2;
> > +
> > +	ssi->playback.transfer = rz_ssi_pio_send;
> > +	ssi->capture.transfer = rz_ssi_pio_recv;
> > +	ssi->playback.priv = ssi;
> > +	ssi->capture.priv = ssi;
> > +
> > +	/* Error Interrupt */
> > +	ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
> > +	if (ssi->irq_int < 0)
> > +		return dev_err_probe(&pdev->dev, -ENODEV,
> > +				     "Unable to get SSI int_req IRQ\n");
> > +
> > +	ret = devm_request_irq(&pdev->dev, ssi->irq_int, &rz_ssi_interrupt,
> > +			       0, dev_name(&pdev->dev), ssi);
> > +	if (ret < 0)
> > +		return dev_err_probe(&pdev->dev, ret,
> > +				     "irq request error (int_req)\n");
> > +
> > +	/* Tx and Rx interrupts (pio only) */
> > +	ssi->irq_tx = platform_get_irq_byname(pdev, "dma_tx");
> > +	if (ssi->irq_tx < 0)
> > +		return dev_err_probe(&pdev->dev, -ENODEV,
> > +				     "Unable to get SSI dma_tx IRQ\n");
> > +
> > +	ret = devm_request_irq(&pdev->dev, ssi->irq_tx, &rz_ssi_interrupt,
> > 0,
> > +			       dev_name(&pdev->dev), ssi);
> > +	if (ret < 0)
> > +		return dev_err_probe(&pdev->dev, ret,
> > +				     "irq request error (dma_tx)\n");
> > +
> > +	ssi->irq_rx = platform_get_irq_byname(pdev, "dma_rx");
> > +	if (ssi->irq_rx < 0)
> > +		return dev_err_probe(&pdev->dev, -ENODEV,
> > +				     "Unable to get SSI dma_rx IRQ\n");
> > +
> > +	ret = devm_request_irq(&pdev->dev, ssi->irq_rx, &rz_ssi_interrupt,
> > 0,
> > +			       dev_name(&pdev->dev), ssi);
> > +	if (ret < 0)
> > +		return dev_err_probe(&pdev->dev, ret,
> > +				     "irq request error (dma_rx)\n");
> > +
> > +	ssi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
> > +	if (IS_ERR(ssi->rstc))
> > +		return PTR_ERR(ssi->rstc);
> > +
> > +	reset_control_deassert(ssi->rstc);
> > +	pm_runtime_enable(&pdev->dev);
> > +	pm_runtime_resume_and_get(&pdev->dev);
> > +
> > +	spin_lock_init(&ssi->lock);
> > +	dev_set_drvdata(&pdev->dev, ssi);
> > +	ret = devm_snd_soc_register_component(&pdev->dev,
> > &rz_ssi_soc_component,
> > +					      rz_ssi_soc_dai,
> > +
> > ARRAY_SIZE(rz_ssi_soc_dai));
> > +	if (ret < 0) {
> > +		pm_runtime_put(ssi->dev);
> > +		pm_runtime_disable(ssi->dev);
> > +		reset_control_assert(ssi->rstc);
> > +		dev_err(&pdev->dev, "failed to register snd component\n");
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int rz_ssi_remove(struct platform_device *pdev) {
> > +	struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
> > +
> > +	pm_runtime_put(ssi->dev);
> > +	pm_runtime_disable(ssi->dev);
> > +	reset_control_assert(ssi->rstc);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct of_device_id rz_ssi_of_match[] = {
> > +	{ .compatible = "renesas,rz-ssi", },
> > +	{/* Sentinel */},
> > +};
> > +MODULE_DEVICE_TABLE(of, rz_ssi_of_match);
> > +
> > +static struct platform_driver rz_ssi_driver = {
> > +	.driver	= {
> > +		.name	= "rz-ssi-pcm-audio",
> > +		.of_match_table = rz_ssi_of_match,
> > +	},
> > +	.probe		= rz_ssi_probe,
> > +	.remove		= rz_ssi_remove,
> > +};
> > +
> > +module_platform_driver(rz_ssi_driver);
> > +
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_DESCRIPTION("Renesas RZ/G2L ASoC Serial Sound Interface
> > +Driver"); MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
> > --
> > 2.17.1
> 
> Best regards,
>   Nobuhiro



^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [PATCH 5.10.y-cip 03/24] ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel configuration parameter
  2022-04-21  8:32   ` Pavel Machek
@ 2022-04-21 10:55     ` Prabhakar Mahadev Lad
  0 siblings, 0 replies; 39+ messages in thread
From: Prabhakar Mahadev Lad @ 2022-04-21 10:55 UTC (permalink / raw)
  To: Pavel Machek; +Cc: cip-dev, Nobuhiro Iwamatsu, Biju Das

Hi Pavel,

Thank you for the review.

> -----Original Message-----
> From: Pavel Machek <pavel@denx.de>
> Sent: 21 April 2022 09:33
> To: Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Cc: cip-dev@lists.cip-project.org; Nobuhiro Iwamatsu
> <nobuhiro1.iwamatsu@toshiba.co.jp>; Pavel Machek <pavel@denx.de>; Biju Das
> <biju.das.jz@bp.renesas.com>
> Subject: Re: [PATCH 5.10.y-cip 03/24] ASoC: dt-bindings: renesas,rz-ssi:
> Update slave dma channel configuration parameter
> 
> Hi!
> 
> >  .../bindings/sound/renesas,rz-ssi.yaml        | 22 +++++++++++++++++--
> >  1 file changed, 20 insertions(+), 2 deletions(-)
> >
> > diff --git
> > a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
> > b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
> > index 471937cb8d05..414ff8035a4e 100644
> > --- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
> > +++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
> > @@ -48,6 +48,24 @@ properties:
> >    dmas:
> >      minItems: 1
> >      maxItems: 2
> > +    description:
> > +      The first cell represents a phandle to dmac
> 
> I would not mind . at the end of the sentence, to be consistent with the
> next paragraph, but that's really a nitpicking.
> 
Do agree, if there are any updates to this file upstream I will update it.

Cheers,
Prabhakar

> > +      The second cell specifies the encoded MID/RID values of the SSI
> port
> > +      connected to the DMA client and the slave channel configuration
> > +      parameters.
> 
> Best regards,
> 								Pavel
> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany


^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [PATCH 5.10.y-cip 05/24] ASoC: sh: rz-ssi: Add SSI DMAC support
  2022-04-21  8:33   ` Pavel Machek
@ 2022-04-21 11:02     ` Prabhakar Mahadev Lad
  0 siblings, 0 replies; 39+ messages in thread
From: Prabhakar Mahadev Lad @ 2022-04-21 11:02 UTC (permalink / raw)
  To: Pavel Machek; +Cc: cip-dev, Nobuhiro Iwamatsu, Biju Das

Hi Pavel,

Thank you for the review.

> -----Original Message-----
> From: Pavel Machek <pavel@denx.de>
> Sent: 21 April 2022 09:33
> To: Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Cc: cip-dev@lists.cip-project.org; Nobuhiro Iwamatsu
> <nobuhiro1.iwamatsu@toshiba.co.jp>; Pavel Machek <pavel@denx.de>; Biju Das
> <biju.das.jz@bp.renesas.com>
> Subject: Re: [PATCH 5.10.y-cip 05/24] ASoC: sh: rz-ssi: Add SSI DMAC
> support
> 
> Hi!
> 
> > @@ -775,8 +949,18 @@ static int rz_ssi_probe(struct platform_device
> *pdev)
> >
> >  	ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi-
> >audio_clk_2;
> >
> > -	ssi->playback.transfer = rz_ssi_pio_send;
> > -	ssi->capture.transfer = rz_ssi_pio_recv;
> > +	/* Detect DMA support */
> > +	ret = rz_ssi_dma_request(ssi, &pdev->dev);
> > +	if (ret < 0) {
> > +		dev_warn(&pdev->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");
> > +		ssi->playback.transfer = rz_ssi_dma_transfer;
> > +		ssi->capture.transfer = rz_ssi_dma_transfer;
> > +	}
> > +
> >  	ssi->playback.priv = ssi;
> >  	ssi->capture.priv = ssi;
> >
> 
> AFAICT rz_ssi_dma_request() allocates resources and
> rz_ssi_release_dma_channels() is needed to free them if we fail.
> 
> But in most failure paths below, that's not done, with one exception:
> 
Ouch you are right, rz_ssi_release_dma_channels() needs to be called in the error path.

Cheers,
Prabhakar

> > @@ -829,6 +1017,8 @@ static int rz_ssi_probe(struct platform_device
> *pdev)
> >  					      rz_ssi_soc_dai,
> >  					      ARRAY_SIZE(rz_ssi_soc_dai));
> >  	if (ret < 0) {
> > +		rz_ssi_release_dma_channels(ssi);
> > +
> >  		pm_runtime_put(ssi->dev);
> >  		pm_runtime_disable(ssi->dev);
> >  		reset_control_assert(ssi->rstc);
> 
> Best regards,
> 								Pavel
> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver
  2022-04-21 10:50     ` Prabhakar Mahadev Lad
@ 2022-04-21 11:02       ` Pavel Machek
  2022-04-21 11:18         ` Prabhakar Mahadev Lad
  0 siblings, 1 reply; 39+ messages in thread
From: Pavel Machek @ 2022-04-21 11:02 UTC (permalink / raw)
  To: Prabhakar Mahadev Lad; +Cc: nobuhiro1.iwamatsu, cip-dev, pavel, Biju Das

[-- Attachment #1: Type: text/plain, Size: 707 bytes --]

Hi!

I guess there was two comments hidden in the quoted text. I'm not sure
if you noticed them?

Best regards,
								Pavel

> > > +#define SSIFSR_TDC_MASK		0x3f
> > > +#define SSIFSR_TDC_SHIFT	24
> > > +#define SSIFSR_RDC_MASK		0x3f
> > > +#define SSIFSR_RDC_SHIFT	8
> > > +
> > > +#define SSIFSR_TDC(x)		(((x) & 0x1f) << 24)
> > 
> > This is not used.
> > If you use it, you can use SSIFSR_TDC_SHIFT and SSIFSR_TDC_MASK.
> > 
> > > +#define SSIFSR_TDE		BIT(16)
> > > +#define SSIFSR_RDC(x)		(((x) & 0x1f) << 8)
> > 
> > Same above.

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 5.10.y-cip 21/24] arm64: dts: renesas: rzg2l-smarc: Enable audio
  2022-04-20 21:34 ` [PATCH 5.10.y-cip 21/24] arm64: dts: renesas: rzg2l-smarc: Enable audio Lad Prabhakar
@ 2022-04-21 11:15   ` Pavel Machek
  2022-04-21 11:18     ` Biju Das
  0 siblings, 1 reply; 39+ messages in thread
From: Pavel Machek @ 2022-04-21 11:15 UTC (permalink / raw)
  To: Lad Prabhakar; +Cc: cip-dev, Nobuhiro Iwamatsu, Pavel Machek, Biju Das

[-- Attachment #1: Type: text/plain, Size: 679 bytes --]

Hi!

I just want to make sure: There are two frequencies, close to each
other but not same. Is that okay?

Best regards,
								Pavel


> diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
> index 549cee1733c7..4bffd6b4c837 100644
> --- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
> +++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi

> +&audio_clk1{
> +	clock-frequency = <11289600>;
> +};
> +
> +&audio_clk2{
> +	clock-frequency = <12288000>;
> +};

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC
  2022-04-21  3:25 ` [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC nobuhiro1.iwamatsu
@ 2022-04-21 11:17   ` Pavel Machek
  2022-04-25  5:52   ` Prabhakar Mahadev Lad
  1 sibling, 0 replies; 39+ messages in thread
From: Pavel Machek @ 2022-04-21 11:17 UTC (permalink / raw)
  To: nobuhiro1.iwamatsu; +Cc: prabhakar.mahadev-lad.rj, cip-dev, pavel, biju.das.jz

[-- Attachment #1: Type: text/plain, Size: 1056 bytes --]

Hi!

> > This patch series adds sound support to Renesas RZ/G2L SoC and enables SSI
> > and codec on Renesas RZ/G2L SMARC EVK.
> > 
> > All the patches have been cherry picked from v5.18-rc3.
> > 
> > Sound support patches were already sent earlier as part of bulk series [0], but
> > due to some review comments the patches were rejected, now that the driver is
> > fixed upstream, re-sending the series with all the fixes.
> > 
> > [0] https://patchwork.kernel.org/project/cip-dev/cover/
> > 20211229101530.22783-1-prabhakar.mahadev-lad.rj@bp.renesas.com/
> 
> Looks good to me. 
> I am testing on https://gitlab.com/cip-project/cip-kernel/linux-cip/-/pipelines/521117833.
> I can merge it if there are no other comments and test is successful.
> 

Aside from minor comments I sent, series looks good to me. I'm okay
with series being merged.

Thanks and best regards,
								Pavel
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver
  2022-04-21 11:02       ` Pavel Machek
@ 2022-04-21 11:18         ` Prabhakar Mahadev Lad
  0 siblings, 0 replies; 39+ messages in thread
From: Prabhakar Mahadev Lad @ 2022-04-21 11:18 UTC (permalink / raw)
  To: Pavel Machek; +Cc: nobuhiro1.iwamatsu, cip-dev, Biju Das

Hi Pavel,

> -----Original Message-----
> From: Pavel Machek <pavel@denx.de>
> Sent: 21 April 2022 12:03
> To: Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Cc: nobuhiro1.iwamatsu@toshiba.co.jp; cip-dev@lists.cip-project.org;
> pavel@denx.de; Biju Das <biju.das.jz@bp.renesas.com>
> Subject: Re: [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver
> 
> Hi!
> 
> I guess there was two comments hidden in the quoted text. I'm not sure if
> you noticed them?
> 
Thanks, I had missed them.

> Best regards,
> 								Pavel
> 
> > > > +#define SSIFSR_TDC_MASK		0x3f
> > > > +#define SSIFSR_TDC_SHIFT	24
> > > > +#define SSIFSR_RDC_MASK		0x3f
> > > > +#define SSIFSR_RDC_SHIFT	8
> > > > +
> > > > +#define SSIFSR_TDC(x)		(((x) & 0x1f) << 24)
> > >
> > > This is not used.
> > > If you use it, you can use SSIFSR_TDC_SHIFT and SSIFSR_TDC_MASK.
> > >
Agreed.

> > > > +#define SSIFSR_TDE		BIT(16)
> > > > +#define SSIFSR_RDC(x)		(((x) & 0x1f) << 8)
> > >
> > > Same above.
> 
Ditto.

Cheers,
Prabhakar


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 5.10.y-cip 21/24] arm64: dts: renesas: rzg2l-smarc: Enable audio
  2022-04-21 11:15   ` Pavel Machek
@ 2022-04-21 11:18     ` Biju Das
  0 siblings, 0 replies; 39+ messages in thread
From: Biju Das @ 2022-04-21 11:18 UTC (permalink / raw)
  To: Pavel Machek, Prabhakar Mahadev Lad; +Cc: cip-dev, Nobuhiro Iwamatsu

It should be fine, as 1 is for multiple for 44.1 and another for 48.

Cheers,
Biju

> -----Original Message-----
> From: Pavel Machek <pavel@denx.de>
> Sent: 21 April 2022 12:16
> To: Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>
> Cc: cip-dev@lists.cip-project.org; Nobuhiro Iwamatsu
> <nobuhiro1.iwamatsu@toshiba.co.jp>; Pavel Machek <pavel@denx.de>; Biju Das
> <biju.das.jz@bp.renesas.com>
> Subject: Re: [PATCH 5.10.y-cip 21/24] arm64: dts: renesas: rzg2l-smarc:
> Enable audio
> 
> Hi!
> 
> I just want to make sure: There are two frequencies, close to each other
> but not same. Is that okay?
> 
> Best regards,
> 								Pavel
> 
> 
> > diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
> > b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
> > index 549cee1733c7..4bffd6b4c837 100644
> > --- a/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
> > +++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi
> 
> > +&audio_clk1{
> > +	clock-frequency = <11289600>;
> > +};
> > +
> > +&audio_clk2{
> > +	clock-frequency = <12288000>;
> > +};
> 
> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany


^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC
  2022-04-21  3:25 ` [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC nobuhiro1.iwamatsu
  2022-04-21 11:17   ` Pavel Machek
@ 2022-04-25  5:52   ` Prabhakar Mahadev Lad
  2022-04-25  7:25     ` nobuhiro1.iwamatsu
  1 sibling, 1 reply; 39+ messages in thread
From: Prabhakar Mahadev Lad @ 2022-04-25  5:52 UTC (permalink / raw)
  To: nobuhiro1.iwamatsu, cip-dev, pavel; +Cc: Biju Das

Hi Nobuhiro-san,

> -----Original Message-----
> From: nobuhiro1.iwamatsu@toshiba.co.jp <nobuhiro1.iwamatsu@toshiba.co.jp>
> Sent: 21 April 2022 04:26
> To: Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@bp.renesas.com>; cip-
> dev@lists.cip-project.org; pavel@denx.de
> Cc: Biju Das <biju.das.jz@bp.renesas.com>
> Subject: RE: [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L
> SoC
> 
> Hi all,
> 
> > -----Original Message-----
> > From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
> > Sent: Thursday, April 21, 2022 6:34 AM
> > To: cip-dev@lists.cip-project.org; iwamatsu nobuhiro(岩松 信洋 □SWC◯
> A
> > CT) <nobuhiro1.iwamatsu@toshiba.co.jp>; Pavel Machek <pavel@denx.de>
> > Cc: Biju Das <biju.das.jz@bp.renesas.com>
> > Subject: [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L
> > SoC
> >
> > Hi All,
> >
> > This patch series adds sound support to Renesas RZ/G2L SoC and enables
> > SSI and codec on Renesas RZ/G2L SMARC EVK.
> >
> > All the patches have been cherry picked from v5.18-rc3.
> >
> > Sound support patches were already sent earlier as part of bulk series
> > [0], but due to some review comments the patches were rejected, now
> > that the driver is fixed upstream, re-sending the series with all the
> fixes.
> >
> > [0]
> > https://jpn01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatc
> > hwork.kernel.org%2Fproject%2Fcip-dev%2Fcover%2F&amp;data=05%7C01%7Cpra
> > bhakar.mahadev-lad.rj%40bp.renesas.com%7Cb4ee1a6285394d44892508da2346a
> > 0d8%7C53d82571da1947e49cb4625a166a4a2a%7C0%7C0%7C637861083493803991%7C
> > Unknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1h
> > aWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=tb4S87F0MCvezWQFTwYhtfUNP
> > ErdCwkz9JsE%2FWJK9qQ%3D&amp;reserved=0
> > 20211229101530.22783-1-prabhakar.mahadev-lad.rj@bp.renesas.com/
> 
> Looks good to me.
> I am testing on
> https://jpn01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.c
> om%2Fcip-project%2Fcip-kernel%2Flinux-cip%2F-
> %2Fpipelines%2F521117833&amp;data=05%7C01%7Cprabhakar.mahadev-
> lad.rj%40bp.renesas.com%7Cb4ee1a6285394d44892508da2346a0d8%7C53d82571da194
> 7e49cb4625a166a4a2a%7C0%7C0%7C637861083493803991%7CUnknown%7CTWFpbGZsb3d8e
> yJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7
> C%7C%7C&amp;sdata=hAsfuV2fT66SH6cFpfI8cuUQMO8QVozG7EVlYAhMRu8%3D&amp;reser
> ved=0.
> I can merge it if there are no other comments and test is successful.
> 
Looks like there is one test failure, pretty sure its unrelated to the changes. Can you please retrigger the failed test so that this patch set gets merged in.

Cheers,
Prabhakar

> >
> > Cheers,
> > Prabhakar
> >
> 
> Best regards,
>   Nobuhiro
> 
> > Biju Das (16):
> >   ASoC: dt-bindings: Document RZ/G2L bindings
> >   ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support
> >   ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel
> >     configuration parameter
> >   ASoC: sh: Add RZ/G2L SSIF-2 driver
> >   ASoC: sh: rz-ssi: Add SSI DMAC support
> >   ASoC: sh: rz-ssi: Fix dereference of noderef expression warning
> >   ASoC: sh: rz-ssi: Fix wrong operator used issue
> >   ASoC: sh: rz-ssi: Improve error handling in rz_ssi_dma_request
> >     function
> >   arm64: dts: renesas: r9a07g044: Add external audio clock nodes
> >   arm64: dts: renesas: r9a07g044: Add SSI support
> >   arm64: dts: renesas: r9a07g044: Add DMA support to SSI
> >   arm64: dts: renesas: rzg2l-smarc: Add WM8978 sound codec
> >   arm64: dts: renesas: rzg2l-smarc: Enable audio
> >   arm64: dts: renesas: rzg2l-smarc: Add Mic routing
> >   arm64: defconfig: Enable SOUND_SOC_RZ
> >   arm64: defconfig: Enable SND_SOC_WM8978
> >
> > Heiner Kallweit (1):
> >   ASoC: sh: rz-ssi: Check return value of pm_runtime_resume_and_get()
> >
> > Lad Prabhakar (7):
> >   ASoC: sh: rz-ssi: Drop calling rz_ssi_pio_recv() recursively
> >   ASoC: sh: rz-ssi: Make the data structures available before
> >     registering the handlers
> >   ASoC: sh: rz-ssi: Drop ssi parameter from rz_ssi_stream_init()
> >   ASoC: sh: rz-ssi: Make return type of rz_ssi_stream_is_valid() to bool
> >   ASoC: sh: rz-ssi: Use a do-while loop in rz_ssi_pio_recv()
> >   ASoC: sh: rz-ssi: Add rz_ssi_set_substream() helper function
> >   ASoC: sh: rz-ssi: Remove duplicate macros
> >
> >  .../bindings/sound/renesas,rz-ssi.yaml        |  118 ++
> >  arch/arm64/boot/dts/renesas/r9a07g044.dtsi    |   98 ++
> >  arch/arm64/boot/dts/renesas/rzg2l-smarc.dtsi  |   79 ++
> >  arch/arm64/configs/defconfig                  |    2 +
> >  sound/soc/sh/Kconfig                          |    6 +
> >  sound/soc/sh/Makefile                         |    4 +
> >  sound/soc/sh/rz-ssi.c                         | 1078
> > +++++++++++++++++
> >  7 files changed, 1385 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
> >  create mode 100644 sound/soc/sh/rz-ssi.c
> >
> > --
> > 2.17.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC
  2022-04-25  5:52   ` Prabhakar Mahadev Lad
@ 2022-04-25  7:25     ` nobuhiro1.iwamatsu
  0 siblings, 0 replies; 39+ messages in thread
From: nobuhiro1.iwamatsu @ 2022-04-25  7:25 UTC (permalink / raw)
  To: prabhakar.mahadev-lad.rj, cip-dev, pavel; +Cc: biju.das.jz

Hi Prabhakar,

> > Looks good to me.
> > I am testing on
> > https://jpn01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitl
> > ab.c
> > om%2Fcip-project%2Fcip-kernel%2Flinux-cip%2F-
> > %2Fpipelines%2F521117833&amp;data=05%7C01%7Cprabhakar.mahadev-
> >
> lad.rj%40bp.renesas.com%7Cb4ee1a6285394d44892508da2346a0d8%7C53d8
> 2571d
> > a194
> >
> 7e49cb4625a166a4a2a%7C0%7C0%7C637861083493803991%7CUnknown%7C
> TWFpbGZsb
> > 3d8e
> >
> yJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3
> D%7C30
> > 00%7
> >
> C%7C%7C&amp;sdata=hAsfuV2fT66SH6cFpfI8cuUQMO8QVozG7EVlYAhMR
> u8%3D&amp;r
> > eser
> > ved=0.
> > I can merge it if there are no other comments and test is successful.
> >
> Looks like there is one test failure, pretty sure its unrelated to the changes. Can
> you please retrigger the failed test so that this patch set gets merged in.

Yeah, I already retrigger it. And I planning to release a kernel including these patches.
Sorry for the late schedule.

Best regards,
  Nobuhiro



^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2022-04-25 19:26 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-20 21:34 [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 01/24] ASoC: dt-bindings: Document RZ/G2L bindings Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 02/24] ASoC: dt-bindings: sound: renesas,rz-ssi: Document DMA support Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 03/24] ASoC: dt-bindings: renesas,rz-ssi: Update slave dma channel configuration parameter Lad Prabhakar
2022-04-21  8:32   ` Pavel Machek
2022-04-21 10:55     ` Prabhakar Mahadev Lad
2022-04-20 21:34 ` [PATCH 5.10.y-cip 04/24] ASoC: sh: Add RZ/G2L SSIF-2 driver Lad Prabhakar
2022-04-21  1:12   ` nobuhiro1.iwamatsu
2022-04-21 10:50     ` Prabhakar Mahadev Lad
2022-04-21 11:02       ` Pavel Machek
2022-04-21 11:18         ` Prabhakar Mahadev Lad
2022-04-20 21:34 ` [PATCH 5.10.y-cip 05/24] ASoC: sh: rz-ssi: Add SSI DMAC support Lad Prabhakar
2022-04-21  8:33   ` Pavel Machek
2022-04-21 11:02     ` Prabhakar Mahadev Lad
2022-04-20 21:34 ` [PATCH 5.10.y-cip 06/24] ASoC: sh: rz-ssi: Fix dereference of noderef expression warning Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 07/24] ASoC: sh: rz-ssi: Fix wrong operator used issue Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 08/24] ASoC: sh: rz-ssi: Improve error handling in rz_ssi_dma_request function Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 09/24] ASoC: sh: rz-ssi: Check return value of pm_runtime_resume_and_get() Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 10/24] ASoC: sh: rz-ssi: Drop calling rz_ssi_pio_recv() recursively Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 11/24] ASoC: sh: rz-ssi: Make the data structures available before registering the handlers Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 12/24] ASoC: sh: rz-ssi: Drop ssi parameter from rz_ssi_stream_init() Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 13/24] ASoC: sh: rz-ssi: Make return type of rz_ssi_stream_is_valid() to bool Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 14/24] ASoC: sh: rz-ssi: Use a do-while loop in rz_ssi_pio_recv() Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 15/24] ASoC: sh: rz-ssi: Add rz_ssi_set_substream() helper function Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 16/24] ASoC: sh: rz-ssi: Remove duplicate macros Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 17/24] arm64: dts: renesas: r9a07g044: Add external audio clock nodes Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 18/24] arm64: dts: renesas: r9a07g044: Add SSI support Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 19/24] arm64: dts: renesas: r9a07g044: Add DMA support to SSI Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 20/24] arm64: dts: renesas: rzg2l-smarc: Add WM8978 sound codec Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 21/24] arm64: dts: renesas: rzg2l-smarc: Enable audio Lad Prabhakar
2022-04-21 11:15   ` Pavel Machek
2022-04-21 11:18     ` Biju Das
2022-04-20 21:34 ` [PATCH 5.10.y-cip 22/24] arm64: dts: renesas: rzg2l-smarc: Add Mic routing Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 23/24] arm64: defconfig: Enable SOUND_SOC_RZ Lad Prabhakar
2022-04-20 21:34 ` [PATCH 5.10.y-cip 24/24] arm64: defconfig: Enable SND_SOC_WM8978 Lad Prabhakar
2022-04-21  3:25 ` [PATCH 5.10.y-cip 00/24] Add sound support to Renesas RZ/G2L SoC nobuhiro1.iwamatsu
2022-04-21 11:17   ` Pavel Machek
2022-04-25  5:52   ` Prabhakar Mahadev Lad
2022-04-25  7:25     ` nobuhiro1.iwamatsu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.