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