diff mbox series

[15/15] ASoC: rsnd: add R-Car Gen4 Sound support

Message ID 87o7qe5ej5.wl-kuninori.morimoto.gx@renesas.com
State Accepted
Commit c2bc65274a307e11743d0f56a762f8e57f279b9e
Headers show
Series ASoC: rsnd: cleanup add R-Car Gen4 Sound support | expand

Commit Message

Kuninori Morimoto Feb. 1, 2023, 2:02 a.m. UTC
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

This patch is tested on V4H White Hawk + ARD-AUDIO-DA7212

Signed-off-by: Linh Phung <linh.phung.jy@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/sh/rcar/adg.c  | 10 ++++++
 sound/soc/sh/rcar/core.c |  5 +--
 sound/soc/sh/rcar/dma.c  | 38 +++++++++++++++++++++-
 sound/soc/sh/rcar/gen.c  | 70 ++++++++++++++++++++++++++++++++++++++++
 sound/soc/sh/rcar/rsnd.h |  8 +++++
 sound/soc/sh/rcar/ssiu.c | 15 +++++++--
 6 files changed, 140 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 00df32be4a4a..7bc4421835d7 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -57,6 +57,10 @@  struct rsnd_adg {
 	     i++)
 #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
 
+static const char * const clkin_name_gen4[] = {
+	[CLKA]	= "clkin",
+};
+
 static const char * const clkin_name_gen2[] = {
 	[CLKA]	= "clk_a",
 	[CLKB]	= "clk_b",
@@ -435,6 +439,10 @@  static int rsnd_adg_get_clkin(struct rsnd_priv *priv)
 
 	clkin_name = clkin_name_gen2;
 	clkin_size = ARRAY_SIZE(clkin_name_gen2);
+	if (rsnd_is_gen4(priv)) {
+		clkin_name = clkin_name_gen4;
+		clkin_size = ARRAY_SIZE(clkin_name_gen4);
+	}
 
 	for (i = 0; i < clkin_size; i++) {
 		clk = devm_clk_get(dev, clkin_name[i]);
@@ -568,6 +576,8 @@  static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
 
 	clkout_name = clkout_name_gen2;
 	clkout_size = ARRAY_SIZE(clkout_name_gen2);
+	if (rsnd_is_gen4(priv))
+		clkout_size = 1; /* reuse clkout_name_gen2[] */
 
 	/*
 	 * ADG supports BRRA/BRRB output only.
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 3de81af41ffc..a9125c1ff75a 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -102,6 +102,7 @@  static const struct of_device_id rsnd_of_match[] = {
 	{ .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 },
 	{ .compatible = "renesas,rcar_sound-gen2", .data = (void *)RSND_GEN2 },
 	{ .compatible = "renesas,rcar_sound-gen3", .data = (void *)RSND_GEN3 },
+	{ .compatible = "renesas,rcar_sound-gen4", .data = (void *)RSND_GEN4 },
 	/* Special Handling */
 	{ .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) },
 	{},
@@ -1467,7 +1468,7 @@  static int rsnd_dai_probe(struct rsnd_priv *priv)
 	if (is_graph) {
 		for_each_endpoint_of_node(dai_node, dai_np) {
 			__rsnd_dai_probe(priv, dai_np, dai_i);
-			if (rsnd_is_gen3(priv)) {
+			if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
 				rdai = rsnd_rdai_get(priv, dai_i);
 
 				rsnd_parse_connect_graph(priv, &rdai->playback, dai_np);
@@ -1478,7 +1479,7 @@  static int rsnd_dai_probe(struct rsnd_priv *priv)
 	} else {
 		for_each_child_of_node(dai_node, dai_np) {
 			__rsnd_dai_probe(priv, dai_np, dai_i);
-			if (rsnd_is_gen3(priv)) {
+			if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
 				rdai = rsnd_rdai_get(priv, dai_i);
 
 				rsnd_parse_connect_simple(priv, &rdai->playback, dai_np);
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 9aca5ff791a3..1c494e521463 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -653,6 +653,36 @@  rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
 		dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr;
 }
 
+/*
+ *	Gen4 DMA read/write register offset
+ *
+ *	ex) R-Car V4H case
+ *		  mod		/ SYS-DMAC in	/ SYS-DMAC out
+ *	SSI_SDMC: 0xec400000	/ 0xec400000	/ 0xec400000
+ */
+#define RDMA_SSI_SDMC(addr, i)	(addr + (0x8000 * i))
+static dma_addr_t
+rsnd_gen4_dma_addr(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
+		   int is_play, int is_from)
+{
+	struct rsnd_priv *priv = rsnd_io_to_priv(io);
+	phys_addr_t addr = rsnd_gen_get_phy_addr(priv, RSND_GEN4_SDMC);
+	int id = rsnd_mod_id(mod);
+	int busif = rsnd_mod_id_sub(mod);
+
+	/*
+	 * SSI0 only is supported
+	 */
+	if (id != 0) {
+		struct device *dev = rsnd_priv_to_dev(priv);
+
+		dev_err(dev, "This driver doesn't support non SSI0");
+		return -EINVAL;
+	}
+
+	return RDMA_SSI_SDMC(addr, busif);
+}
+
 static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
 				struct rsnd_mod *mod,
 				int is_play, int is_from)
@@ -667,6 +697,8 @@  static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
 	 */
 	if (rsnd_is_gen1(priv))
 		return 0;
+	else if (rsnd_is_gen4(priv))
+		return rsnd_gen4_dma_addr(io, mod, is_play, is_from);
 	else
 		return rsnd_gen2_dma_addr(io, mod, is_play, is_from);
 }
@@ -891,6 +923,10 @@  int rsnd_dma_probe(struct rsnd_priv *priv)
 		return 0; /* it will be PIO mode */
 	}
 
+	/* for Gen4 doesn't have DMA-pp */
+	if (rsnd_is_gen4(priv))
+		goto audmapp_end;
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audmapp");
 	if (!res) {
 		dev_err(dev, "lack of audmapp in DT\n");
@@ -902,7 +938,7 @@  int rsnd_dma_probe(struct rsnd_priv *priv)
 	dmac->ppbase = devm_ioremap_resource(dev, res);
 	if (IS_ERR(dmac->ppbase))
 		return PTR_ERR(dmac->ppbase);
-
+audmapp_end:
 	priv->dma = dmac;
 
 	/* dummy mem mod for debug */
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index 925565baaa41..86bdecc24956 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -215,6 +215,74 @@  static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
 	return 0;
 }
 
+/*
+ *		Gen4
+ */
+static int rsnd_gen4_probe(struct rsnd_priv *priv)
+{
+	static const struct rsnd_regmap_field_conf conf_ssiu[] = {
+		RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0,	0x850),
+		RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2,	0x858),
+		RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4,	0x890),
+		RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6,	0x898),
+		RSND_GEN_S_REG(SSI_SYS_STATUS0,		0x840),
+		RSND_GEN_S_REG(SSI_SYS_STATUS2,		0x848),
+		RSND_GEN_S_REG(SSI_SYS_STATUS4,		0x880),
+		RSND_GEN_S_REG(SSI_SYS_STATUS6,		0x888),
+
+		RSND_GEN_S_REG(SSI_BUSIF0_MODE,		0x0),
+		RSND_GEN_S_REG(SSI_BUSIF0_ADINR,	0x4),
+		RSND_GEN_S_REG(SSI_BUSIF0_DALIGN,	0x8),
+		RSND_GEN_S_REG(SSI_BUSIF1_MODE,		0x20),
+		RSND_GEN_S_REG(SSI_BUSIF1_ADINR,	0x24),
+		RSND_GEN_S_REG(SSI_BUSIF1_DALIGN,	0x28),
+		RSND_GEN_S_REG(SSI_BUSIF2_MODE,		0x40),
+		RSND_GEN_S_REG(SSI_BUSIF2_ADINR,	0x44),
+		RSND_GEN_S_REG(SSI_BUSIF2_DALIGN,	0x48),
+		RSND_GEN_S_REG(SSI_BUSIF3_MODE,		0x60),
+		RSND_GEN_S_REG(SSI_BUSIF3_ADINR,	0x64),
+		RSND_GEN_S_REG(SSI_BUSIF3_DALIGN,	0x68),
+		RSND_GEN_S_REG(SSI_BUSIF4_MODE,		0x500),
+		RSND_GEN_S_REG(SSI_BUSIF4_ADINR,	0x504),
+		RSND_GEN_S_REG(SSI_BUSIF4_DALIGN,	0x508),
+		RSND_GEN_S_REG(SSI_BUSIF5_MODE,		0x520),
+		RSND_GEN_S_REG(SSI_BUSIF5_ADINR,	0x524),
+		RSND_GEN_S_REG(SSI_BUSIF5_DALIGN,	0x528),
+		RSND_GEN_S_REG(SSI_BUSIF6_MODE,		0x540),
+		RSND_GEN_S_REG(SSI_BUSIF6_ADINR,	0x544),
+		RSND_GEN_S_REG(SSI_BUSIF6_DALIGN,	0x548),
+		RSND_GEN_S_REG(SSI_BUSIF7_MODE,		0x560),
+		RSND_GEN_S_REG(SSI_BUSIF7_ADINR,	0x564),
+		RSND_GEN_S_REG(SSI_BUSIF7_DALIGN,	0x568),
+		RSND_GEN_S_REG(SSI_CTRL,		0x010),
+		RSND_GEN_S_REG(SSI_INT_ENABLE,		0x018),
+		RSND_GEN_S_REG(SSI_MODE,		0x00c),
+		RSND_GEN_S_REG(SSI_MODE2,		0xa0c),
+	};
+	static const struct rsnd_regmap_field_conf conf_adg[] = {
+		RSND_GEN_S_REG(BRRA,			0x00),
+		RSND_GEN_S_REG(BRRB,			0x04),
+		RSND_GEN_S_REG(BRGCKR,			0x08),
+		RSND_GEN_S_REG(AUDIO_CLK_SEL0,		0x0c),
+	};
+	static const struct rsnd_regmap_field_conf conf_ssi[] = {
+		RSND_GEN_S_REG(SSICR,			0x00),
+		RSND_GEN_S_REG(SSISR,			0x04),
+		RSND_GEN_S_REG(SSITDR,			0x08),
+		RSND_GEN_S_REG(SSIRDR,			0x0c),
+		RSND_GEN_S_REG(SSIWSR,			0x20),
+	};
+	static const struct rsnd_regmap_field_conf conf_sdmc[] = {
+		RSND_GEN_M_REG(SSI_BUSIF,		0x0, 0x8000),
+	};
+	int ret_adg  = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_ADG,  "adg",  conf_adg);
+	int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSIU, "ssiu", conf_ssiu);
+	int ret_ssi  = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSI,  "ssi",  conf_ssi);
+	int ret_sdmc = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SDMC, "sdmc", conf_sdmc);
+
+	return ret_adg | ret_ssiu | ret_ssi | ret_sdmc;
+}
+
 /*
  *		Gen2
  */
