devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] ASoC: spacemit: add i2s support to K1 SoC
@ 2025-08-14  8:54 Troy Mitchell
  2025-08-14  8:54 ` [PATCH 1/2] dt-bindings: i2s: spacemit: add support for " Troy Mitchell
  2025-08-14  8:54 ` [PATCH 2/2] ASoC: spacemit: i2s: " Troy Mitchell
  0 siblings, 2 replies; 8+ messages in thread
From: Troy Mitchell @ 2025-08-14  8:54 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Yixun Lan, Jaroslav Kysela, Takashi Iwai,
	Philipp Zabel
  Cc: linux-sound, devicetree, linux-riscv, spacemit, linux-kernel,
	Troy Mitchell, Jinmei Wei

On the K1 SoC, there is a full-duplex I2S controller.

The I2S is programmable, with the sample width configurable
to 8, 16, 18, or 32 bits.

A dedicated FIFO is provided for transmit (TXFIFO) and another
for receive (RXFIFO). In non-packed mode, both FIFOs are 32
entries deep and 32 bits wide, giving a total of 32 samples each.

The register definitions can be found here[1]

Link:
https://developer.spacemit.com/documentation?token=Rn9Kw3iFHirAMgkIpTAcV2Arnkf#18.2-spi%2Fi2s [1]

Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
Troy Mitchell (2):
      dt-bindings: i2s: spacemit: add support for K1 SoC
      ASoC: spacemit: i2s: add support for K1 SoC

 .../devicetree/bindings/sound/spacemit,k1-i2s.yaml |  88 ++++
 sound/soc/Kconfig                                  |   1 +
 sound/soc/Makefile                                 |   1 +
 sound/soc/spacemit/Kconfig                         |  14 +
 sound/soc/spacemit/Makefile                        |   5 +
 sound/soc/spacemit/k1_i2s.c                        | 444 +++++++++++++++++++++
 6 files changed, 553 insertions(+)
---
base-commit: 6be7a5a768aafcb07d177bd2ae36ab84e4e0acde
change-id: 20250813-k1-i2s-115bf65eaac8
prerequisite-change-id: 20250804-k1-clk-i2s-generation-eee7049ee17a:v2
prerequisite-patch-id: 21c0ef38a82ad5f8e471bd904559e5bf68099445
prerequisite-patch-id: 6fa5b6872559a75651342831399676ec96cc3974
prerequisite-patch-id: 03cbe1816e519bc16c641055972558fb5eec6a37
prerequisite-patch-id: 1ef339ef1a80a508b5761dab1ddf448a985864e9
prerequisite-change-id: 20250717-k1-clk-i2s-e4272f1f915b:v5
prerequisite-patch-id: 6f2626811da4833395f52f712d9f2a5fb553cb48
prerequisite-patch-id: d2594982f7a8f39c2aa4f21490a19e93ab67254d
prerequisite-change-id: 20250701-working_dma_0701_v2-7d2cf506aad7:v3
prerequisite-patch-id: 3fe97698036c32c20d03b1b835a5735e8ee8126c
prerequisite-patch-id: bf64cb2fbb9699d2ace64ae517532f13c6f8d277
prerequisite-patch-id: 49263c65c84a0b045f9b5ae6831dc011c4dea52f
prerequisite-patch-id: a62678262e4fd2361b8c0c535ce34853febf492a
prerequisite-patch-id: 1b840918a99543f4497b6475ee52977bdb59f1c3
prerequisite-patch-id: 75e5a355a32ceb2b0047ead035c07c5b201bebbc
prerequisite-patch-id: bc8f599bef77297a7bd69736bb5307a0964aeff5
prerequisite-patch-id: 62d0b3678cf825bca51424ad85cf35ebdd6dc171

Best regards,
-- 
Troy Mitchell <troy.mitchell@linux.spacemit.com>


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

* [PATCH 1/2] dt-bindings: i2s: spacemit: add support for K1 SoC
  2025-08-14  8:54 [PATCH 0/2] ASoC: spacemit: add i2s support to K1 SoC Troy Mitchell
@ 2025-08-14  8:54 ` Troy Mitchell
  2025-08-16  9:13   ` Troy Mitchell
  2025-08-20  8:03   ` Krzysztof Kozlowski
  2025-08-14  8:54 ` [PATCH 2/2] ASoC: spacemit: i2s: " Troy Mitchell
  1 sibling, 2 replies; 8+ messages in thread
From: Troy Mitchell @ 2025-08-14  8:54 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Yixun Lan, Jaroslav Kysela, Takashi Iwai,
	Philipp Zabel
  Cc: linux-sound, devicetree, linux-riscv, spacemit, linux-kernel,
	Troy Mitchell

Add dt-binding for the i2s driver of SpacemiT's K1 SoC.

Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
 .../devicetree/bindings/sound/spacemit,k1-i2s.yaml | 88 ++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml b/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7d9110638d71792db6e5bb72559f6abaf4cb59bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml
@@ -0,0 +1,88 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/spacemit,k1-i2s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: K1 I2S controller
+
+description:
+  The I2S bus (Inter-IC sound bus) is a serial link for digital
+  audio data transfer between devices in the system.
+
+maintainers:
+  - Troy Mitchell <troy.mitchell@linux.spacemit.com>
+
+allOf:
+  - $ref: dai-common.yaml#
+
+properties:
+  compatible:
+    const: spacemit,k1-i2s
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: clock for I2S sysclk
+      - description: clock for I2S bclk
+      - description: clock for I2S bus
+      - description: clock for I2S controller
+
+  clock-names:
+    items:
+      - const: sysclk
+      - const: bclk
+      - const: bus
+      - const: func
+
+  dmas:
+    minItems: 1
+    maxItems: 2
+
+  dma-names:
+    oneOf:
+      - const: rx
+      - items:
+          - const: tx
+          - const: rx
+
+  resets:
+    maxItems: 1
+
+  port:
+    $ref: audio-graph-port.yaml#
+    unevaluatedProperties: false
+
+  "#sound-dai-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - dmas
+  - dma-names
+  - resets
+  - "#sound-dai-cells"
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/spacemit,k1-syscon.h>
+    i2s@d4026000 {
+      compatible = "spacemit,k1-i2s";
+      reg = <0xd4026000 0x30>;
+      clocks = <&syscon_mpmu CLK_I2S_SYSCLK>,
+               <&syscon_mpmu CLK_I2S_BCLK>,
+               <&syscon_apbc CLK_SSPA0_BUS>,
+               <&syscon_apbc CLK_SSPA0>;
+      clock-names = "sysclk", "bclk", "bus", "func";
+      dmas = <&pdma0 21 1>, <&pdma0 22 1>;
+      dma-names = "tx", "rx";
+      resets = <&syscon_apbc RESET_SSPA0>;
+      #sound-dai-cells = <0>;
+    };

-- 
2.50.1


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

* [PATCH 2/2] ASoC: spacemit: i2s: add support for K1 SoC
  2025-08-14  8:54 [PATCH 0/2] ASoC: spacemit: add i2s support to K1 SoC Troy Mitchell
  2025-08-14  8:54 ` [PATCH 1/2] dt-bindings: i2s: spacemit: add support for " Troy Mitchell
@ 2025-08-14  8:54 ` Troy Mitchell
  2025-08-14 10:36   ` Philipp Zabel
  2025-08-15  5:59   ` Troy Mitchell
  1 sibling, 2 replies; 8+ messages in thread
From: Troy Mitchell @ 2025-08-14  8:54 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Yixun Lan, Jaroslav Kysela, Takashi Iwai,
	Philipp Zabel
  Cc: linux-sound, devicetree, linux-riscv, spacemit, linux-kernel,
	Troy Mitchell, Jinmei Wei

Add ASoC platform driver for the SpacemiT K1 SoC full-duplex I2S
controller.

Co-developer: Jinmei Wei <weijinmei@linux.spacemit.com>
Signed-off-by: Jinmei Wei <weijinmei@linux.spacemit.com>
Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
---
 sound/soc/Kconfig           |   1 +
 sound/soc/Makefile          |   1 +
 sound/soc/spacemit/Kconfig  |  14 ++
 sound/soc/spacemit/Makefile |   5 +
 sound/soc/spacemit/k1_i2s.c | 444 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 465 insertions(+)

diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index bf362bfca4564f0a7760850be8088ac7cc402b89..63d5c7a3ff4e1988cacfac01c58fd2bd36bd5903 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -128,6 +128,7 @@ source "sound/soc/renesas/Kconfig"
 source "sound/soc/rockchip/Kconfig"
 source "sound/soc/samsung/Kconfig"
 source "sound/soc/sdca/Kconfig"
+source "sound/soc/spacemit/Kconfig"
 source "sound/soc/spear/Kconfig"
 source "sound/soc/sprd/Kconfig"
 source "sound/soc/starfive/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 462322c38aa42d4c394736239de0317d5918d5a7..8c0480e6484e75eb0b6db306630ba77d259ba8e3 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_SND_SOC)	+= rockchip/
 obj-$(CONFIG_SND_SOC)	+= samsung/
 obj-$(CONFIG_SND_SOC)	+= sdca/
 obj-$(CONFIG_SND_SOC)	+= sof/
+obj-$(CONFIG_SND_SOC)	+= spacemit/
 obj-$(CONFIG_SND_SOC)	+= spear/
 obj-$(CONFIG_SND_SOC)	+= sprd/
 obj-$(CONFIG_SND_SOC)	+= starfive/
diff --git a/sound/soc/spacemit/Kconfig b/sound/soc/spacemit/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..d0cb7400f9fb62c1178aac7049c59baaa5a2d4e4
--- /dev/null
+++ b/sound/soc/spacemit/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menu "SpacemiT"
+	depends on COMPILE_TEST || ARCH_SPACEMIT
+	depends on HAVE_CLK
+
+config SND_SOC_K1_I2S
+	tristate "K1 I2S Device Driver"
+	select SND_SOC_GENERIC_DMAENGINE_PCM
+	help
+	  Say Y or M if you want to add support for I2S driver for
+	  K1 I2S controller. The device supports up to maximum of
+	  2 channels each for play and record.
+
+endmenu
diff --git a/sound/soc/spacemit/Makefile b/sound/soc/spacemit/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..9069de8ef89c84db8cc7d3a4d3b154fff9bd7aff
--- /dev/null
+++ b/sound/soc/spacemit/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+# K1 Platform Support
+snd-soc-k1-i2s-y := k1_i2s.o
+
+obj-$(CONFIG_SND_SOC_K1_I2S) += snd-soc-k1-i2s.o
diff --git a/sound/soc/spacemit/k1_i2s.c b/sound/soc/spacemit/k1_i2s.c
new file mode 100644
index 0000000000000000000000000000000000000000..9e41525afbf3f08ab9a26b562772861d86f39cd7
--- /dev/null
+++ b/sound/soc/spacemit/k1_i2s.c
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Troy Mitchell <troy.mitchell@linux.spacemit.com> */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#define SSCR			0x00	/* SPI/I2S top control register */
+#define SSFCR			0x04	/* SPI/I2S FIFO control register */
+#define SSINTEN			0x08	/* SPI/I2S interrupt enable register */
+#define SSDATR			0x10	/* SPI/I2S data register */
+#define SSPSP			0x18	/* SPI/I2S programmable serial protocol control register */
+#define SSRWT			0x24	/* SPI/I2S root control register */
+
+/* SPI/I2S Work data size, register bits value 0~31 indicated data size 1~32 bits */
+#define SSCR_FIELD_DSS		GENMASK(9, 5)
+#define SSCR_DW_8BYTE		FIELD_PREP(SSCR_FIELD_DSS, 0x7)
+#define SSCR_DW_16BYTE		FIELD_PREP(SSCR_FIELD_DSS, 0xf)
+#define SSCR_DW_18BYTE		FIELD_PREP(SSCR_FIELD_DSS, 0x11)
+#define SSCR_DW_32BYTE		FIELD_PREP(SSCR_FIELD_DSS, 0x1f)
+
+#define SSCR_SSE		BIT(0)		/* SPI/I2S Enable */
+#define SSCR_FRF_PSP		GENMASK(2, 1)	/* Frame Format*/
+#define SSCR_TRAIL		BIT(13)		/* Trailing Byte */
+
+#define SSFCR_FIELD_TFT		GENMASK(3, 0)   /* TXFIFO Trigger Threshold */
+#define SSFCR_FIELD_RFT		GENMASK(8, 5)   /* RXFIFO Trigger Threshold */
+#define SSFCR_TSRE		BIT(10)		/* Transmit Service Request Enable */
+#define SSFCR_RSRE		BIT(11)		/* Receive Service Request Enable */
+
+#define SSPSP_FSRT		BIT(3)		/* Frame Sync Relative Timing Bit */
+#define SSPSP_SFRMP		BIT(4)		/* Serial Frame Polarity */
+#define SSPSP_FIELD_SFRMWDTH	GENMASK(17, 12)	/* Serial Frame Width field  */
+
+#define SSRWT_RWOT		BIT(0)		/* Receive Without Transmit */
+
+#define SPACEMIT_PCM_RATES	SNDRV_PCM_RATE_8000_192000
+#define SPACEMIT_PCM_FORMATS	(SNDRV_PCM_FMTBIT_S8 | \
+				 SNDRV_PCM_FMTBIT_S16_LE | \
+				 SNDRV_PCM_FMTBIT_S24_LE | \
+				 SNDRV_PCM_FMTBIT_S32_LE)
+
+#define SPACEMIT_I2S_PERIOD_SIZE 1024
+
+struct spacemit_i2s_dev {
+	struct device *dev;
+
+	void __iomem *base;
+
+	struct reset_control *reset;
+
+	struct clk *sysclk;
+	struct clk *bclk;
+	struct clk *sspa_clk;
+
+	struct snd_dmaengine_dai_dma_data capture_dma_data;
+	struct snd_dmaengine_dai_dma_data playback_dma_data;
+
+	bool has_capture;
+	bool has_playback;
+
+	int dai_fmt;
+
+	int started_count;
+};
+
+static const struct snd_pcm_hardware spacemit_pcm_hardware = {
+	.info		  = SNDRV_PCM_INFO_INTERLEAVED |
+			    SNDRV_PCM_INFO_BATCH,
+	.formats          = SPACEMIT_PCM_FORMATS,
+	.rates		  = SPACEMIT_PCM_RATES,
+	.rate_min         = SNDRV_PCM_RATE_8000,
+	.rate_max         = SNDRV_PCM_RATE_192000,
+	.channels_min     = 1,
+	.channels_max     = 2,
+	.buffer_bytes_max = SPACEMIT_I2S_PERIOD_SIZE * 4 * 4,
+	.period_bytes_min = SPACEMIT_I2S_PERIOD_SIZE * 2,
+	.period_bytes_max = SPACEMIT_I2S_PERIOD_SIZE * 4,
+	.periods_min	  = 2,
+	.periods_max	  = 4,
+};
+
+static const struct snd_dmaengine_pcm_config spacemit_dmaengine_pcm_config = {
+	.pcm_hardware = &spacemit_pcm_hardware,
+	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+	.chan_names = {"tx", "rx"},
+	.prealloc_buffer_size = 32 * 1024,
+};
+
+static void spacemit_i2s_init(struct spacemit_i2s_dev *i2s)
+{
+	u32 sscr_val, sspsp_val, ssfcr_val, ssrwt_val;
+
+	sscr_val = SSCR_TRAIL | SSCR_FRF_PSP;
+	ssfcr_val = FIELD_PREP(SSFCR_FIELD_TFT, 5) |
+		    FIELD_PREP(SSFCR_FIELD_RFT, 5) |
+		    SSFCR_RSRE | SSFCR_TSRE;
+	ssrwt_val = SSRWT_RWOT;
+
+	/* SSPSP register was set by set_fmt */
+	sspsp_val = readl(i2s->base + SSPSP);
+	sspsp_val |= SSPSP_SFRMP;
+
+	writel(sscr_val, i2s->base + SSCR);
+	writel(ssfcr_val, i2s->base + SSFCR);
+	writel(sspsp_val, i2s->base + SSPSP);
+	writel(ssrwt_val, i2s->base + SSRWT);
+	writel(0, i2s->base + SSINTEN);
+}
+
+static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
+	struct snd_dmaengine_dai_dma_data *dma_data;
+	u32 data_width, data_bits;
+	unsigned long bclk_rate;
+	u32 val;
+	int ret;
+
+	val = readl(i2s->base + SSCR);
+	if (val & SSCR_SSE)
+		return 0;
+
+	dma_data = &i2s->playback_dma_data;
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		dma_data = &i2s->capture_dma_data;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		data_bits = 8;
+		data_width = SSCR_DW_8BYTE;
+		dma_data->maxburst = 8;
+		dma_data->addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		data_bits = 16;
+		data_width = SSCR_DW_16BYTE;
+		dma_data->maxburst = 16;
+		dma_data->addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		if ((i2s->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) {
+			data_width = SSCR_DW_32BYTE;
+			dma_data->maxburst = 32;
+			dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		}
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		data_bits = 32;
+		data_width = SSCR_DW_32BYTE;
+		dma_data->maxburst = 32;
+		dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+		break;
+	default:
+		dev_dbg(i2s->dev, "unexpected data width type");
+		return -EINVAL;
+	}
+
+	val = readl(i2s->base + SSCR);
+	val &= ~SSCR_DW_32BYTE;
+	val |= data_width;
+	writel(val, i2s->base + SSCR);
+
+	bclk_rate = params_channels(params) *
+		    params_rate(params) *
+		    data_bits;
+
+	ret = clk_set_rate(i2s->bclk, bclk_rate);
+	if (ret)
+		return ret;
+
+	return clk_set_rate(i2s->sspa_clk, bclk_rate);
+}
+
+static int spacemit_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
+				   unsigned int freq, int dir)
+{
+	struct spacemit_i2s_dev *i2s = dev_get_drvdata(cpu_dai->dev);
+
+	if (freq == 0)
+		return 0;
+
+	return clk_set_rate(i2s->sysclk, freq);
+}
+
+static int spacemit_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+				unsigned int fmt)
+{
+	struct spacemit_i2s_dev *i2s = dev_get_drvdata(cpu_dai->dev);
+	u32 sspsp_val;
+
+	sspsp_val = readl(i2s->base + SSPSP);
+	sspsp_val &= ~SSPSP_FIELD_SFRMWDTH;
+
+	i2s->dai_fmt = fmt;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		cpu_dai->driver->playback.formats = SNDRV_PCM_FMTBIT_S16_LE;
+		cpu_dai->driver->capture.formats = SNDRV_PCM_FMTBIT_S16_LE;
+		sspsp_val |= FIELD_PREP(SSPSP_FIELD_SFRMWDTH, 0x10) |
+			     SSPSP_FSRT;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		cpu_dai->driver->playback.channels_min = 1;
+		cpu_dai->driver->playback.channels_max = 1;
+		cpu_dai->driver->capture.channels_min = 1;
+		cpu_dai->driver->capture.channels_max = 1;
+		cpu_dai->driver->playback.formats = SNDRV_PCM_FMTBIT_S32_LE;
+		cpu_dai->driver->capture.formats = SNDRV_PCM_FMTBIT_S32_LE;
+		sspsp_val |= FIELD_PREP(SSPSP_FIELD_SFRMWDTH, 0x1);
+		break;
+	default:
+		dev_dbg(i2s->dev, "unexpected format type");
+		return -EINVAL;
+	}
+
+	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A)
+		sspsp_val |= SSPSP_FSRT;
+
+	writel(sspsp_val, i2s->base + SSPSP);
+
+	return 0;
+}
+
+static int spacemit_i2s_trigger(struct snd_pcm_substream *substream,
+				int cmd, struct snd_soc_dai *dai)
+{
+	struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
+	u32 val;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (!i2s->started_count) {
+			val = readl(i2s->base + SSCR);
+			val |= SSCR_SSE;
+			writel(val, i2s->base + SSCR);
+		}
+		i2s->started_count++;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (i2s->started_count)
+			i2s->started_count--;
+
+		if (!i2s->started_count) {
+			val = readl(i2s->base + SSCR);
+			val &= ~SSCR_SSE;
+			writel(val, i2s->base + SSCR);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int spacemit_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+	struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
+
+	snd_soc_dai_init_dma_data(dai,
+				  i2s->has_playback ? &i2s->playback_dma_data : NULL,
+				  i2s->has_capture ? &i2s->capture_dma_data : NULL);
+
+	reset_control_deassert(i2s->reset);
+
+	spacemit_i2s_init(i2s);
+
+	return 0;
+}
+
+static const struct snd_soc_dai_ops spacemit_i2s_dai_ops = {
+	.probe = spacemit_i2s_dai_probe,
+	.hw_params = spacemit_i2s_hw_params,
+	.set_sysclk = spacemit_i2s_set_sysclk,
+	.set_fmt = spacemit_i2s_set_fmt,
+	.trigger = spacemit_i2s_trigger,
+};
+
+static struct snd_soc_dai_driver spacemit_i2s_dai = {
+	.ops = &spacemit_i2s_dai_ops,
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SPACEMIT_PCM_RATES,
+		.rate_min = SNDRV_PCM_RATE_8000,
+		.rate_max = SNDRV_PCM_RATE_192000,
+		.formats = SPACEMIT_PCM_FORMATS,
+	},
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SPACEMIT_PCM_RATES,
+		.rate_min = SNDRV_PCM_RATE_8000,
+		.rate_max = SNDRV_PCM_RATE_192000,
+		.formats = SPACEMIT_PCM_FORMATS,
+	},
+	.symmetric_rate = 1,
+};
+
+static int spacemit_i2s_init_dai(struct spacemit_i2s_dev *i2s,
+				 struct snd_soc_dai_driver **dp,
+				 dma_addr_t addr)
+{
+	struct device_node *node = i2s->dev->of_node;
+	struct snd_soc_dai_driver *dai;
+	struct property *dma_names;
+	const char *dma_name;
+
+	of_property_for_each_string(node, "dma-names", dma_names, dma_name) {
+		if (!strcmp(dma_name, "tx"))
+			i2s->has_playback = true;
+		if (!strcmp(dma_name, "rx"))
+			i2s->has_capture = true;
+	}
+
+	dai = devm_kmemdup(i2s->dev, &spacemit_i2s_dai,
+			   sizeof(*dai), GFP_KERNEL);
+	if (!dai)
+		return -ENOMEM;
+
+	if (i2s->has_playback) {
+		dai->playback.stream_name = "Playback";
+		dai->playback.channels_min = 1;
+		dai->playback.channels_max = 2;
+		dai->playback.rates = SPACEMIT_PCM_RATES;
+		dai->playback.formats = SPACEMIT_PCM_FORMATS;
+
+		i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		i2s->playback_dma_data.maxburst = 32;
+		i2s->playback_dma_data.addr = addr;
+	}
+
+	if (i2s->has_capture) {
+		dai->capture.stream_name = "Capture";
+		dai->capture.channels_min = 1;
+		dai->capture.channels_max = 2;
+		dai->capture.rates = SPACEMIT_PCM_RATES;
+		dai->capture.formats = SPACEMIT_PCM_FORMATS;
+
+		i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+		i2s->capture_dma_data.maxburst = 32;
+		i2s->capture_dma_data.addr = addr;
+	}
+
+	if (dp)
+		*dp = dai;
+
+	return 0;
+}
+
+static const struct snd_soc_component_driver spacemit_i2s_component = {
+	.name = "i2s-k1",
+	.legacy_dai_naming = 1,
+};
+
+static int spacemit_i2s_probe(struct platform_device *pdev)
+{
+	struct snd_soc_dai_driver *dai;
+	struct spacemit_i2s_dev *i2s;
+	struct resource *res;
+	struct clk *clk;
+	int ret;
+
+	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
+	if (!i2s)
+		return -ENOMEM;
+
+	i2s->dev = &pdev->dev;
+
+	i2s->sysclk = devm_clk_get_enabled(i2s->dev, "sysclk");
+	if (IS_ERR(i2s->sysclk))
+		return dev_err_probe(i2s->dev, PTR_ERR(i2s->sysclk),
+				     "failed to enable sysbase clock\n");
+
+	i2s->bclk = devm_clk_get_enabled(i2s->dev, "bclk");
+	if (IS_ERR(i2s->bclk))
+		return dev_err_probe(i2s->dev, PTR_ERR(i2s->bclk), "failed to enable bit clock\n");
+
+	clk = devm_clk_get_enabled(i2s->dev, "sspa_bus");
+	if (IS_ERR(clk))
+		return dev_err_probe(i2s->dev, PTR_ERR(clk), "failed to enable sspa_bus clock\n");
+
+	i2s->sspa_clk = devm_clk_get_enabled(i2s->dev, "sspa");
+	if (IS_ERR(clk))
+		return dev_err_probe(i2s->dev, PTR_ERR(clk), "failed to enable sspa clock\n");
+
+	i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+	if (IS_ERR(i2s->base))
+		return dev_err_probe(i2s->dev, PTR_ERR(i2s->base), "failed to map registers\n");
+
+	i2s->reset =  devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(i2s->reset))
+		return dev_err_probe(i2s->dev, PTR_ERR(i2s->reset),
+				     "failed to get reset control");
+
+	dev_set_drvdata(i2s->dev, i2s);
+
+	spacemit_i2s_init_dai(i2s, &dai, res->start + SSDATR);
+
+	ret = devm_snd_soc_register_component(i2s->dev,
+					      &spacemit_i2s_component,
+					      dai, 1);
+	if (ret)
+		return dev_err_probe(i2s->dev, ret, "failed to register component");
+
+	return devm_snd_dmaengine_pcm_register(&pdev->dev, &spacemit_dmaengine_pcm_config, 0);
+}
+
+static void spacemit_i2s_remove(struct platform_device *pdev)
+{
+	struct spacemit_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);
+
+	reset_control_assert(i2s->reset);
+}
+
+static const struct of_device_id spacemit_i2s_of_match[] = {
+	{ .compatible = "spacemit,k1-i2s", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, spacemit_i2s_of_match);
+
+static struct platform_driver spacemit_i2s_driver = {
+	.probe = spacemit_i2s_probe,
+	.remove = spacemit_i2s_remove,
+	.driver = {
+		.name = "i2s-k1",
+		.of_match_table = spacemit_i2s_of_match,
+	},
+};
+module_platform_driver(spacemit_i2s_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("I2S bus driver for SpacemiT K1 SoC");

-- 
2.50.1


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

* Re: [PATCH 2/2] ASoC: spacemit: i2s: add support for K1 SoC
  2025-08-14  8:54 ` [PATCH 2/2] ASoC: spacemit: i2s: " Troy Mitchell
@ 2025-08-14 10:36   ` Philipp Zabel
  2025-08-14 12:55     ` Troy Mitchell
  2025-08-15  5:59   ` Troy Mitchell
  1 sibling, 1 reply; 8+ messages in thread
From: Philipp Zabel @ 2025-08-14 10:36 UTC (permalink / raw)
  To: Troy Mitchell, Liam Girdwood, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Yixun Lan, Jaroslav Kysela,
	Takashi Iwai
  Cc: linux-sound, devicetree, linux-riscv, spacemit, linux-kernel,
	Jinmei Wei

On Do, 2025-08-14 at 16:54 +0800, Troy Mitchell wrote:
> Add ASoC platform driver for the SpacemiT K1 SoC full-duplex I2S
> controller.
> 
> Co-developer: Jinmei Wei <weijinmei@linux.spacemit.com>
> Signed-off-by: Jinmei Wei <weijinmei@linux.spacemit.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  sound/soc/Kconfig           |   1 +
>  sound/soc/Makefile          |   1 +
>  sound/soc/spacemit/Kconfig  |  14 ++
>  sound/soc/spacemit/Makefile |   5 +
>  sound/soc/spacemit/k1_i2s.c | 444 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 465 insertions(+)
> 
[...]
> diff --git a/sound/soc/spacemit/k1_i2s.c b/sound/soc/spacemit/k1_i2s.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..9e41525afbf3f08ab9a26b562772861d86f39cd7
> --- /dev/null
> +++ b/sound/soc/spacemit/k1_i2s.c
> @@ -0,0 +1,444 @@
[...]

> +static int spacemit_i2s_probe(struct platform_device *pdev)
> +{
> +	struct snd_soc_dai_driver *dai;
> +	struct spacemit_i2s_dev *i2s;
> +	struct resource *res;
> +	struct clk *clk;
> +	int ret;
> +
> +	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
> +	if (!i2s)
> +		return -ENOMEM;
> +
> +	i2s->dev = &pdev->dev;
> +
> +	i2s->sysclk = devm_clk_get_enabled(i2s->dev, "sysclk");
> +	if (IS_ERR(i2s->sysclk))
> +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->sysclk),
> +				     "failed to enable sysbase clock\n");
> +
> +	i2s->bclk = devm_clk_get_enabled(i2s->dev, "bclk");
> +	if (IS_ERR(i2s->bclk))
> +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->bclk), "failed to enable bit clock\n");
> +
> +	clk = devm_clk_get_enabled(i2s->dev, "sspa_bus");
> +	if (IS_ERR(clk))
> +		return dev_err_probe(i2s->dev, PTR_ERR(clk), "failed to enable sspa_bus clock\n");
> +
> +	i2s->sspa_clk = devm_clk_get_enabled(i2s->dev, "sspa");
> +	if (IS_ERR(clk))
> +		return dev_err_probe(i2s->dev, PTR_ERR(clk), "failed to enable sspa clock\n");
> +
> +	i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
> +	if (IS_ERR(i2s->base))
> +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->base), "failed to map registers\n");
> +
> +	i2s->reset =  devm_reset_control_get(&pdev->dev, NULL);

