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

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

ASoC: rsnd: use mod base common method on CMD



Renesas sound needs many devices
(SSI/SSIU/SRC/CTU/MIX/DVC/CMD/AudioDMAC/AudioDMACpp).
SSI/SRC/CTU/MIX/DVC are implemented as module.
SSI parent, SSIU are implemented as part of SSI
CMD is implemented as part of CTU/MIX/DVC
AudioDMAC/AudioDMACpp are implemented as part of SSI/SRC
It is nice sense that these all devices are implemented as mod.

This patch makes CMD mod base common method

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 497debaa
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
snd-soc-rcar-objs	:= core.o gen.o dma.o adg.o ssi.o src.o ctu.o mix.o dvc.o
snd-soc-rcar-objs	:= core.o gen.o dma.o adg.o ssi.o src.o ctu.o mix.o dvc.o cmd.o
obj-$(CONFIG_SND_SOC_RCAR)	+= snd-soc-rcar.o
obj-$(CONFIG_SND_SOC_RCAR)	+= snd-soc-rcar.o


snd-soc-rsrc-card-objs	:= rsrc-card.o
snd-soc-rsrc-card-objs	:= rsrc-card.o
+153 −0
Original line number Original line Diff line number Diff line
/*
 * Renesas R-Car CMD support
 *
 * Copyright (C) 2015 Renesas Solutions Corp.
 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include "rsnd.h"

struct rsnd_cmd {
	struct rsnd_mod mod;
};

#define CMD_NAME "cmd"

#define rsnd_cmd_nr(priv) ((priv)->cmd_nr)
#define for_each_rsnd_cmd(pos, priv, i)					\
	for ((i) = 0;							\
	     ((i) < rsnd_cmd_nr(priv)) &&				\
		     ((pos) = (struct rsnd_cmd *)(priv)->cmd + i);	\
	     i++)

static int rsnd_cmd_init(struct rsnd_mod *mod,
			 struct rsnd_dai_stream *io,
			 struct rsnd_priv *priv)
{
	struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
	struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
	struct rsnd_mod *src = rsnd_io_to_mod_src(io);
	struct device *dev = rsnd_priv_to_dev(priv);
	u32 data;

	if (!mix && !dvc)
		return 0;

	if (mix) {
		struct rsnd_dai *rdai;
		int i;
		u32 path[] = {
			[0] = 0,
			[1] = 1 << 0,
			[2] = 0,
			[3] = 0,
			[4] = 0,
			[5] = 1 << 8
		};

		/*
		 * it is assuming that integrater is well understanding about
		 * data path. Here doesn't check impossible connection,
		 * like src2 + src5
		 */
		data = 0;
		for_each_rsnd_dai(rdai, priv, i) {
			io = &rdai->playback;
			if (mix == rsnd_io_to_mod_mix(io))
				data |= path[rsnd_mod_id(src)];

			io = &rdai->capture;
			if (mix == rsnd_io_to_mod_mix(io))
				data |= path[rsnd_mod_id(src)];
		}

	} else {
		u32 path[] = {
			[0] = 0x30000,
			[1] = 0x30001,
			[2] = 0x40000,
			[3] = 0x10000,
			[4] = 0x20000,
			[5] = 0x40100
		};

		data = path[rsnd_mod_id(src)];
	}

	dev_dbg(dev, "ctu/mix path = 0x%08x", data);

	rsnd_mod_write(mod, CMD_ROUTE_SLCT, data);

	rsnd_mod_write(mod, CMD_CTRL, 0x10);

	return 0;
}

static struct rsnd_mod_ops rsnd_cmd_ops = {
	.name	= CMD_NAME,
	.init	= rsnd_cmd_init,
};

int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id)
{
	struct rsnd_priv *priv = rsnd_io_to_priv(io);
	struct rsnd_mod *mod = rsnd_cmd_mod_get(priv, id);

	return rsnd_dai_connect(mod, io, mod->type);
}

struct rsnd_mod *rsnd_cmd_mod_get(struct rsnd_priv *priv, int id)
{
	if (WARN_ON(id < 0 || id >= rsnd_cmd_nr(priv)))
		id = 0;

	return rsnd_mod_get((struct rsnd_cmd *)(priv->cmd) + id);
}