@@ -484,6 +552,8 @@  int rsnd_gen_probe(struct rsnd_priv *priv)
 	else if (rsnd_is_gen2(priv) ||
 		 rsnd_is_gen3(priv))
 		ret = rsnd_gen2_probe(priv);
+	else if (rsnd_is_gen4(priv))
+		ret = rsnd_gen4_probe(priv);
 
 	if (ret < 0)
 		dev_err(dev, "unknown generation R-Car sound device\n");
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 3e1184f56ffd..239705d52517 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -31,6 +31,11 @@ 
 #define RSND_GEN2_SSIU	2
 #define RSND_GEN2_SSI	3
 
+#define RSND_GEN4_ADG	0
+#define RSND_GEN4_SSIU	1
+#define RSND_GEN4_SSI	2
+#define RSND_GEN4_SDMC	3
+
 #define RSND_BASE_MAX	4
 
 /*
@@ -197,6 +202,7 @@  enum rsnd_reg {
 	SSI_SYS_INT_ENABLE5,
 	SSI_SYS_INT_ENABLE6,
 	SSI_SYS_INT_ENABLE7,
+	SSI_BUSIF,
 	HDMI0_SEL,
 	HDMI1_SEL,
 	SSI9_BUSIF0_MODE,
@@ -629,6 +635,7 @@  struct rsnd_priv {
 #define RSND_GEN1	(1 << 0)
 #define RSND_GEN2	(2 << 0)
 #define RSND_GEN3	(3 << 0)
+#define RSND_GEN4	(4 << 0)
 #define RSND_SOC_MASK	(0xFF << 4)
 #define RSND_SOC_E	(1 << 4) /* E1/E2/E3 */
 