Please use devm_reset_control_get_exclusive() directly.

> +	if (IS_ERR(i2s->reset))
> +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->reset),
> +				     "failed to get reset control");
> +
> +	dev_set_drvdata(i2s->dev, i2s);
> +
> +	spacemit_i2s_init_dai(i2s, &dai, res->start + SSDATR);
> +
> +	ret = devm_snd_soc_register_component(i2s->dev,
> +					      &spacemit_i2s_component,
> +					      dai, 1);
> +	if (ret)
> +		return dev_err_probe(i2s->dev, ret, "failed to register component");
> +
> +	return devm_snd_dmaengine_pcm_register(&pdev->dev, &spacemit_dmaengine_pcm_config, 0);
> +}
> +
> +static void spacemit_i2s_remove(struct platform_device *pdev)
> +{
> +	struct spacemit_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);
> +
> +	reset_control_assert(i2s->reset);

I'd move the reset_control_assert() be moved to snd_soc_dai_ops::remove
for symmetry.

regards
Philipp

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

* Re: [PATCH 2/2] ASoC: spacemit: i2s: add support for K1 SoC
  2025-08-14 10:36   ` Philipp Zabel
@ 2025-08-14 12:55     ` Troy Mitchell
  0 siblings, 0 replies; 8+ messages in thread
