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 int (*probe
)(struct platform_device
*pdev
,
15 struct rcar_snd_info
*info
,
16 struct rsnd_priv
*priv
);
17 void (*remove
)(struct platform_device
*pdev
,
18 struct rsnd_priv
*priv
);
19 int (*path_init
)(struct rsnd_priv
*priv
,
20 struct rsnd_dai
*rdai
,
21 struct rsnd_dai_stream
*io
);
22 int (*path_exit
)(struct rsnd_priv
*priv
,
23 struct rsnd_dai
*rdai
,
24 struct rsnd_dai_stream
*io
);
28 void __iomem
*base
[RSND_BASE_MAX
];
30 struct rsnd_gen_ops
*ops
;
32 struct regmap
*regmap
;
33 struct regmap_field
*regs
[RSND_REG_MAX
];
36 #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
38 #define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \
40 .reg = (unsigned int)gen->base[reg_id] + offset, \
43 .id_size = _id_size, \
44 .id_offset = _id_offset, \
50 static int rsnd_regmap_write32(void *context
, const void *_data
, size_t count
)
52 struct rsnd_priv
*priv
= context
;
53 struct device
*dev
= rsnd_priv_to_dev(priv
);
54 u32
*data
= (u32
*)_data
;
56 void __iomem
*reg
= (void *)data
[0];
60 dev_dbg(dev
, "w %p : %08x\n", reg
, val
);
65 static int rsnd_regmap_read32(void *context
,
66 const void *_data
, size_t reg_size
,
67 void *_val
, size_t val_size
)
69 struct rsnd_priv
*priv
= context
;
70 struct device
*dev
= rsnd_priv_to_dev(priv
);
71 u32
*data
= (u32
*)_data
;
72 u32
*val
= (u32
*)_val
;
73 void __iomem
*reg
= (void *)data
[0];
77 dev_dbg(dev
, "r %p : %08x\n", reg
, *val
);
82 static struct regmap_bus rsnd_regmap_bus
= {
83 .write
= rsnd_regmap_write32
,
84 .read
= rsnd_regmap_read32
,
85 .reg_format_endian_default
= REGMAP_ENDIAN_NATIVE
,
86 .val_format_endian_default
= REGMAP_ENDIAN_NATIVE
,
89 u32
rsnd_read(struct rsnd_priv
*priv
,
90 struct rsnd_mod
*mod
, enum rsnd_reg reg
)
92 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
95 regmap_fields_read(gen
->regs
[reg
], rsnd_mod_id(mod
), &val
);
100 void rsnd_write(struct rsnd_priv
*priv
,
101 struct rsnd_mod
*mod
,
102 enum rsnd_reg reg
, u32 data
)
104 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
106 regmap_fields_write(gen
->regs
[reg
], rsnd_mod_id(mod
), data
);
109 void rsnd_bset(struct rsnd_priv
*priv
, struct rsnd_mod
*mod
,
110 enum rsnd_reg reg
, u32 mask
, u32 data
)
112 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
114 regmap_fields_update_bits(gen
->regs
[reg
], rsnd_mod_id(mod
),
120 * will be filled in the future
126 static int rsnd_gen1_path_init(struct rsnd_priv
*priv
,
127 struct rsnd_dai
*rdai
,
128 struct rsnd_dai_stream
*io
)
130 struct rsnd_mod
*mod
;
135 * Gen1 is created by SRU/SSI, and this SRU is base module of
136 * Gen2's SCU/SSIU/SSI. (Gen2 SCU/SSIU came from SRU)
139 * Gen1 SRU = Gen2 SCU + SSIU + etc
141 * Gen2 SCU path is very flexible, but, Gen1 SRU (SCU parts) is
144 * Then, SSI id = SCU id here
148 mod
= rsnd_ssi_mod_get_frm_dai(priv
,
149 rsnd_dai_id(priv
, rdai
),
150 rsnd_dai_is_play(rdai
, io
));
151 id
= rsnd_mod_id(mod
);
154 mod
= rsnd_ssi_mod_get(priv
, id
);
155 ret
= rsnd_dai_connect(rdai
, mod
, io
);
160 mod
= rsnd_scu_mod_get(priv
, id
);
161 ret
= rsnd_dai_connect(rdai
, mod
, io
);
166 static int rsnd_gen1_path_exit(struct rsnd_priv
*priv
,
167 struct rsnd_dai
*rdai
,
168 struct rsnd_dai_stream
*io
)
170 struct rsnd_mod
*mod
, *n
;
174 * remove all mod from rdai
176 for_each_rsnd_mod(mod
, n
, io
)
177 ret
|= rsnd_dai_disconnect(mod
);
182 /* single address mapping */
183 #define RSND_GEN1_S_REG(gen, reg, id, offset) \
184 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)
186 /* multi address mapping */
187 #define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \
188 RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9)
190 static int rsnd_gen1_regmap_init(struct rsnd_priv
*priv
, struct rsnd_gen
*gen
)
193 struct device
*dev
= rsnd_priv_to_dev(priv
);
194 struct regmap_config regc
;
195 struct reg_field regf
[RSND_REG_MAX
] = {
196 RSND_GEN1_S_REG(gen
, SRU
, SRC_ROUTE_SEL
, 0x00),
197 RSND_GEN1_S_REG(gen
, SRU
, SRC_TMG_SEL0
, 0x08),
198 RSND_GEN1_S_REG(gen
, SRU
, SRC_TMG_SEL1
, 0x0c),
199 RSND_GEN1_S_REG(gen
, SRU
, SRC_TMG_SEL2
, 0x10),
200 RSND_GEN1_S_REG(gen
, SRU
, SRC_CTRL
, 0xc0),
201 RSND_GEN1_S_REG(gen
, SRU
, SSI_MODE0
, 0xD0),
202 RSND_GEN1_S_REG(gen
, SRU
, SSI_MODE1
, 0xD4),
203 RSND_GEN1_M_REG(gen
, SRU
, BUSIF_MODE
, 0x20, 0x4),
204 RSND_GEN1_M_REG(gen
, SRU
, BUSIF_ADINR
, 0x214, 0x40),
206 RSND_GEN1_S_REG(gen
, ADG
, BRRA
, 0x00),
207 RSND_GEN1_S_REG(gen
, ADG
, BRRB
, 0x04),
208 RSND_GEN1_S_REG(gen
, ADG
, SSICKR
, 0x08),
209 RSND_GEN1_S_REG(gen
, ADG
, AUDIO_CLK_SEL0
, 0x0c),
210 RSND_GEN1_S_REG(gen
, ADG
, AUDIO_CLK_SEL1
, 0x10),
211 RSND_GEN1_S_REG(gen
, ADG
, AUDIO_CLK_SEL3
, 0x18),
212 RSND_GEN1_S_REG(gen
, ADG
, AUDIO_CLK_SEL4
, 0x1c),
213 RSND_GEN1_S_REG(gen
, ADG
, AUDIO_CLK_SEL5
, 0x20),
215 RSND_GEN1_M_REG(gen
, SSI
, SSICR
, 0x00, 0x40),
216 RSND_GEN1_M_REG(gen
, SSI
, SSISR
, 0x04, 0x40),
217 RSND_GEN1_M_REG(gen
, SSI
, SSITDR
, 0x08, 0x40),
218 RSND_GEN1_M_REG(gen
, SSI
, SSIRDR
, 0x0c, 0x40),
219 RSND_GEN1_M_REG(gen
, SSI
, SSIWSR
, 0x20, 0x40),
222 memset(®c
, 0, sizeof(regc
));
226 gen
->regmap
= devm_regmap_init(dev
, &rsnd_regmap_bus
, priv
, ®c
);
227 if (IS_ERR(gen
->regmap
)) {
228 dev_err(dev
, "regmap error %ld\n", PTR_ERR(gen
->regmap
));
229 return PTR_ERR(gen
->regmap
);
232 for (i
= 0; i
< RSND_REG_MAX
; i
++) {
233 gen
->regs
[i
] = devm_regmap_field_alloc(dev
, gen
->regmap
, regf
[i
]);
234 if (IS_ERR(gen
->regs
[i
]))
235 return PTR_ERR(gen
->regs
[i
]);
242 static int rsnd_gen1_probe(struct platform_device
*pdev
,
243 struct rcar_snd_info
*info
,
244 struct rsnd_priv
*priv
)
246 struct device
*dev
= rsnd_priv_to_dev(priv
);
247 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
248 struct resource
*sru_res
;
249 struct resource
*adg_res
;
250 struct resource
*ssi_res
;
256 sru_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN1_SRU
);
257 adg_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN1_ADG
);
258 ssi_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, RSND_GEN1_SSI
);
260 gen
->base
[RSND_GEN1_SRU
] = devm_ioremap_resource(dev
, sru_res
);
261 gen
->base
[RSND_GEN1_ADG
] = devm_ioremap_resource(dev
, adg_res
);
262 gen
->base
[RSND_GEN1_SSI
] = devm_ioremap_resource(dev
, ssi_res
);
263 if (IS_ERR(gen
->base
[RSND_GEN1_SRU
]) ||
264 IS_ERR(gen
->base
[RSND_GEN1_ADG
]) ||
265 IS_ERR(gen
->base
[RSND_GEN1_SSI
]))
268 ret
= rsnd_gen1_regmap_init(priv
, gen
);
272 dev_dbg(dev
, "Gen1 device probed\n");
273 dev_dbg(dev
, "SRU : %08x => %p\n", sru_res
->start
,
274 gen
->base
[RSND_GEN1_SRU
]);
275 dev_dbg(dev
, "ADG : %08x => %p\n", adg_res
->start
,
276 gen
->base
[RSND_GEN1_ADG
]);
277 dev_dbg(dev
, "SSI : %08x => %p\n", ssi_res
->start
,
278 gen
->base
[RSND_GEN1_SSI
]);
284 static void rsnd_gen1_remove(struct platform_device
*pdev
,
285 struct rsnd_priv
*priv
)
289 static struct rsnd_gen_ops rsnd_gen1_ops
= {
290 .probe
= rsnd_gen1_probe
,
291 .remove
= rsnd_gen1_remove
,
292 .path_init
= rsnd_gen1_path_init
,
293 .path_exit
= rsnd_gen1_path_exit
,
299 int rsnd_gen_path_init(struct rsnd_priv
*priv
,
300 struct rsnd_dai
*rdai
,
301 struct rsnd_dai_stream
*io
)
303 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
305 return gen
->ops
->path_init(priv
, rdai
, io
);
308 int rsnd_gen_path_exit(struct rsnd_priv
*priv
,
309 struct rsnd_dai
*rdai
,
310 struct rsnd_dai_stream
*io
)
312 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
314 return gen
->ops
->path_exit(priv
, rdai
, io
);
317 int rsnd_gen_probe(struct platform_device
*pdev
,
318 struct rcar_snd_info
*info
,
319 struct rsnd_priv
*priv
)
321 struct device
*dev
= rsnd_priv_to_dev(priv
);
322 struct rsnd_gen
*gen
;
324 gen
= devm_kzalloc(dev
, sizeof(*gen
), GFP_KERNEL
);
326 dev_err(dev
, "GEN allocate failed\n");
330 if (rsnd_is_gen1(priv
))
331 gen
->ops
= &rsnd_gen1_ops
;
334 dev_err(dev
, "unknown generation R-Car sound device\n");
340 return gen
->ops
->probe(pdev
, info
, priv
);
343 void rsnd_gen_remove(struct platform_device
*pdev
,
344 struct rsnd_priv
*priv
)
346 struct rsnd_gen
*gen
= rsnd_priv_to_gen(priv
);
348 gen
->ops
->remove(pdev
, priv
);