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

Commit 1b7b08ef authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

ASoC: rsnd: extracts Gen1/Gen2 common parts



Renesas sound IP Gen1/Gen2 are similar, but different.
This patch extracts Gen1/Gen2 common and dependency parts,
and create Gen1/Gen2 ops to control it.

According to this structure, SSIU setup which
has been implemented on ssi.c can be moved to scu.c
(SRU/SSIU/SCU should be implemented on scu.c)

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 32f27ebf
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ enum rsnd_reg {
	RSND_REG_SRC_IFSCR,
	RSND_REG_SRC_IFSVR,
	RSND_REG_SRC_SRCCR,
	RSND_REG_SRC_MNFSR,
	RSND_REG_SRC_MNFSR,		/* for Gen1 */

	/* ADG */
	RSND_REG_BRRA,
+204 −132
Original line number Diff line number Diff line
@@ -110,6 +110,9 @@ struct rsnd_scu {
 *
 */

/*
 *		Gen1/Gen2 common functions
 */
static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod,
				  struct rsnd_dai *rdai,
				  struct rsnd_dai_stream *io)
@@ -151,9 +154,143 @@ static int rsnd_scu_ssi_mode_init(struct rsnd_mod *mod,
	return 0;
}

/* Gen1 only */
static int rsnd_src_set_route_if_gen1(
			      struct rsnd_mod *mod,
unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv,
				   struct rsnd_mod *ssi_mod,
				   struct snd_pcm_runtime *runtime)
{
	struct rsnd_scu *scu;
	unsigned int rate;

	/* this function is assuming SSI id = SCU id here */
	scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod)));

	/*
	 * return convert rate if SRC is used,
	 * otherwise, return runtime->rate as usual
	 */
	rate = rsnd_scu_convert_rate(scu);
	if (!rate)
		rate = runtime->rate;

	return rate;
}

static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod,
				     struct rsnd_dai *rdai,
				     struct rsnd_dai_stream *io)
{
	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
	u32 convert_rate = rsnd_scu_convert_rate(scu);
	u32 adinr = runtime->channels;
	u32 fsrate = 0;

	if (convert_rate)
		fsrate = 0x0400000 / convert_rate * runtime->rate;

	/* set/clear soft reset */
	rsnd_mod_write(mod, SRC_SWRSR, 0);
	rsnd_mod_write(mod, SRC_SWRSR, 1);

	/*
	 * Initialize the operation of the SRC internal circuits
	 * see rsnd_scu_start()
	 */
	rsnd_mod_write(mod, SRC_SRCIR, 1);

	/* Set channel number and output bit length */
	switch (runtime->sample_bits) {
	case 16:
		adinr |= OTBL_16;
		break;
	case 32:
		adinr |= OTBL_24;
		break;
	default:
		return -EIO;
	}
	rsnd_mod_write(mod, SRC_ADINR, adinr);

	/* Enable the initial value of IFS */
	if (fsrate) {
		rsnd_mod_write(mod, SRC_IFSCR, 1);

		/* Set initial value of IFS */
		rsnd_mod_write(mod, SRC_IFSVR, fsrate);
	}

	/* use DMA transfer */
	rsnd_mod_write(mod, SRC_BUSIF_MODE, 1);

	return 0;
}

static int rsnd_scu_init(struct rsnd_mod *mod,
			 struct rsnd_dai *rdai,
			 struct rsnd_dai_stream *io)
{
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
	int ret;

	clk_enable(scu->clk);

	ret = rsnd_scu_ssi_mode_init(mod, rdai, io);
	if (ret < 0)
		return ret;

	return 0;
}

static int rsnd_scu_quit(struct rsnd_mod *mod,
			 struct rsnd_dai *rdai,
			 struct rsnd_dai_stream *io)
{
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);

	clk_disable(scu->clk);

	return 0;
}

static int rsnd_scu_start(struct rsnd_mod *mod,
			  struct rsnd_dai *rdai,
			  struct rsnd_dai_stream *io)
{
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);

	/*
	 * Cancel the initialization and operate the SRC function
	 * see rsnd_scu_set_convert_rate()
	 */
	rsnd_mod_write(mod, SRC_SRCIR, 0);

	if (rsnd_scu_convert_rate(scu))
		rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1);

	return 0;
}


static int rsnd_scu_stop(struct rsnd_mod *mod,
			 struct rsnd_dai *rdai,
			 struct rsnd_dai_stream *io)
{
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);

	if (rsnd_scu_convert_rate(scu))
		rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0);

	return 0;
}

