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