From: Troy Mitchell @ 2025-08-14 12:55 UTC (permalink / raw)
  To: Philipp Zabel, Troy Mitchell, Liam Girdwood, Mark Brown,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yixun Lan,
	Jaroslav Kysela, Takashi Iwai
  Cc: linux-sound, devicetree, linux-riscv, spacemit, linux-kernel,
	Jinmei Wei

On Thu, Aug 14, 2025 at 12:36:45PM +0200, Philipp Zabel wrote:
> On Do, 2025-08-14 at 16:54 +0800, Troy Mitchell wrote:
> > Add ASoC platform driver for the SpacemiT K1 SoC full-duplex I2S
> > controller.
> > 
> > Co-developer: Jinmei Wei <weijinmei@linux.spacemit.com>
> > Signed-off-by: Jinmei Wei <weijinmei@linux.spacemit.com>
> > Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> > ---
> >  sound/soc/Kconfig           |   1 +
> >  sound/soc/Makefile          |   1 +
> >  sound/soc/spacemit/Kconfig  |  14 ++
> >  sound/soc/spacemit/Makefile |   5 +
> >  sound/soc/spacemit/k1_i2s.c | 444 ++++++++++++++++++++++++++++++++++++++++++++
> >  5 files changed, 465 insertions(+)
> > 
> [...]
> > diff --git a/sound/soc/spacemit/k1_i2s.c b/sound/soc/spacemit/k1_i2s.c
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..9e41525afbf3f08ab9a26b562772861d86f39cd7
> > --- /dev/null
> > +++ b/sound/soc/spacemit/k1_i2s.c
> > @@ -0,0 +1,444 @@
> [...]
> 
> > +static int spacemit_i2s_probe(struct platform_device *pdev)
> > +{
> > +	struct snd_soc_dai_driver *dai;
> > +	struct spacemit_i2s_dev *i2s;
> > +	struct resource *res;
> > +	struct clk *clk;
> > +	int ret;
> > +
> > +	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
> > +	if (!i2s)
> > +		return -ENOMEM;
> > +
> > +	i2s->dev = &pdev->dev;
> > +
> > +	i2s->sysclk = devm_clk_get_enabled(i2s->dev, "sysclk");
> > +	if (IS_ERR(i2s->sysclk))
> > +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->sysclk),
> > +				     "failed to enable sysbase clock\n");
> > +
> > +	i2s->bclk = devm_clk_get_enabled(i2s->dev, "bclk");
> > +	if (IS_ERR(i2s->bclk))
> > +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->bclk), "failed to enable bit clock\n");
> > +
> > +	clk = devm_clk_get_enabled(i2s->dev, "sspa_bus");
> > +	if (IS_ERR(clk))
> > +		return dev_err_probe(i2s->dev, PTR_ERR(clk), "failed to enable sspa_bus clock\n");
> > +
> > +	i2s->sspa_clk = devm_clk_get_enabled(i2s->dev, "sspa");
> > +	if (IS_ERR(clk))
> > +		return dev_err_probe(i2s->dev, PTR_ERR(clk), "failed to enable sspa clock\n");
> > +
> > +	i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
> > +	if (IS_ERR(i2s->base))
> > +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->base), "failed to map registers\n");
> > +
> > +	i2s->reset =  devm_reset_control_get(&pdev->dev, NULL);
> 
> Please use devm_reset_control_get_exclusive() directly.
Tnx. I will use in the next version.