static struct rsnd_mod_ops rsnd_scu_non_ops = {
	.name	= "scu (non)",
};

/*
 *		Gen1 functions
 */
static int rsnd_src_set_route_gen1(struct rsnd_mod *mod,
				   struct rsnd_dai *rdai,
				   struct rsnd_dai_stream *io)
{
@@ -171,17 +308,10 @@ static int rsnd_src_set_route_if_gen1(
		{ 0x3, 28, }, /* 7 */
		{ 0x3, 30, }, /* 8 */
	};
	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
	u32 mask;
	u32 val;
	int id;

	/*
	 * Gen1 only
	 */
	if (!rsnd_is_gen1(priv))
		return 0;

	id = rsnd_mod_id(mod);
	if (id < 0 || id >= ARRAY_SIZE(routes))
		return -EIO;
@@ -257,104 +387,43 @@ static int rsnd_scu_set_convert_timing_gen1(struct rsnd_mod *mod,
	return 0;
}

unsigned int rsnd_scu_get_ssi_rate(struct rsnd_priv *priv,
				   struct rsnd_mod *ssi_mod,
				   struct snd_pcm_runtime *runtime)
{
	struct rsnd_scu *scu;
	unsigned int rate;

	/* this function is assuming SSI id = SCU id here */
	scu = rsnd_mod_to_scu(rsnd_scu_mod_get(priv, rsnd_mod_id(ssi_mod)));

	/*
	 * return convert rate if SRC is used,
	 * otherwise, return runtime->rate as usual
	 */
	rate = rsnd_scu_convert_rate(scu);
	if (!rate)
		rate = runtime->rate;

	return rate;
}

static int rsnd_scu_set_convert_rate(struct rsnd_mod *mod,
static int rsnd_scu_set_convert_rate_gen1(struct rsnd_mod *mod,
					  struct rsnd_dai *rdai,
					  struct rsnd_dai_stream *io)
{
	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
	u32 convert_rate = rsnd_scu_convert_rate(scu);
	u32 adinr = runtime->channels;

	/* set/clear soft reset */
	rsnd_mod_write(mod, SRC_SWRSR, 0);
	rsnd_mod_write(mod, SRC_SWRSR, 1);

	/* Initialize the operation of the SRC internal circuits */
	rsnd_mod_write(mod, SRC_SRCIR, 1);

	/* Set channel number and output bit length */
	switch (runtime->sample_bits) {
	case 16:
		adinr |= OTBL_16;
		break;
	case 32:
		adinr |= OTBL_24;
		break;
	default:
		return -EIO;
	}
	rsnd_mod_write(mod, SRC_ADINR, adinr);

	if (convert_rate) {
		u32 fsrate = 0x0400000 / convert_rate * runtime->rate;

		/* Enable the initial value of IFS */
		rsnd_mod_write(mod, SRC_IFSCR, 1);
	int ret;

		/* Set initial value of IFS */
		rsnd_mod_write(mod, SRC_IFSVR, fsrate);
	ret = rsnd_scu_set_convert_rate(mod, rdai, io);
	if (ret < 0)
		return ret;

	/* Select SRC mode (fixed value) */
	rsnd_mod_write(mod, SRC_SRCCR, 0x00010110);

	/* Set the restriction value of the FS ratio (98%) */
		rsnd_mod_write(mod, SRC_MNFSR, fsrate / 100 * 98);
	rsnd_mod_write(mod, SRC_MNFSR,
		       rsnd_mod_read(mod, SRC_IFSVR) / 100 * 98);

		if (rsnd_is_gen1(priv)) {
	/* no SRC_BFSSR settings, since SRC_SRCCR::BUFMD is 0 */
		}
	}

	/* Cancel the initialization and operate the SRC function */
	rsnd_mod_write(mod, SRC_SRCIR, 0);

	/* use DMA transfer */
	rsnd_mod_write(mod, SRC_BUSIF_MODE, 1);

	return 0;
}

static int rsnd_scu_init(struct rsnd_mod *mod,
static int rsnd_scu_init_gen1(struct rsnd_mod *mod,
			      struct rsnd_dai *rdai,
			      struct rsnd_dai_stream *io)
{
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
	int ret;

	clk_enable(scu->clk);

	ret = rsnd_scu_ssi_mode_init(mod, rdai, io);
	ret = rsnd_scu_init(mod, rdai, io);
	if (ret < 0)
		return ret;

	ret = rsnd_src_set_route_if_gen1(mod, rdai, io);
	ret = rsnd_src_set_route_gen1(mod, rdai, io);
	if (ret < 0)
		return ret;

	ret = rsnd_scu_set_convert_rate(mod, rdai, io);
	ret = rsnd_scu_set_convert_rate_gen1(mod, rdai, io);
	if (ret < 0)
		return ret;

@@ -365,62 +434,58 @@ static int rsnd_scu_init(struct rsnd_mod *mod,
	return 0;
}

static int rsnd_scu_quit(struct rsnd_mod *mod,
static int rsnd_scu_start_gen1(struct rsnd_mod *mod,
			       struct rsnd_dai *rdai,
			       struct rsnd_dai_stream *io)
{
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
	int id = rsnd_mod_id(mod);

	clk_disable(scu->clk);
	rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id));

	return 0;
	return rsnd_scu_start(mod, rdai, io);
}

static int rsnd_scu_start(struct rsnd_mod *mod,
static int rsnd_scu_stop_gen1(struct rsnd_mod *mod,
			      struct rsnd_dai *rdai,
			      struct rsnd_dai_stream *io)
{
	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
	int id = rsnd_mod_id(mod);

	if (rsnd_is_gen1(priv))
		rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), (1 << id));

	if (rsnd_scu_convert_rate(scu))
		rsnd_mod_write(mod, SRC_ROUTE_MODE0, 1);
	rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0);

	return 0;
	return rsnd_scu_stop(mod, rdai, io);
}

static int rsnd_scu_stop(struct rsnd_mod *mod,
static struct rsnd_mod_ops rsnd_scu_gen1_ops = {
	.name	= "sru (gen1)",
	.init	= rsnd_scu_init_gen1,
	.quit	= rsnd_scu_quit,
	.start	= rsnd_scu_start_gen1,
	.stop	= rsnd_scu_stop_gen1,
};

static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = {
	.name	= "non-sru (gen1)",
	.init	= rsnd_scu_ssi_mode_init,
};

/*
 *		Gen2 functions
 */
static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod,
				   struct rsnd_dai *rdai,
				   struct rsnd_dai_stream *io)
{
	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
	int id = rsnd_mod_id(mod);

