Unverified Commit c2bc6527 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

ASoC: rsnd: add R-Car Gen4 Sound support



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

Signed-off-by: default avatarLinh Phung <linh.phung.jy@renesas.com>
Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87o7qe5ej5.wl-kuninori.morimoto.gx@renesas.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent f76fec60
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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.
+3 −2
Original line number Diff line number Diff line
@@ -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);
+37 −1
Original line number Diff line number Diff line
@@ -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 */
+70 −0
Original line number Diff line number Diff line
@@ -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");
+8 −0
Original line number Diff line number Diff line
@@ -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))
Loading