1
2
3
4
5
6
7#include "rsnd.h"
8
9#define SSIU_NAME "ssiu"
10
11struct rsnd_ssiu {
12 struct rsnd_mod mod;
13 u32 busif_status[8];
14 unsigned int usrcnt;
15 int id;
16 int id_sub;
17};
18
19
20#define TDM_EXT (1 << 0)
21#define TDM_SPLIT (1 << 8)
22
23#define rsnd_ssiu_nr(priv) ((priv)->ssiu_nr)
24#define rsnd_mod_to_ssiu(_mod) container_of((_mod), struct rsnd_ssiu, mod)
25#define for_each_rsnd_ssiu(pos, priv, i) \
26 for (i = 0; \
27 (i < rsnd_ssiu_nr(priv)) && \
28 ((pos) = ((struct rsnd_ssiu *)(priv)->ssiu + i)); \
29 i++)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45static const int gen2_id[] = { 0, 4, 8, 12, 13, 14, 15, 16, 17, 18 };
46static const int gen3_id[] = { 0, 8, 16, 24, 32, 40, 41, 42, 43, 44 };
47
48static u32 *rsnd_ssiu_get_status(struct rsnd_mod *mod,
49 struct rsnd_dai_stream *io,
50 enum rsnd_mod_type type)
51{
52 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
53 int busif = rsnd_mod_id_sub(mod);
54
55 return &ssiu->busif_status[busif];
56}
57
58static int rsnd_ssiu_init(struct rsnd_mod *mod,
59 struct rsnd_dai_stream *io,
60 struct rsnd_priv *priv)
61{
62 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
63 u32 multi_ssi_slaves = rsnd_ssi_multi_slaves_runtime(io);
64 int use_busif = rsnd_ssi_use_busif(io);
65 int id = rsnd_mod_id(mod);
66 u32 mask1, val1;
67 u32 mask2, val2;
68 int i;
69
70
71 switch (id) {
72 case 0:
73 case 1:
74 case 2:
75 case 3:
76 case 4:
77 for (i = 0; i < 4; i++)
78 rsnd_mod_write(mod, SSI_SYS_STATUS(i * 2), 0xf << (id * 4));
79 break;
80 case 9:
81 for (i = 0; i < 4; i++)
82 rsnd_mod_write(mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << 4);
83 break;
84 }
85
86
87
88
89 rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
90
91
92
93
94 mask1 = (1 << 4) | (1 << 20);
95 mask2 = (1 << 4);
96 val1 = val2 = 0;
97 if (id == 8) {
98
99
100
101 } else if (rsnd_ssi_is_pin_sharing(io)) {
102 int shift = -1;
103
104 switch (id) {
105 case 1:
106 shift = 0;
107 break;
108 case 2:
109 shift = 2;
110 break;
111 case 4:
112 shift = 16;
113 break;
114 default:
115 return -EINVAL;
116 }
117
118 mask1 |= 0x3 << shift;
119 val1 = rsnd_rdai_is_clk_master(rdai) ?
120 0x2 << shift : 0x1 << shift;
121
122 } else if (multi_ssi_slaves) {
123
124 mask2 |= 0x00000007;
125 mask1 |= 0x0000000f;
126
127 switch (multi_ssi_slaves) {
128 case 0x0206:
129 val2 = (1 << 4) |
130 (rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1);
131
132 case 0x0006:
133 val1 = rsnd_rdai_is_clk_master(rdai) ?
134 0xa : 0x5;
135
136 if (!val2)
137 val1 |= (1 << 4);
138 }
139 }
140
141 rsnd_mod_bset(mod, SSI_MODE1, mask1, val1);
142 rsnd_mod_bset(mod, SSI_MODE2, mask2, val2);
143
144 return 0;
145}
146
147static struct rsnd_mod_ops rsnd_ssiu_ops_gen1 = {
148 .name = SSIU_NAME,
149 .init = rsnd_ssiu_init,
150 .get_status = rsnd_ssiu_get_status,
151};
152
153static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
154 struct rsnd_dai_stream *io,
155 struct rsnd_priv *priv)
156{
157 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
158 u32 has_hdmi0 = rsnd_flags_has(io, RSND_STREAM_HDMI0);
159 u32 has_hdmi1 = rsnd_flags_has(io, RSND_STREAM_HDMI1);
160 int ret;
161 u32 mode = 0;
162
163 ret = rsnd_ssiu_init(mod, io, priv);
164 if (ret < 0)
165 return ret;
166
167 ssiu->usrcnt++;
168
169
170
171
172
173
174 if (rsnd_runtime_is_tdm(io))
175 mode = TDM_EXT;
176 else if (rsnd_runtime_is_tdm_split(io))
177 mode = TDM_SPLIT;
178
179 rsnd_mod_write(mod, SSI_MODE, mode);
180
181 if (rsnd_ssi_use_busif(io)) {
182 int id = rsnd_mod_id(mod);
183 int busif = rsnd_mod_id_sub(mod);
184 enum rsnd_reg adinr_reg, mode_reg, dalign_reg;
185
186 if ((id == 9) && (busif >= 4)) {
187 adinr_reg = SSI9_BUSIF_ADINR(busif);
188 mode_reg = SSI9_BUSIF_MODE(busif);
189 dalign_reg = SSI9_BUSIF_DALIGN(busif);
190 } else {
191 adinr_reg = SSI_BUSIF_ADINR(busif);
192 mode_reg = SSI_BUSIF_MODE(busif);
193 dalign_reg = SSI_BUSIF_DALIGN(busif);
194 }
195
196 rsnd_mod_write(mod, adinr_reg,
197 rsnd_get_adinr_bit(mod, io) |
198 (rsnd_io_is_play(io) ?
199 rsnd_runtime_channel_after_ctu(io) :
200 rsnd_runtime_channel_original(io)));
201 rsnd_mod_write(mod, mode_reg,
202 rsnd_get_busif_shift(io, mod) | 1);
203 rsnd_mod_write(mod, dalign_reg,
204 rsnd_get_dalign(mod, io));
205 }
206
207 if (has_hdmi0 || has_hdmi1) {
208 enum rsnd_mod_type rsnd_ssi_array[] = {
209 RSND_MOD_SSIM1,
210 RSND_MOD_SSIM2,
211 RSND_MOD_SSIM3,
212 };
213 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
214 struct rsnd_mod *pos;
215 u32 val;
216 int i, shift;
217
218 i = rsnd_mod_id(ssi_mod);
219
220
221 val = i << 16 |
222 i << 20 |
223 i << 24 |
224 i << 28 |
225 i;
226
227 for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) {
228 shift = (i * 4) + 16;
229 val = (val & ~(0xF << shift)) |
230 rsnd_mod_id(pos) << shift;
231 }
232
233 if (has_hdmi0)
234 rsnd_mod_write(mod, HDMI0_SEL, val);
235 if (has_hdmi1)
236 rsnd_mod_write(mod, HDMI1_SEL, val);
237 }
238
239 return 0;
240}
241
242static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod,
243 struct rsnd_dai_stream *io,
244 struct rsnd_priv *priv)
245{
246 int busif = rsnd_mod_id_sub(mod);
247
248 if (!rsnd_ssi_use_busif(io))
249 return 0;
250
251 rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4));
252
253 if (rsnd_ssi_multi_slaves_runtime(io))
254 rsnd_mod_write(mod, SSI_CONTROL, 0x1);
255
256 return 0;
257}
258
259static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod,
260 struct rsnd_dai_stream *io,
261 struct rsnd_priv *priv)
262{
263 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
264 int busif = rsnd_mod_id_sub(mod);
265
266 if (!rsnd_ssi_use_busif(io))
267 return 0;
268
269 rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0);
270
271 if (--ssiu->usrcnt)
272 return 0;
273
274 if (rsnd_ssi_multi_slaves_runtime(io))
275 rsnd_mod_write(mod, SSI_CONTROL, 0);
276
277 return 0;
278}
279
280static int rsnd_ssiu_id(struct rsnd_mod *mod)
281{
282 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
283
284
285 return ssiu->id;
286}
287
288static int rsnd_ssiu_id_sub(struct rsnd_mod *mod)
289{
290 struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
291
292
293 return ssiu->id_sub;
294}
295
296static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io,
297 struct rsnd_mod *mod)
298{
299 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
300 int is_play = rsnd_io_is_play(io);
301 char *name;
302
303
304
305
306
307
308
309
310
311
312
313
314 name = is_play ? "rx" : "tx";
315
316 return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv),
317 mod, name);
318}
319
320static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = {
321 .name = SSIU_NAME,
322 .dma_req = rsnd_ssiu_dma_req,
323 .init = rsnd_ssiu_init_gen2,
324 .start = rsnd_ssiu_start_gen2,
325 .stop = rsnd_ssiu_stop_gen2,
326 .get_status = rsnd_ssiu_get_status,
327};
328
329static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id)
330{
331 if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv)))
332 id = 0;
333
334 return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id);
335}
336
337static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv,
338 struct rsnd_dai_stream *io)
339{
340 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
341 struct rsnd_mod *mod;
342 struct rsnd_ssiu *ssiu;
343 int i;
344
345 if (!ssi_mod)
346 return;
347
348
349 for_each_rsnd_ssiu(ssiu, priv, i) {
350 mod = rsnd_mod_get(ssiu);
351
352 if ((rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) &&
353 (rsnd_mod_id_sub(mod) == 0)) {
354 rsnd_dai_connect(mod, io, mod->type);
355 return;
356 }
357 }
358}
359
360void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
361 struct device_node *playback,
362 struct device_node *capture)
363{
364 struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
365 struct device_node *node = rsnd_ssiu_of_node(priv);
366 struct device_node *np;
367 struct rsnd_mod *mod;
368 struct rsnd_dai_stream *io_p = &rdai->playback;
369 struct rsnd_dai_stream *io_c = &rdai->capture;
370 int i;
371
372
373 if (node) {
374 i = 0;
375 for_each_child_of_node(node, np) {
376 mod = rsnd_ssiu_mod_get(priv, i);
377 if (np == playback)
378 rsnd_dai_connect(mod, io_p, mod->type);
379 if (np == capture)
380 rsnd_dai_connect(mod, io_c, mod->type);
381 i++;
382 }
383
384 of_node_put(node);
385 }
386
387
388 if (!rsnd_io_to_mod_ssiu(io_p))
389 rsnd_parse_connect_ssiu_compatible(priv, io_p);
390 if (!rsnd_io_to_mod_ssiu(io_c))
391 rsnd_parse_connect_ssiu_compatible(priv, io_c);
392}
393
394int rsnd_ssiu_probe(struct rsnd_priv *priv)
395{
396 struct device *dev = rsnd_priv_to_dev(priv);
397 struct device_node *node;
398 struct rsnd_ssiu *ssiu;
399 struct rsnd_mod_ops *ops;
400 const int *list = NULL;
401 int i, nr, ret;
402
403
404
405
406
407
408
409
410 node = rsnd_ssiu_of_node(priv);
411 if (node)
412 nr = of_get_child_count(node);
413 else
414 nr = priv->ssi_nr;
415
416 ssiu = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL);
417 if (!ssiu)
418 return -ENOMEM;
419
420 priv->ssiu = ssiu;
421 priv->ssiu_nr = nr;
422
423 if (rsnd_is_gen1(priv))
424 ops = &rsnd_ssiu_ops_gen1;
425 else
426 ops = &rsnd_ssiu_ops_gen2;
427
428
429 nr = 0;
430 if ((node) &&
431 (ops == &rsnd_ssiu_ops_gen2)) {
432 ops->id = rsnd_ssiu_id;
433 ops->id_sub = rsnd_ssiu_id_sub;
434
435 if (rsnd_is_gen2(priv)) {
436 list = gen2_id;
437 nr = ARRAY_SIZE(gen2_id);
438 } else if (rsnd_is_gen3(priv)) {
439 list = gen3_id;
440 nr = ARRAY_SIZE(gen3_id);
441 } else {
442 dev_err(dev, "unknown SSIU\n");
443 return -ENODEV;
444 }
445 }
446
447 for_each_rsnd_ssiu(ssiu, priv, i) {
448 if (node) {
449 int j;
450
451
452
453
454
455
456 for (j = 0; j < nr; j++) {
457 if (list[j] > i)
458 break;
459 ssiu->id = j;
460 ssiu->id_sub = i - list[ssiu->id];
461 }
462 } else {
463 ssiu->id = i;
464 }
465
466 ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu),
467 ops, NULL, RSND_MOD_SSIU, i);
468 if (ret)
469 return ret;
470 }
471
472 return 0;
473}
474
475void rsnd_ssiu_remove(struct rsnd_priv *priv)
476{
477 struct rsnd_ssiu *ssiu;
478 int i;
479
480 for_each_rsnd_ssiu(ssiu, priv, i) {
481 rsnd_mod_quit(rsnd_mod_get(ssiu));
482 }
483}
484