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