2 * Renesas R-Car Gen1 SRU/SSI support
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
14 void __iomem
*base
[RSND_BASE_MAX
];
16 struct rsnd_gen_ops
*ops
;
18 struct regmap
*regmap
;
19 struct regmap_field
*regs
[RSND_REG_MAX
];
22 #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
24 #define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \
26 .reg = (unsigned int)gen->base[reg_id] + offset, \
29 .id_size = _id_size, \
30 .id_offset = _id_offset, \
36 static int rsnd_regmap_write32(void *context
, const void *_data
, size_t count
)
38 struct rsnd_priv
*priv
= context
;
39 struct device
*dev
= rsnd_priv_to_dev(priv
);
40 u32
*data
= (u32
*)_data
;
42 void __iomem
*reg
= (void *)data
[0];
46 dev_dbg(dev
, "w %p : %08x\n", reg
, val
);
51 static int rsnd_regmap_read32(void *context
,
52 const void *_data
, size_t reg_size
,
53 void *_val
, size_t val_size
)
55 struct rsnd_priv
*priv
= context
;
56 struct device
*dev
= rsnd_priv_to_dev(priv
);
57 u32
*data
= (u32
*)_data
;
58 u32
*val
= (u32
*)_val
;
59 void __iomem
*reg
= (void *)data
[0];
63 dev_dbg(dev
, "r %p : %08x\n", reg
, *val
);
68 static struct regmap_bus rsnd_regmap_bus
= {
69 .write
= rsnd_regmap_write32
,
70 .read
= rsnd_regmap_read32
,
71 .reg_format_endian_default
= REGMAP_ENDIAN_NATIVE
,
72 .val_format_endian_default
= REGMAP_ENDIAN_NATIVE
,
75 static int rsnd_is_accessible_reg(struct rsnd_priv
*priv
,
76 struct rsnd_gen
*gen
, enum rsnd_reg reg
)
78 if (!gen
->regs
[reg
]) {
79 struct device
*dev
= rsnd_priv_to_dev(priv
);
81 dev_err(dev
, "unsupported register access %x\n", reg
);
88 u32
rsnd_read(struct rsnd_priv
*priv
,
89 struct rsnd_mod
*mod
, enum rsnd_reg reg
)
91 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
94 if (!rsnd_is_accessible_reg(priv
, gen
, reg
))
97 regmap_fields_read(gen
->regs
[reg
], rsnd_mod_id(mod
), &val
);
102 void rsnd_write(struct rsnd_priv
*priv
,
103 struct rsnd_mod
*mod
,
104 enum rsnd_reg reg
, u32 data
)
106 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
108 if (!rsnd_is_accessible_reg(priv
, gen
, reg
))
111 regmap_fields_write(gen
->regs
[reg
], rsnd_mod_id(mod
), data
);
114 void rsnd_bset(struct rsnd_priv
*priv
, struct rsnd_mod
*mod
,
115 enum rsnd_reg reg
, u32 mask
, u32 data
)
117 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
119 if (!rsnd_is_accessible_reg(priv
, gen
, reg
))
122 regmap_fields_update_bits(gen
->regs
[reg
], rsnd_mod_id(mod
),
126 static int rsnd_gen_regmap_init(struct rsnd_priv
*priv
,
127 struct rsnd_gen
*gen
,
128 struct reg_field
*regf
)
131 struct device
*dev
= rsnd_priv_to_dev(priv
);
132 struct regmap_config regc
;
134 memset(®c
, 0, sizeof(regc
));
138 gen
->regmap
= devm_regmap_init(dev
, &rsnd_regmap_bus
, priv
, ®c
);
139 if (IS_ERR(gen
->regmap
)) {
140 dev_err(dev
, "regmap error %ld\n", PTR_ERR(gen
->regmap
));
141 return PTR_ERR(gen
->regmap
);
144 for (i
= 0; i
< RSND_REG_MAX
; i
++) {
149 gen
->regs
[i
] = devm_regmap_field_alloc(dev
, gen
->regmap
, regf
[i
]);
150 if (IS_ERR(gen
->regs
[i
]))
151 return PTR_ERR(gen
->regs
[i
]);
158 int rsnd_gen_path_init(struct rsnd_priv
*priv
,
159 struct rsnd_dai
*rdai
,
160 struct rsnd_dai_stream
*io
)
162 struct rsnd_mod
*mod
;
167 * Gen1 is created by SRU/SSI, and this SRU is base module of
168 * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU)
171 * Gen1 SRU = Gen2 SCU + SSIU + etc
173 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
176 * Then, SSI id = SCU id here
180 mod
= rsnd_ssi_mod_get_frm_dai(priv
,
181 rsnd_dai_id(priv
, rdai
),
182 rsnd_dai_is_play(rdai
, io
));
183 id
= rsnd_mod_id(mod
);
186 mod
= rsnd_ssi_mod_get(priv
, id
);
187 ret
= rsnd_dai_connect(rdai
, mod
, io
);
192 mod
= rsnd_scu_mod_get(priv
, id
);
193 ret
= rsnd_dai_connect(rdai
, mod
, io
);
198 int rsnd_gen_path_exit(struct rsnd_priv
*priv
,
199 struct rsnd_dai
*rdai
,
200 struct rsnd_dai_stream
*io
)
202 struct rsnd_mod
*mod
, *n
;
206 * remove all mod from rdai
208 for_each_rsnd_mod(mod
, n
, io
)
209 ret
|= rsnd_dai_disconnect(mod
);
218 /* single address mapping */
219 #define RSND_GEN2_S_REG(gen, reg, id, offset) \
220 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10)
222 /* multi address mapping */
223 #define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \
224 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10)
226 static int rsnd_gen2_regmap_init(struct rsnd_priv
*priv
, struct rsnd_gen
*gen
)
228 struct reg_field regf
[RSND_REG_MAX
] = {
229 RSND_GEN2_S_REG(gen
, SSIU
, SSI_MODE0
, 0x800),
230 RSND_GEN2_S_REG(gen
, SSIU
, SSI_MODE1
, 0x804),
231 /* FIXME: it needs SSI_MODE2/3 in the future */
232 RSND_GEN2_M_REG(gen
, SSIU
, INT_ENABLE
, 0x18, 0x80),
234 RSND_GEN2_S_REG(gen
, ADG
, BRRA
, 0x00),
235 RSND_GEN2_S_REG(gen
, ADG
, BRRB
, 0x04),
236 RSND_GEN2_S_REG(gen
, ADG
, SSICKR
, 0x08),
237 RSND_GEN2_S_REG(gen
, ADG
, AUDIO_CLK_SEL0
, 0x0c),
238 RSND_GEN2_S_REG(gen
, ADG
, AUDIO_CLK_SEL1
, 0x10),
239 RSND_GEN2_S_REG(gen
, ADG
, AUDIO_CLK_SEL2
, 0x14),
241 RSND_GEN2_M_REG(gen
, SSI
, SSICR
, 0x00, 0x40),
242 RSND_GEN2_M_REG(gen
, SSI
, SSISR
, 0x04, 0x40),
243 RSND_GEN2_M_REG(gen
, SSI
, SSITDR
, 0x08, 0x40),
244 RSND_GEN2_M_REG(gen
, SSI
, SSIRDR
, 0x0c, 0x40),
245 RSND_GEN2_M_REG(gen
, SSI
, SSIWSR
, 0x20, 0x40),
248 return rsnd_gen_regmap_init(priv
, gen
, regf
);
251 static int rsnd_gen2_probe(struct platform_device
*pdev
,
252 struct rcar_snd_info
*info
,
253 struct rsnd_priv
*priv
)
255 struct device
*dev
= rsnd_priv_to_dev(priv
);
256 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
257 struct resource
*scu_res
;
258 struct resource
*adg_res
;
259 struct resource
*ssiu_res
;
260 struct resource
*ssi_res
;
266 scu_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN2_SCU
);
267 adg_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN2_ADG
);
268 ssiu_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN2_SSIU
);
269 ssi_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN2_SSI
);
271 gen
->base
[RSND_GEN2_SCU
] = devm_ioremap_resource(dev
, scu_res
);
272 gen
->base
[RSND_GEN2_ADG
] = devm_ioremap_resource(dev
, adg_res
);
273 gen
->base
[RSND_GEN2_SSIU
] = devm_ioremap_resource(dev
, ssiu_res
);
274 gen
->base
[RSND_GEN2_SSI
] = devm_ioremap_resource(dev
, ssi_res
);
275 if (IS_ERR(gen
->base
[RSND_GEN2_SCU
]) ||
276 IS_ERR(gen
->base
[RSND_GEN2_ADG
]) ||
277 IS_ERR(gen
->base
[RSND_GEN2_SSIU
]) ||
278 IS_ERR(gen
->base
[RSND_GEN2_SSI
]))
281 ret
= rsnd_gen2_regmap_init(priv
, gen
);
285 dev_dbg(dev
, "Gen2 device probed\n");
286 dev_dbg(dev
, "SRU : %08x => %p\n", scu_res
->start
,
287 gen
->base
[RSND_GEN2_SCU
]);
288 dev_dbg(dev
, "ADG : %08x => %p\n", adg_res
->start
,
289 gen
->base
[RSND_GEN2_ADG
]);
290 dev_dbg(dev
, "SSIU : %08x => %p\n", ssiu_res
->start
,
291 gen
->base
[RSND_GEN2_SSIU
]);
292 dev_dbg(dev
, "SSI : %08x => %p\n", ssi_res
->start
,
293 gen
->base
[RSND_GEN2_SSI
]);
302 /* single address mapping */
303 #define RSND_GEN1_S_REG(gen, reg, id, offset) \
304 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)
306 /* multi address mapping */
307 #define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \
308 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9)
310 static int rsnd_gen1_regmap_init(struct rsnd_priv
*priv
, struct rsnd_gen
*gen
)
312 struct reg_field regf
[RSND_REG_MAX
] = {
313 RSND_GEN1_S_REG(gen
, SRU
, SRC_ROUTE_SEL
, 0x00),
314 RSND_GEN1_S_REG(gen
, SRU
, SRC_TMG_SEL0
, 0x08),
315 RSND_GEN1_S_REG(gen
, SRU
, SRC_TMG_SEL1
, 0x0c),
316 RSND_GEN1_S_REG(gen
, SRU
, SRC_TMG_SEL2
, 0x10),
317 RSND_GEN1_S_REG(gen
, SRU
, SRC_ROUTE_CTRL
, 0xc0),
318 RSND_GEN1_S_REG(gen
, SRU
, SSI_MODE0
, 0xD0),
319 RSND_GEN1_S_REG(gen
, SRU
, SSI_MODE1
, 0xD4),
320 RSND_GEN1_M_REG(gen
, SRU
, BUSIF_MODE
, 0x20, 0x4),
321 RSND_GEN1_M_REG(gen
, SRU
, SRC_ADINR
, 0x214, 0x40),
323 RSND_GEN1_S_REG(gen
, ADG
, BRRA
, 0x00),
324 RSND_GEN1_S_REG(gen
, ADG
, BRRB
, 0x04),
325 RSND_GEN1_S_REG(gen
, ADG
, SSICKR
, 0x08),
326 RSND_GEN1_S_REG(gen
, ADG
, AUDIO_CLK_SEL0
, 0x0c),
327 RSND_GEN1_S_REG(gen
, ADG
, AUDIO_CLK_SEL1
, 0x10),
329 RSND_GEN1_M_REG(gen
, SSI
, SSICR
, 0x00, 0x40),
330 RSND_GEN1_M_REG(gen
, SSI
, SSISR
, 0x04, 0x40),
331 RSND_GEN1_M_REG(gen
, SSI
, SSITDR
, 0x08, 0x40),
332 RSND_GEN1_M_REG(gen
, SSI
, SSIRDR
, 0x0c, 0x40),
333 RSND_GEN1_M_REG(gen
, SSI
, SSIWSR
, 0x20, 0x40),
336 return rsnd_gen_regmap_init(priv
, gen
, regf
);
339 static int rsnd_gen1_probe(struct platform_device
*pdev
,
340 struct rcar_snd_info
*info
,
341 struct rsnd_priv
*priv
)
343 struct device
*dev
= rsnd_priv_to_dev(priv
);
344 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
345 struct resource
*sru_res
;
346 struct resource
*adg_res
;
347 struct resource
*ssi_res
;
353 sru_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN1_SRU
);
354 adg_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN1_ADG
);
355 ssi_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN1_SSI
);
357 gen
->base
[RSND_GEN1_SRU
] = devm_ioremap_resource(dev
, sru_res
);
358 gen
->base
[RSND_GEN1_ADG
] = devm_ioremap_resource(dev
, adg_res
);
359 gen
->base
[RSND_GEN1_SSI
] = devm_ioremap_resource(dev
, ssi_res
);
360 if (IS_ERR(gen
->base
[RSND_GEN1_SRU
]) ||
361 IS_ERR(gen
->base
[RSND_GEN1_ADG
]) ||
362 IS_ERR(gen
->base
[RSND_GEN1_SSI
]))
365 ret
= rsnd_gen1_regmap_init(priv
, gen
);
369 dev_dbg(dev
, "Gen1 device probed\n");
370 dev_dbg(dev
, "SRU : %08x => %p\n", sru_res
->start
,
371 gen
->base
[RSND_GEN1_SRU
]);
372 dev_dbg(dev
, "ADG : %08x => %p\n", adg_res
->start
,
373 gen
->base
[RSND_GEN1_ADG
]);
374 dev_dbg(dev
, "SSI : %08x => %p\n", ssi_res
->start
,
375 gen
->base
[RSND_GEN1_SSI
]);
384 int rsnd_gen_probe(struct platform_device
*pdev
,
385 struct rcar_snd_info
*info
,
386 struct rsnd_priv
*priv
)
388 struct device
*dev
= rsnd_priv_to_dev(priv
);
389 struct rsnd_gen
*gen
;
392 gen
= devm_kzalloc(dev
, sizeof(*gen
), GFP_KERNEL
);
394 dev_err(dev
, "GEN allocate failed\n");
401 if (rsnd_is_gen1(priv
))
402 ret
= rsnd_gen1_probe(pdev
, info
, priv
);
403 else if (rsnd_is_gen2(priv
))
404 ret
= rsnd_gen2_probe(pdev
, info
, priv
);
407 dev_err(dev
, "unknown generation R-Car sound device\n");
412 void rsnd_gen_remove(struct platform_device
*pdev
,
413 struct rsnd_priv
*priv
)