int rsnd_cmd_probe(struct platform_device *pdev,
		   const struct rsnd_of_data *of_data,
		   struct rsnd_priv *priv)
{
	struct device *dev = rsnd_priv_to_dev(priv);
	struct rsnd_cmd *cmd;
	int i, nr, ret;

	/* This driver doesn't support Gen1 at this point */
	if (rsnd_is_gen1(priv))
		return 0;

	/* same number as DVC */
	nr = priv->dvc_nr;
	if (!nr)
		return 0;

	cmd = devm_kzalloc(dev, sizeof(*cmd) * nr, GFP_KERNEL);
	if (!cmd)
		return -ENOMEM;

	priv->cmd_nr	= nr;
	priv->cmd	= cmd;

	for_each_rsnd_cmd(cmd, priv, i) {
		ret = rsnd_mod_init(priv, rsnd_mod_get(cmd),
				    &rsnd_cmd_ops, NULL, RSND_MOD_CMD, i);
		if (ret)
			return ret;
	}

	return 0;
}

void rsnd_cmd_remove(struct platform_device *pdev,
		     struct rsnd_priv *priv)
{
	struct rsnd_cmd *cmd;
	int i;

	for_each_rsnd_cmd(cmd, priv, i) {
		rsnd_mod_quit(rsnd_mod_get(cmd));
	}
}
+2 −73
Original line number Original line Diff line number Diff line
@@ -589,79 +589,6 @@ static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
	ret;							\
	ret;							\
})
})


void rsnd_path_parse(struct rsnd_priv *priv,
		     struct rsnd_dai_stream *io)
{
	struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io);
	struct rsnd_mod *mix = rsnd_io_to_mod_mix(io);
	struct rsnd_mod *src = rsnd_io_to_mod_src(io);
	struct rsnd_mod *cmd;
	struct device *dev = rsnd_priv_to_dev(priv);
	u32 data;

	/* Gen1 is not supported */
	if (rsnd_is_gen1(priv))
		return;

	if (!mix && !dvc)
		return;

	if (mix) {
		struct rsnd_dai *rdai;
		int i;
		u32 path[] = {
			[0] = 0,
			[1] = 1 << 0,
			[2] = 0,
			[3] = 0,
			[4] = 0,
			[5] = 1 << 8
		};

		/*
		 * it is assuming that integrater is well understanding about
		 * data path. Here doesn't check impossible connection,
		 * like src2 + src5
		 */
		data = 0;
		for_each_rsnd_dai(rdai, priv, i) {
			io = &rdai->playback;
			if (mix == rsnd_io_to_mod_mix(io))
				data |= path[rsnd_mod_id(src)];

			io = &rdai->capture;
			if (mix == rsnd_io_to_mod_mix(io))
				data |= path[rsnd_mod_id(src)];
		}

		/*
		 * We can't use ctu = rsnd_io_ctu() here.
		 * Since, ID of dvc/mix are 0 or 1 (= same as CMD number)
		 * but ctu IDs are 0 - 7 (= CTU00 - CTU13)
		 */
		cmd = mix;
	} else {
		u32 path[] = {
			[0] = 0x30000,
			[1] = 0x30001,
			[2] = 0x40000,
			[3] = 0x10000,
			[4] = 0x20000,
			[5] = 0x40100
		};

		data = path[rsnd_mod_id(src)];

		cmd = dvc;
	}

	dev_dbg(dev, "ctu/mix path = 0x%08x", data);

	rsnd_mod_write(cmd, CMD_ROUTE_SLCT, data);

	rsnd_mod_write(cmd, CMD_CTRL, 0x10);
}

static int rsnd_path_init(struct rsnd_priv *priv,
static int rsnd_path_init(struct rsnd_priv *priv,
			  struct rsnd_dai *rdai,
			  struct rsnd_dai *rdai,
			  struct rsnd_dai_stream *io)
			  struct rsnd_dai_stream *io)
@@ -1208,6 +1135,7 @@ static int rsnd_probe(struct platform_device *pdev)
		rsnd_ctu_probe,
		rsnd_ctu_probe,
		rsnd_mix_probe,
		rsnd_mix_probe,
		rsnd_dvc_probe,
		rsnd_dvc_probe,
		rsnd_cmd_probe,
		rsnd_adg_probe,
		rsnd_adg_probe,
		rsnd_dai_probe,
		rsnd_dai_probe,
	};
	};