> 
> > +	if (IS_ERR(i2s->reset))
> > +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->reset),
> > +				     "failed to get reset control");
> > +
> > +	dev_set_drvdata(i2s->dev, i2s);
> > +
> > +	spacemit_i2s_init_dai(i2s, &dai, res->start + SSDATR);
> > +
> > +	ret = devm_snd_soc_register_component(i2s->dev,
> > +					      &spacemit_i2s_component,
> > +					      dai, 1);
> > +	if (ret)
> > +		return dev_err_probe(i2s->dev, ret, "failed to register component");
> > +
> > +	return devm_snd_dmaengine_pcm_register(&pdev->dev, &spacemit_dmaengine_pcm_config, 0);
> > +}
> > +
> > +static void spacemit_i2s_remove(struct platform_device *pdev)
> > +{
> > +	struct spacemit_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);
> > +
> > +	reset_control_assert(i2s->reset);
> 
> I'd move the reset_control_assert() be moved to snd_soc_dai_ops::remove
> for symmetry.
>
It makes sense.

deassert in ops::probe and assert in ops::remove.

                - Troy
> 
> regards
> Philipp
> 

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

* Re: [PATCH 2/2] ASoC: spacemit: i2s: add support for K1 SoC
  2025-08-14  8:54 ` [PATCH 2/2] ASoC: spacemit: i2s: " Troy Mitchell
  2025-08-14 10:36   ` Philipp Zabel