@@ -703,6 +710,7 @@  struct rsnd_priv {
 #define rsnd_is_gen1(priv)	(((priv)->flags & RSND_GEN_MASK) == RSND_GEN1)
 #define rsnd_is_gen2(priv)	(((priv)->flags & RSND_GEN_MASK) == RSND_GEN2)
 #define rsnd_is_gen3(priv)	(((priv)->flags & RSND_GEN_MASK) == RSND_GEN3)
+#define rsnd_is_gen4(priv)	(((priv)->flags & RSND_GEN_MASK) == RSND_GEN4)
 #define rsnd_is_e3(priv)	(((priv)->flags & \
 					(RSND_GEN_MASK | RSND_SOC_MASK)) == \
 					(RSND_GEN3 | RSND_SOC_E))
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c
index 281bc20d4c5d..17bd8cc86dd0 100644
--- a/sound/soc/sh/rcar/ssiu.c
+++ b/sound/soc/sh/rcar/ssiu.c
@@ -29,8 +29,8 @@  struct rsnd_ssiu {
 	     i++)
 
 /*
- *	SSI	Gen2		Gen3
- *	0	BUSIF0-3	BUSIF0-7
+ *	SSI	Gen2		Gen3		Gen4
+ *	0	BUSIF0-3	BUSIF0-7	BUSIF0-7
  *	1	BUSIF0-3	BUSIF0-7
  *	2	BUSIF0-3	BUSIF0-7
  *	3	BUSIF0		BUSIF0-7
@@ -40,10 +40,11 @@  struct rsnd_ssiu {
  *	7	BUSIF0		BUSIF0
  *	8	BUSIF0		BUSIF0
  *	9	BUSIF0-3	BUSIF0-7
- *	total	22		52
+ *	total	22		52		8
  */
 static const int gen2_id[] = { 0, 4,  8, 12, 13, 14, 15, 16, 17, 18 };
 static const int gen3_id[] = { 0, 8, 16, 24, 32, 40, 41, 42, 43, 44 };
