Commit | Line | Data |
---|---|---|
3337744a KM |
1 | /* |
2 | * Renesas R-Car Gen1 SRU/SSI support | |
3 | * | |
4 | * Copyright (C) 2013 Renesas Solutions Corp. | |
5 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | |
6 | * | |
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. | |
10 | */ | |
ace0eb1e KM |
11 | |
12 | /* | |
13 | * #define DEBUG | |
14 | * | |
15 | * you can also add below in | |
16 | * ${LINUX}/drivers/base/regmap/regmap.c | |
17 | * for regmap debug | |
18 | * | |
19 | * #define LOG_DEVICE "xxxx.rcar_sound" | |
20 | */ | |
21 | ||
3337744a KM |
22 | #include "rsnd.h" |
23 | ||
3337744a KM |
24 | struct rsnd_gen { |
25 | void __iomem *base[RSND_BASE_MAX]; | |
26 | ||
3337744a | 27 | struct rsnd_gen_ops *ops; |
55e5b6fd | 28 | |
b8c63786 | 29 | struct regmap *regmap[RSND_BASE_MAX]; |
55e5b6fd | 30 | struct regmap_field *regs[RSND_REG_MAX]; |
3337744a KM |
31 | }; |
32 | ||
33 | #define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) | |
34 | ||
b8c63786 KM |
35 | struct rsnd_regmap_field_conf { |
36 | int idx; | |
37 | unsigned int reg_offset; | |
38 | unsigned int id_offset; | |
39 | }; | |
55e5b6fd | 40 | |
b8c63786 KM |
41 | #define RSND_REG_SET(id, offset, _id_offset) \ |
42 | { \ | |
43 | .idx = id, \ | |
44 | .reg_offset = offset, \ | |
45 | .id_offset = _id_offset, \ | |
55e5b6fd | 46 | } |
b8c63786 KM |
47 | /* single address mapping */ |
48 | #define RSND_GEN_S_REG(id, offset) \ | |
49 | RSND_REG_SET(RSND_REG_##id, offset, 0) | |
55e5b6fd | 50 | |
b8c63786 KM |
51 | /* multi address mapping */ |
52 | #define RSND_GEN_M_REG(id, offset, _id_offset) \ | |
53 | RSND_REG_SET(RSND_REG_##id, offset, _id_offset) | |
55e5b6fd | 54 | |
b8c63786 KM |
55 | /* |
56 | * basic function | |
57 | */ | |
42ee5d22 KM |
58 | static int rsnd_is_accessible_reg(struct rsnd_priv *priv, |
59 | struct rsnd_gen *gen, enum rsnd_reg reg) | |
60 | { | |
61 | if (!gen->regs[reg]) { | |
62 | struct device *dev = rsnd_priv_to_dev(priv); | |
63 | ||
64 | dev_err(dev, "unsupported register access %x\n", reg); | |
65 | return 0; | |
66 | } | |
67 | ||
68 | return 1; | |
69 | } | |
70 | ||
55e5b6fd KM |
71 | u32 rsnd_read(struct rsnd_priv *priv, |
72 | struct rsnd_mod *mod, enum rsnd_reg reg) | |
73 | { | |
b8c63786 | 74 | struct device *dev = rsnd_priv_to_dev(priv); |
55e5b6fd KM |
75 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
76 | u32 val; | |
77 | ||
42ee5d22 KM |
78 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
79 | return 0; | |
80 | ||
30cc4faf | 81 | dev_dbg(dev, "r %s[%d] - %4d : %08x\n", |
ace0eb1e | 82 | rsnd_mod_name(mod), rsnd_mod_id(mod), reg, val); |
55e5b6fd | 83 | |
ace0eb1e | 84 | regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val); |
b8c63786 | 85 | |
55e5b6fd KM |
86 | return val; |
87 | } | |
88 | ||
89 | void rsnd_write(struct rsnd_priv *priv, | |
90 | struct rsnd_mod *mod, | |
91 | enum rsnd_reg reg, u32 data) | |
92 | { | |
b8c63786 | 93 | struct device *dev = rsnd_priv_to_dev(priv); |
55e5b6fd KM |
94 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
95 | ||
42ee5d22 KM |
96 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
97 | return; | |
98 | ||
30cc4faf | 99 | dev_dbg(dev, "w %s[%d] - %4d : %08x\n", |
ace0eb1e | 100 | rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data); |
b8c63786 | 101 | |
ace0eb1e | 102 | regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data); |
55e5b6fd KM |
103 | } |
104 | ||
105 | void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, | |
106 | enum rsnd_reg reg, u32 mask, u32 data) | |
107 | { | |
4f8f86aa | 108 | struct device *dev = rsnd_priv_to_dev(priv); |
55e5b6fd KM |
109 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); |
110 | ||
42ee5d22 KM |
111 | if (!rsnd_is_accessible_reg(priv, gen, reg)) |
112 | return; | |
113 | ||
30cc4faf | 114 | dev_dbg(dev, "b %s[%d] - %4d : %08x/%08x\n", |
ace0eb1e KM |
115 | rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data, mask); |
116 | ||
55e5b6fd KM |
117 | regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod), |
118 | mask, data); | |
119 | } | |
120 | ||
b8c63786 KM |
121 | #define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \ |
122 | _rsnd_gen_regmap_init(priv, id_size, reg_id, conf, ARRAY_SIZE(conf)) | |
123 | static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, | |
124 | int id_size, | |
125 | int reg_id, | |
126 | struct rsnd_regmap_field_conf *conf, | |
127 | int conf_size) | |
c1e6cc5e | 128 | { |
b8c63786 KM |
129 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); |
130 | struct rsnd_gen *gen = rsnd_priv_to_gen(priv); | |
c1e6cc5e | 131 | struct device *dev = rsnd_priv_to_dev(priv); |
b8c63786 | 132 | struct resource *res; |
c1e6cc5e | 133 | struct regmap_config regc; |
b8c63786 KM |
134 | struct regmap_field *regs; |
135 | struct regmap *regmap; | |
136 | struct reg_field regf; | |
137 | void __iomem *base; | |
138 | int i; | |
c1e6cc5e KM |
139 | |
140 | memset(®c, 0, sizeof(regc)); | |
141 | regc.reg_bits = 32; | |
142 | regc.val_bits = 32; | |
b8c63786 | 143 | regc.reg_stride = 4; |
c1e6cc5e | 144 | |
b8c63786 KM |
145 | res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id); |
146 | if (!res) | |
147 | return -ENODEV; | |
148 | ||
149 | base = devm_ioremap_resource(dev, res); | |
150 | if (IS_ERR(base)) | |
151 | return PTR_ERR(base); | |
c1e6cc5e | 152 | |
b8c63786 KM |
153 | regmap = devm_regmap_init_mmio(dev, base, ®c); |
154 | if (IS_ERR(regmap)) | |
155 | return PTR_ERR(regmap); | |
42ee5d22 | 156 | |
b8c63786 KM |
157 | gen->base[reg_id] = base; |
158 | gen->regmap[reg_id] = regmap; | |
c1e6cc5e | 159 | |
b8c63786 KM |
160 | for (i = 0; i < conf_size; i++) { |
161 | ||
162 | regf.reg = conf[i].reg_offset; | |
163 | regf.id_offset = conf[i].id_offset; | |
164 | regf.lsb = 0; | |
165 | regf.msb = 31; | |
166 | regf.id_size = id_size; | |
167 | ||
168 | regs = devm_regmap_field_alloc(dev, regmap, regf); | |
169 | if (IS_ERR(regs)) | |
170 | return PTR_ERR(regs); | |
171 | ||
172 | gen->regs[conf[i].idx] = regs; | |
c1e6cc5e KM |
173 | } |
174 | ||
175 | return 0; | |
176 | } | |
3337744a | 177 | |
ad32d0c7 KM |
178 | /* |
179 | * DMA read/write register offset | |
180 | * | |
181 | * RSND_xxx_I_N for Audio DMAC input | |
182 | * RSND_xxx_O_N for Audio DMAC output | |
183 | * RSND_xxx_I_P for Audio DMAC peri peri input | |
184 | * RSND_xxx_O_P for Audio DMAC peri peri output | |
185 | * | |
186 | * ex) R-Car H2 case | |
187 | * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out | |
d9288d0b KM |
188 | * SSI : 0xec541000 / 0xec241008 / 0xec24100c |
189 | * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000 | |
ad32d0c7 | 190 | * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 |
37523034 | 191 | * CMD : 0xec500000 / / 0xec008000 0xec308000 |
ad32d0c7 KM |
192 | */ |
193 | #define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) | |
194 | #define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) | |
195 | ||
d9288d0b KM |
196 | #define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) |
197 | #define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) | |
198 | ||
199 | #define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | |
200 | #define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) | |
ad32d0c7 KM |
201 | |
202 | #define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) | |
203 | #define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) | |
204 | ||
205 | #define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i)) | |
206 | #define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i)) | |
207 | ||
208 | #define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) | |
209 | #define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) | |
210 | ||
37523034 KM |
211 | static dma_addr_t |
212 | rsnd_gen2_dma_addr(struct rsnd_priv *priv, | |
213 | struct rsnd_mod *mod, | |
214 | int is_play, int is_from) | |
ad32d0c7 KM |
215 | { |
216 | struct platform_device *pdev = rsnd_priv_to_pdev(priv); | |
217 | struct device *dev = rsnd_priv_to_dev(priv); | |
ad32d0c7 KM |
218 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
219 | dma_addr_t ssi_reg = platform_get_resource(pdev, | |
220 | IORESOURCE_MEM, RSND_GEN2_SSI)->start; | |
221 | dma_addr_t src_reg = platform_get_resource(pdev, | |
222 | IORESOURCE_MEM, RSND_GEN2_SCU)->start; | |
223 | int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); | |
224 | int use_src = !!rsnd_io_to_mod_src(io); | |
225 | int use_dvc = !!rsnd_io_to_mod_dvc(io); | |
226 | int id = rsnd_mod_id(mod); | |
227 | struct dma_addr { | |
37523034 KM |
228 | dma_addr_t out_addr; |
229 | dma_addr_t in_addr; | |
d9288d0b KM |
230 | } dma_addrs[3][2][3] = { |
231 | /* SRC */ | |
232 | {{{ 0, 0 }, | |
233 | /* Capture */ | |
37523034 KM |
234 | { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) }, |
235 | { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } }, | |
d9288d0b KM |
236 | /* Playback */ |
237 | {{ 0, 0, }, | |
37523034 KM |
238 | { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) }, |
239 | { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } } | |
d9288d0b KM |
240 | }, |
241 | /* SSI */ | |
242 | /* Capture */ | |
243 | {{{ RDMA_SSI_O_N(ssi, id), 0 }, | |
37523034 KM |
244 | { RDMA_SSIU_O_P(ssi, id), 0 }, |
245 | { RDMA_SSIU_O_P(ssi, id), 0 } }, | |
d9288d0b KM |
246 | /* Playback */ |
247 | {{ 0, RDMA_SSI_I_N(ssi, id) }, | |
37523034 KM |
248 | { 0, RDMA_SSIU_I_P(ssi, id) }, |
249 | { 0, RDMA_SSIU_I_P(ssi, id) } } | |
d9288d0b KM |
250 | }, |
251 | /* SSIU */ | |
252 | /* Capture */ | |
253 | {{{ RDMA_SSIU_O_N(ssi, id), 0 }, | |
37523034 KM |
254 | { RDMA_SSIU_O_P(ssi, id), 0 }, |
255 | { RDMA_SSIU_O_P(ssi, id), 0 } }, | |
d9288d0b KM |
256 | /* Playback */ |
257 | {{ 0, RDMA_SSIU_I_N(ssi, id) }, | |
37523034 KM |
258 | { 0, RDMA_SSIU_I_P(ssi, id) }, |
259 | { 0, RDMA_SSIU_I_P(ssi, id) } } }, | |
ad32d0c7 KM |
260 | }; |
261 | ||
ad32d0c7 | 262 | /* it shouldn't happen */ |
c8e6e960 | 263 | if (use_dvc && !use_src) |
ad32d0c7 | 264 | dev_err(dev, "DVC is selected without SRC\n"); |
ad32d0c7 | 265 | |
d9288d0b KM |
266 | /* use SSIU or SSI ? */ |
267 | if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu"))) | |
268 | is_ssi++; | |
269 | ||
37523034 KM |
270 | return (is_from) ? |
271 | dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr : | |
272 | dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; | |
ad32d0c7 KM |
273 | } |
274 | ||
37523034 KM |
275 | dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, |
276 | struct rsnd_mod *mod, | |
277 | int is_play, int is_from) | |
64eae986 | 278 | { |
64eae986 KM |
279 | /* |
280 | * gen1 uses default DMA addr | |
281 | */ | |
282 | if (rsnd_is_gen1(priv)) | |
37523034 | 283 | return 0; |
64eae986 | 284 | |
37523034 KM |
285 | if (!mod) |
286 | return 0; | |
64eae986 | 287 | |
37523034 KM |
288 | return rsnd_gen2_dma_addr(priv, mod, is_play, is_from); |
289 | } | |
64eae986 | 290 | |
994a9df1 KM |
291 | /* |
292 | * Gen2 | |
994a9df1 | 293 | */ |
507d466c | 294 | static int rsnd_gen2_probe(struct platform_device *pdev, |
507d466c KM |
295 | struct rsnd_priv *priv) |
296 | { | |
297 | struct device *dev = rsnd_priv_to_dev(priv); | |
b8c63786 KM |
298 | struct rsnd_regmap_field_conf conf_ssiu[] = { |
299 | RSND_GEN_S_REG(SSI_MODE0, 0x800), | |
300 | RSND_GEN_S_REG(SSI_MODE1, 0x804), | |
301 | /* FIXME: it needs SSI_MODE2/3 in the future */ | |
302 | RSND_GEN_M_REG(SSI_BUSIF_MODE, 0x0, 0x80), | |
303 | RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4, 0x80), | |
1cc71959 | 304 | RSND_GEN_M_REG(BUSIF_DALIGN, 0x8, 0x80), |
b8c63786 KM |
305 | RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), |
306 | RSND_GEN_M_REG(INT_ENABLE, 0x18, 0x80), | |
307 | }; | |
308 | struct rsnd_regmap_field_conf conf_scu[] = { | |
309 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), | |
310 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), | |
311 | RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), | |
cfcefe01 | 312 | RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), |
b8c63786 KM |
313 | RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), |
314 | RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), | |
cfcefe01 KM |
315 | RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8), |
316 | RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc), | |
317 | RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0), | |
318 | RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1c4), | |
b8c63786 KM |
319 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), |
320 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), | |
321 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), | |
322 | RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), | |
323 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), | |
324 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), | |
325 | RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), | |
326 | RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), | |
327 | RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), | |
328 | RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), | |
329 | RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), | |
330 | RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100), | |
331 | RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100), | |
3539cacf KM |
332 | RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100), |
333 | RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100), | |
334 | RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100), | |
b8c63786 KM |
335 | RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100), |
336 | RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100), | |
337 | RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), | |
338 | }; | |
339 | struct rsnd_regmap_field_conf conf_adg[] = { | |
340 | RSND_GEN_S_REG(BRRA, 0x00), | |
341 | RSND_GEN_S_REG(BRRB, 0x04), | |
342 | RSND_GEN_S_REG(SSICKR, 0x08), | |
343 | RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), | |
344 | RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), | |
345 | RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14), | |
346 | RSND_GEN_S_REG(DIV_EN, 0x30), | |
347 | RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34), | |
348 | RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38), | |
349 | RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c), | |
350 | RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40), | |
351 | RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44), | |
352 | RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48), | |
353 | RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c), | |
354 | RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50), | |
355 | RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54), | |
356 | RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58), | |
357 | RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c), | |
358 | }; | |
359 | struct rsnd_regmap_field_conf conf_ssi[] = { | |
360 | RSND_GEN_M_REG(SSICR, 0x00, 0x40), | |
361 | RSND_GEN_M_REG(SSISR, 0x04, 0x40), | |
362 | RSND_GEN_M_REG(SSITDR, 0x08, 0x40), | |
363 | RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), | |
364 | RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), | |
365 | }; | |
366 | int ret_ssiu; | |
367 | int ret_scu; | |
368 | int ret_adg; | |
369 | int ret_ssi; | |
370 | ||
371 | ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, conf_ssiu); | |
372 | ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, conf_scu); | |
373 | ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, conf_adg); | |
374 | ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, conf_ssi); | |
375 | if (ret_ssiu < 0 || | |
376 | ret_scu < 0 || | |
377 | ret_adg < 0 || | |
378 | ret_ssi < 0) | |
379 | return ret_ssiu | ret_scu | ret_adg | ret_ssi; | |
380 | ||
381 | dev_dbg(dev, "Gen2 is probed\n"); | |
507d466c KM |
382 | |
383 | return 0; | |
384 | } | |
385 | ||
994a9df1 KM |
386 | /* |
387 | * Gen1 | |
388 | */ | |
389 | ||
3337744a | 390 | static int rsnd_gen1_probe(struct platform_device *pdev, |
3337744a KM |
391 | struct rsnd_priv *priv) |
392 | { | |
07539c1d | 393 | struct device *dev = rsnd_priv_to_dev(priv); |
b8c63786 KM |
394 | struct rsnd_regmap_field_conf conf_sru[] = { |
395 | RSND_GEN_S_REG(SRC_ROUTE_SEL, 0x00), | |
396 | RSND_GEN_S_REG(SRC_TMG_SEL0, 0x08), | |
397 | RSND_GEN_S_REG(SRC_TMG_SEL1, 0x0c), | |
398 | RSND_GEN_S_REG(SRC_TMG_SEL2, 0x10), | |
399 | RSND_GEN_S_REG(SRC_ROUTE_CTRL, 0xc0), | |
400 | RSND_GEN_S_REG(SSI_MODE0, 0xD0), | |
401 | RSND_GEN_S_REG(SSI_MODE1, 0xD4), | |
402 | RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x20, 0x4), | |
403 | RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0x50, 0x8), | |
404 | RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), | |
405 | RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), | |
406 | RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), | |
407 | RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), | |
408 | RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), | |
409 | RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), | |
410 | RSND_GEN_M_REG(SRC_MNFSR, 0x228, 0x40), | |
cfcefe01 KM |
411 | /* |
412 | * ADD US | |
413 | * | |
414 | * SRC_STATUS | |
415 | * SRC_INT_EN | |
416 | * SCU_SYS_STATUS0 | |
417 | * SCU_SYS_STATUS1 | |
418 | * SCU_SYS_INT_EN0 | |
419 | * SCU_SYS_INT_EN1 | |
420 | */ | |
b8c63786 KM |
421 | }; |
422 | struct rsnd_regmap_field_conf conf_adg[] = { | |
423 | RSND_GEN_S_REG(BRRA, 0x00), | |
424 | RSND_GEN_S_REG(BRRB, 0x04), | |
425 | RSND_GEN_S_REG(SSICKR, 0x08), | |
426 | RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), | |
427 | RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), | |
428 | RSND_GEN_S_REG(AUDIO_CLK_SEL3, 0x18), | |
429 | RSND_GEN_S_REG(AUDIO_CLK_SEL4, 0x1c), | |
430 | RSND_GEN_S_REG(AUDIO_CLK_SEL5, 0x20), | |
431 | }; | |
432 | struct rsnd_regmap_field_conf conf_ssi[] = { | |
433 | RSND_GEN_M_REG(SSICR, 0x00, 0x40), | |
434 | RSND_GEN_M_REG(SSISR, 0x04, 0x40), | |
435 | RSND_GEN_M_REG(SSITDR, 0x08, 0x40), | |
436 | RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), | |
437 | RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), | |
438 | }; | |
439 | int ret_sru; | |
440 | int ret_adg; | |
441 | int ret_ssi; | |
07539c1d | 442 | |
b8c63786 KM |
443 | ret_sru = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU, conf_sru); |
444 | ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, conf_adg); | |
445 | ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, conf_ssi); | |
446 | if (ret_sru < 0 || | |
447 | ret_adg < 0 || | |
448 | ret_ssi < 0) | |
449 | return ret_sru | ret_adg | ret_ssi; | |
07539c1d | 450 | |
b8c63786 | 451 | dev_dbg(dev, "Gen1 is probed\n"); |
07539c1d | 452 | |
3337744a KM |
453 | return 0; |
454 | } | |
455 | ||
3337744a KM |
456 | /* |
457 | * Gen | |
458 | */ | |
90e8e50f KM |
459 | static void rsnd_of_parse_gen(struct platform_device *pdev, |
460 | const struct rsnd_of_data *of_data, | |
461 | struct rsnd_priv *priv) | |
462 | { | |
463 | struct rcar_snd_info *info = priv->info; | |
464 | ||
465 | if (!of_data) | |
466 | return; | |
467 | ||
468 | info->flags = of_data->flags; | |
469 | } | |
470 | ||
3337744a | 471 | int rsnd_gen_probe(struct platform_device *pdev, |
90e8e50f | 472 | const struct rsnd_of_data *of_data, |
3337744a KM |
473 | struct rsnd_priv *priv) |
474 | { | |
475 | struct device *dev = rsnd_priv_to_dev(priv); | |
476 | struct rsnd_gen *gen; | |
531eaf49 | 477 | int ret; |
3337744a | 478 | |
90e8e50f KM |
479 | rsnd_of_parse_gen(pdev, of_data, priv); |
480 | ||
3337744a KM |
481 | gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL); |
482 | if (!gen) { | |
483 | dev_err(dev, "GEN allocate failed\n"); | |
484 | return -ENOMEM; | |
485 | } | |
486 | ||
531eaf49 | 487 | priv->gen = gen; |
072188b6 | 488 | |
507d466c KM |
489 | ret = -ENODEV; |
490 | if (rsnd_is_gen1(priv)) | |
5da39cf3 | 491 | ret = rsnd_gen1_probe(pdev, priv); |
507d466c | 492 | else if (rsnd_is_gen2(priv)) |
5da39cf3 | 493 | ret = rsnd_gen2_probe(pdev, priv); |
507d466c KM |
494 | |
495 | if (ret < 0) | |
072188b6 | 496 | dev_err(dev, "unknown generation R-Car sound device\n"); |
072188b6 | 497 | |
531eaf49 | 498 | return ret; |
3337744a | 499 | } |