xref: /openbmc/linux/sound/soc/sh/rcar/gen.c (revision dfc9403b)
13337744aSKuninori Morimoto /*
23337744aSKuninori Morimoto  * Renesas R-Car Gen1 SRU/SSI support
33337744aSKuninori Morimoto  *
43337744aSKuninori Morimoto  * Copyright (C) 2013 Renesas Solutions Corp.
53337744aSKuninori Morimoto  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
63337744aSKuninori Morimoto  *
73337744aSKuninori Morimoto  * This program is free software; you can redistribute it and/or modify
83337744aSKuninori Morimoto  * it under the terms of the GNU General Public License version 2 as
93337744aSKuninori Morimoto  * published by the Free Software Foundation.
103337744aSKuninori Morimoto  */
113337744aSKuninori Morimoto #include "rsnd.h"
123337744aSKuninori Morimoto 
133337744aSKuninori Morimoto struct rsnd_gen_ops {
143337744aSKuninori Morimoto 	int (*path_init)(struct rsnd_priv *priv,
153337744aSKuninori Morimoto 			 struct rsnd_dai *rdai,
163337744aSKuninori Morimoto 			 struct rsnd_dai_stream *io);
173337744aSKuninori Morimoto 	int (*path_exit)(struct rsnd_priv *priv,
183337744aSKuninori Morimoto 			 struct rsnd_dai *rdai,
193337744aSKuninori Morimoto 			 struct rsnd_dai_stream *io);
203337744aSKuninori Morimoto };
213337744aSKuninori Morimoto 
223337744aSKuninori Morimoto struct rsnd_gen_reg_map {
233337744aSKuninori Morimoto 	int index;	/* -1 : not supported */
243337744aSKuninori Morimoto 	u32 offset_id;	/* offset of ssi0, ssi1, ssi2... */
253337744aSKuninori Morimoto 	u32 offset_adr;	/* offset of SSICR, SSISR, ... */
263337744aSKuninori Morimoto };
273337744aSKuninori Morimoto 
283337744aSKuninori Morimoto struct rsnd_gen {
293337744aSKuninori Morimoto 	void __iomem *base[RSND_BASE_MAX];
303337744aSKuninori Morimoto 
313337744aSKuninori Morimoto 	struct rsnd_gen_reg_map reg_map[RSND_REG_MAX];
323337744aSKuninori Morimoto 	struct rsnd_gen_ops *ops;
333337744aSKuninori Morimoto };
343337744aSKuninori Morimoto 
353337744aSKuninori Morimoto #define rsnd_priv_to_gen(p)	((struct rsnd_gen *)(p)->gen)
363337744aSKuninori Morimoto 
373337744aSKuninori Morimoto #define rsnd_is_gen1(s)		((s)->info->flags & RSND_GEN1)
383337744aSKuninori Morimoto #define rsnd_is_gen2(s)		((s)->info->flags & RSND_GEN2)
393337744aSKuninori Morimoto 
403337744aSKuninori Morimoto /*
413337744aSKuninori Morimoto  *		Gen2
423337744aSKuninori Morimoto  *		will be filled in the future
433337744aSKuninori Morimoto  */
443337744aSKuninori Morimoto 
453337744aSKuninori Morimoto /*
463337744aSKuninori Morimoto  *		Gen1
473337744aSKuninori Morimoto  */
4807539c1dSKuninori Morimoto static int rsnd_gen1_path_init(struct rsnd_priv *priv,
4907539c1dSKuninori Morimoto 			       struct rsnd_dai *rdai,
5007539c1dSKuninori Morimoto 			       struct rsnd_dai_stream *io)
5107539c1dSKuninori Morimoto {
5207539c1dSKuninori Morimoto 	struct rsnd_dai_platform_info *info = rsnd_dai_get_platform_info(rdai);
5307539c1dSKuninori Morimoto 	struct rsnd_mod *mod;
5407539c1dSKuninori Morimoto 	int ret;
5507539c1dSKuninori Morimoto 	int id;
5607539c1dSKuninori Morimoto 
5707539c1dSKuninori Morimoto 	/*
5807539c1dSKuninori Morimoto 	 * Gen1 is created by SRU/SSI, and this SRU is base module of
5907539c1dSKuninori Morimoto 	 * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU)
6007539c1dSKuninori Morimoto 	 *
6107539c1dSKuninori Morimoto 	 * Easy image is..
6207539c1dSKuninori Morimoto 	 *	Gen1 SRU = Gen2 SCU + SSIU + etc
6307539c1dSKuninori Morimoto 	 *
6407539c1dSKuninori Morimoto 	 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
6507539c1dSKuninori Morimoto 	 * using fixed path.
6607539c1dSKuninori Morimoto 	 *
6707539c1dSKuninori Morimoto 	 * Then, SSI id = SCU id here
6807539c1dSKuninori Morimoto 	 */
6907539c1dSKuninori Morimoto 
7007539c1dSKuninori Morimoto 	if (rsnd_dai_is_play(rdai, io))
7107539c1dSKuninori Morimoto 		id = info->ssi_id_playback;
7207539c1dSKuninori Morimoto 	else
7307539c1dSKuninori Morimoto 		id = info->ssi_id_capture;
7407539c1dSKuninori Morimoto 
7507539c1dSKuninori Morimoto 	/* SCU */
7607539c1dSKuninori Morimoto 	mod = rsnd_scu_mod_get(priv, id);
7707539c1dSKuninori Morimoto 	ret = rsnd_dai_connect(rdai, mod, io);
7807539c1dSKuninori Morimoto 
7907539c1dSKuninori Morimoto 	return ret;
8007539c1dSKuninori Morimoto }
8107539c1dSKuninori Morimoto 
8207539c1dSKuninori Morimoto static int rsnd_gen1_path_exit(struct rsnd_priv *priv,
8307539c1dSKuninori Morimoto 			       struct rsnd_dai *rdai,
8407539c1dSKuninori Morimoto 			       struct rsnd_dai_stream *io)
8507539c1dSKuninori Morimoto {
8607539c1dSKuninori Morimoto 	struct rsnd_mod *mod, *n;
8707539c1dSKuninori Morimoto 	int ret = 0;
8807539c1dSKuninori Morimoto 
8907539c1dSKuninori Morimoto 	/*
9007539c1dSKuninori Morimoto 	 * remove all mod from rdai
9107539c1dSKuninori Morimoto 	 */
9207539c1dSKuninori Morimoto 	for_each_rsnd_mod(mod, n, io)
9307539c1dSKuninori Morimoto 		ret |= rsnd_dai_disconnect(mod);
9407539c1dSKuninori Morimoto 
9507539c1dSKuninori Morimoto 	return ret;
9607539c1dSKuninori Morimoto }
9707539c1dSKuninori Morimoto 
9807539c1dSKuninori Morimoto static struct rsnd_gen_ops rsnd_gen1_ops = {
9907539c1dSKuninori Morimoto 	.path_init	= rsnd_gen1_path_init,
10007539c1dSKuninori Morimoto 	.path_exit	= rsnd_gen1_path_exit,
10107539c1dSKuninori Morimoto };
10207539c1dSKuninori Morimoto 
10307539c1dSKuninori Morimoto #define RSND_GEN1_REG_MAP(g, s, i, oi, oa)				\
10407539c1dSKuninori Morimoto 	do {								\
10507539c1dSKuninori Morimoto 		(g)->reg_map[RSND_REG_##i].index  = RSND_GEN1_##s;	\
10607539c1dSKuninori Morimoto 		(g)->reg_map[RSND_REG_##i].offset_id = oi;		\
10707539c1dSKuninori Morimoto 		(g)->reg_map[RSND_REG_##i].offset_adr = oa;		\
10807539c1dSKuninori Morimoto 	} while (0)
10907539c1dSKuninori Morimoto 
11007539c1dSKuninori Morimoto static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen)
11107539c1dSKuninori Morimoto {
11207539c1dSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, SRU,	SSI_MODE0,	0x0,	0xD0);
11307539c1dSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, SRU,	SSI_MODE1,	0x0,	0xD4);
114dfc9403bSKuninori Morimoto 
115dfc9403bSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, ADG,	BRRA,		0x0,	0x00);
116dfc9403bSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, ADG,	BRRB,		0x0,	0x04);
117dfc9403bSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, ADG,	SSICKR,		0x0,	0x08);
118dfc9403bSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL0,	0x0,	0x0c);
119dfc9403bSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL1,	0x0,	0x10);
120dfc9403bSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL3,	0x0,	0x18);
121dfc9403bSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL4,	0x0,	0x1c);
122dfc9403bSKuninori Morimoto 	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL5,	0x0,	0x20);
12307539c1dSKuninori Morimoto }
12407539c1dSKuninori Morimoto 
1253337744aSKuninori Morimoto static int rsnd_gen1_probe(struct platform_device *pdev,
1263337744aSKuninori Morimoto 			   struct rcar_snd_info *info,
1273337744aSKuninori Morimoto 			   struct rsnd_priv *priv)
1283337744aSKuninori Morimoto {
12907539c1dSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
13007539c1dSKuninori Morimoto 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
13107539c1dSKuninori Morimoto 	struct resource *sru_res;
132dfc9403bSKuninori Morimoto 	struct resource *adg_res;
13307539c1dSKuninori Morimoto 
13407539c1dSKuninori Morimoto 	/*
13507539c1dSKuninori Morimoto 	 * map address
13607539c1dSKuninori Morimoto 	 */
13707539c1dSKuninori Morimoto 	sru_res	= platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU);
138dfc9403bSKuninori Morimoto 	adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG);
139dfc9403bSKuninori Morimoto 	if (!sru_res ||
140dfc9403bSKuninori Morimoto 	    !adg_res) {
14107539c1dSKuninori Morimoto 		dev_err(dev, "Not enough SRU/SSI/ADG platform resources.\n");
14207539c1dSKuninori Morimoto 		return -ENODEV;
14307539c1dSKuninori Morimoto 	}
14407539c1dSKuninori Morimoto 
14507539c1dSKuninori Morimoto 	gen->ops = &rsnd_gen1_ops;
14607539c1dSKuninori Morimoto 
14707539c1dSKuninori Morimoto 	gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res);
148dfc9403bSKuninori Morimoto 	gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res);
149dfc9403bSKuninori Morimoto 	if (!gen->base[RSND_GEN1_SRU] ||
150dfc9403bSKuninori Morimoto 	    !gen->base[RSND_GEN1_ADG]) {
15107539c1dSKuninori Morimoto 		dev_err(dev, "SRU/SSI/ADG ioremap failed\n");
15207539c1dSKuninori Morimoto 		return -ENODEV;
15307539c1dSKuninori Morimoto 	}
15407539c1dSKuninori Morimoto 
15507539c1dSKuninori Morimoto 	rsnd_gen1_reg_map_init(gen);
15607539c1dSKuninori Morimoto 
15707539c1dSKuninori Morimoto 	dev_dbg(dev, "Gen1 device probed\n");
15807539c1dSKuninori Morimoto 	dev_dbg(dev, "SRU : %08x => %p\n",	sru_res->start,
15907539c1dSKuninori Morimoto 						gen->base[RSND_GEN1_SRU]);
160dfc9403bSKuninori Morimoto 	dev_dbg(dev, "ADG : %08x => %p\n",	adg_res->start,
161dfc9403bSKuninori Morimoto 						gen->base[RSND_GEN1_ADG]);
16207539c1dSKuninori Morimoto 
1633337744aSKuninori Morimoto 	return 0;
1643337744aSKuninori Morimoto }
1653337744aSKuninori Morimoto 
1663337744aSKuninori Morimoto static void rsnd_gen1_remove(struct platform_device *pdev,
1673337744aSKuninori Morimoto 			     struct rsnd_priv *priv)
1683337744aSKuninori Morimoto {
1693337744aSKuninori Morimoto }
1703337744aSKuninori Morimoto 
1713337744aSKuninori Morimoto /*
1723337744aSKuninori Morimoto  *		Gen
1733337744aSKuninori Morimoto  */
1743337744aSKuninori Morimoto int rsnd_gen_path_init(struct rsnd_priv *priv,
1753337744aSKuninori Morimoto 		       struct rsnd_dai *rdai,
1763337744aSKuninori Morimoto 		       struct rsnd_dai_stream *io)
1773337744aSKuninori Morimoto {
1783337744aSKuninori Morimoto 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
1793337744aSKuninori Morimoto 
1803337744aSKuninori Morimoto 	return gen->ops->path_init(priv, rdai, io);
1813337744aSKuninori Morimoto }
1823337744aSKuninori Morimoto 
1833337744aSKuninori Morimoto int rsnd_gen_path_exit(struct rsnd_priv *priv,
1843337744aSKuninori Morimoto 		       struct rsnd_dai *rdai,
1853337744aSKuninori Morimoto 		       struct rsnd_dai_stream *io)
1863337744aSKuninori Morimoto {
1873337744aSKuninori Morimoto 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
1883337744aSKuninori Morimoto 
1893337744aSKuninori Morimoto 	return gen->ops->path_exit(priv, rdai, io);
1903337744aSKuninori Morimoto }
1913337744aSKuninori Morimoto 
1923337744aSKuninori Morimoto void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
1933337744aSKuninori Morimoto 			       struct rsnd_mod *mod,
1943337744aSKuninori Morimoto 			       enum rsnd_reg reg)
1953337744aSKuninori Morimoto {
1963337744aSKuninori Morimoto 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
1973337744aSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
1983337744aSKuninori Morimoto 	int index;
1993337744aSKuninori Morimoto 	u32 offset_id, offset_adr;
2003337744aSKuninori Morimoto 
2013337744aSKuninori Morimoto 	if (reg >= RSND_REG_MAX) {
2023337744aSKuninori Morimoto 		dev_err(dev, "rsnd_reg reg error\n");
2033337744aSKuninori Morimoto 		return NULL;
2043337744aSKuninori Morimoto 	}
2053337744aSKuninori Morimoto 
2063337744aSKuninori Morimoto 	index		= gen->reg_map[reg].index;
2073337744aSKuninori Morimoto 	offset_id	= gen->reg_map[reg].offset_id;
2083337744aSKuninori Morimoto 	offset_adr	= gen->reg_map[reg].offset_adr;
2093337744aSKuninori Morimoto 
2103337744aSKuninori Morimoto 	if (index < 0) {
2113337744aSKuninori Morimoto 		dev_err(dev, "unsupported reg access %d\n", reg);
2123337744aSKuninori Morimoto 		return NULL;
2133337744aSKuninori Morimoto 	}
2143337744aSKuninori Morimoto 
2153337744aSKuninori Morimoto 	if (offset_id && mod)
2163337744aSKuninori Morimoto 		offset_id *= rsnd_mod_id(mod);
2173337744aSKuninori Morimoto 
2183337744aSKuninori Morimoto 	/*
2193337744aSKuninori Morimoto 	 * index/offset were set on gen1/gen2
2203337744aSKuninori Morimoto 	 */
2213337744aSKuninori Morimoto 
2223337744aSKuninori Morimoto 	return gen->base[index] + offset_id + offset_adr;
2233337744aSKuninori Morimoto }
2243337744aSKuninori Morimoto 
2253337744aSKuninori Morimoto int rsnd_gen_probe(struct platform_device *pdev,
2263337744aSKuninori Morimoto 		   struct rcar_snd_info *info,
2273337744aSKuninori Morimoto 		   struct rsnd_priv *priv)
2283337744aSKuninori Morimoto {
2293337744aSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
2303337744aSKuninori Morimoto 	struct rsnd_gen *gen;
2313337744aSKuninori Morimoto 	int i;
2323337744aSKuninori Morimoto 
2333337744aSKuninori Morimoto 	gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
2343337744aSKuninori Morimoto 	if (!gen) {
2353337744aSKuninori Morimoto 		dev_err(dev, "GEN allocate failed\n");
2363337744aSKuninori Morimoto 		return -ENOMEM;
2373337744aSKuninori Morimoto 	}
2383337744aSKuninori Morimoto 
2393337744aSKuninori Morimoto 	priv->gen = gen;
2403337744aSKuninori Morimoto 
2413337744aSKuninori Morimoto 	/*
2423337744aSKuninori Morimoto 	 * see
2433337744aSKuninori Morimoto 	 *	rsnd_reg_get()
2443337744aSKuninori Morimoto 	 *	rsnd_gen_probe()
2453337744aSKuninori Morimoto 	 */
2463337744aSKuninori Morimoto 	for (i = 0; i < RSND_REG_MAX; i++)
2473337744aSKuninori Morimoto 		gen->reg_map[i].index = -1;
2483337744aSKuninori Morimoto 
2493337744aSKuninori Morimoto 	/*
2503337744aSKuninori Morimoto 	 *	init each module
2513337744aSKuninori Morimoto 	 */
2523337744aSKuninori Morimoto 	if (rsnd_is_gen1(priv))
2533337744aSKuninori Morimoto 		return rsnd_gen1_probe(pdev, info, priv);
2543337744aSKuninori Morimoto 
2553337744aSKuninori Morimoto 	dev_err(dev, "unknown generation R-Car sound device\n");
2563337744aSKuninori Morimoto 
2573337744aSKuninori Morimoto 	return -ENODEV;
2583337744aSKuninori Morimoto }
2593337744aSKuninori Morimoto 
2603337744aSKuninori Morimoto void rsnd_gen_remove(struct platform_device *pdev,
2613337744aSKuninori Morimoto 		     struct rsnd_priv *priv)
2623337744aSKuninori Morimoto {
2633337744aSKuninori Morimoto 	if (rsnd_is_gen1(priv))
2643337744aSKuninori Morimoto 		rsnd_gen1_remove(pdev, priv);
2653337744aSKuninori Morimoto }
266