@@ -1296,6 +1224,7 @@ static int rsnd_remove(struct platform_device *pdev)
		rsnd_ctu_remove,
		rsnd_ctu_remove,
		rsnd_mix_remove,
		rsnd_mix_remove,
		rsnd_dvc_remove,
		rsnd_dvc_remove,
		rsnd_cmd_remove,
	};
	};
	int ret = 0, i;
	int ret = 0, i;


+8 −0
Original line number Original line Diff line number Diff line
@@ -31,6 +31,13 @@ static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable)
	rsnd_mod_write(mod, CTU_CTUIR, enable);
	rsnd_mod_write(mod, CTU_CTUIR, enable);
}
}


static int rsnd_ctu_probe_(struct rsnd_mod *mod,
			   struct rsnd_dai_stream *io,
			   struct rsnd_priv *priv)
{
	return rsnd_cmd_attach(io, rsnd_mod_id(mod) / 4);
}

static int rsnd_ctu_init(struct rsnd_mod *mod,
static int rsnd_ctu_init(struct rsnd_mod *mod,
			 struct rsnd_dai_stream *io,
			 struct rsnd_dai_stream *io,
			 struct rsnd_priv *priv)
			 struct rsnd_priv *priv)
@@ -57,6 +64,7 @@ static int rsnd_ctu_quit(struct rsnd_mod *mod,


static struct rsnd_mod_ops rsnd_ctu_ops = {
static struct rsnd_mod_ops rsnd_ctu_ops = {
	.name		= CTU_NAME,
	.name		= CTU_NAME,
	.probe		= rsnd_ctu_probe_,
	.init		= rsnd_ctu_init,
	.init		= rsnd_ctu_init,
	.quit		= rsnd_ctu_quit,
	.quit		= rsnd_ctu_quit,
};
};
+12 −6
Original line number Original line Diff line number Diff line
@@ -134,7 +134,14 @@ static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
	rsnd_mod_write(mod, DVC_DVUER, 1);
	rsnd_mod_write(mod, DVC_DVUER, 1);
}
}


static int rsnd_dvc_remove_gen2(struct rsnd_mod *mod,
static int rsnd_dvc_probe_(struct rsnd_mod *mod,
			   struct rsnd_dai_stream *io,
			   struct rsnd_priv *priv)
{
	return rsnd_cmd_attach(io, rsnd_mod_id(mod));
}

static int rsnd_dvc_remove_(struct rsnd_mod *mod,
			    struct rsnd_dai_stream *io,
			    struct rsnd_dai_stream *io,
			    struct rsnd_priv *priv)
			    struct rsnd_priv *priv)
{
{
@@ -159,8 +166,6 @@ static int rsnd_dvc_init(struct rsnd_mod *mod,


	rsnd_dvc_initialize_lock(mod);
	rsnd_dvc_initialize_lock(mod);


	rsnd_path_parse(priv, io);

	rsnd_mod_write(mod, DVC_ADINR, rsnd_get_adinr_bit(mod, io));
	rsnd_mod_write(mod, DVC_ADINR, rsnd_get_adinr_bit(mod, io));


	/* ch0/ch1 Volume */
	/* ch0/ch1 Volume */
@@ -269,7 +274,8 @@ static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io,
static struct rsnd_mod_ops rsnd_dvc_ops = {
static struct rsnd_mod_ops rsnd_dvc_ops = {
	.name		= DVC_NAME,
	.name		= DVC_NAME,
	.dma_req	= rsnd_dvc_dma_req,
	.dma_req	= rsnd_dvc_dma_req,
	.remove		= rsnd_dvc_remove_gen2,
	.probe		= rsnd_dvc_probe_,
	.remove		= rsnd_dvc_remove_,
	.init		= rsnd_dvc_init,
	.init		= rsnd_dvc_init,
	.quit		= rsnd_dvc_quit,
	.quit		= rsnd_dvc_quit,
	.start		= rsnd_dvc_start,
	.start		= rsnd_dvc_start,
Loading