@ 2025-08-15  5:59   ` Troy Mitchell
  1 sibling, 0 replies; 8+ messages in thread
From: Troy Mitchell @ 2025-08-15  5:59 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Yixun Lan, Jaroslav Kysela, Takashi Iwai,
	Philipp Zabel
  Cc: linux-sound, devicetree, linux-riscv, spacemit, linux-kernel,
	Troy Mitchell, Jinmei Wei

On Thu, Aug 14, 2025 at 04:54:20PM +0800, Troy Mitchell wrote:
> Add ASoC platform driver for the SpacemiT K1 SoC full-duplex I2S
> controller.
> 
> Co-developer: Jinmei Wei <weijinmei@linux.spacemit.com>
> Signed-off-by: Jinmei Wei <weijinmei@linux.spacemit.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  sound/soc/Kconfig           |   1 +
>  sound/soc/Makefile          |   1 +
>  sound/soc/spacemit/Kconfig  |  14 ++
>  sound/soc/spacemit/Makefile |   5 +
>  sound/soc/spacemit/k1_i2s.c | 444 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 465 insertions(+)
> 
> diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
> index bf362bfca4564f0a7760850be8088ac7cc402b89..63d5c7a3ff4e1988cacfac01c58fd2bd36bd5903 100644
> --- a/sound/soc/Kconfig
> +++ b/sound/soc/Kconfig
> @@ -128,6 +128,7 @@ source "sound/soc/renesas/Kconfig"
>  source "sound/soc/rockchip/Kconfig"
>  source "sound/soc/samsung/Kconfig"
>  source "sound/soc/sdca/Kconfig"
> +source "sound/soc/spacemit/Kconfig"
>  source "sound/soc/spear/Kconfig"
>  source "sound/soc/sprd/Kconfig"
>  source "sound/soc/starfive/Kconfig"
> diff --git a/sound/soc/Makefile b/sound/soc/Makefile
> index 462322c38aa42d4c394736239de0317d5918d5a7..8c0480e6484e75eb0b6db306630ba77d259ba8e3 100644
> --- a/sound/soc/Makefile
> +++ b/sound/soc/Makefile
> @@ -70,6 +70,7 @@ obj-$(CONFIG_SND_SOC)	+= rockchip/
>  obj-$(CONFIG_SND_SOC)	+= samsung/
>  obj-$(CONFIG_SND_SOC)	+= sdca/
>  obj-$(CONFIG_SND_SOC)	+= sof/
> +obj-$(CONFIG_SND_SOC)	+= spacemit/
>  obj-$(CONFIG_SND_SOC)	+= spear/
>  obj-$(CONFIG_SND_SOC)	+= sprd/
>  obj-$(CONFIG_SND_SOC)	+= starfive/
> diff --git a/sound/soc/spacemit/Kconfig b/sound/soc/spacemit/Kconfig
> new file mode 100644
> index 0000000000000000000000000000000000000000..d0cb7400f9fb62c1178aac7049c59baaa5a2d4e4
> --- /dev/null
> +++ b/sound/soc/spacemit/Kconfig
> @@ -0,0 +1,14 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +menu "SpacemiT"
> +	depends on COMPILE_TEST || ARCH_SPACEMIT
> +	depends on HAVE_CLK
> +
> +config SND_SOC_K1_I2S
> +	tristate "K1 I2S Device Driver"
> +	select SND_SOC_GENERIC_DMAENGINE_PCM
I think I need select CMA and DMA_CMA here.
Otherwise I got this error:
```
[    1.302864] ALSA pcmC0D0p,0:: cannot preallocate for size 32768
[    1.308704] ALSA pcmC0D0c,0:d4026000.i2s0-ES8326 HiFi ES8326 HiFi-0: cannot preallocate for size 32768
```
                - Troy

> +	help
> +	  Say Y or M if you want to add support for I2S driver for
> +	  K1 I2S controller. The device supports up to maximum of
> +	  2 channels each for play and record.
> +
> +endmenu
> diff --git a/sound/soc/spacemit/Makefile b/sound/soc/spacemit/Makefile
> new file mode 100644
> index 0000000000000000000000000000000000000000..9069de8ef89c84db8cc7d3a4d3b154fff9bd7aff
> --- /dev/null
> +++ b/sound/soc/spacemit/Makefile
> @@ -0,0 +1,5 @@
> +# SPDX-License-Identifier: GPL-2.0
> +# K1 Platform Support
> +snd-soc-k1-i2s-y := k1_i2s.o
> +
> +obj-$(CONFIG_SND_SOC_K1_I2S) += snd-soc-k1-i2s.o
> diff --git a/sound/soc/spacemit/k1_i2s.c b/sound/soc/spacemit/k1_i2s.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..9e41525afbf3f08ab9a26b562772861d86f39cd7
> --- /dev/null
> +++ b/sound/soc/spacemit/k1_i2s.c
> @@ -0,0 +1,444 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2025 Troy Mitchell <troy.mitchell@linux.spacemit.com> */
> +
> +#include <linux/bitfield.h>
> +#include <linux/clk.h>
> +#include <linux/reset.h>
> +#include <sound/dmaengine_pcm.h>
> +#include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +
> +#define SSCR			0x00	/* SPI/I2S top control register */
> +#define SSFCR			0x04	/* SPI/I2S FIFO control register */
> +#define SSINTEN			0x08	/* SPI/I2S interrupt enable register */
> +#define SSDATR			0x10	/* SPI/I2S data register */
> +#define SSPSP			0x18	/* SPI/I2S programmable serial protocol control register */
> +#define SSRWT			0x24	/* SPI/I2S root control register */
> +
> +/* SPI/I2S Work data size, register bits value 0~31 indicated data size 1~32 bits */
> +#define SSCR_FIELD_DSS		GENMASK(9, 5)
> +#define SSCR_DW_8BYTE		FIELD_PREP(SSCR_FIELD_DSS, 0x7)
> +#define SSCR_DW_16BYTE		FIELD_PREP(SSCR_FIELD_DSS, 0xf)
> +#define SSCR_DW_18BYTE		FIELD_PREP(SSCR_FIELD_DSS, 0x11)
> +#define SSCR_DW_32BYTE		FIELD_PREP(SSCR_FIELD_DSS, 0x1f)
> +
> +#define SSCR_SSE		BIT(0)		/* SPI/I2S Enable */
> +#define SSCR_FRF_PSP		GENMASK(2, 1)	/* Frame Format*/
> +#define SSCR_TRAIL		BIT(13)		/* Trailing Byte */
> +
> +#define SSFCR_FIELD_TFT		GENMASK(3, 0)   /* TXFIFO Trigger Threshold */
> +#define SSFCR_FIELD_RFT		GENMASK(8, 5)   /* RXFIFO Trigger Threshold */
> +#define SSFCR_TSRE		BIT(10)		/* Transmit Service Request Enable */
> +#define SSFCR_RSRE		BIT(11)		/* Receive Service Request Enable */
> +
> +#define SSPSP_FSRT		BIT(3)		/* Frame Sync Relative Timing Bit */
> +#define SSPSP_SFRMP		BIT(4)		/* Serial Frame Polarity */
> +#define SSPSP_FIELD_SFRMWDTH	GENMASK(17, 12)	/* Serial Frame Width field  */
> +
> +#define SSRWT_RWOT		BIT(0)		/* Receive Without Transmit */
> +
> +#define SPACEMIT_PCM_RATES	SNDRV_PCM_RATE_8000_192000
> +#define SPACEMIT_PCM_FORMATS	(SNDRV_PCM_FMTBIT_S8 | \
> +				 SNDRV_PCM_FMTBIT_S16_LE | \
> +				 SNDRV_PCM_FMTBIT_S24_LE | \
> +				 SNDRV_PCM_FMTBIT_S32_LE)
> +
> +#define SPACEMIT_I2S_PERIOD_SIZE 1024
> +
> +struct spacemit_i2s_dev {
> +	struct device *dev;
> +
> +	void __iomem *base;
> +
> +	struct reset_control *reset;
> +
> +	struct clk *sysclk;
> +	struct clk *bclk;
> +	struct clk *sspa_clk;
> +
> +	struct snd_dmaengine_dai_dma_data capture_dma_data;
> +	struct snd_dmaengine_dai_dma_data playback_dma_data;
> +
> +	bool has_capture;
> +	bool has_playback;
> +
> +	int dai_fmt;
> +
> +	int started_count;
> +};
> +
> +static const struct snd_pcm_hardware spacemit_pcm_hardware = {
> +	.info		  = SNDRV_PCM_INFO_INTERLEAVED |
> +			    SNDRV_PCM_INFO_BATCH,
> +	.formats          = SPACEMIT_PCM_FORMATS,
> +	.rates		  = SPACEMIT_PCM_RATES,
> +	.rate_min         = SNDRV_PCM_RATE_8000,
> +	.rate_max         = SNDRV_PCM_RATE_192000,
> +	.channels_min     = 1,
> +	.channels_max     = 2,
> +	.buffer_bytes_max = SPACEMIT_I2S_PERIOD_SIZE * 4 * 4,
> +	.period_bytes_min = SPACEMIT_I2S_PERIOD_SIZE * 2,
> +	.period_bytes_max = SPACEMIT_I2S_PERIOD_SIZE * 4,
> +	.periods_min	  = 2,
> +	.periods_max	  = 4,
> +};
> +
> +static const struct snd_dmaengine_pcm_config spacemit_dmaengine_pcm_config = {
> +	.pcm_hardware = &spacemit_pcm_hardware,
> +	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
> +	.chan_names = {"tx", "rx"},
> +	.prealloc_buffer_size = 32 * 1024,
> +};
> +
> +static void spacemit_i2s_init(struct spacemit_i2s_dev *i2s)
> +{
> +	u32 sscr_val, sspsp_val, ssfcr_val, ssrwt_val;
> +
> +	sscr_val = SSCR_TRAIL | SSCR_FRF_PSP;
> +	ssfcr_val = FIELD_PREP(SSFCR_FIELD_TFT, 5) |
> +		    FIELD_PREP(SSFCR_FIELD_RFT, 5) |
> +		    SSFCR_RSRE | SSFCR_TSRE;
> +	ssrwt_val = SSRWT_RWOT;
> +
> +	/* SSPSP register was set by set_fmt */
> +	sspsp_val = readl(i2s->base + SSPSP);
> +	sspsp_val |= SSPSP_SFRMP;
> +
> +	writel(sscr_val, i2s->base + SSCR);
> +	writel(ssfcr_val, i2s->base + SSFCR);
> +	writel(sspsp_val, i2s->base + SSPSP);
> +	writel(ssrwt_val, i2s->base + SSRWT);
> +	writel(0, i2s->base + SSINTEN);
> +}
> +
> +static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream,
> +				  struct snd_pcm_hw_params *params,
> +				  struct snd_soc_dai *dai)
> +{
> +	struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
> +	struct snd_dmaengine_dai_dma_data *dma_data;
> +	u32 data_width, data_bits;
> +	unsigned long bclk_rate;
> +	u32 val;
> +	int ret;
> +
> +	val = readl(i2s->base + SSCR);
> +	if (val & SSCR_SSE)
> +		return 0;
> +
> +	dma_data = &i2s->playback_dma_data;
> +
> +	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
> +		dma_data = &i2s->capture_dma_data;
> +
> +	switch (params_format(params)) {
> +	case SNDRV_PCM_FORMAT_S8:
> +		data_bits = 8;
> +		data_width = SSCR_DW_8BYTE;
> +		dma_data->maxburst = 8;
> +		dma_data->addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> +		break;
> +	case SNDRV_PCM_FORMAT_S16_LE:
> +		data_bits = 16;
> +		data_width = SSCR_DW_16BYTE;
> +		dma_data->maxburst = 16;
> +		dma_data->addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
> +		if ((i2s->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) {
> +			data_width = SSCR_DW_32BYTE;
> +			dma_data->maxburst = 32;
> +			dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> +		}
> +		break;
> +	case SNDRV_PCM_FORMAT_S32_LE:
> +		data_bits = 32;
> +		data_width = SSCR_DW_32BYTE;
> +		dma_data->maxburst = 32;
> +		dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> +		break;
> +	default:
> +		dev_dbg(i2s->dev, "unexpected data width type");
> +		return -EINVAL;
> +	}
> +
> +	val = readl(i2s->base + SSCR);
> +	val &= ~SSCR_DW_32BYTE;
> +	val |= data_width;
> +	writel(val, i2s->base + SSCR);
> +
> +	bclk_rate = params_channels(params) *
> +		    params_rate(params) *
> +		    data_bits;
> +
> +	ret = clk_set_rate(i2s->bclk, bclk_rate);
> +	if (ret)
> +		return ret;
> +
> +	return clk_set_rate(i2s->sspa_clk, bclk_rate);
> +}
> +
> +static int spacemit_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
> +				   unsigned int freq, int dir)
> +{
> +	struct spacemit_i2s_dev *i2s = dev_get_drvdata(cpu_dai->dev);
> +
> +	if (freq == 0)
> +		return 0;
> +
> +	return clk_set_rate(i2s->sysclk, freq);
> +}
> +
> +static int spacemit_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
> +				unsigned int fmt)
> +{
> +	struct spacemit_i2s_dev *i2s = dev_get_drvdata(cpu_dai->dev);
> +	u32 sspsp_val;
> +
> +	sspsp_val = readl(i2s->base + SSPSP);
> +	sspsp_val &= ~SSPSP_FIELD_SFRMWDTH;
> +
> +	i2s->dai_fmt = fmt;
> +
> +	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
> +	case SND_SOC_DAIFMT_I2S:
> +		cpu_dai->driver->playback.formats = SNDRV_PCM_FMTBIT_S16_LE;
> +		cpu_dai->driver->capture.formats = SNDRV_PCM_FMTBIT_S16_LE;
> +		sspsp_val |= FIELD_PREP(SSPSP_FIELD_SFRMWDTH, 0x10) |
> +			     SSPSP_FSRT;
> +		break;
> +	case SND_SOC_DAIFMT_DSP_A:
> +	case SND_SOC_DAIFMT_DSP_B:
> +		cpu_dai->driver->playback.channels_min = 1;
> +		cpu_dai->driver->playback.channels_max = 1;
> +		cpu_dai->driver->capture.channels_min = 1;
> +		cpu_dai->driver->capture.channels_max = 1;
> +		cpu_dai->driver->playback.formats = SNDRV_PCM_FMTBIT_S32_LE;
> +		cpu_dai->driver->capture.formats = SNDRV_PCM_FMTBIT_S32_LE;
> +		sspsp_val |= FIELD_PREP(SSPSP_FIELD_SFRMWDTH, 0x1);
> +		break;
> +	default:
> +		dev_dbg(i2s->dev, "unexpected format type");
> +		return -EINVAL;
> +	}
> +
> +	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A)
> +		sspsp_val |= SSPSP_FSRT;
> +
> +	writel(sspsp_val, i2s->base + SSPSP);
> +
> +	return 0;
> +}
> +
> +static int spacemit_i2s_trigger(struct snd_pcm_substream *substream,
> +				int cmd, struct snd_soc_dai *dai)
> +{
> +	struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
> +	u32 val;
> +
> +	switch (cmd) {
> +	case SNDRV_PCM_TRIGGER_START:
> +	case SNDRV_PCM_TRIGGER_RESUME:
> +	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
> +		if (!i2s->started_count) {
> +			val = readl(i2s->base + SSCR);
> +			val |= SSCR_SSE;
> +			writel(val, i2s->base + SSCR);
> +		}
> +		i2s->started_count++;
> +		break;
> +	case SNDRV_PCM_TRIGGER_STOP:
> +	case SNDRV_PCM_TRIGGER_SUSPEND:
> +	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
> +		if (i2s->started_count)
> +			i2s->started_count--;
> +
> +		if (!i2s->started_count) {
> +			val = readl(i2s->base + SSCR);
> +			val &= ~SSCR_SSE;
> +			writel(val, i2s->base + SSCR);
> +		}
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int spacemit_i2s_dai_probe(struct snd_soc_dai *dai)
> +{
> +	struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
> +
> +	snd_soc_dai_init_dma_data(dai,
> +				  i2s->has_playback ? &i2s->playback_dma_data : NULL,
> +				  i2s->has_capture ? &i2s->capture_dma_data : NULL);
> +
> +	reset_control_deassert(i2s->reset);
> +
> +	spacemit_i2s_init(i2s);
> +
> +	return 0;
> +}
> +
> +static const struct snd_soc_dai_ops spacemit_i2s_dai_ops = {
> +	.probe = spacemit_i2s_dai_probe,
> +	.hw_params = spacemit_i2s_hw_params,
> +	.set_sysclk = spacemit_i2s_set_sysclk,
> +	.set_fmt = spacemit_i2s_set_fmt,
> +	.trigger = spacemit_i2s_trigger,
> +};
> +
> +static struct snd_soc_dai_driver spacemit_i2s_dai = {
> +	.ops = &spacemit_i2s_dai_ops,
> +	.playback = {
> +		.channels_min = 1,
> +		.channels_max = 2,
> +		.rates = SPACEMIT_PCM_RATES,
> +		.rate_min = SNDRV_PCM_RATE_8000,
> +		.rate_max = SNDRV_PCM_RATE_192000,
> +		.formats = SPACEMIT_PCM_FORMATS,
> +	},
> +	.capture = {
> +		.channels_min = 1,
> +		.channels_max = 2,
> +		.rates = SPACEMIT_PCM_RATES,
> +		.rate_min = SNDRV_PCM_RATE_8000,
> +		.rate_max = SNDRV_PCM_RATE_192000,
> +		.formats = SPACEMIT_PCM_FORMATS,
> +	},
> +	.symmetric_rate = 1,
> +};
> +
> +static int spacemit_i2s_init_dai(struct spacemit_i2s_dev *i2s,
> +				 struct snd_soc_dai_driver **dp,
> +				 dma_addr_t addr)
> +{
> +	struct device_node *node = i2s->dev->of_node;
> +	struct snd_soc_dai_driver *dai;
> +	struct property *dma_names;
> +	const char *dma_name;
> +
> +	of_property_for_each_string(node, "dma-names", dma_names, dma_name) {
> +		if (!strcmp(dma_name, "tx"))
> +			i2s->has_playback = true;
> +		if (!strcmp(dma_name, "rx"))
> +			i2s->has_capture = true;
> +	}
> +
> +	dai = devm_kmemdup(i2s->dev, &spacemit_i2s_dai,
> +			   sizeof(*dai), GFP_KERNEL);
> +	if (!dai)
> +		return -ENOMEM;
> +
> +	if (i2s->has_playback) {
> +		dai->playback.stream_name = "Playback";
> +		dai->playback.channels_min = 1;
> +		dai->playback.channels_max = 2;
> +		dai->playback.rates = SPACEMIT_PCM_RATES;
> +		dai->playback.formats = SPACEMIT_PCM_FORMATS;
> +
> +		i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
> +		i2s->playback_dma_data.maxburst = 32;
> +		i2s->playback_dma_data.addr = addr;
> +	}
> +
> +	if (i2s->has_capture) {
> +		dai->capture.stream_name = "Capture";
> +		dai->capture.channels_min = 1;
> +		dai->capture.channels_max = 2;
> +		dai->capture.rates = SPACEMIT_PCM_RATES;
> +		dai->capture.formats = SPACEMIT_PCM_FORMATS;
> +
> +		i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
> +		i2s->capture_dma_data.maxburst = 32;
> +		i2s->capture_dma_data.addr = addr;
> +	}
> +
> +	if (dp)
> +		*dp = dai;
> +
> +	return 0;
> +}
> +
> +static const struct snd_soc_component_driver spacemit_i2s_component = {
> +	.name = "i2s-k1",
> +	.legacy_dai_naming = 1,
> +};
> +
> +static int spacemit_i2s_probe(struct platform_device *pdev)
> +{
> +	struct snd_soc_dai_driver *dai;
> +	struct spacemit_i2s_dev *i2s;
> +	struct resource *res;
> +	struct clk *clk;
> +	int ret;
> +
> +	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
> +	if (!i2s)
> +		return -ENOMEM;
> +
> +	i2s->dev = &pdev->dev;
> +
> +	i2s->sysclk = devm_clk_get_enabled(i2s->dev, "sysclk");
> +	if (IS_ERR(i2s->sysclk))
> +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->sysclk),
> +				     "failed to enable sysbase clock\n");
> +
> +	i2s->bclk = devm_clk_get_enabled(i2s->dev, "bclk");
> +	if (IS_ERR(i2s->bclk))
> +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->bclk), "failed to enable bit clock\n");
> +
> +	clk = devm_clk_get_enabled(i2s->dev, "sspa_bus");
> +	if (IS_ERR(clk))
> +		return dev_err_probe(i2s->dev, PTR_ERR(clk), "failed to enable sspa_bus clock\n");
> +
> +	i2s->sspa_clk = devm_clk_get_enabled(i2s->dev, "sspa");
> +	if (IS_ERR(clk))
> +		return dev_err_probe(i2s->dev, PTR_ERR(clk), "failed to enable sspa clock\n");
> +
> +	i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
> +	if (IS_ERR(i2s->base))
> +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->base), "failed to map registers\n");
> +
> +	i2s->reset =  devm_reset_control_get(&pdev->dev, NULL);
> +	if (IS_ERR(i2s->reset))
> +		return dev_err_probe(i2s->dev, PTR_ERR(i2s->reset),
> +				     "failed to get reset control");
> +
> +	dev_set_drvdata(i2s->dev, i2s);
> +
> +	spacemit_i2s_init_dai(i2s, &dai, res->start + SSDATR);
> +
> +	ret = devm_snd_soc_register_component(i2s->dev,
> +					      &spacemit_i2s_component,
> +					      dai, 1);
> +	if (ret)
> +		return dev_err_probe(i2s->dev, ret, "failed to register component");
> +
> +	return devm_snd_dmaengine_pcm_register(&pdev->dev, &spacemit_dmaengine_pcm_config, 0);
> +}
> +
> +static void spacemit_i2s_remove(struct platform_device *pdev)
> +{
> +	struct spacemit_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);
> +
> +	reset_control_assert(i2s->reset);
> +}
> +
> +static const struct of_device_id spacemit_i2s_of_match[] = {
> +	{ .compatible = "spacemit,k1-i2s", },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, spacemit_i2s_of_match);
> +
> +static struct platform_driver spacemit_i2s_driver = {
> +	.probe = spacemit_i2s_probe,
> +	.remove = spacemit_i2s_remove,
> +	.driver = {
> +		.name = "i2s-k1",
> +		.of_match_table = spacemit_i2s_of_match,
> +	},
> +};
> +module_platform_driver(spacemit_i2s_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("I2S bus driver for SpacemiT K1 SoC");
> 
> -- 
> 2.50.1
> 

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

* Re: [PATCH 1/2] dt-bindings: i2s: spacemit: add support for K1 SoC
  2025-08-14  8:54 ` [PATCH 1/2] dt-bindings: i2s: spacemit: add support for " Troy Mitchell
