ASoC: rsnd: check for zero node count
[linux-2.6-microblaze.git] / sound / soc / sh / rcar / ssiu.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Renesas R-Car SSIU support
4 //
5 // Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6
7 #include "rsnd.h"
8
9 #define SSIU_NAME "ssiu"
10
11 struct rsnd_ssiu {
12         struct rsnd_mod mod;
13         u32 busif_status[8]; /* for BUSIF0 - BUSIF7 */
14         unsigned int usrcnt;
15         int id;
16         int id_sub;
17 };
18
19 /* SSI_MODE */
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  *      SSI     Gen2            Gen3
33  *      0       BUSIF0-3        BUSIF0-7
34  *      1       BUSIF0-3        BUSIF0-7
35  *      2       BUSIF0-3        BUSIF0-7
36  *      3       BUSIF0          BUSIF0-7
37  *      4       BUSIF0          BUSIF0-7
38  *      5       BUSIF0          BUSIF0
39  *      6       BUSIF0          BUSIF0
40  *      7       BUSIF0          BUSIF0
41  *      8       BUSIF0          BUSIF0
42  *      9       BUSIF0-3        BUSIF0-7
43  *      total   22              52
44  */
45 static const int gen2_id[] = { 0, 4,  8, 12, 13, 14, 15, 16, 17, 18 };
46 static const int gen3_id[] = { 0, 8, 16, 24, 32, 40, 41, 42, 43, 44 };
47
48 /* enable busif buffer over/under run interrupt. */
49 #define rsnd_ssiu_busif_err_irq_enable(mod)  rsnd_ssiu_busif_err_irq_ctrl(mod, 1)
50 #define rsnd_ssiu_busif_err_irq_disable(mod) rsnd_ssiu_busif_err_irq_ctrl(mod, 0)
51 static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable)
52 {
53         int id = rsnd_mod_id(mod);
54         int shift, offset;
55         int i;
56
57         switch (id) {
58         case 0:
59         case 1:
60         case 2:
61         case 3:
62         case 4:
63                 shift  = id;
64                 offset = 0;
65                 break;
66         case 9:
67                 shift  = 1;
68                 offset = 1;
69                 break;
70         }
71
72         for (i = 0; i < 4; i++) {
73                 enum rsnd_reg reg = SSI_SYS_INT_ENABLE((i * 2) + offset);
74                 u32 val = 0xf << (shift * 4);
75                 u32 sys_int_enable = rsnd_mod_read(mod, reg);
76
77                 if (enable)
78                         sys_int_enable |= val;
79                 else
80                         sys_int_enable &= ~val;
81                 rsnd_mod_write(mod, reg, sys_int_enable);
82         }
83 }
84
85 bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod)
86 {
87         bool error = false;
88         int id = rsnd_mod_id(mod);
89         int shift, offset;
90         int i;
91
92         switch (id) {
93         case 0:
94         case 1:
95         case 2:
96         case 3:
97         case 4:
98                 shift  = id;
99                 offset = 0;
100                 break;
101         case 9:
102                 shift  = 1;
103                 offset = 1;
104                 break;
105         }
106
107         for (i = 0; i < 4; i++) {
108                 u32 reg = SSI_SYS_STATUS(i * 2) + offset;
109                 u32 status = rsnd_mod_read(mod, reg);
110                 u32 val = 0xf << (shift * 4);
111
112                 status &= val;
113                 if (status) {
114                         struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
115                         struct device *dev = rsnd_priv_to_dev(priv);
116
117                         rsnd_print_irq_status(dev, "%s err status : 0x%08x\n",
118                                               rsnd_mod_name(mod), status);
119                         error = true;
120                 }
121                 rsnd_mod_write(mod, reg, val);
122         }
123
124         return error;
125 }
126
127 static u32 *rsnd_ssiu_get_status(struct rsnd_mod *mod,
128                                  struct rsnd_dai_stream *io,
129                                  enum rsnd_mod_type type)
130 {
131         struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
132         int busif = rsnd_mod_id_sub(mod);
133
134         return &ssiu->busif_status[busif];
135 }
136
137 static int rsnd_ssiu_init(struct rsnd_mod *mod,
138                           struct rsnd_dai_stream *io,
139                           struct rsnd_priv *priv)
140 {
141         struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
142         u32 ssis = rsnd_ssi_multi_secondaries_runtime(io);
143         int use_busif = rsnd_ssi_use_busif(io);
144         int id = rsnd_mod_id(mod);
145         int is_clk_master = rsnd_rdai_is_clk_master(rdai);
146         u32 val1, val2;
147
148         /* clear status */
149         rsnd_ssiu_busif_err_status_clear(mod);
150
151         /*
152          * SSI_MODE0
153          */
154         rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
155
156         /*
157          * SSI_MODE1 / SSI_MODE2
158          *
159          * FIXME
160          * sharing/multi with SSI0 are mainly supported
161          */
162         val1 = rsnd_mod_read(mod, SSI_MODE1);
163         val2 = rsnd_mod_read(mod, SSI_MODE2);
164         if (rsnd_ssi_is_pin_sharing(io)) {
165
166                 ssis |= (1 << id);
167
168         } else if (ssis) {
169                 /*
170                  * Multi SSI
171                  *
172                  * set synchronized bit here
173                  */
174
175                 /* SSI4 is synchronized with SSI3 */
176                 if (ssis & (1 << 4))
177                         val1 |= (1 << 20);
178                 /* SSI012 are synchronized */
179                 if (ssis == 0x0006)
180                         val1 |= (1 << 4);
181                 /* SSI0129 are synchronized */
182                 if (ssis == 0x0206)
183                         val2 |= (1 << 4);
184         }
185
186         /* SSI1 is sharing pin with SSI0 */
187         if (ssis & (1 << 1))
188                 val1 |= is_clk_master ? 0x2 : 0x1;
189
190         /* SSI2 is sharing pin with SSI0 */
191         if (ssis & (1 << 2))
192                 val1 |= is_clk_master ? 0x2 << 2 :
193                                         0x1 << 2;
194         /* SSI4 is sharing pin with SSI3 */
195         if (ssis & (1 << 4))
196                 val1 |= is_clk_master ? 0x2 << 16 :
197                                         0x1 << 16;
198         /* SSI9 is sharing pin with SSI0 */
199         if (ssis & (1 << 9))
200                 val2 |= is_clk_master ? 0x2 : 0x1;
201
202         rsnd_mod_bset(mod, SSI_MODE1, 0x0013001f, val1);
203         rsnd_mod_bset(mod, SSI_MODE2, 0x00000017, val2);
204
205         /*
206          * Enable busif buffer over/under run interrupt.
207          * It will be handled from ssi.c
208          * see
209          *      __rsnd_ssi_interrupt()
210          */
211         rsnd_ssiu_busif_err_irq_enable(mod);
212
213         return 0;
214 }
215
216 static int rsnd_ssiu_quit(struct rsnd_mod *mod,
217                           struct rsnd_dai_stream *io,
218                           struct rsnd_priv *priv)
219 {
220         /* disable busif buffer over/under run interrupt. */
221         rsnd_ssiu_busif_err_irq_disable(mod);
222
223         return 0;
224 }
225
226 static struct rsnd_mod_ops rsnd_ssiu_ops_gen1 = {
227         .name           = SSIU_NAME,
228         .init           = rsnd_ssiu_init,
229         .quit           = rsnd_ssiu_quit,
230         .get_status     = rsnd_ssiu_get_status,
231 };
232
233 static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
234                                struct rsnd_dai_stream *io,
235                                struct rsnd_priv *priv)
236 {
237         struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
238         u32 has_hdmi0 = rsnd_flags_has(io, RSND_STREAM_HDMI0);
239         u32 has_hdmi1 = rsnd_flags_has(io, RSND_STREAM_HDMI1);
240         int ret;
241         u32 mode = 0;
242
243         ret = rsnd_ssiu_init(mod, io, priv);
244         if (ret < 0)
245                 return ret;
246
247         ssiu->usrcnt++;
248
249         /*
250          * TDM Extend/Split Mode
251          * see
252          *      rsnd_ssi_config_init()
253          */
254         if (rsnd_runtime_is_tdm(io))
255                 mode = TDM_EXT;
256         else if (rsnd_runtime_is_tdm_split(io))
257                 mode = TDM_SPLIT;
258
259         rsnd_mod_write(mod, SSI_MODE, mode);
260
261         if (rsnd_ssi_use_busif(io)) {
262                 int id = rsnd_mod_id(mod);
263                 int busif = rsnd_mod_id_sub(mod);
264                 enum rsnd_reg adinr_reg, mode_reg, dalign_reg;
265
266                 if ((id == 9) && (busif >= 4)) {
267                         adinr_reg = SSI9_BUSIF_ADINR(busif);
268                         mode_reg = SSI9_BUSIF_MODE(busif);
269                         dalign_reg = SSI9_BUSIF_DALIGN(busif);
270                 } else {
271                         adinr_reg = SSI_BUSIF_ADINR(busif);
272                         mode_reg = SSI_BUSIF_MODE(busif);
273                         dalign_reg = SSI_BUSIF_DALIGN(busif);
274                 }
275
276                 rsnd_mod_write(mod, adinr_reg,
277                                rsnd_get_adinr_bit(mod, io) |
278                                (rsnd_io_is_play(io) ?
279                                 rsnd_runtime_channel_after_ctu(io) :
280                                 rsnd_runtime_channel_original(io)));
281                 rsnd_mod_write(mod, mode_reg,
282                                rsnd_get_busif_shift(io, mod) | 1);
283                 rsnd_mod_write(mod, dalign_reg,
284                                rsnd_get_dalign(mod, io));
285         }
286
287         if (has_hdmi0 || has_hdmi1) {
288                 enum rsnd_mod_type rsnd_ssi_array[] = {
289                         RSND_MOD_SSIM1,
290                         RSND_MOD_SSIM2,
291                         RSND_MOD_SSIM3,
292                 };
293                 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
294                 struct rsnd_mod *pos;
295                 u32 val;
296                 int i;
297
298                 i = rsnd_mod_id(ssi_mod);
299
300                 /* output all same SSI as default */
301                 val =   i << 16 |
302                         i << 20 |
303                         i << 24 |
304                         i << 28 |
305                         i;
306
307                 for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) {
308                         int shift = (i * 4) + 20;
309
310                         val     = (val & ~(0xF << shift)) |
311                                 rsnd_mod_id(pos) << shift;
312                 }
313
314                 if (has_hdmi0)
315                         rsnd_mod_write(mod, HDMI0_SEL, val);
316                 if (has_hdmi1)
317                         rsnd_mod_write(mod, HDMI1_SEL, val);
318         }
319
320         return 0;
321 }
322
323 static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod,
324                                 struct rsnd_dai_stream *io,
325                                 struct rsnd_priv *priv)
326 {
327         int busif = rsnd_mod_id_sub(mod);
328
329         if (!rsnd_ssi_use_busif(io))
330                 return 0;
331
332         rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4));
333
334         if (rsnd_ssi_multi_secondaries_runtime(io))
335                 rsnd_mod_write(mod, SSI_CONTROL, 0x1);
336
337         return 0;
338 }
339
340 static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod,
341                                struct rsnd_dai_stream *io,
342                                struct rsnd_priv *priv)
343 {
344         struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
345         int busif = rsnd_mod_id_sub(mod);
346
347         if (!rsnd_ssi_use_busif(io))
348                 return 0;
349
350         rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0);
351
352         if (--ssiu->usrcnt)
353                 return 0;
354
355         if (rsnd_ssi_multi_secondaries_runtime(io))
356                 rsnd_mod_write(mod, SSI_CONTROL, 0);
357
358         return 0;
359 }
360
361 static int rsnd_ssiu_id(struct rsnd_mod *mod)
362 {
363         struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
364
365         /* see rsnd_ssiu_probe() */
366         return ssiu->id;
367 }
368
369 static int rsnd_ssiu_id_sub(struct rsnd_mod *mod)
370 {
371         struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
372
373         /* see rsnd_ssiu_probe() */
374         return ssiu->id_sub;
375 }
376
377 static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io,
378                                           struct rsnd_mod *mod)
379 {
380         struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
381         int is_play = rsnd_io_is_play(io);
382         char *name;
383
384         /*
385          * It should use "rcar_sound,ssiu" on DT.
386          * But, we need to keep compatibility for old version.
387          *
388          * If it has "rcar_sound.ssiu", it will be used.
389          * If not, "rcar_sound.ssi" will be used.
390          * see
391          *      rsnd_ssi_dma_req()
392          *      rsnd_dma_of_path()
393          */
394
395         name = is_play ? "rx" : "tx";
396
397         return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv),
398                                         SSIU_NAME, mod, name);
399 }
400
401 #ifdef CONFIG_DEBUG_FS
402 static void rsnd_ssiu_debug_info(struct seq_file *m,
403                                  struct rsnd_dai_stream *io,
404                                 struct rsnd_mod *mod)
405 {
406         rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SSIU,
407                                   rsnd_mod_id(mod) * 0x80, 0x80);
408 }
409 #define DEBUG_INFO .debug_info = rsnd_ssiu_debug_info
410 #else
411 #define DEBUG_INFO
412 #endif
413
414 static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = {
415         .name           = SSIU_NAME,
416         .dma_req        = rsnd_ssiu_dma_req,
417         .init           = rsnd_ssiu_init_gen2,
418         .start          = rsnd_ssiu_start_gen2,
419         .stop           = rsnd_ssiu_stop_gen2,
420         .get_status     = rsnd_ssiu_get_status,
421         DEBUG_INFO
422 };
423
424 static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id)
425 {
426         if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv)))
427                 id = 0;
428
429         return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id);
430 }
431
432 static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv,
433                                                struct rsnd_dai_stream *io)
434 {
435         struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
436         struct rsnd_ssiu *ssiu;
437         int is_dma_mode;
438         int i;
439
440         if (!ssi_mod)
441                 return;
442
443         is_dma_mode = rsnd_ssi_is_dma_mode(ssi_mod);
444
445         /* select BUSIF0 */
446         for_each_rsnd_ssiu(ssiu, priv, i) {
447                 struct rsnd_mod *mod = rsnd_mod_get(ssiu);
448
449                 if (is_dma_mode &&
450                     (rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) &&
451                     (rsnd_mod_id_sub(mod) == 0)) {
452                         rsnd_dai_connect(mod, io, mod->type);
453                         return;
454                 }
455         }
456 }
457
458 void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
459                              struct device_node *playback,
460                              struct device_node *capture)
461 {
462         struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
463         struct device_node *node = rsnd_ssiu_of_node(priv);
464         struct rsnd_dai_stream *io_p = &rdai->playback;
465         struct rsnd_dai_stream *io_c = &rdai->capture;
466
467         /* use rcar_sound,ssiu if exist */
468         if (node) {
469                 struct device_node *np;
470                 int i = 0;
471
472                 for_each_child_of_node(node, np) {
473                         struct rsnd_mod *mod;
474
475                         i = rsnd_node_fixed_index(np, SSIU_NAME, i);
476
477                         mod = rsnd_ssiu_mod_get(priv, i);
478
479                         if (np == playback)
480                                 rsnd_dai_connect(mod, io_p, mod->type);
481                         if (np == capture)
482                                 rsnd_dai_connect(mod, io_c, mod->type);
483                         i++;
484                 }
485
486                 of_node_put(node);
487         }
488
489         /* Keep DT compatibility */
490         if (!rsnd_io_to_mod_ssiu(io_p))
491                 rsnd_parse_connect_ssiu_compatible(priv, io_p);
492         if (!rsnd_io_to_mod_ssiu(io_c))
493                 rsnd_parse_connect_ssiu_compatible(priv, io_c);
494 }
495
496 int rsnd_ssiu_probe(struct rsnd_priv *priv)
497 {
498         struct device *dev = rsnd_priv_to_dev(priv);
499         struct device_node *node;
500         struct rsnd_ssiu *ssiu;
501         struct rsnd_mod_ops *ops;
502         const int *list = NULL;
503         int i, nr;
504
505         /*
506          * Keep DT compatibility.
507          * if it has "rcar_sound,ssiu", use it.
508          * if not, use "rcar_sound,ssi"
509          * see
510          *      rsnd_ssiu_bufsif_to_id()
511          */
512         node = rsnd_ssiu_of_node(priv);
513         if (node)
514                 nr = rsnd_node_count(priv, node, SSIU_NAME);
515         else
516                 nr = priv->ssi_nr;
517
518         if (!nr)
519                 return -EINVAL;
520
521         ssiu    = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL);
522         if (!ssiu)
523                 return -ENOMEM;
524
525         priv->ssiu      = ssiu;
526         priv->ssiu_nr   = nr;
527
528         if (rsnd_is_gen1(priv))
529                 ops = &rsnd_ssiu_ops_gen1;
530         else
531                 ops = &rsnd_ssiu_ops_gen2;
532
533         /* Keep compatibility */
534         nr = 0;
535         if ((node) &&
536             (ops == &rsnd_ssiu_ops_gen2)) {
537                 ops->id         = rsnd_ssiu_id;
538                 ops->id_sub     = rsnd_ssiu_id_sub;
539
540                 if (rsnd_is_gen2(priv)) {
541                         list    = gen2_id;
542                         nr      = ARRAY_SIZE(gen2_id);
543                 } else if (rsnd_is_gen3(priv)) {
544                         list    = gen3_id;
545                         nr      = ARRAY_SIZE(gen3_id);
546                 } else {
547                         dev_err(dev, "unknown SSIU\n");
548                         return -ENODEV;
549                 }
550         }
551
552         for_each_rsnd_ssiu(ssiu, priv, i) {
553                 int ret;
554
555                 if (node) {
556                         int j;
557
558                         /*
559                          * see
560                          *      rsnd_ssiu_get_id()
561                          *      rsnd_ssiu_get_id_sub()
562                          */
563                         for (j = 0; j < nr; j++) {
564                                 if (list[j] > i)
565                                         break;
566                                 ssiu->id        = j;
567                                 ssiu->id_sub    = i - list[ssiu->id];
568                         }
569                 } else {
570                         ssiu->id = i;
571                 }
572
573                 ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu),
574                                     ops, NULL, RSND_MOD_SSIU, i);
575                 if (ret)
576                         return ret;
577         }
578
579         return 0;
580 }
581
582 void rsnd_ssiu_remove(struct rsnd_priv *priv)
583 {
584         struct rsnd_ssiu *ssiu;
585         int i;
586
587         for_each_rsnd_ssiu(ssiu, priv, i) {
588                 rsnd_mod_quit(rsnd_mod_get(ssiu));
589         }
590 }