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

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

ASoC: add Renesas R-Car module 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)

Gen1 series consists of SRU/SSI/ADG, and
Gen2 series consists of SCU/SSIU/SSI/ADG.

In order to control these by same method,
these are treated as "mod" on this driver.

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 1536a968
Loading
Loading
Loading
Loading
+80 −0
Original line number Diff line number Diff line
@@ -107,9 +107,74 @@
	 priv->info->func(param))


/*
 *	rsnd_mod functions
 */
char *rsnd_mod_name(struct rsnd_mod *mod)
{
	if (!mod || !mod->ops)
		return "unknown";

	return mod->ops->name;
}

void rsnd_mod_init(struct rsnd_priv *priv,
		   struct rsnd_mod *mod,
		   struct rsnd_mod_ops *ops,
		   int id)
{
	mod->priv	= priv;
	mod->id		= id;
	mod->ops	= ops;
	INIT_LIST_HEAD(&mod->list);
}

/*
 *	rsnd_dai functions
 */
#define rsnd_dai_call(rdai, io, fn)			\
({							\
	struct rsnd_mod *mod, *n;			\
	int ret = 0;					\
	for_each_rsnd_mod(mod, n, io) {			\
		ret = rsnd_mod_call(mod, fn, rdai, io);	\
		if (ret < 0)				\
			break;				\
	}						\
	ret;						\
})

int rsnd_dai_connect(struct rsnd_dai *rdai,
		     struct rsnd_mod *mod,
		     struct rsnd_dai_stream *io)
{
	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
	struct device *dev = rsnd_priv_to_dev(priv);

	if (!mod) {
		dev_err(dev, "NULL mod\n");
		return -EIO;
	}

	if (!list_empty(&mod->list)) {
		dev_err(dev, "%s%d is not empty\n",
			rsnd_mod_name(mod),
			rsnd_mod_id(mod));
		return -EIO;
	}

	list_add_tail(&mod->list, &io->head);

	return 0;
}

int rsnd_dai_disconnect(struct rsnd_mod *mod)
{
	list_del_init(&mod->list);

	return 0;
}

struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id)
{
	return priv->rdai + id;
@@ -224,8 +289,23 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
		if (ret < 0)
			goto dai_trigger_end;

		ret = rsnd_dai_call(rdai, io, init);
		if (ret < 0)
			goto dai_trigger_end;

		ret = rsnd_dai_call(rdai, io, start);
		if (ret < 0)
			goto dai_trigger_end;
		break;
	case SNDRV_PCM_TRIGGER_STOP:
		ret = rsnd_dai_call(rdai, io, stop);
		if (ret < 0)
			goto dai_trigger_end;

		ret = rsnd_dai_call(rdai, io, quit);
		if (ret < 0)
			goto dai_trigger_end;

		ret = rsnd_platform_call(priv, dai, stop, ssi_id);
		if (ret < 0)
			goto dai_trigger_end;
+46 −0
Original line number Diff line number Diff line
@@ -28,9 +28,52 @@
 * see gen1/gen2 for detail
 */
struct rsnd_priv;
struct rsnd_mod;
struct rsnd_dai;
struct rsnd_dai_stream;

/*
 *	R-Car sound mod
 */

struct rsnd_mod_ops {
	char *name;
	int (*init)(struct rsnd_mod *mod,
		    struct rsnd_dai *rdai,
		    struct rsnd_dai_stream *io);
	int (*quit)(struct rsnd_mod *mod,
		    struct rsnd_dai *rdai,
		    struct rsnd_dai_stream *io);
	int (*start)(struct rsnd_mod *mod,
		     struct rsnd_dai *rdai,
		     struct rsnd_dai_stream *io);
	int (*stop)(struct rsnd_mod *mod,
		    struct rsnd_dai *rdai,
		    struct rsnd_dai_stream *io);
};

struct rsnd_mod {
	int id;
	struct rsnd_priv *priv;
	struct rsnd_mod_ops *ops;
	struct list_head list; /* connect to rsnd_dai playback/capture */
};

#define rsnd_mod_to_priv(mod) ((mod)->priv)
#define rsnd_mod_id(mod) ((mod)->id)
#define for_each_rsnd_mod(pos, n, io)	\
	list_for_each_entry_safe(pos, n, &(io)->head, list)
#define rsnd_mod_call(mod, func, rdai, io)	\
	(!(mod) ? -ENODEV :			\
	 !((mod)->ops->func) ? 0 :		\
	 (mod)->ops->func(mod, rdai, io))

void rsnd_mod_init(struct rsnd_priv *priv,
		   struct rsnd_mod *mod,
		   struct rsnd_mod_ops *ops,
		   int id);
char *rsnd_mod_name(struct rsnd_mod *mod);

/*
 *	R-Car sound DAI
 */
@@ -64,6 +107,9 @@ struct rsnd_dai {
	     i++, (rdai) = rsnd_dai_get(priv, i))

struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id);
int rsnd_dai_disconnect(struct rsnd_mod *mod);
int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod,
		     struct rsnd_dai_stream *io);
int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io);
#define rsnd_dai_get_platform_info(rdai) ((rdai)->info)