Merge branches 'clk-imx', 'clk-samsung', 'clk-ti', 'clk-uniphier-gear' and 'clk-mmp2...
[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 static 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
58 static 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         /* clear status */
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          * SSI_MODE0
88          */
89         rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
90
91         /*
92          * SSI_MODE1
93          */
94         mask1 = (1 << 4) | (1 << 20);   /* mask sync bit */
95         mask2 = (1 << 4);               /* mask sync bit */
96         val1  = val2  = 0;
97         if (id == 8) {
98                 /*
99                  * SSI8 pin is sharing with SSI7, nothing to do.
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: /* SSI0/1/2/9 */
129                         val2 = (1 << 4) | /* SSI0129 sync */
130                                 (rsnd_rdai_is_clk_master(rdai) ? 0x2 : 0x1);
131                         /* fall through */
132                 case 0x0006: /* SSI0/1/2 */
133                         val1 = rsnd_rdai_is_clk_master(rdai) ?
134                                 0xa : 0x5;
135
136                         if (!val2)  /* SSI012 sync */
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
147 static 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
153 static 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          * TDM Extend/Split Mode
171          * see
172          *      rsnd_ssi_config_init()
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
185                 /*
186                  * FIXME
187                  *
188                  * We can't support SSI9-4/5/6/7, because its address is
189                  * out of calculation rule
190                  */
191                 if ((id == 9) && (busif >= 4)) {
192                         struct device *dev = rsnd_priv_to_dev(priv);
193
194                         dev_err(dev, "This driver doesn't support SSI%d-%d, so far",
195                                 id, busif);
196                 }
197
198                 rsnd_mod_write(mod, SSI_BUSIF_ADINR(busif),
199                                rsnd_get_adinr_bit(mod, io) |
200                                (rsnd_io_is_play(io) ?
201                                 rsnd_runtime_channel_after_ctu(io) :
202                                 rsnd_runtime_channel_original(io)));
203                 rsnd_mod_write(mod, SSI_BUSIF_MODE(busif),
204                                rsnd_get_busif_shift(io, mod) | 1);
205                 rsnd_mod_write(mod, SSI_BUSIF_DALIGN(busif),
206                                rsnd_get_dalign(mod, io));
207         }
208
209         if (has_hdmi0 || has_hdmi1) {
210                 enum rsnd_mod_type rsnd_ssi_array[] = {
211                         RSND_MOD_SSIM1,
212                         RSND_MOD_SSIM2,
213                         RSND_MOD_SSIM3,
214                 };
215                 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
216                 struct rsnd_mod *pos;
217                 u32 val;
218                 int i, shift;
219
220                 i = rsnd_mod_id(ssi_mod);
221
222                 /* output all same SSI as default */
223                 val =   i << 16 |
224                         i << 20 |
225                         i << 24 |
226                         i << 28 |
227                         i;
228
229                 for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) {
230                         shift   = (i * 4) + 16;
231                         val     = (val & ~(0xF << shift)) |
232                                 rsnd_mod_id(pos) << shift;
233                 }
234
235                 if (has_hdmi0)
236                         rsnd_mod_write(mod, HDMI0_SEL, val);
237                 if (has_hdmi1)
238                         rsnd_mod_write(mod, HDMI1_SEL, val);
239         }
240
241         return 0;
242 }
243
244 static int rsnd_ssiu_start_gen2(struct rsnd_mod *mod,
245                                 struct rsnd_dai_stream *io,
246                                 struct rsnd_priv *priv)
247 {
248         int busif = rsnd_mod_id_sub(mod);
249
250         if (!rsnd_ssi_use_busif(io))
251                 return 0;
252
253         rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 1 << (busif * 4));
254
255         if (rsnd_ssi_multi_slaves_runtime(io))
256                 rsnd_mod_write(mod, SSI_CONTROL, 0x1);
257
258         return 0;
259 }
260
261 static int rsnd_ssiu_stop_gen2(struct rsnd_mod *mod,
262                                struct rsnd_dai_stream *io,
263                                struct rsnd_priv *priv)
264 {
265         struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
266         int busif = rsnd_mod_id_sub(mod);
267
268         if (!rsnd_ssi_use_busif(io))
269                 return 0;
270
271         rsnd_mod_bset(mod, SSI_CTRL, 1 << (busif * 4), 0);
272
273         if (--ssiu->usrcnt)
274                 return 0;
275
276         if (rsnd_ssi_multi_slaves_runtime(io))
277                 rsnd_mod_write(mod, SSI_CONTROL, 0);
278
279         return 0;
280 }
281
282 static int rsnd_ssiu_id(struct rsnd_mod *mod)
283 {
284         struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
285
286         /* see rsnd_ssiu_probe() */
287         return ssiu->id;
288 }
289
290 static int rsnd_ssiu_id_sub(struct rsnd_mod *mod)
291 {
292         struct rsnd_ssiu *ssiu = rsnd_mod_to_ssiu(mod);
293
294         /* see rsnd_ssiu_probe() */
295         return ssiu->id_sub;
296 }
297
298 static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io,
299                                           struct rsnd_mod *mod)
300 {
301         struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
302         int is_play = rsnd_io_is_play(io);
303         char *name;
304
305         /*
306          * It should use "rcar_sound,ssiu" on DT.
307          * But, we need to keep compatibility for old version.
308          *
309          * If it has "rcar_sound.ssiu", it will be used.
310          * If not, "rcar_sound.ssi" will be used.
311          * see
312          *      rsnd_ssi_dma_req()
313          *      rsnd_dma_of_path()
314          */
315
316         name = is_play ? "rx" : "tx";
317
318         return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv),
319                                         mod, name);
320 }
321
322 static struct rsnd_mod_ops rsnd_ssiu_ops_gen2 = {
323         .name           = SSIU_NAME,
324         .dma_req        = rsnd_ssiu_dma_req,
325         .init           = rsnd_ssiu_init_gen2,
326         .start          = rsnd_ssiu_start_gen2,
327         .stop           = rsnd_ssiu_stop_gen2,
328         .get_status     = rsnd_ssiu_get_status,
329 };
330
331 static struct rsnd_mod *rsnd_ssiu_mod_get(struct rsnd_priv *priv, int id)
332 {
333         if (WARN_ON(id < 0 || id >= rsnd_ssiu_nr(priv)))
334                 id = 0;
335
336         return rsnd_mod_get((struct rsnd_ssiu *)(priv->ssiu) + id);
337 }
338
339 static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv,
340                                                struct rsnd_dai_stream *io)
341 {
342         struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
343         struct rsnd_mod *mod;
344         struct rsnd_ssiu *ssiu;
345         int i;
346
347         if (!ssi_mod)
348                 return;
349
350         /* select BUSIF0 */
351         for_each_rsnd_ssiu(ssiu, priv, i) {
352                 mod = rsnd_mod_get(ssiu);
353
354                 if ((rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) &&
355                     (rsnd_mod_id_sub(mod) == 0)) {
356                         rsnd_dai_connect(mod, io, mod->type);
357                         return;
358                 }
359         }
360 }
361
362 void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
363                              struct device_node *playback,
364                              struct device_node *capture)
365 {
366         struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
367         struct device_node *node = rsnd_ssiu_of_node(priv);
368         struct device_node *np;
369         struct rsnd_mod *mod;
370         struct rsnd_dai_stream *io_p = &rdai->playback;
371         struct rsnd_dai_stream *io_c = &rdai->capture;
372         int i;
373
374         /* use rcar_sound,ssiu if exist */
375         if (node) {
376                 i = 0;
377                 for_each_child_of_node(node, np) {
378                         mod = rsnd_ssiu_mod_get(priv, i);
379                         if (np == playback)
380                                 rsnd_dai_connect(mod, io_p, mod->type);
381                         if (np == capture)
382                                 rsnd_dai_connect(mod, io_c, mod->type);
383                         i++;
384                 }
385
386                 of_node_put(node);
387         }
388
389         /* Keep DT compatibility */
390         if (!rsnd_io_to_mod_ssiu(io_p))
391                 rsnd_parse_connect_ssiu_compatible(priv, io_p);
392         if (!rsnd_io_to_mod_ssiu(io_c))
393                 rsnd_parse_connect_ssiu_compatible(priv, io_c);
394 }
395
396 int rsnd_ssiu_probe(struct rsnd_priv *priv)
397 {
398         struct device *dev = rsnd_priv_to_dev(priv);
399         struct device_node *node;
400         struct rsnd_ssiu *ssiu;
401         struct rsnd_mod_ops *ops;
402         const int *list = NULL;
403         int i, nr, ret;
404
405         /*
406          * Keep DT compatibility.
407          * if it has "rcar_sound,ssiu", use it.
408          * if not, use "rcar_sound,ssi"
409          * see
410          *      rsnd_ssiu_bufsif_to_id()
411          */
412         node = rsnd_ssiu_of_node(priv);
413         if (node)
414                 nr = of_get_child_count(node);
415         else
416                 nr = priv->ssi_nr;
417
418         ssiu    = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL);
419         if (!ssiu)
420                 return -ENOMEM;
421
422         priv->ssiu      = ssiu;
423         priv->ssiu_nr   = nr;
424
425         if (rsnd_is_gen1(priv))
426                 ops = &rsnd_ssiu_ops_gen1;
427         else
428                 ops = &rsnd_ssiu_ops_gen2;
429
430         /* Keep compatibility */
431         nr = 0;
432         if ((node) &&
433             (ops == &rsnd_ssiu_ops_gen2)) {
434                 ops->id         = rsnd_ssiu_id;
435                 ops->id_sub     = rsnd_ssiu_id_sub;
436
437                 if (rsnd_is_gen2(priv)) {
438                         list    = gen2_id;
439                         nr      = ARRAY_SIZE(gen2_id);
440                 } else if (rsnd_is_gen3(priv)) {
441                         list    = gen3_id;
442                         nr      = ARRAY_SIZE(gen3_id);
443                 } else {
444                         dev_err(dev, "unknown SSIU\n");
445                         return -ENODEV;
446                 }
447         }
448
449         for_each_rsnd_ssiu(ssiu, priv, i) {
450                 if (node) {
451                         int j;
452
453                         /*
454                          * see
455                          *      rsnd_ssiu_get_id()
456                          *      rsnd_ssiu_get_id_sub()
457                          */
458                         for (j = 0; j < nr; j++) {
459                                 if (list[j] > i)
460                                         break;
461                                 ssiu->id        = j;
462                                 ssiu->id_sub    = i - list[ssiu->id];
463                         }
464                 } else {
465                         ssiu->id = i;
466                 }
467
468                 ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu),
469                                     ops, NULL, RSND_MOD_SSIU, i);
470                 if (ret)
471                         return ret;
472         }
473
474         return 0;
475 }
476
477 void rsnd_ssiu_remove(struct rsnd_priv *priv)
478 {
479         struct rsnd_ssiu *ssiu;
480         int i;
481
482         for_each_rsnd_ssiu(ssiu, priv, i) {
483                 rsnd_mod_quit(rsnd_mod_get(ssiu));
484         }
485 }