@ 2025-08-16  9:13   ` Troy Mitchell
  2025-08-20  8:03   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 8+ messages in thread
From: Troy Mitchell @ 2025-08-16  9:13 UTC (permalink / raw)
  To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Yixun Lan, Jaroslav Kysela, Takashi Iwai,
	Philipp Zabel
  Cc: linux-sound, devicetree, linux-riscv, spacemit, linux-kernel,
	Troy Mitchell

On Thu, Aug 14, 2025 at 04:54:19PM +0800, Troy Mitchell wrote:
> Add dt-binding for the i2s driver of SpacemiT's K1 SoC.
> 
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  .../devicetree/bindings/sound/spacemit,k1-i2s.yaml | 88 ++++++++++++++++++++++
>  1 file changed, 88 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml b/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..7d9110638d71792db6e5bb72559f6abaf4cb59bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml
> @@ -0,0 +1,88 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/spacemit,k1-i2s.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: K1 I2S controller
> +
> +description:
> +  The I2S bus (Inter-IC sound bus) is a serial link for digital
> +  audio data transfer between devices in the system.
> +
> +maintainers:
> +  - Troy Mitchell <troy.mitchell@linux.spacemit.com>
> +
> +allOf:
> +  - $ref: dai-common.yaml#
> +
> +properties:
> +  compatible:
> +    const: spacemit,k1-i2s
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    items:
> +      - description: clock for I2S sysclk
> +      - description: clock for I2S bclk
> +      - description: clock for I2S bus
> +      - description: clock for I2S controller
> +
> +  clock-names:
> +    items:
> +      - const: sysclk
> +      - const: bclk
> +      - const: bus
> +      - const: func
> +
> +  dmas:
> +    minItems: 1
> +    maxItems: 2
> +
> +  dma-names:
> +    oneOf:
> +      - const: rx
> +      - items:
> +          - const: tx
> +          - const: rx
> +
> +  resets:
> +    maxItems: 1
> +
> +  port:
> +    $ref: audio-graph-port.yaml#
> +    unevaluatedProperties: false
> +
> +  "#sound-dai-cells":
> +    const: 0
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +  - dmas
> +  - dma-names
> +  - resets
> +  - "#sound-dai-cells"
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/spacemit,k1-syscon.h>
> +    i2s@d4026000 {
> +      compatible = "spacemit,k1-i2s";
> +      reg = <0xd4026000 0x30>;
> +      clocks = <&syscon_mpmu CLK_I2S_SYSCLK>,
> +               <&syscon_mpmu CLK_I2S_BCLK>,
> +               <&syscon_apbc CLK_SSPA0_BUS>,
> +               <&syscon_apbc CLK_SSPA0>;
> +      clock-names = "sysclk", "bclk", "bus", "func";
> +      dmas = <&pdma0 21 1>, <&pdma0 22 1>;
I'll keep to 1 cell in the next version.

> +      dma-names = "tx", "rx";
> +      resets = <&syscon_apbc RESET_SSPA0>;
> +      #sound-dai-cells = <0>;
> +    };
> 
> -- 
> 2.50.1
> 

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

* Re: [PATCH 1/2] dt-bindings: i2s: spacemit: add support for K1 SoC
  2025-08-14  8:54 ` [PATCH 1/2] dt-bindings: i2s: spacemit: add support for " Troy Mitchell
  2025-08-16  9:13   ` Troy Mitchell
@ 2025-08-20  8:03   ` Krzysztof Kozlowski
  1 sibling, 0 replies; 8+ messages in thread
