Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07539c1d authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

ASoC: add Renesas R-Car SCU feature



Renesas R-Car series sound circuit consists of SSI and its peripheral.
But this peripheral circuit is different between
R-Car Generation1 (E1/M1/H1) and Generation2 (E2/M2/H2)
(Actually, there are many difference in Generation1 chips)

This patch adds SCU feature on this driver.
But, it defines SCU style only, does nothing at this point.

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 3337744a
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -14,8 +14,15 @@

#include <linux/sh_clk.h>

#define RSND_GEN1_SRU	0

#define RSND_BASE_MAX	0
#define RSND_GEN2_SRU	0

#define RSND_BASE_MAX	1

struct rsnd_scu_platform_info {
	u32 flags;
};

struct rsnd_dai_platform_info {
	int ssi_id_playback;
@@ -34,6 +41,8 @@ struct rsnd_dai_platform_info {

struct rcar_snd_info {
	u32 flags;
	struct rsnd_scu_platform_info *scu_info;
	int scu_info_nr;
	struct rsnd_dai_platform_info *dai_info;
	int dai_info_nr;
	int (*start)(int id);
+2 −2
Original line number Diff line number Diff line
snd-soc-rcar-objs	:= core.o gen.o
snd-soc-rcar-objs	:= core.o gen.o scu.o
obj-$(CONFIG_SND_SOC_RCAR)	+= snd-soc-rcar.o
 No newline at end of file
+5 −0
Original line number Diff line number Diff line
@@ -631,6 +631,10 @@ static int rsnd_probe(struct platform_device *pdev)
	if (ret < 0)
		return ret;

	ret = rsnd_scu_probe(pdev, info, priv);
	if (ret < 0)
		return ret;

	/*
	 *	asoc register
	 */
@@ -669,6 +673,7 @@ static int rsnd_remove(struct platform_device *pdev)
	/*
	 *	remove each module
	 */
	rsnd_scu_remove(pdev, priv);
	rsnd_dai_remove(pdev, priv);
	rsnd_gen_remove(pdev, priv);

+95 −0
Original line number Diff line number Diff line
@@ -45,10 +45,105 @@ struct rsnd_gen {
/*
 *		Gen1
 */
static int rsnd_gen1_path_init(struct rsnd_priv *priv,
			       struct rsnd_dai *rdai,
			       struct rsnd_dai_stream *io)
{
	struct rsnd_dai_platform_info *info = rsnd_dai_get_platform_info(rdai);
	struct rsnd_mod *mod;
	int ret;
	int id;

	/*
	 * Gen1 is created by SRU/SSI, and this SRU is base module of
	 * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU)
	 *
	 * Easy image is..
	 *	Gen1 SRU = Gen2 SCU + SSIU + etc
	 *
	 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
	 * using fixed path.
	 *
	 * Then, SSI id = SCU id here
	 */

	if (rsnd_dai_is_play(rdai, io))
		id = info->ssi_id_playback;
	else
		id = info->ssi_id_capture;

	/* SCU */
	mod = rsnd_scu_mod_get(priv, id);
	ret = rsnd_dai_connect(rdai, mod, io);

	return ret;
}

static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
			       struct rsnd_dai *rdai,
			       struct rsnd_dai_stream *io)
{
	struct rsnd_mod *mod, *n;
	int ret = 0;

	/*
	 * remove all mod from rdai
	 */
	for_each_rsnd_mod(mod, n, io)
		ret |= rsnd_dai_disconnect(mod);

	return ret;
}

static struct rsnd_gen_ops rsnd_gen1_ops = {
	.path_init	= rsnd_gen1_path_init,
	.path_exit	= rsnd_gen1_path_exit,
};

#define RSND_GEN1_REG_MAP(g, s, i, oi, oa)				\
	do {								\
		(g)->reg_map[RSND_REG_##i].index  = RSND_GEN1_##s;	\
		(g)->reg_map[RSND_REG_##i].offset_id = oi;		\
		(g)->reg_map[RSND_REG_##i].offset_adr = oa;		\
	} while (0)

static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen)
{
	RSND_GEN1_REG_MAP(gen, SRU,	SSI_MODE0,	0x0,	0xD0);
	RSND_GEN1_REG_MAP(gen, SRU,	SSI_MODE1,	0x0,	0xD4);
}

static int rsnd_gen1_probe(struct platform_device *pdev,
			   struct rcar_snd_info *info,
			   struct rsnd_priv *priv)
{
	struct device *dev = rsnd_priv_to_dev(priv);
	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
	struct resource *sru_res;

	/*
	 * map address
	 */
	sru_res	= platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU);
	if (!sru_res) {
		dev_err(dev, "Not enough SRU/SSI/ADG platform resources.\n");
		return -ENODEV;
	}

	gen->ops = &rsnd_gen1_ops;

	gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res);
	if (!gen->base[RSND_GEN1_SRU]) {
		dev_err(dev, "SRU/SSI/ADG ioremap failed\n");
		return -ENODEV;
	}

	rsnd_gen1_reg_map_init(gen);

	dev_dbg(dev, "Gen1 device probed\n");
	dev_dbg(dev, "SRU : %08x => %p\n",	sru_res->start,
						gen->base[RSND_GEN1_SRU]);

	return 0;
}

+21 −0
Original line number Diff line number Diff line
@@ -28,6 +28,10 @@
 * see gen1/gen2 for detail
 */
enum rsnd_reg {
	/* SRU/SCU */
	RSND_REG_SSI_MODE0,
	RSND_REG_SSI_MODE1,

	RSND_REG_MAX,
};

@@ -172,6 +176,12 @@ struct rsnd_priv {
	 */
	void *gen;

	/*
	 * below value will be filled on rsnd_scu_probe()
	 */
	void *scu;
	int scu_nr;

	/*
	 * below value will be filled on rsnd_dai_probe()
	 */
@@ -184,4 +194,15 @@ struct rsnd_priv {
#define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
#define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)

/*
 *	R-Car SCU
 */
int rsnd_scu_probe(struct platform_device *pdev,
		   struct rcar_snd_info *info,
		   struct rsnd_priv *priv);
void rsnd_scu_remove(struct platform_device *pdev,
		     struct rsnd_priv *priv);
struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
#define rsnd_scu_nr(priv) ((priv)->scu_nr)

#endif
Loading