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