	if (rsnd_is_gen1(priv))
		rsnd_mod_bset(mod, SRC_ROUTE_CTRL, (1 << id), 0);

	if (rsnd_scu_convert_rate(scu))
		rsnd_mod_write(mod, SRC_ROUTE_MODE0, 0);
	/* enable PIO interrupt */
	rsnd_mod_write(mod, INT_ENABLE, 0x0f000000);

	return 0;
}

static struct rsnd_mod_ops rsnd_scu_ops = {
	.name	= "scu",
	.init	= rsnd_scu_init,
	.quit	= rsnd_scu_quit,
	.start	= rsnd_scu_start,
	.stop	= rsnd_scu_stop,
};

static struct rsnd_mod_ops rsnd_scu_non_ops = {
	.name	= "scu (non)",
static struct rsnd_mod_ops rsnd_scu_non_gen2_ops = {
	.name	= "non-scu (gen2)",
	.init	= rsnd_scu_ssi_mode_init,
	.start	= rsnd_scu_start_non_gen2,
};

struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id)
@@ -466,8 +531,15 @@ int rsnd_scu_probe(struct platform_device *pdev,
		scu->clk = clk;

		ops = &rsnd_scu_non_ops;
		if (rsnd_scu_hpbif_is_enable(scu))
			ops = &rsnd_scu_ops;
		if (rsnd_scu_hpbif_is_enable(scu)) {
			if (rsnd_is_gen1(priv))
				ops = &rsnd_scu_gen1_ops;
		} else {
			if (rsnd_is_gen1(priv))
				ops = &rsnd_scu_non_gen1_ops;
			if (rsnd_is_gen2(priv))
				ops = &rsnd_scu_non_gen2_ops;
		}

		rsnd_mod_init(priv, &scu->mod, ops, i);

+0 −5
Original line number Diff line number Diff line
@@ -363,16 +363,11 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
			      struct rsnd_dai *rdai,
			      struct rsnd_dai_stream *io)
{
	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);

	/* enable PIO IRQ */
	ssi->cr_etc = UIEN | OIEN | DIEN;

	/* enable PIO interrupt if gen2 */
	if (rsnd_is_gen2(priv))
		rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000);

	rsnd_ssi_hw_start(ssi, rdai, io);

	return 0;