1 // SPDX-License-Identifier: GPL-2.0
3 // Renesas R-Car SSIU support
5 // Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
9 #define SSIU_NAME "ssiu"
13 u32 busif_status
[8]; /* for BUSIF0 - BUSIF7 */
20 #define TDM_EXT (1 << 0)
21 #define TDM_SPLIT (1 << 8)
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) \
27 (i < rsnd_ssiu_nr(priv)) && \
28 ((pos) = ((struct rsnd_ssiu *)(priv)->ssiu + i)); \
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 };
48 static u32
*rsnd_ssiu_get_status(struct rsnd_mod
*mod
,
49 struct rsnd_dai_stream
*io
,
50 enum rsnd_mod_type type
)
52 struct rsnd_ssiu
*ssiu
= rsnd_mod_to_ssiu(mod
);
53 int busif
= rsnd_mod_id_sub(mod
);
55 return &ssiu
->busif_status
[busif
];
58 static int rsnd_ssiu_init(struct rsnd_mod
*mod
,
59 struct rsnd_dai_stream
*io
,
60 struct rsnd_priv
*priv
)
62 struct rsnd_dai
*rdai
= rsnd_io_to_rdai(io
);
63 u32 ssis
= rsnd_ssi_multi_secondaries_runtime(io
);
64 int use_busif
= rsnd_ssi_use_busif(io
);
65 int id
= rsnd_mod_id(mod
);
66 int is_clk_master
= rsnd_rdai_is_clk_master(rdai
);
77 for (i
= 0; i
< 4; i
++)
78 rsnd_mod_write(mod
, SSI_SYS_STATUS(i
* 2), 0xf << (id
* 4));
81 for (i
= 0; i
< 4; i
++)
82 rsnd_mod_write(mod
, SSI_SYS_STATUS((i
* 2) + 1), 0xf << 4);
89 rsnd_mod_bset(mod
, SSI_MODE0
, (1 << id
), !use_busif
<< id
);
92 * SSI_MODE1 / SSI_MODE2
95 * sharing/multi with SSI0 are mainly supported
97 val1
= rsnd_mod_read(mod
, SSI_MODE1
);
98 val2
= rsnd_mod_read(mod
, SSI_MODE2
);
99 if (rsnd_ssi_is_pin_sharing(io
)) {
107 * set synchronized bit here
110 /* SSI4 is synchronized with SSI3 */
113 /* SSI012 are synchronized */
116 /* SSI0129 are synchronized */
121 /* SSI1 is sharing pin with SSI0 */
123 val1
|= is_clk_master
? 0x2 : 0x1;
125 /* SSI2 is sharing pin with SSI0 */
127 val1
|= is_clk_master
? 0x2 << 2 :
129 /* SSI4 is sharing pin with SSI3 */
131 val1
|= is_clk_master
? 0x2 << 16 :
133 /* SSI9 is sharing pin with SSI0 */
135 val2
|= is_clk_master
? 0x2 : 0x1;
137 rsnd_mod_bset(mod
, SSI_MODE1
, 0x0013001f, val1
);
138 rsnd_mod_bset(mod
, SSI_MODE2
, 0x00000017, val2
);
143 static struct rsnd_mod_ops rsnd_ssiu_ops_gen1
= {
145 .init
= rsnd_ssiu_init
,
146 .get_status
= rsnd_ssiu_get_status
,
149 static int rsnd_ssiu_init_gen2(struct rsnd_mod
*mod
,
150 struct rsnd_dai_stream
*io
,
151 struct rsnd_priv
*priv
)
153 struct rsnd_ssiu
*ssiu
= rsnd_mod_to_ssiu(mod
);
154 u32 has_hdmi0
= rsnd_flags_has(io
, RSND_STREAM_HDMI0
);
155 u32 has_hdmi1
= rsnd_flags_has(io
, RSND_STREAM_HDMI1
);
159 ret
= rsnd_ssiu_init(mod
, io
, priv
);
166 * TDM Extend/Split Mode
168 * rsnd_ssi_config_init()
170 if (rsnd_runtime_is_tdm(io
))
172 else if (rsnd_runtime_is_tdm_split(io
))
175 rsnd_mod_write(mod
, SSI_MODE
, mode
);
177 if (rsnd_ssi_use_busif(io
)) {
178 int id
= rsnd_mod_id(mod
);
179 int busif
= rsnd_mod_id_sub(mod
);
180 enum rsnd_reg adinr_reg
, mode_reg
, dalign_reg
;
182 if ((id
== 9) && (busif
>= 4)) {
183 adinr_reg
= SSI9_BUSIF_ADINR(busif
);
184 mode_reg
= SSI9_BUSIF_MODE(busif
);
185 dalign_reg
= SSI9_BUSIF_DALIGN(busif
);
187 adinr_reg
= SSI_BUSIF_ADINR(busif
);
188 mode_reg
= SSI_BUSIF_MODE(busif
);
189 dalign_reg
= SSI_BUSIF_DALIGN(busif
);
192 rsnd_mod_write(mod
, adinr_reg
,
193 rsnd_get_adinr_bit(mod
, io
) |
194 (rsnd_io_is_play(io
) ?
195 rsnd_runtime_channel_after_ctu(io
) :
196 rsnd_runtime_channel_original(io
)));
197 rsnd_mod_write(mod
, mode_reg
,
198 rsnd_get_busif_shift(io
, mod
) | 1);
199 rsnd_mod_write(mod
, dalign_reg
,
200 rsnd_get_dalign(mod
, io
));
203 if (has_hdmi0
|| has_hdmi1
) {
204 enum rsnd_mod_type rsnd_ssi_array
[] = {
209 struct rsnd_mod
*ssi_mod
= rsnd_io_to_mod_ssi(io
);
210 struct rsnd_mod
*pos
;
214 i
= rsnd_mod_id(ssi_mod
);
216 /* output all same SSI as default */
223 for_each_rsnd_mod_array(i
, pos
, io
, rsnd_ssi_array
) {
224 shift
= (i
* 4) + 20;
225 val
= (val
& ~(0xF << shift
)) |
226 rsnd_mod_id(pos
) << shift
;
230 rsnd_mod_write(mod
, HDMI0_SEL
, val
);
232 rsnd_mod_write(mod
, HDMI1_SEL
, val
);
238 static int rsnd_ssiu_start_gen2(struct rsnd_mod
*mod
,
239 struct rsnd_dai_stream
*io
,
240 struct rsnd_priv
*priv
)
242 int busif
= rsnd_mod_id_sub(mod
);
244 if (!rsnd_ssi_use_busif(io
))
247 rsnd_mod_bset(mod
, SSI_CTRL
, 1 << (busif
* 4), 1 << (busif
* 4));
249 if (rsnd_ssi_multi_secondaries_runtime(io
))
250 rsnd_mod_write(mod
, SSI_CONTROL
, 0x1);
255 static int rsnd_ssiu_stop_gen2(struct rsnd_mod
*mod
,
256 struct rsnd_dai_stream
*io
,
257 struct rsnd_priv
*priv
)
259 struct rsnd_ssiu
*ssiu
= rsnd_mod_to_ssiu(mod
);
260 int busif
= rsnd_mod_id_sub(mod
);
262 if (!rsnd_ssi_use_busif(io
))
265 rsnd_mod_bset(mod
, SSI_CTRL
, 1 << (busif
* 4), 0);
270 if (rsnd_ssi_multi_secondaries_runtime(io
))
271 rsnd_mod_write(mod
, SSI_CONTROL
, 0);
276 static int rsnd_ssiu_id(struct rsnd_mod
*mod
)
278 struct rsnd_ssiu
*ssiu
= rsnd_mod_to_ssiu(mod
);
280 /* see rsnd_ssiu_probe() */
284 static int rsnd_ssiu_id_sub(struct rsnd_mod
*mod
)
286 struct rsnd_ssiu
*ssiu
= rsnd_mod_to_ssiu(mod
);
288 /* see rsnd_ssiu_probe() */
292 static struct dma_chan
*rsnd_ssiu_dma_req(struct rsnd_dai_stream
*io
,
293 struct rsnd_mod
*mod
)
295 struct rsnd_priv
*priv
= rsnd_mod_to_priv(mod
);
296 int is_play
= rsnd_io_is_play(io
);
300 * It should use "rcar_sound,ssiu" on DT.
301 * But, we need to keep compatibility for old version.
303 * If it has "rcar_sound.ssiu", it will be used.
304 * If not, "rcar_sound.ssi" will be used.
310 name
= is_play
? "rx" : "tx";
312 return rsnd_dma_request_channel(rsnd_ssiu_of_node(priv
),
316 static struct rsnd_mod_ops rsnd_ssiu_ops_gen2
= {
318 .dma_req
= rsnd_ssiu_dma_req
,
319 .init
= rsnd_ssiu_init_gen2
,
320 .start
= rsnd_ssiu_start_gen2
,
321 .stop
= rsnd_ssiu_stop_gen2
,
322 .get_status
= rsnd_ssiu_get_status
,
325 static struct rsnd_mod
*rsnd_ssiu_mod_get(struct rsnd_priv
*priv
, int id
)
327 if (WARN_ON(id
< 0 || id
>= rsnd_ssiu_nr(priv
)))
330 return rsnd_mod_get((struct rsnd_ssiu
*)(priv
->ssiu
) + id
);
333 static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv
*priv
,
334 struct rsnd_dai_stream
*io
)
336 struct rsnd_mod
*ssi_mod
= rsnd_io_to_mod_ssi(io
);
337 struct rsnd_mod
*mod
;
338 struct rsnd_ssiu
*ssiu
;
345 for_each_rsnd_ssiu(ssiu
, priv
, i
) {
346 mod
= rsnd_mod_get(ssiu
);
348 if ((rsnd_mod_id(ssi_mod
) == rsnd_mod_id(mod
)) &&
349 (rsnd_mod_id_sub(mod
) == 0)) {
350 rsnd_dai_connect(mod
, io
, mod
->type
);
356 void rsnd_parse_connect_ssiu(struct rsnd_dai
*rdai
,
357 struct device_node
*playback
,
358 struct device_node
*capture
)
360 struct rsnd_priv
*priv
= rsnd_rdai_to_priv(rdai
);
361 struct device_node
*node
= rsnd_ssiu_of_node(priv
);
362 struct device_node
*np
;
363 struct rsnd_mod
*mod
;
364 struct rsnd_dai_stream
*io_p
= &rdai
->playback
;
365 struct rsnd_dai_stream
*io_c
= &rdai
->capture
;
368 /* use rcar_sound,ssiu if exist */
371 for_each_child_of_node(node
, np
) {
372 mod
= rsnd_ssiu_mod_get(priv
, i
);
374 rsnd_dai_connect(mod
, io_p
, mod
->type
);
376 rsnd_dai_connect(mod
, io_c
, mod
->type
);
383 /* Keep DT compatibility */
384 if (!rsnd_io_to_mod_ssiu(io_p
))
385 rsnd_parse_connect_ssiu_compatible(priv
, io_p
);
386 if (!rsnd_io_to_mod_ssiu(io_c
))
387 rsnd_parse_connect_ssiu_compatible(priv
, io_c
);
390 int rsnd_ssiu_probe(struct rsnd_priv
*priv
)
392 struct device
*dev
= rsnd_priv_to_dev(priv
);
393 struct device_node
*node
;
394 struct rsnd_ssiu
*ssiu
;
395 struct rsnd_mod_ops
*ops
;
396 const int *list
= NULL
;
400 * Keep DT compatibility.
401 * if it has "rcar_sound,ssiu", use it.
402 * if not, use "rcar_sound,ssi"
404 * rsnd_ssiu_bufsif_to_id()
406 node
= rsnd_ssiu_of_node(priv
);
408 nr
= of_get_child_count(node
);
412 ssiu
= devm_kcalloc(dev
, nr
, sizeof(*ssiu
), GFP_KERNEL
);
419 if (rsnd_is_gen1(priv
))
420 ops
= &rsnd_ssiu_ops_gen1
;
422 ops
= &rsnd_ssiu_ops_gen2
;
424 /* Keep compatibility */
427 (ops
== &rsnd_ssiu_ops_gen2
)) {
428 ops
->id
= rsnd_ssiu_id
;
429 ops
->id_sub
= rsnd_ssiu_id_sub
;
431 if (rsnd_is_gen2(priv
)) {
433 nr
= ARRAY_SIZE(gen2_id
);
434 } else if (rsnd_is_gen3(priv
)) {
436 nr
= ARRAY_SIZE(gen3_id
);
438 dev_err(dev
, "unknown SSIU\n");
443 for_each_rsnd_ssiu(ssiu
, priv
, i
) {
450 * rsnd_ssiu_get_id_sub()
452 for (j
= 0; j
< nr
; j
++) {
456 ssiu
->id_sub
= i
- list
[ssiu
->id
];
462 ret
= rsnd_mod_init(priv
, rsnd_mod_get(ssiu
),
463 ops
, NULL
, RSND_MOD_SSIU
, i
);
471 void rsnd_ssiu_remove(struct rsnd_priv
*priv
)
473 struct rsnd_ssiu
*ssiu
;
476 for_each_rsnd_ssiu(ssiu
, priv
, i
) {
477 rsnd_mod_quit(rsnd_mod_get(ssiu
));