xref: /openbmc/linux/sound/soc/sh/rcar/gen.c (revision 4f8f86aa)
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 {
143337744aSKuninori Morimoto 	void __iomem *base[RSND_BASE_MAX];
153337744aSKuninori Morimoto 
163337744aSKuninori Morimoto 	struct rsnd_gen_ops *ops;
1755e5b6fdSKuninori Morimoto 
18b8c63786SKuninori Morimoto 	struct regmap *regmap[RSND_BASE_MAX];
1955e5b6fdSKuninori Morimoto 	struct regmap_field *regs[RSND_REG_MAX];
203337744aSKuninori Morimoto };
213337744aSKuninori Morimoto 
223337744aSKuninori Morimoto #define rsnd_priv_to_gen(p)	((struct rsnd_gen *)(p)->gen)
233337744aSKuninori Morimoto 
24b8c63786SKuninori Morimoto struct rsnd_regmap_field_conf {
25b8c63786SKuninori Morimoto 	int idx;
26b8c63786SKuninori Morimoto 	unsigned int reg_offset;
27b8c63786SKuninori Morimoto 	unsigned int id_offset;
28b8c63786SKuninori Morimoto };
29b8c63786SKuninori Morimoto 
30b8c63786SKuninori Morimoto #define RSND_REG_SET(id, offset, _id_offset)	\
31b8c63786SKuninori Morimoto {						\
32b8c63786SKuninori Morimoto 	.idx = id,				\
33b8c63786SKuninori Morimoto 	.reg_offset = offset,			\
3455e5b6fdSKuninori Morimoto 	.id_offset = _id_offset,		\
3555e5b6fdSKuninori Morimoto }
36b8c63786SKuninori Morimoto /* single address mapping */
37b8c63786SKuninori Morimoto #define RSND_GEN_S_REG(id, offset)	\
38b8c63786SKuninori Morimoto 	RSND_REG_SET(RSND_REG_##id, offset, 0)
39b8c63786SKuninori Morimoto 
40b8c63786SKuninori Morimoto /* multi address mapping */
41b8c63786SKuninori Morimoto #define RSND_GEN_M_REG(id, offset, _id_offset)	\
42b8c63786SKuninori Morimoto 	RSND_REG_SET(RSND_REG_##id, offset, _id_offset)
4355e5b6fdSKuninori Morimoto 
4455e5b6fdSKuninori Morimoto /*
4555e5b6fdSKuninori Morimoto  *		basic function
4655e5b6fdSKuninori Morimoto  */
4742ee5d22SKuninori Morimoto static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
4842ee5d22SKuninori Morimoto 				  struct rsnd_gen *gen, enum rsnd_reg reg)
4942ee5d22SKuninori Morimoto {
5042ee5d22SKuninori Morimoto 	if (!gen->regs[reg]) {
5142ee5d22SKuninori Morimoto 		struct device *dev = rsnd_priv_to_dev(priv);
5242ee5d22SKuninori Morimoto 
5342ee5d22SKuninori Morimoto 		dev_err(dev, "unsupported register access %x\n", reg);
5442ee5d22SKuninori Morimoto 		return 0;
5542ee5d22SKuninori Morimoto 	}
5642ee5d22SKuninori Morimoto 
5742ee5d22SKuninori Morimoto 	return 1;
5842ee5d22SKuninori Morimoto }
5942ee5d22SKuninori Morimoto 
6055e5b6fdSKuninori Morimoto u32 rsnd_read(struct rsnd_priv *priv,
6155e5b6fdSKuninori Morimoto 	      struct rsnd_mod *mod, enum rsnd_reg reg)
6255e5b6fdSKuninori Morimoto {
63b8c63786SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
6455e5b6fdSKuninori Morimoto 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
6555e5b6fdSKuninori Morimoto 	u32 val;
6655e5b6fdSKuninori Morimoto 
6742ee5d22SKuninori Morimoto 	if (!rsnd_is_accessible_reg(priv, gen, reg))
6842ee5d22SKuninori Morimoto 		return 0;
6942ee5d22SKuninori Morimoto 
7055e5b6fdSKuninori Morimoto 	regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
7155e5b6fdSKuninori Morimoto 
72b8c63786SKuninori Morimoto 	dev_dbg(dev, "r %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, val);
73b8c63786SKuninori Morimoto 
7455e5b6fdSKuninori Morimoto 	return val;
7555e5b6fdSKuninori Morimoto }
7655e5b6fdSKuninori Morimoto 
7755e5b6fdSKuninori Morimoto void rsnd_write(struct rsnd_priv *priv,
7855e5b6fdSKuninori Morimoto 		struct rsnd_mod *mod,
7955e5b6fdSKuninori Morimoto 		enum rsnd_reg reg, u32 data)
8055e5b6fdSKuninori Morimoto {
81b8c63786SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
8255e5b6fdSKuninori Morimoto 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
8355e5b6fdSKuninori Morimoto 
8442ee5d22SKuninori Morimoto 	if (!rsnd_is_accessible_reg(priv, gen, reg))
8542ee5d22SKuninori Morimoto 		return;
8642ee5d22SKuninori Morimoto 
8755e5b6fdSKuninori Morimoto 	regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
88b8c63786SKuninori Morimoto 
89b8c63786SKuninori Morimoto 	dev_dbg(dev, "w %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, data);
9055e5b6fdSKuninori Morimoto }
9155e5b6fdSKuninori Morimoto 
9255e5b6fdSKuninori Morimoto void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
9355e5b6fdSKuninori Morimoto 	       enum rsnd_reg reg, u32 mask, u32 data)
9455e5b6fdSKuninori Morimoto {
954f8f86aaSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
9655e5b6fdSKuninori Morimoto 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
9755e5b6fdSKuninori Morimoto 
9842ee5d22SKuninori Morimoto 	if (!rsnd_is_accessible_reg(priv, gen, reg))
9942ee5d22SKuninori Morimoto 		return;
10042ee5d22SKuninori Morimoto 
10155e5b6fdSKuninori Morimoto 	regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
10255e5b6fdSKuninori Morimoto 				  mask, data);
1034f8f86aaSKuninori Morimoto 
1044f8f86aaSKuninori Morimoto 	dev_dbg(dev, "b %s - 0x%04d : %08x/%08x\n",
1054f8f86aaSKuninori Morimoto 		rsnd_mod_name(mod), reg, data, mask);
10655e5b6fdSKuninori Morimoto }
10755e5b6fdSKuninori Morimoto 
108b8c63786SKuninori Morimoto #define rsnd_gen_regmap_init(priv, id_size, reg_id, conf)		\
109b8c63786SKuninori Morimoto 	_rsnd_gen_regmap_init(priv, id_size, reg_id, conf, ARRAY_SIZE(conf))
110b8c63786SKuninori Morimoto static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
111b8c63786SKuninori Morimoto 				 int id_size,
112b8c63786SKuninori Morimoto 				 int reg_id,
113b8c63786SKuninori Morimoto 				 struct rsnd_regmap_field_conf *conf,
114b8c63786SKuninori Morimoto 				 int conf_size)
115c1e6cc5eSKuninori Morimoto {
116b8c63786SKuninori Morimoto 	struct platform_device *pdev = rsnd_priv_to_pdev(priv);
117b8c63786SKuninori Morimoto 	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
118c1e6cc5eSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
119b8c63786SKuninori Morimoto 	struct resource *res;
120c1e6cc5eSKuninori Morimoto 	struct regmap_config regc;
121b8c63786SKuninori Morimoto 	struct regmap_field *regs;
122b8c63786SKuninori Morimoto 	struct regmap *regmap;
123b8c63786SKuninori Morimoto 	struct reg_field regf;
124b8c63786SKuninori Morimoto 	void __iomem *base;
125b8c63786SKuninori Morimoto 	int i;
126c1e6cc5eSKuninori Morimoto 
127c1e6cc5eSKuninori Morimoto 	memset(&regc, 0, sizeof(regc));
128c1e6cc5eSKuninori Morimoto 	regc.reg_bits = 32;
129c1e6cc5eSKuninori Morimoto 	regc.val_bits = 32;
130b8c63786SKuninori Morimoto 	regc.reg_stride = 4;
131c1e6cc5eSKuninori Morimoto 
132b8c63786SKuninori Morimoto 	res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id);
133b8c63786SKuninori Morimoto 	if (!res)
134b8c63786SKuninori Morimoto 		return -ENODEV;
135c1e6cc5eSKuninori Morimoto 
136b8c63786SKuninori Morimoto 	base = devm_ioremap_resource(dev, res);
137b8c63786SKuninori Morimoto 	if (IS_ERR(base))
138b8c63786SKuninori Morimoto 		return PTR_ERR(base);
13942ee5d22SKuninori Morimoto 
140b8c63786SKuninori Morimoto 	regmap = devm_regmap_init_mmio(dev, base, &regc);
141b8c63786SKuninori Morimoto 	if (IS_ERR(regmap))
142b8c63786SKuninori Morimoto 		return PTR_ERR(regmap);
143c1e6cc5eSKuninori Morimoto 
144b8c63786SKuninori Morimoto 	gen->base[reg_id] = base;
145b8c63786SKuninori Morimoto 	gen->regmap[reg_id] = regmap;
146b8c63786SKuninori Morimoto 
147b8c63786SKuninori Morimoto 	for (i = 0; i < conf_size; i++) {
148b8c63786SKuninori Morimoto 
149b8c63786SKuninori Morimoto 		regf.reg	= conf[i].reg_offset;
150b8c63786SKuninori Morimoto 		regf.id_offset	= conf[i].id_offset;
151b8c63786SKuninori Morimoto 		regf.lsb	= 0;
152b8c63786SKuninori Morimoto 		regf.msb	= 31;
153b8c63786SKuninori Morimoto 		regf.id_size	= id_size;
154b8c63786SKuninori Morimoto 
155b8c63786SKuninori Morimoto 		regs = devm_regmap_field_alloc(dev, regmap, regf);
156b8c63786SKuninori Morimoto 		if (IS_ERR(regs))
157b8c63786SKuninori Morimoto 			return PTR_ERR(regs);
158b8c63786SKuninori Morimoto 
159b8c63786SKuninori Morimoto 		gen->regs[conf[i].idx] = regs;
160c1e6cc5eSKuninori Morimoto 	}
161c1e6cc5eSKuninori Morimoto 
162c1e6cc5eSKuninori Morimoto 	return 0;
163c1e6cc5eSKuninori Morimoto }
1643337744aSKuninori Morimoto 
165994a9df1SKuninori Morimoto /*
166ad32d0c7SKuninori Morimoto  *	DMA read/write register offset
167ad32d0c7SKuninori Morimoto  *
168ad32d0c7SKuninori Morimoto  *	RSND_xxx_I_N	for Audio DMAC input
169ad32d0c7SKuninori Morimoto  *	RSND_xxx_O_N	for Audio DMAC output
170ad32d0c7SKuninori Morimoto  *	RSND_xxx_I_P	for Audio DMAC peri peri input
171ad32d0c7SKuninori Morimoto  *	RSND_xxx_O_P	for Audio DMAC peri peri output
172ad32d0c7SKuninori Morimoto  *
173ad32d0c7SKuninori Morimoto  *	ex) R-Car H2 case
174ad32d0c7SKuninori Morimoto  *	      mod        / DMAC in    / DMAC out   / DMAC PP in / DMAC pp out
175d9288d0bSKuninori Morimoto  *	SSI : 0xec541000 / 0xec241008 / 0xec24100c
176d9288d0bSKuninori Morimoto  *	SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
177ad32d0c7SKuninori Morimoto  *	SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
17837523034SKuninori Morimoto  *	CMD : 0xec500000 /            / 0xec008000                0xec308000
179ad32d0c7SKuninori Morimoto  */
180ad32d0c7SKuninori Morimoto #define RDMA_SSI_I_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
181ad32d0c7SKuninori Morimoto #define RDMA_SSI_O_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
182ad32d0c7SKuninori Morimoto 
183d9288d0bSKuninori Morimoto #define RDMA_SSIU_I_N(addr, i)	(addr ##_reg - 0x00441000 + (0x1000 * i))
184d9288d0bSKuninori Morimoto #define RDMA_SSIU_O_N(addr, i)	(addr ##_reg - 0x00441000 + (0x1000 * i))
185d9288d0bSKuninori Morimoto 
186d9288d0bSKuninori Morimoto #define RDMA_SSIU_I_P(addr, i)	(addr ##_reg - 0x00141000 + (0x1000 * i))
187d9288d0bSKuninori Morimoto #define RDMA_SSIU_O_P(addr, i)	(addr ##_reg - 0x00141000 + (0x1000 * i))
188ad32d0c7SKuninori Morimoto 
189ad32d0c7SKuninori Morimoto #define RDMA_SRC_I_N(addr, i)	(addr ##_reg - 0x00500000 + (0x400 * i))
190ad32d0c7SKuninori Morimoto #define RDMA_SRC_O_N(addr, i)	(addr ##_reg - 0x004fc000 + (0x400 * i))
191ad32d0c7SKuninori Morimoto 
192ad32d0c7SKuninori Morimoto #define RDMA_SRC_I_P(addr, i)	(addr ##_reg - 0x00200000 + (0x400 * i))
193ad32d0c7SKuninori Morimoto #define RDMA_SRC_O_P(addr, i)	(addr ##_reg - 0x001fc000 + (0x400 * i))
194ad32d0c7SKuninori Morimoto 
195ad32d0c7SKuninori Morimoto #define RDMA_CMD_O_N(addr, i)	(addr ##_reg - 0x004f8000 + (0x400 * i))
196ad32d0c7SKuninori Morimoto #define RDMA_CMD_O_P(addr, i)	(addr ##_reg - 0x001f8000 + (0x400 * i))
197ad32d0c7SKuninori Morimoto 
19837523034SKuninori Morimoto static dma_addr_t
19937523034SKuninori Morimoto rsnd_gen2_dma_addr(struct rsnd_priv *priv,
20037523034SKuninori Morimoto 		   struct rsnd_mod *mod,
20137523034SKuninori Morimoto 		   int is_play, int is_from)
202ad32d0c7SKuninori Morimoto {
203ad32d0c7SKuninori Morimoto 	struct platform_device *pdev = rsnd_priv_to_pdev(priv);
204ad32d0c7SKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
205ad32d0c7SKuninori Morimoto 	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
206ad32d0c7SKuninori Morimoto 	dma_addr_t ssi_reg = platform_get_resource(pdev,
207ad32d0c7SKuninori Morimoto 				IORESOURCE_MEM, RSND_GEN2_SSI)->start;
208ad32d0c7SKuninori Morimoto 	dma_addr_t src_reg = platform_get_resource(pdev,
209ad32d0c7SKuninori Morimoto 				IORESOURCE_MEM, RSND_GEN2_SCU)->start;
210ad32d0c7SKuninori Morimoto 	int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod);
211ad32d0c7SKuninori Morimoto 	int use_src = !!rsnd_io_to_mod_src(io);
212ad32d0c7SKuninori Morimoto 	int use_dvc = !!rsnd_io_to_mod_dvc(io);
213ad32d0c7SKuninori Morimoto 	int id = rsnd_mod_id(mod);
214ad32d0c7SKuninori Morimoto 	struct dma_addr {
21537523034SKuninori Morimoto 		dma_addr_t out_addr;
21637523034SKuninori Morimoto 		dma_addr_t in_addr;
217d9288d0bSKuninori Morimoto 	} dma_addrs[3][2][3] = {
218d9288d0bSKuninori Morimoto 		/* SRC */
219d9288d0bSKuninori Morimoto 		{{{ 0,				0 },
220ad32d0c7SKuninori Morimoto 		/* Capture */
22137523034SKuninori Morimoto 		  { RDMA_SRC_O_N(src, id),	RDMA_SRC_I_P(src, id) },
22237523034SKuninori Morimoto 		  { RDMA_CMD_O_N(src, id),	RDMA_SRC_I_P(src, id) } },
223ad32d0c7SKuninori Morimoto 		 /* Playback */
224ad32d0c7SKuninori Morimoto 		 {{ 0,				0, },
22537523034SKuninori Morimoto 		  { RDMA_SRC_O_P(src, id),	RDMA_SRC_I_N(src, id) },
22637523034SKuninori Morimoto 		  { RDMA_CMD_O_P(src, id),	RDMA_SRC_I_N(src, id) } }
227d9288d0bSKuninori Morimoto 		},
228d9288d0bSKuninori Morimoto 		/* SSI */
229ad32d0c7SKuninori Morimoto 		/* Capture */
230d9288d0bSKuninori Morimoto 		{{{ RDMA_SSI_O_N(ssi, id),	0 },
23137523034SKuninori Morimoto 		  { RDMA_SSIU_O_P(ssi, id),	0 },
23237523034SKuninori Morimoto 		  { RDMA_SSIU_O_P(ssi, id),	0 } },
233ad32d0c7SKuninori Morimoto 		 /* Playback */
234ad32d0c7SKuninori Morimoto 		 {{ 0,				RDMA_SSI_I_N(ssi, id) },
23537523034SKuninori Morimoto 		  { 0,				RDMA_SSIU_I_P(ssi, id) },
23637523034SKuninori Morimoto 		  { 0,				RDMA_SSIU_I_P(ssi, id) } }
237d9288d0bSKuninori Morimoto 		},
238d9288d0bSKuninori Morimoto 		/* SSIU */
239d9288d0bSKuninori Morimoto 		/* Capture */
240d9288d0bSKuninori Morimoto 		{{{ RDMA_SSIU_O_N(ssi, id),	0 },
24137523034SKuninori Morimoto 		  { RDMA_SSIU_O_P(ssi, id),	0 },
24237523034SKuninori Morimoto 		  { RDMA_SSIU_O_P(ssi, id),	0 } },
243d9288d0bSKuninori Morimoto 		 /* Playback */
244d9288d0bSKuninori Morimoto 		 {{ 0,				RDMA_SSIU_I_N(ssi, id) },
24537523034SKuninori Morimoto 		  { 0,				RDMA_SSIU_I_P(ssi, id) },
24637523034SKuninori Morimoto 		  { 0,				RDMA_SSIU_I_P(ssi, id) } } },
247ad32d0c7SKuninori Morimoto 	};
248ad32d0c7SKuninori Morimoto 
249ad32d0c7SKuninori Morimoto 	/* it shouldn't happen */
25037523034SKuninori Morimoto 	if (use_dvc & !use_src)
251ad32d0c7SKuninori Morimoto 		dev_err(dev, "DVC is selected without SRC\n");
252ad32d0c7SKuninori Morimoto 
253d9288d0bSKuninori Morimoto 	/* use SSIU or SSI ? */
254d9288d0bSKuninori Morimoto 	if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu")))
255d9288d0bSKuninori Morimoto 		is_ssi++;
256d9288d0bSKuninori Morimoto 
25737523034SKuninori Morimoto 	return (is_from) ?
25837523034SKuninori Morimoto 		dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr :
25937523034SKuninori Morimoto 		dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr;
260ad32d0c7SKuninori Morimoto }
261ad32d0c7SKuninori Morimoto 
26237523034SKuninori Morimoto dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv,
26337523034SKuninori Morimoto 			     struct rsnd_mod *mod,
26437523034SKuninori Morimoto 			     int is_play, int is_from)
26564eae986SKuninori Morimoto {
26664eae986SKuninori Morimoto 	/*
26764eae986SKuninori Morimoto 	 * gen1 uses default DMA addr
26864eae986SKuninori Morimoto 	 */
26964eae986SKuninori Morimoto 	if (rsnd_is_gen1(priv))
27037523034SKuninori Morimoto 		return 0;
27164eae986SKuninori Morimoto 
27237523034SKuninori Morimoto 	if (!mod)
27337523034SKuninori Morimoto 		return 0;
27437523034SKuninori Morimoto 
27537523034SKuninori Morimoto 	return rsnd_gen2_dma_addr(priv, mod, is_play, is_from);
27664eae986SKuninori Morimoto }
27764eae986SKuninori Morimoto 
278ad32d0c7SKuninori Morimoto /*
279994a9df1SKuninori Morimoto  *		Gen2
280994a9df1SKuninori Morimoto  */
281507d466cSKuninori Morimoto static int rsnd_gen2_probe(struct platform_device *pdev,
282507d466cSKuninori Morimoto 			   struct rsnd_priv *priv)
283507d466cSKuninori Morimoto {
284507d466cSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
285b8c63786SKuninori Morimoto 	struct rsnd_regmap_field_conf conf_ssiu[] = {
286b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SSI_MODE0,	0x800),
287b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SSI_MODE1,	0x804),
288b8c63786SKuninori Morimoto 		/* FIXME: it needs SSI_MODE2/3 in the future */
289b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSI_BUSIF_MODE,	0x0,	0x80),
290b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSI_BUSIF_ADINR,	0x4,	0x80),
2911cc71959SKuninori Morimoto 		RSND_GEN_M_REG(BUSIF_DALIGN,	0x8,	0x80),
292b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSI_CTRL,	0x10,	0x80),
293b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(INT_ENABLE,	0x18,	0x80),
294b8c63786SKuninori Morimoto 	};
295b8c63786SKuninori Morimoto 	struct rsnd_regmap_field_conf conf_scu[] = {
296b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_BUSIF_MODE,	0x0,	0x20),
297b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_ROUTE_MODE0,	0xc,	0x20),
298b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_CTRL,	0x10,	0x20),
299b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(CMD_ROUTE_SLCT,	0x18c,	0x20),
300b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(CMD_CTRL,	0x190,	0x20),
301b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_SWRSR,	0x200,	0x40),
302b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_SRCIR,	0x204,	0x40),
303b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_ADINR,	0x214,	0x40),
304b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_IFSCR,	0x21c,	0x40),
305b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_IFSVR,	0x220,	0x40),
306b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_SRCCR,	0x224,	0x40),
307b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_BSDSR,	0x22c,	0x40),
308b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_BSISR,	0x238,	0x40),
309b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(DVC_SWRSR,	0xe00,	0x100),
310b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(DVC_DVUIR,	0xe04,	0x100),
311b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(DVC_ADINR,	0xe08,	0x100),
312b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(DVC_DVUCR,	0xe10,	0x100),
313b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(DVC_ZCMCR,	0xe14,	0x100),
314b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(DVC_VOL0R,	0xe28,	0x100),
315b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(DVC_VOL1R,	0xe2c,	0x100),
316b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(DVC_DVUER,	0xe48,	0x100),
317b8c63786SKuninori Morimoto 	};
318b8c63786SKuninori Morimoto 	struct rsnd_regmap_field_conf conf_adg[] = {
319b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(BRRA,		0x00),
320b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(BRRB,		0x04),
321b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SSICKR,		0x08),
322b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(AUDIO_CLK_SEL0,	0x0c),
323b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(AUDIO_CLK_SEL1,	0x10),
324b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(AUDIO_CLK_SEL2,	0x14),
325b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(DIV_EN,		0x30),
326b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCIN_TIMSEL0,	0x34),
327b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCIN_TIMSEL1,	0x38),
328b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCIN_TIMSEL2,	0x3c),
329b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCIN_TIMSEL3,	0x40),
330b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCIN_TIMSEL4,	0x44),
331b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCOUT_TIMSEL0,	0x48),
332b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCOUT_TIMSEL1,	0x4c),
333b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCOUT_TIMSEL2,	0x50),
334b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCOUT_TIMSEL3,	0x54),
335b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRCOUT_TIMSEL4,	0x58),
336b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(CMDOUT_TIMSEL,	0x5c),
337b8c63786SKuninori Morimoto 	};
338b8c63786SKuninori Morimoto 	struct rsnd_regmap_field_conf conf_ssi[] = {
339b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSICR,		0x00,	0x40),
340b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSISR,		0x04,	0x40),
341b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSITDR,		0x08,	0x40),
342b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSIRDR,		0x0c,	0x40),
343b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSIWSR,		0x20,	0x40),
344b8c63786SKuninori Morimoto 	};
345b8c63786SKuninori Morimoto 	int ret_ssiu;
346b8c63786SKuninori Morimoto 	int ret_scu;
347b8c63786SKuninori Morimoto 	int ret_adg;
348b8c63786SKuninori Morimoto 	int ret_ssi;
349507d466cSKuninori Morimoto 
350b8c63786SKuninori Morimoto 	ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, conf_ssiu);
351b8c63786SKuninori Morimoto 	ret_scu  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU,  conf_scu);
352b8c63786SKuninori Morimoto 	ret_adg  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG,  conf_adg);
353b8c63786SKuninori Morimoto 	ret_ssi  = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI,  conf_ssi);
354b8c63786SKuninori Morimoto 	if (ret_ssiu < 0 ||
355b8c63786SKuninori Morimoto 	    ret_scu  < 0 ||
356b8c63786SKuninori Morimoto 	    ret_adg  < 0 ||
357b8c63786SKuninori Morimoto 	    ret_ssi  < 0)
358b8c63786SKuninori Morimoto 		return ret_ssiu | ret_scu | ret_adg | ret_ssi;
359507d466cSKuninori Morimoto 
360b8c63786SKuninori Morimoto 	dev_dbg(dev, "Gen2 is probed\n");
361507d466cSKuninori Morimoto 
362507d466cSKuninori Morimoto 	return 0;
363507d466cSKuninori Morimoto }
364507d466cSKuninori Morimoto 
365994a9df1SKuninori Morimoto /*
366994a9df1SKuninori Morimoto  *		Gen1
367994a9df1SKuninori Morimoto  */
368994a9df1SKuninori Morimoto 
3693337744aSKuninori Morimoto static int rsnd_gen1_probe(struct platform_device *pdev,
3703337744aSKuninori Morimoto 			   struct rsnd_priv *priv)
3713337744aSKuninori Morimoto {
37207539c1dSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
373b8c63786SKuninori Morimoto 	struct rsnd_regmap_field_conf conf_sru[] = {
374b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRC_ROUTE_SEL,	0x00),
375b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRC_TMG_SEL0,	0x08),
376b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRC_TMG_SEL1,	0x0c),
377b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRC_TMG_SEL2,	0x10),
378b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SRC_ROUTE_CTRL,	0xc0),
379b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SSI_MODE0,	0xD0),
380b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SSI_MODE1,	0xD4),
381b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_BUSIF_MODE,	0x20,	0x4),
382b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_ROUTE_MODE0,	0x50,	0x8),
383b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_SWRSR,	0x200,	0x40),
384b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_SRCIR,	0x204,	0x40),
385b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_ADINR,	0x214,	0x40),
386b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_IFSCR,	0x21c,	0x40),
387b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_IFSVR,	0x220,	0x40),
388b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_SRCCR,	0x224,	0x40),
389b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SRC_MNFSR,	0x228,	0x40),
390b8c63786SKuninori Morimoto 	};
391b8c63786SKuninori Morimoto 	struct rsnd_regmap_field_conf conf_adg[] = {
392b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(BRRA,		0x00),
393b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(BRRB,		0x04),
394b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(SSICKR,		0x08),
395b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(AUDIO_CLK_SEL0,	0x0c),
396b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(AUDIO_CLK_SEL1,	0x10),
397b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(AUDIO_CLK_SEL3,	0x18),
398b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(AUDIO_CLK_SEL4,	0x1c),
399b8c63786SKuninori Morimoto 		RSND_GEN_S_REG(AUDIO_CLK_SEL5,	0x20),
400b8c63786SKuninori Morimoto 	};
401b8c63786SKuninori Morimoto 	struct rsnd_regmap_field_conf conf_ssi[] = {
402b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSICR,		0x00,	0x40),
403b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSISR,		0x04,	0x40),
404b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSITDR,		0x08,	0x40),
405b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSIRDR,		0x0c,	0x40),
406b8c63786SKuninori Morimoto 		RSND_GEN_M_REG(SSIWSR,		0x20,	0x40),
407b8c63786SKuninori Morimoto 	};
408b8c63786SKuninori Morimoto 	int ret_sru;
409b8c63786SKuninori Morimoto 	int ret_adg;
410b8c63786SKuninori Morimoto 	int ret_ssi;
41107539c1dSKuninori Morimoto 
412b8c63786SKuninori Morimoto 	ret_sru  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU,  conf_sru);
413b8c63786SKuninori Morimoto 	ret_adg  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG,  conf_adg);
414b8c63786SKuninori Morimoto 	ret_ssi  = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI,  conf_ssi);
415b8c63786SKuninori Morimoto 	if (ret_sru  < 0 ||
416b8c63786SKuninori Morimoto 	    ret_adg  < 0 ||
417b8c63786SKuninori Morimoto 	    ret_ssi  < 0)
418b8c63786SKuninori Morimoto 		return ret_sru | ret_adg | ret_ssi;
41907539c1dSKuninori Morimoto 
420b8c63786SKuninori Morimoto 	dev_dbg(dev, "Gen1 is probed\n");
42107539c1dSKuninori Morimoto 
4223337744aSKuninori Morimoto 	return 0;
4233337744aSKuninori Morimoto }
4243337744aSKuninori Morimoto 
4253337744aSKuninori Morimoto /*
4263337744aSKuninori Morimoto  *		Gen
4273337744aSKuninori Morimoto  */
42890e8e50fSKuninori Morimoto static void rsnd_of_parse_gen(struct platform_device *pdev,
42990e8e50fSKuninori Morimoto 			      const struct rsnd_of_data *of_data,
43090e8e50fSKuninori Morimoto 			      struct rsnd_priv *priv)
43190e8e50fSKuninori Morimoto {
43290e8e50fSKuninori Morimoto 	struct rcar_snd_info *info = priv->info;
43390e8e50fSKuninori Morimoto 
43490e8e50fSKuninori Morimoto 	if (!of_data)
43590e8e50fSKuninori Morimoto 		return;
43690e8e50fSKuninori Morimoto 
43790e8e50fSKuninori Morimoto 	info->flags = of_data->flags;
43890e8e50fSKuninori Morimoto }
43990e8e50fSKuninori Morimoto 
4403337744aSKuninori Morimoto int rsnd_gen_probe(struct platform_device *pdev,
44190e8e50fSKuninori Morimoto 		   const struct rsnd_of_data *of_data,
4423337744aSKuninori Morimoto 		   struct rsnd_priv *priv)
4433337744aSKuninori Morimoto {
4443337744aSKuninori Morimoto 	struct device *dev = rsnd_priv_to_dev(priv);
4453337744aSKuninori Morimoto 	struct rsnd_gen *gen;
446531eaf49SKuninori Morimoto 	int ret;
4473337744aSKuninori Morimoto 
44890e8e50fSKuninori Morimoto 	rsnd_of_parse_gen(pdev, of_data, priv);
44990e8e50fSKuninori Morimoto 
4503337744aSKuninori Morimoto 	gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
4513337744aSKuninori Morimoto 	if (!gen) {
4523337744aSKuninori Morimoto 		dev_err(dev, "GEN allocate failed\n");
4533337744aSKuninori Morimoto 		return -ENOMEM;
4543337744aSKuninori Morimoto 	}
4553337744aSKuninori Morimoto 
456531eaf49SKuninori Morimoto 	priv->gen = gen;
457072188b6SKuninori Morimoto 
458507d466cSKuninori Morimoto 	ret = -ENODEV;
459507d466cSKuninori Morimoto 	if (rsnd_is_gen1(priv))
4605da39cf3SKuninori Morimoto 		ret = rsnd_gen1_probe(pdev, priv);
461507d466cSKuninori Morimoto 	else if (rsnd_is_gen2(priv))
4625da39cf3SKuninori Morimoto 		ret = rsnd_gen2_probe(pdev, priv);
463507d466cSKuninori Morimoto 
464507d466cSKuninori Morimoto 	if (ret < 0)
465072188b6SKuninori Morimoto 		dev_err(dev, "unknown generation R-Car sound device\n");
466072188b6SKuninori Morimoto 
467531eaf49SKuninori Morimoto 	return ret;
4683337744aSKuninori Morimoto }
469