+static const int gen4_id[] = { 0 };
 
 /* enable busif buffer over/under run interrupt. */
 #define rsnd_ssiu_busif_err_irq_enable(mod)  rsnd_ssiu_busif_err_irq_ctrl(mod, 1)
@@ -152,6 +153,10 @@  static int rsnd_ssiu_init(struct rsnd_mod *mod,
 	/* clear status */
 	rsnd_ssiu_busif_err_status_clear(mod);
 
+	/* Gen4 doesn't have SSI_MODE */
+	if (rsnd_is_gen4(priv))
+		goto ssi_mode_setting_end;
+
 	/*
 	 * SSI_MODE0
 	 */
@@ -206,6 +211,7 @@  static int rsnd_ssiu_init(struct rsnd_mod *mod,
 	rsnd_mod_bset(mod, SSI_MODE1, 0x0013001f, val1);
 	rsnd_mod_bset(mod, SSI_MODE2, 0x00000017, val2);
 
+ssi_mode_setting_end:
 	/*
 	 * Enable busif buffer over/under run interrupt.
 	 * It will be handled from ssi.c
@@ -553,6 +559,9 @@  int rsnd_ssiu_probe(struct rsnd_priv *priv)
 		} else if (rsnd_is_gen3(priv)) {
 			list	= gen3_id;
 			nr	= ARRAY_SIZE(gen3_id);
+		} else if (rsnd_is_gen4(priv)) {
+			list	= gen4_id;
+			nr	= ARRAY_SIZE(gen4_id);
 		} else {
 			dev_err(dev, "unknown SSIU\n");
 			return -ENODEV;