From: Krzysztof Kozlowski @ 2025-08-20  8:03 UTC (permalink / raw)
  To: Troy Mitchell
  Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Yixun Lan, Jaroslav Kysela, Takashi Iwai,
	Philipp Zabel, linux-sound, devicetree, linux-riscv, spacemit,
	linux-kernel

On Thu, Aug 14, 2025 at 04:54:19PM +0800, Troy Mitchell wrote:
> Add dt-binding for the i2s driver of SpacemiT's K1 SoC.
> 
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  .../devicetree/bindings/sound/spacemit,k1-i2s.yaml | 88 ++++++++++++++++++++++
>  1 file changed, 88 insertions(+)

Please run scripts/checkpatch.pl on the patches and fix reported
warnings. After that, run also 'scripts/checkpatch.pl --strict' on the
patches and (probably) fix more warnings. Some warnings can be ignored,
especially from --strict run, but the code here looks like it needs a
fix. Feel free to get in touch if the warning is not clear.

Please use subject prefixes matching the subsystem. You can get them for
example with 'git log --oneline -- DIRECTORY_OR_FILE' on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters


Best regards,
Krzysztof


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

end of thread, other threads:[~2025-08-20  8:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-14  8:54 [PATCH 0/2] ASoC: spacemit: add i2s support to K1 SoC Troy Mitchell
2025-08-14  8:54 ` [PATCH 1/2] dt-bindings: i2s: spacemit: add support for " Troy Mitchell
2025-08-16  9:13   ` Troy Mitchell
2025-08-20  8:03   ` Krzysztof Kozlowski
2025-08-14  8:54 ` [PATCH 2/2] ASoC: spacemit: i2s: " Troy Mitchell
2025-08-14 10:36   ` Philipp Zabel
2025-08-14 12:55     ` Troy Mitchell
2025-08-15  5:59   ` Troy Mitchell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).