]> Git Repo - linux.git/blame - sound/soc/sh/rcar/ssi.c
ASoC: rsnd: SSI parent cares SWSP bit
[linux.git] / sound / soc / sh / rcar / ssi.c
CommitLineData
ae5c3223
KM
1/*
2 * Renesas R-Car SSIU/SSI support
3 *
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * Kuninori Morimoto <[email protected]>
6 *
7 * Based on fsi.c
8 * Kuninori Morimoto <[email protected]>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
2b627869
KM
14
15/*
16 * you can enable below define if you don't need
17 * SSI interrupt status debug message when debugging
18 * see rsnd_dbg_irq_status()
19 *
20 * #define RSND_DEBUG_NO_IRQ_STATUS 1
21 */
22
7fa72cca 23#include <sound/simple_card_utils.h>
ae5c3223
KM
24#include <linux/delay.h>
25#include "rsnd.h"
26#define RSND_SSI_NAME_SIZE 16
27
28/*
29 * SSICR
30 */
31#define FORCE (1 << 31) /* Fixed */
849fc82a 32#define DMEN (1 << 28) /* DMA Enable */
ae5c3223
KM
33#define UIEN (1 << 27) /* Underflow Interrupt Enable */
34#define OIEN (1 << 26) /* Overflow Interrupt Enable */
35#define IIEN (1 << 25) /* Idle Mode Interrupt Enable */
36#define DIEN (1 << 24) /* Data Interrupt Enable */
186fadc1
KM
37#define CHNL_4 (1 << 22) /* Channels */
38#define CHNL_6 (2 << 22) /* Channels */
39#define CHNL_8 (3 << 22) /* Channels */
203cdf51 40#define DWL_MASK (7 << 19) /* Data Word Length mask */
ae5c3223
KM
41#define DWL_8 (0 << 19) /* Data Word Length */
42#define DWL_16 (1 << 19) /* Data Word Length */
43#define DWL_18 (2 << 19) /* Data Word Length */
44#define DWL_20 (3 << 19) /* Data Word Length */
45#define DWL_22 (4 << 19) /* Data Word Length */
46#define DWL_24 (5 << 19) /* Data Word Length */
47#define DWL_32 (6 << 19) /* Data Word Length */
48
49#define SWL_32 (3 << 16) /* R/W System Word Length */
50#define SCKD (1 << 15) /* Serial Bit Clock Direction */
51#define SWSD (1 << 14) /* Serial WS Direction */
52#define SCKP (1 << 13) /* Serial Bit Clock Polarity */
53#define SWSP (1 << 12) /* Serial WS Polarity */
54#define SDTA (1 << 10) /* Serial Data Alignment */
f46a93b8 55#define PDTA (1 << 9) /* Parallel Data Alignment */
ae5c3223
KM
56#define DEL (1 << 8) /* Serial Data Delay */
57#define CKDV(v) (v << 4) /* Serial Clock Division Ratio */
58#define TRMD (1 << 1) /* Transmit/Receive Mode Select */
59#define EN (1 << 0) /* SSI Module Enable */
60
61/*
62 * SSISR
63 */
64#define UIRQ (1 << 27) /* Underflow Error Interrupt Status */
65#define OIRQ (1 << 26) /* Overflow Error Interrupt Status */
66#define IIRQ (1 << 25) /* Idle Mode Interrupt Status */
67#define DIRQ (1 << 24) /* Data Interrupt Status Flag */
68
849fc82a
KM
69/*
70 * SSIWSR
71 */
72#define CONT (1 << 8) /* WS Continue Function */
186fadc1 73#define WS_MODE (1 << 0) /* WS Mode */
849fc82a 74
8aefda50
KM
75#define SSI_NAME "ssi"
76
ae5c3223 77struct rsnd_ssi {
ae5c3223 78 struct rsnd_mod mod;
940e9479 79 struct rsnd_mod *dma;
ae5c3223 80
02534f2f 81 u32 flags;
ae5c3223
KM
82 u32 cr_own;
83 u32 cr_clk;
e7d850dd 84 u32 cr_mode;
597b046f 85 u32 cr_en;
08bada26 86 u32 wsr;
919567d9 87 int chan;
e7d850dd 88 int rate;
02534f2f 89 int irq;
ae5c3223 90 unsigned int usrcnt;
a97a06c7 91
d8d9b973 92 /* for PIO */
a97a06c7 93 int byte_pos;
a97a06c7
KM
94 int byte_per_period;
95 int next_period_byte;
ae5c3223
KM
96};
97
02534f2f
KM
98/* flags */
99#define RSND_SSI_CLK_PIN_SHARE (1 << 0)
100#define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */
7fa72cca
KM
101#define RSND_SSI_HDMI0 (1 << 2) /* for HDMI0 */
102#define RSND_SSI_HDMI1 (1 << 3) /* for HDMI1 */
b6e58fca 103#define RSND_SSI_PROBED (1 << 4)
02534f2f 104
ae5c3223
KM
105#define for_each_rsnd_ssi(pos, priv, i) \
106 for (i = 0; \
107 (i < rsnd_ssi_nr(priv)) && \
dd27d808 108 ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \
ae5c3223
KM
109 i++)
110
02534f2f 111#define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id)
dd27d808 112#define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
ae5c3223 113#define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
e7d850dd 114#define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io))
c308abe4
KM
115#define rsnd_ssi_is_multi_slave(mod, io) \
116 (rsnd_ssi_multi_slaves(io) & (1 << rsnd_mod_id(mod)))
fd9adcfd
KM
117#define rsnd_ssi_is_run_mods(mod, io) \
118 (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod)))
bb002f92 119#define rsnd_ssi_can_output_clk(mod) (!__rsnd_ssi_is_pin_sharing(mod))
ae5c3223 120
7fa72cca
KM
121int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io)
122{
123 struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
124 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
125
42991989 126 if (rsnd_flags_has(ssi, RSND_SSI_HDMI0))
7fa72cca
KM
127 return RSND_SSI_HDMI_PORT0;
128
42991989 129 if (rsnd_flags_has(ssi, RSND_SSI_HDMI1))
7fa72cca
KM
130 return RSND_SSI_HDMI_PORT1;
131
132 return 0;
133}
134
b415b4d3 135int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
d9288d0b 136{
b415b4d3 137 struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
d9288d0b 138 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
d9288d0b
KM
139 int use_busif = 0;
140
7b466fc6
KM
141 if (!rsnd_ssi_is_dma_mode(mod))
142 return 0;
143
42991989 144 if (!(rsnd_flags_has(ssi, RSND_SSI_NO_BUSIF)))
d9288d0b
KM
145 use_busif = 1;
146 if (rsnd_io_to_mod_src(io))
147 use_busif = 1;
148
149 return use_busif;
150}
151
e10369d8
KM
152static void rsnd_ssi_status_clear(struct rsnd_mod *mod)
153{
154 rsnd_mod_write(mod, SSISR, 0);
155}
156
157static u32 rsnd_ssi_status_get(struct rsnd_mod *mod)
158{
159 return rsnd_mod_read(mod, SSISR);
160}
161
ae5c3223
KM
162static void rsnd_ssi_status_check(struct rsnd_mod *mod,
163 u32 bit)
164{
165 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
166 struct device *dev = rsnd_priv_to_dev(priv);
167 u32 status;
168 int i;
169
170 for (i = 0; i < 1024; i++) {
e10369d8 171 status = rsnd_ssi_status_get(mod);
ae5c3223
KM
172 if (status & bit)
173 return;
174
3fd391fb 175 udelay(5);
ae5c3223
KM
176 }
177
1120dbff
KM
178 dev_warn(dev, "%s[%d] status check failed\n",
179 rsnd_mod_name(mod), rsnd_mod_id(mod));
ae5c3223
KM
180}
181
4f5c634d 182static u32 rsnd_ssi_multi_slaves(struct rsnd_dai_stream *io)
b4c83b17
KM
183{
184 struct rsnd_mod *mod;
b4c83b17
KM
185 enum rsnd_mod_type types[] = {
186 RSND_MOD_SSIM1,
187 RSND_MOD_SSIM2,
188 RSND_MOD_SSIM3,
189 };
190 int i, mask;
191
b4c83b17
KM
192 mask = 0;
193 for (i = 0; i < ARRAY_SIZE(types); i++) {
194 mod = rsnd_io_to_mod(io, types[i]);
195 if (!mod)
196 continue;
197
198 mask |= 1 << rsnd_mod_id(mod);
199 }
200
201 return mask;
202}
203
fd9adcfd
KM
204static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io)
205{
206 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
207 struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
21781e87 208 u32 mods;
fd9adcfd 209
21781e87
KM
210 mods = rsnd_ssi_multi_slaves_runtime(io) |
211 1 << rsnd_mod_id(ssi_mod);
212
213 if (ssi_parent_mod)
214 mods |= 1 << rsnd_mod_id(ssi_parent_mod);
215
216 return mods;
fd9adcfd
KM
217}
218
4f5c634d
KM
219u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io)
220{
eed76bb8
KM
221 if (rsnd_runtime_is_ssi_multi(io))
222 return rsnd_ssi_multi_slaves(io);
4f5c634d
KM
223
224 return 0;
225}
226
947f4eb5 227unsigned int rsnd_ssi_clk_query(struct rsnd_priv *priv,
ef4cf5d6
KM
228 int param1, int param2, int *idx)
229{
230 int ssi_clk_mul_table[] = {
231 1, 2, 4, 8, 16, 6, 12,
232 };
233 int j, ret;
947f4eb5 234 unsigned int main_rate;
ef4cf5d6
KM
235
236 for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) {
237
238 /*
239 * It will set SSIWSR.CONT here, but SSICR.CKDV = 000
240 * with it is not allowed. (SSIWSR.WS_MODE with
241 * SSICR.CKDV = 000 is not allowed either).
242 * Skip it. See SSICR.CKDV
243 */
244 if (j == 0)
245 continue;
246
247 /*
248 * this driver is assuming that
249 * system word is 32bit x chan
250 * see rsnd_ssi_init()
251 */
252 main_rate = 32 * param1 * param2 * ssi_clk_mul_table[j];
253
254 ret = rsnd_adg_clk_query(priv, main_rate);
255 if (ret < 0)
256 continue;
257
258 if (idx)
259 *idx = j;
260
261 return main_rate;
262 }
263
947f4eb5 264 return 0;
ef4cf5d6
KM
265}
266
26d34b11 267static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
adcf7d5e 268 struct rsnd_dai_stream *io)
ae5c3223 269{
1b13d118 270 struct rsnd_priv *priv = rsnd_io_to_priv(io);
ae5c3223 271 struct device *dev = rsnd_priv_to_dev(priv);
e7d850dd 272 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
26d34b11 273 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
eed76bb8 274 int chan = rsnd_runtime_channel_for_ssi(io);
ef4cf5d6 275 int idx, ret;
ae5c3223 276 unsigned int main_rate;
cbf1494f
KM
277 unsigned int rate = rsnd_io_is_play(io) ?
278 rsnd_src_get_out_rate(priv, io) :
279 rsnd_src_get_in_rate(priv, io);
ae5c3223 280
e7d850dd
KM
281 if (!rsnd_rdai_is_clk_master(rdai))
282 return 0;
283
bb002f92 284 if (!rsnd_ssi_can_output_clk(mod))
e7d850dd
KM
285 return 0;
286
b4c83b17
KM
287 if (rsnd_ssi_is_multi_slave(mod, io))
288 return 0;
289
e7d850dd
KM
290 if (ssi->usrcnt > 1) {
291 if (ssi->rate != rate) {
292 dev_err(dev, "SSI parent/child should use same rate\n");
293 return -EINVAL;
294 }
295
296 return 0;
297 }
298
ef4cf5d6 299 main_rate = rsnd_ssi_clk_query(priv, rate, chan, &idx);
947f4eb5 300 if (!main_rate) {
ef4cf5d6
KM
301 dev_err(dev, "unsupported clock rate\n");
302 return -EIO;
303 }
eae6fff4 304
ef4cf5d6
KM
305 ret = rsnd_adg_ssi_clk_try_start(mod, main_rate);
306 if (ret < 0)
307 return ret;
e7d850dd 308
597b046f
KM
309 /*
310 * SSI clock will be output contiguously
311 * by below settings.
312 * This means, rsnd_ssi_master_clk_start()
313 * and rsnd_ssi_register_setup() are necessary
314 * for SSI parent
315 *
316 * SSICR : FORCE, SCKD, SWSD
317 * SSIWSR : CONT
318 */
ef4cf5d6
KM
319 ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(idx);
320 ssi->wsr = CONT;
321 ssi->rate = rate;
eae6fff4 322
ef4cf5d6
KM
323 dev_dbg(dev, "%s[%d] outputs %u Hz\n",
324 rsnd_mod_name(mod),
325 rsnd_mod_id(mod), rate);
ae5c3223 326
ef4cf5d6 327 return 0;
ae5c3223
KM
328}
329
26d34b11 330static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod,
e7d850dd 331 struct rsnd_dai_stream *io)
ae5c3223 332{
f708d944 333 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
26d34b11 334 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
3ba84f45 335
e7d850dd 336 if (!rsnd_rdai_is_clk_master(rdai))
ae5c3223 337 return;
ae5c3223 338
bb002f92 339 if (!rsnd_ssi_can_output_clk(mod))
e7d850dd 340 return;
ae5c3223 341
e7d850dd
KM
342 if (ssi->usrcnt > 1)
343 return;
919567d9 344
e7d850dd
KM
345 ssi->cr_clk = 0;
346 ssi->rate = 0;
ae5c3223 347
e7d850dd 348 rsnd_adg_ssi_clk_stop(mod);
ae5c3223
KM
349}
350
0dc6bf75 351static void rsnd_ssi_config_init(struct rsnd_mod *mod,
840ada3b
KM
352 struct rsnd_dai_stream *io)
353{
354 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
355 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
26d34b11 356 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
203cdf51
KM
357 u32 cr_own = ssi->cr_own;
358 u32 cr_mode = ssi->cr_mode;
359 u32 wsr = ssi->wsr;
f98ed119
KM
360 int is_tdm;
361
eed76bb8 362 is_tdm = rsnd_runtime_is_ssi_tdm(io);
840ada3b
KM
363
364 /*
365 * always use 32bit system word.
366 * see also rsnd_ssi_master_clk_enable()
367 */
203cdf51 368 cr_own |= FORCE | SWL_32;
840ada3b
KM
369
370 if (rdai->bit_clk_inv)
371 cr_own |= SCKP;
f98ed119 372 if (rdai->frm_clk_inv ^ is_tdm)
840ada3b
KM
373 cr_own |= SWSP;
374 if (rdai->data_alignment)
375 cr_own |= SDTA;
376 if (rdai->sys_delay)
377 cr_own |= DEL;
203cdf51
KM
378
379 /*
380 * We shouldn't exchange SWSP after running.
381 * This means, parent needs to care it.
382 */
383 if (rsnd_ssi_is_parent(mod, io))
384 goto init_end;
385
840ada3b
KM
386 if (rsnd_io_is_play(io))
387 cr_own |= TRMD;
388
203cdf51 389 cr_own &= ~DWL_MASK;
41acc8ec 390 switch (snd_pcm_format_width(runtime->format)) {
840ada3b
KM
391 case 16:
392 cr_own |= DWL_16;
393 break;
41acc8ec 394 case 24:
840ada3b
KM
395 cr_own |= DWL_24;
396 break;
840ada3b
KM
397 }
398
26d34b11 399 if (rsnd_ssi_is_dma_mode(mod)) {
840ada3b
KM
400 cr_mode = UIEN | OIEN | /* over/under run */
401 DMEN; /* DMA : enable DMA */
402 } else {
403 cr_mode = DIEN; /* PIO : enable Data interrupt */
404 }
405
186fadc1
KM
406 /*
407 * TDM Extend Mode
408 * see
409 * rsnd_ssiu_init_gen2()
410 */
411 wsr = ssi->wsr;
f98ed119 412 if (is_tdm) {
186fadc1
KM
413 wsr |= WS_MODE;
414 cr_own |= CHNL_8;
415 }
203cdf51 416init_end:
840ada3b
KM
417 ssi->cr_own = cr_own;
418 ssi->cr_mode = cr_mode;
186fadc1 419 ssi->wsr = wsr;
0dc6bf75 420}
840ada3b 421
0dc6bf75
KM
422static void rsnd_ssi_register_setup(struct rsnd_mod *mod)
423{
424 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
425
426 rsnd_mod_write(mod, SSIWSR, ssi->wsr);
427 rsnd_mod_write(mod, SSICR, ssi->cr_own |
428 ssi->cr_clk |
597b046f
KM
429 ssi->cr_mode |
430 ssi->cr_en);
840ada3b
KM
431}
432
ae5c3223
KM
433/*
434 * SSI mod common functions
435 */
436static int rsnd_ssi_init(struct rsnd_mod *mod,
2c0fac19 437 struct rsnd_dai_stream *io,
690602fc 438 struct rsnd_priv *priv)
ae5c3223
KM
439{
440 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
e7d850dd
KM
441 int ret;
442
fd9adcfd
KM
443 if (!rsnd_ssi_is_run_mods(mod, io))
444 return 0;
445
e7d850dd
KM
446 ssi->usrcnt++;
447
448 rsnd_mod_power_on(mod);
449
26d34b11 450 ret = rsnd_ssi_master_clk_start(mod, io);
e7d850dd
KM
451 if (ret < 0)
452 return ret;
453
bf23c6a3 454 rsnd_ssi_config_init(mod, io);
ae5c3223 455
0dc6bf75 456 rsnd_ssi_register_setup(mod);
e7d850dd 457
e7d850dd
KM
458 /* clear error status */
459 rsnd_ssi_status_clear(mod);
460
ae5c3223
KM
461 return 0;
462}
463
464static int rsnd_ssi_quit(struct rsnd_mod *mod,
2c0fac19 465 struct rsnd_dai_stream *io,
690602fc 466 struct rsnd_priv *priv)
ae5c3223
KM
467{
468 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
ae5c3223
KM
469 struct device *dev = rsnd_priv_to_dev(priv);
470
fd9adcfd
KM
471 if (!rsnd_ssi_is_run_mods(mod, io))
472 return 0;
473
e5d9cfc6
AH
474 if (!ssi->usrcnt) {
475 dev_err(dev, "%s[%d] usrcnt error\n",
476 rsnd_mod_name(mod), rsnd_mod_id(mod));
477 return -EIO;
478 }
e7d850dd 479
26d34b11 480 rsnd_ssi_master_clk_stop(mod, io);
e7d850dd
KM
481
482 rsnd_mod_power_off(mod);
483
484 ssi->usrcnt--;
485
203cdf51
KM
486 if (!ssi->usrcnt) {
487 ssi->cr_own = 0;
488 ssi->cr_mode = 0;
489 ssi->wsr = 0;
490 }
491
ae5c3223
KM
492 return 0;
493}
494
919567d9 495static int rsnd_ssi_hw_params(struct rsnd_mod *mod,
2c0fac19 496 struct rsnd_dai_stream *io,
919567d9
KM
497 struct snd_pcm_substream *substream,
498 struct snd_pcm_hw_params *params)
499{
500 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
919567d9
KM
501 int chan = params_channels(params);
502
503 /*
6bf66b1c
KM
504 * snd_pcm_ops::hw_params will be called *before*
505 * snd_soc_dai_ops::trigger. Thus, ssi->usrcnt is 0
506 * in 1st call.
919567d9 507 */
6bf66b1c 508 if (ssi->usrcnt) {
919567d9 509 /*
6bf66b1c
KM
510 * Already working.
511 * It will happen if SSI has parent/child connection.
919567d9
KM
512 * it is error if child <-> parent SSI uses
513 * different channels.
514 */
515 if (ssi->chan != chan)
516 return -EIO;
517 }
518
919567d9 519 ssi->chan = chan;
919567d9
KM
520
521 return 0;
522}
523
6a25c8da
KM
524static int rsnd_ssi_start(struct rsnd_mod *mod,
525 struct rsnd_dai_stream *io,
526 struct rsnd_priv *priv)
e7d850dd 527{
597b046f
KM
528 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
529
fd9adcfd
KM
530 if (!rsnd_ssi_is_run_mods(mod, io))
531 return 0;
532
b4c83b17
KM
533 /*
534 * EN will be set via SSIU :: SSI_CONTROL
535 * if Multi channel mode
536 */
4f5c634d 537 if (rsnd_ssi_multi_slaves_runtime(io))
0dc6bf75 538 return 0;
e7d850dd 539
597b046f
KM
540 /*
541 * EN is for data output.
542 * SSI parent EN is not needed.
543 */
544 if (rsnd_ssi_is_parent(mod, io))
545 return 0;
546
547 ssi->cr_en = EN;
548
549 rsnd_mod_write(mod, SSICR, ssi->cr_own |
550 ssi->cr_clk |
551 ssi->cr_mode |
552 ssi->cr_en);
e7d850dd
KM
553
554 return 0;
555}
556
6a25c8da
KM
557static int rsnd_ssi_stop(struct rsnd_mod *mod,
558 struct rsnd_dai_stream *io,
559 struct rsnd_priv *priv)
e7d850dd 560{
6a25c8da
KM
561 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
562 u32 cr;
563
fd9adcfd
KM
564 if (!rsnd_ssi_is_run_mods(mod, io))
565 return 0;
566
597b046f 567 if (rsnd_ssi_is_parent(mod, io))
6a25c8da 568 return 0;
e7d850dd 569
e7d850dd
KM
570 cr = ssi->cr_own |
571 ssi->cr_clk;
4e7d606c 572
ce548931
KM
573 /*
574 * disable all IRQ,
575 * Playback: Wait all data was sent
576 * Capture: It might not receave data. Do nothing
577 */
578 if (rsnd_io_is_play(io)) {
579 rsnd_mod_write(mod, SSICR, cr | EN);
580 rsnd_ssi_status_check(mod, DIRQ);
581 }
4e7d606c 582
e7d850dd
KM
583 /*
584 * disable SSI,
585 * and, wait idle state
586 */
587 rsnd_mod_write(mod, SSICR, cr); /* disabled all */
588 rsnd_ssi_status_check(mod, IIRQ);
4e7d606c 589
597b046f
KM
590 ssi->cr_en = 0;
591
4e7d606c
KM
592 return 0;
593}
594
615fb6c7
KM
595static int rsnd_ssi_irq(struct rsnd_mod *mod,
596 struct rsnd_dai_stream *io,
597 struct rsnd_priv *priv,
598 int enable)
599{
600 u32 val = 0;
601
602 if (rsnd_is_gen1(priv))
603 return 0;
604
605 if (rsnd_ssi_is_parent(mod, io))
606 return 0;
607
fd9adcfd
KM
608 if (!rsnd_ssi_is_run_mods(mod, io))
609 return 0;
610
615fb6c7
KM
611 if (enable)
612 val = rsnd_ssi_is_dma_mode(mod) ? 0x0e000000 : 0x0f000000;
613
614 rsnd_mod_write(mod, SSI_INT_ENABLE, val);
615
616 return 0;
617}
618
d8d9b973
KM
619static bool rsnd_ssi_pio_interrupt(struct rsnd_mod *mod,
620 struct rsnd_dai_stream *io);
bfc0cfe6
KM
621static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
622 struct rsnd_dai_stream *io)
ae5c3223 623{
690602fc 624 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
2b627869 625 struct device *dev = rsnd_priv_to_dev(priv);
765ae7c8 626 int is_dma = rsnd_ssi_is_dma_mode(mod);
02299d98 627 u32 status;
75defee0 628 bool elapsed = false;
6a25c8da 629 bool stop = false;
02299d98
KM
630
631 spin_lock(&priv->lock);
ae5c3223 632
02299d98 633 /* ignore all cases if not working */
d5bbe7de 634 if (!rsnd_io_is_working(io))
02299d98
KM
635 goto rsnd_ssi_interrupt_out;
636
6a25c8da 637 status = rsnd_ssi_status_get(mod);
4e7d606c
KM
638
639 /* PIO only */
d8d9b973
KM
640 if (!is_dma && (status & DIRQ))
641 elapsed = rsnd_ssi_pio_interrupt(mod, io);
ae5c3223 642
12927a8f 643 /* DMA only */
2b627869
KM
644 if (is_dma && (status & (UIRQ | OIRQ))) {
645 rsnd_dbg_irq_status(dev, "%s[%d] err status : 0x%08x\n",
646 rsnd_mod_name(mod), rsnd_mod_id(mod), status);
647
6a25c8da 648 stop = true;
2b627869 649 }
69e32a58 650
5342dff2 651 rsnd_ssi_status_clear(mod);
02299d98
KM
652rsnd_ssi_interrupt_out:
653 spin_unlock(&priv->lock);
654
75defee0
KM
655 if (elapsed)
656 rsnd_dai_period_elapsed(io);
6a25c8da
KM
657
658 if (stop)
659 snd_pcm_stop_xrun(io->substream);
660
bfc0cfe6
KM
661}
662
663static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
664{
665 struct rsnd_mod *mod = data;
666
667 rsnd_mod_interrupt(mod, __rsnd_ssi_interrupt);
75defee0 668
4e7d606c 669 return IRQ_HANDLED;
ae5c3223
KM
670}
671
6cfad789
KM
672/*
673 * SSI PIO
674 */
e7d850dd 675static void rsnd_ssi_parent_attach(struct rsnd_mod *mod,
098bd891 676 struct rsnd_dai_stream *io)
e7d850dd 677{
098bd891
KM
678 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
679 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
680
e7d850dd
KM
681 if (!__rsnd_ssi_is_pin_sharing(mod))
682 return;
683
098bd891
KM
684 if (!rsnd_rdai_is_clk_master(rdai))
685 return;
686
e7d850dd
KM
687 switch (rsnd_mod_id(mod)) {
688 case 1:
689 case 2:
690 rsnd_dai_connect(rsnd_ssi_mod_get(priv, 0), io, RSND_MOD_SSIP);
691 break;
692 case 4:
693 rsnd_dai_connect(rsnd_ssi_mod_get(priv, 3), io, RSND_MOD_SSIP);
694 break;
695 case 8:
696 rsnd_dai_connect(rsnd_ssi_mod_get(priv, 7), io, RSND_MOD_SSIP);
697 break;
698 }
699}
700
098bd891
KM
701static int rsnd_ssi_pcm_new(struct rsnd_mod *mod,
702 struct rsnd_dai_stream *io,
703 struct snd_soc_pcm_runtime *rtd)
704{
705 /*
706 * rsnd_rdai_is_clk_master() will be enabled after set_fmt,
707 * and, pcm_new will be called after it.
708 * This function reuse pcm_new at this point.
709 */
710 rsnd_ssi_parent_attach(mod, io);
711
712 return 0;
713}
714
c7f69ab5
KM
715static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
716 struct rsnd_dai_stream *io,
717 struct rsnd_priv *priv)
ff8f30e6 718{
ff8f30e6
KM
719 struct device *dev = rsnd_priv_to_dev(priv);
720 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
ff8f30e6
KM
721 int ret;
722
b4c83b17
KM
723 /*
724 * SSIP/SSIU/IRQ are not needed on
725 * SSI Multi slaves
726 */
727 if (rsnd_ssi_is_multi_slave(mod, io))
728 return 0;
729
098bd891
KM
730 /*
731 * It can't judge ssi parent at this point
732 * see rsnd_ssi_pcm_new()
733 */
e7d850dd 734
c7f69ab5
KM
735 ret = rsnd_ssiu_attach(io, mod);
736 if (ret < 0)
737 return ret;
738
701172dc
KM
739 /*
740 * SSI might be called again as PIO fallback
741 * It is easy to manual handling for IRQ request/free
b6e58fca
KM
742 *
743 * OTOH, this function might be called many times if platform is
744 * using MIX. It needs xxx_attach() many times on xxx_probe().
745 * Because of it, we can't control .probe/.remove calling count by
746 * mod->status.
747 * But it don't need to call request_irq() many times.
748 * Let's control it by RSND_SSI_PROBED flag.
701172dc 749 */
42991989 750 if (!rsnd_flags_has(ssi, RSND_SSI_PROBED)) {
b6e58fca
KM
751 ret = request_irq(ssi->irq,
752 rsnd_ssi_interrupt,
753 IRQF_SHARED,
754 dev_name(dev), mod);
755
42991989 756 rsnd_flags_set(ssi, RSND_SSI_PROBED);
b6e58fca 757 }
8aefda50 758
ff8f30e6
KM
759 return ret;
760}
761
213691c7
KM
762static int rsnd_ssi_common_remove(struct rsnd_mod *mod,
763 struct rsnd_dai_stream *io,
764 struct rsnd_priv *priv)
765{
766 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
767 struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io);
768
769 /* Do nothing if non SSI (= SSI parent, multi SSI) mod */
770 if (pure_ssi_mod != mod)
771 return 0;
772
773 /* PIO will request IRQ again */
42991989 774 if (rsnd_flags_has(ssi, RSND_SSI_PROBED)) {
b6e58fca
KM
775 free_irq(ssi->irq, mod);
776
42991989 777 rsnd_flags_del(ssi, RSND_SSI_PROBED);
b6e58fca 778 }
213691c7
KM
779
780 return 0;
781}
782
d8d9b973
KM
783/*
784 * SSI PIO functions
785 */
786static bool rsnd_ssi_pio_interrupt(struct rsnd_mod *mod,
787 struct rsnd_dai_stream *io)
788{
789 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
790 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
791 u32 *buf = (u32 *)(runtime->dma_area + ssi->byte_pos);
792 int shift = 0;
793 int byte_pos;
794 bool elapsed = false;
795
796 if (snd_pcm_format_width(runtime->format) == 24)
797 shift = 8;
798
799 /*
800 * 8/16/32 data can be assesse to TDR/RDR register
801 * directly as 32bit data
802 * see rsnd_ssi_init()
803 */
804 if (rsnd_io_is_play(io))
805 rsnd_mod_write(mod, SSITDR, (*buf) << shift);
806 else
807 *buf = (rsnd_mod_read(mod, SSIRDR) >> shift);
808
809 byte_pos = ssi->byte_pos + sizeof(*buf);
810
811 if (byte_pos >= ssi->next_period_byte) {
812 int period_pos = byte_pos / ssi->byte_per_period;
813
814 if (period_pos >= runtime->periods) {
815 byte_pos = 0;
816 period_pos = 0;
817 }
818
819 ssi->next_period_byte = (period_pos + 1) * ssi->byte_per_period;
820
821 elapsed = true;
822 }
823
824 WRITE_ONCE(ssi->byte_pos, byte_pos);
825
826 return elapsed;
827}
828
829static int rsnd_ssi_pio_init(struct rsnd_mod *mod,
830 struct rsnd_dai_stream *io,
831 struct rsnd_priv *priv)
832{
833 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
834 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
835
836 if (!rsnd_ssi_is_parent(mod, io)) {
837 ssi->byte_pos = 0;
838 ssi->byte_per_period = runtime->period_size *
839 runtime->channels *
840 samples_to_bytes(runtime, 1);
841 ssi->next_period_byte = ssi->byte_per_period;
842 }
843
844 return rsnd_ssi_init(mod, io, priv);
845}
846
847static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod,
07b7acb5
KM
848 struct rsnd_dai_stream *io,
849 snd_pcm_uframes_t *pointer)
850{
a97a06c7 851 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
07b7acb5
KM
852 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
853
33f80136 854 *pointer = bytes_to_frames(runtime, READ_ONCE(ssi->byte_pos));
07b7acb5
KM
855
856 return 0;
857}
858
ae5c3223 859static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
8aefda50 860 .name = SSI_NAME,
c7f69ab5 861 .probe = rsnd_ssi_common_probe,
213691c7 862 .remove = rsnd_ssi_common_remove,
d8d9b973 863 .init = rsnd_ssi_pio_init,
ae5c3223 864 .quit = rsnd_ssi_quit,
49229850
KM
865 .start = rsnd_ssi_start,
866 .stop = rsnd_ssi_stop,
b5b442ab 867 .irq = rsnd_ssi_irq,
d8d9b973 868 .pointer = rsnd_ssi_pio_pointer,
098bd891 869 .pcm_new = rsnd_ssi_pcm_new,
919567d9 870 .hw_params = rsnd_ssi_hw_params,
ae5c3223
KM
871};
872
ff8f30e6 873static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
2c0fac19 874 struct rsnd_dai_stream *io,
690602fc 875 struct rsnd_priv *priv)
ff8f30e6 876{
ff8f30e6 877 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
ff8f30e6
KM
878 int ret;
879
b4c83b17
KM
880 /*
881 * SSIP/SSIU/IRQ/DMA are not needed on
882 * SSI Multi slaves
883 */
884 if (rsnd_ssi_is_multi_slave(mod, io))
885 return 0;
886
c7f69ab5 887 ret = rsnd_ssi_common_probe(mod, io, priv);
4e7d606c 888 if (ret)
b543b52a 889 return ret;
4e7d606c 890
355cb84f 891 /* SSI probe might be called many times in MUX multi path */
b99305d2 892 ret = rsnd_dma_attach(io, mod, &ssi->dma);
8aefda50 893
ff8f30e6
KM
894 return ret;
895}
896
97463e19 897static int rsnd_ssi_fallback(struct rsnd_mod *mod,
2c0fac19 898 struct rsnd_dai_stream *io,
690602fc 899 struct rsnd_priv *priv)
ff8f30e6 900{
d3a76823
KM
901 struct device *dev = rsnd_priv_to_dev(priv);
902
d3a76823
KM
903 /*
904 * fallback to PIO
905 *
906 * SSI .probe might be called again.
907 * see
908 * rsnd_rdai_continuance_probe()
909 */
910 mod->ops = &rsnd_ssi_pio_ops;
911
912 dev_info(dev, "%s[%d] fallback to PIO mode\n",
913 rsnd_mod_name(mod), rsnd_mod_id(mod));
914
ff8f30e6
KM
915 return 0;
916}
917
9b99e9a7
KM
918static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io,
919 struct rsnd_mod *mod)
d9288d0b 920{
72adc61f 921 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
72adc61f
KM
922 int is_play = rsnd_io_is_play(io);
923 char *name;
924
b415b4d3 925 if (rsnd_ssi_use_busif(io))
72adc61f
KM
926 name = is_play ? "rxu" : "txu";
927 else
928 name = is_play ? "rx" : "tx";
929
930 return rsnd_dma_request_channel(rsnd_ssi_of_node(priv),
931 mod, name);
d9288d0b
KM
932}
933
849fc82a 934static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
8aefda50 935 .name = SSI_NAME,
72adc61f 936 .dma_req = rsnd_ssi_dma_req,
ff8f30e6 937 .probe = rsnd_ssi_dma_probe,
213691c7 938 .remove = rsnd_ssi_common_remove,
849fc82a
KM
939 .init = rsnd_ssi_init,
940 .quit = rsnd_ssi_quit,
497debaa
KM
941 .start = rsnd_ssi_start,
942 .stop = rsnd_ssi_stop,
c8e969a8 943 .irq = rsnd_ssi_irq,
098bd891 944 .pcm_new = rsnd_ssi_pcm_new,
97463e19 945 .fallback = rsnd_ssi_fallback,
919567d9 946 .hw_params = rsnd_ssi_hw_params,
849fc82a
KM
947};
948
05795411
KM
949int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)
950{
951 return mod->ops == &rsnd_ssi_dma_ops;
952}
953
954
ae5c3223
KM
955/*
956 * ssi mod function
957 */
b4c83b17
KM
958static void rsnd_ssi_connect(struct rsnd_mod *mod,
959 struct rsnd_dai_stream *io)
960{
961 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
962 enum rsnd_mod_type types[] = {
963 RSND_MOD_SSI,
964 RSND_MOD_SSIM1,
965 RSND_MOD_SSIM2,
966 RSND_MOD_SSIM3,
967 };
968 enum rsnd_mod_type type;
969 int i;
970
971 /* try SSI -> SSIM1 -> SSIM2 -> SSIM3 */
972 for (i = 0; i < ARRAY_SIZE(types); i++) {
973 type = types[i];
974 if (!rsnd_io_to_mod(io, type)) {
975 rsnd_dai_connect(mod, io, type);
1ff9593d
KM
976 rsnd_rdai_channels_set(rdai, (i + 1) * 2);
977 rsnd_rdai_ssi_lane_set(rdai, (i + 1));
b4c83b17
KM
978 return;
979 }
980 }
981}
982
983void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
984 struct device_node *playback,
985 struct device_node *capture)
986{
987 struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
988 struct device_node *node;
989 struct device_node *np;
990 struct rsnd_mod *mod;
991 int i;
992
993 node = rsnd_ssi_of_node(priv);
994 if (!node)
995 return;
996
997 i = 0;
998 for_each_child_of_node(node, np) {
999 mod = rsnd_ssi_mod_get(priv, i);
1000 if (np == playback)
1001 rsnd_ssi_connect(mod, &rdai->playback);
1002 if (np == capture)
1003 rsnd_ssi_connect(mod, &rdai->capture);
1004 i++;
1005 }
1006
1007 of_node_put(node);
1008}
1009
7fa72cca
KM
1010static void __rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
1011 struct rsnd_dai_stream *io,
1012 struct device_node *remote_ep)
1013{
1014 struct device *dev = rsnd_priv_to_dev(priv);
1015 struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
1016 struct rsnd_ssi *ssi;
9ff73866
KM
1017 struct device_node *remote_node = of_graph_get_port_parent(remote_ep);
1018
1019 /* support Gen3 only */
1020 if (!rsnd_is_gen3(priv))
1021 return;
7fa72cca
KM
1022
1023 if (!mod)
1024 return;
1025
1026 ssi = rsnd_mod_to_ssi(mod);
1027
9ff73866
KM
1028 /* HDMI0 */
1029 if (strstr(remote_node->full_name, "hdmi@fead0000")) {
42991989 1030 rsnd_flags_set(ssi, RSND_SSI_HDMI0);
7fa72cca
KM
1031 dev_dbg(dev, "%s[%d] connected to HDMI0\n",
1032 rsnd_mod_name(mod), rsnd_mod_id(mod));
1033 }
1034
9ff73866
KM
1035 /* HDMI1 */
1036 if (strstr(remote_node->full_name, "hdmi@feae0000")) {
42991989 1037 rsnd_flags_set(ssi, RSND_SSI_HDMI1);
7fa72cca
KM
1038 dev_dbg(dev, "%s[%d] connected to HDMI1\n",
1039 rsnd_mod_name(mod), rsnd_mod_id(mod));
1040 }
1041}
1042
1043void rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
1044 struct device_node *endpoint,
1045 int dai_i)
1046{
1047 struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i);
1048 struct device_node *remote_ep;
1049
1050 remote_ep = of_graph_get_remote_endpoint(endpoint);
1051 if (!remote_ep)
1052 return;
1053
1054 __rsnd_ssi_parse_hdmi_connection(priv, &rdai->playback, remote_ep);
1055 __rsnd_ssi_parse_hdmi_connection(priv, &rdai->capture, remote_ep);
1056}
1057
ae5c3223
KM
1058struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
1059{
8b14719b
TI
1060 if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
1061 id = 0;
ae5c3223 1062
02534f2f 1063 return rsnd_mod_get(rsnd_ssi_get(priv, id));
ae5c3223
KM
1064}
1065
b415b4d3 1066int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
7b5ce975 1067{
7cc90a5c
KM
1068 if (!mod)
1069 return 0;
7b5ce975 1070
7cc90a5c 1071 return !!(rsnd_flags_has(rsnd_mod_to_ssi(mod), RSND_SSI_CLK_PIN_SHARE));
7b5ce975
KM
1072}
1073
5ba17b42
KM
1074static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io,
1075 struct rsnd_mod *mod,
1076 enum rsnd_mod_type type)
1077{
1078 /*
1079 * SSIP (= SSI parent) needs to be special, otherwise,
1080 * 2nd SSI might doesn't start. see also rsnd_mod_call()
1081 *
1082 * We can't include parent SSI status on SSI, because we don't know
1083 * how many SSI requests parent SSI. Thus, it is localed on "io" now.
1084 * ex) trouble case
1085 * Playback: SSI0
1086 * Capture : SSI1 (needs SSI0)
1087 *
1088 * 1) start Capture -> SSI0/SSI1 are started.
1089 * 2) start Playback -> SSI0 doesn't work, because it is already
1090 * marked as "started" on 1)
1091 *
1092 * OTOH, using each mod's status is good for MUX case.
1093 * It doesn't need to start in 2nd start
1094 * ex)
1095 * IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0
1096 * |
1097 * IO-1: SRC1 -> CTU2 -+
1098 *
1099 * 1) start IO-0 -> start SSI0
1100 * 2) start IO-1 -> SSI0 doesn't need to start, because it is
1101 * already started on 1)
1102 */
1103 if (type == RSND_MOD_SSIP)
1104 return &io->parent_ssi_status;
1105
1106 return rsnd_mod_get_status(io, mod, type);
1107}
1108
2ea6b074 1109int rsnd_ssi_probe(struct rsnd_priv *priv)
ae5c3223 1110{
02534f2f
KM
1111 struct device_node *node;
1112 struct device_node *np;
ae5c3223
KM
1113 struct device *dev = rsnd_priv_to_dev(priv);
1114 struct rsnd_mod_ops *ops;
1115 struct clk *clk;
ae5c3223
KM
1116 struct rsnd_ssi *ssi;
1117 char name[RSND_SSI_NAME_SIZE];
2f78dd7f 1118 int i, nr, ret;
ae5c3223 1119
02534f2f
KM
1120 node = rsnd_ssi_of_node(priv);
1121 if (!node)
1122 return -EINVAL;
1123
1124 nr = of_get_child_count(node);
1125 if (!nr) {
1126 ret = -EINVAL;
1127 goto rsnd_ssi_probe_done;
1128 }
90e8e50f 1129
dd27d808 1130 ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL);
02534f2f
KM
1131 if (!ssi) {
1132 ret = -ENOMEM;
1133 goto rsnd_ssi_probe_done;
1134 }
ae5c3223 1135
dd27d808
KM
1136 priv->ssi = ssi;
1137 priv->ssi_nr = nr;
ae5c3223 1138
02534f2f
KM
1139 i = 0;
1140 for_each_child_of_node(node, np) {
9e9e95df
KM
1141 if (!of_device_is_available(np))
1142 goto skip;
1143
02534f2f 1144 ssi = rsnd_ssi_get(priv, i);
ae5c3223 1145
8aefda50
KM
1146 snprintf(name, RSND_SSI_NAME_SIZE, "%s.%d",
1147 SSI_NAME, i);
ae5c3223 1148
60dbb4f1 1149 clk = devm_clk_get(dev, name);
02534f2f
KM
1150 if (IS_ERR(clk)) {
1151 ret = PTR_ERR(clk);
53ba2aa3 1152 of_node_put(np);
02534f2f
KM
1153 goto rsnd_ssi_probe_done;
1154 }
ae5c3223 1155
02534f2f 1156 if (of_get_property(np, "shared-pin", NULL))
42991989 1157 rsnd_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE);
02534f2f
KM
1158
1159 if (of_get_property(np, "no-busif", NULL))
42991989 1160 rsnd_flags_set(ssi, RSND_SSI_NO_BUSIF);
02534f2f
KM
1161
1162 ssi->irq = irq_of_parse_and_map(np, 0);
1163 if (!ssi->irq) {
1164 ret = -EINVAL;
53ba2aa3 1165 of_node_put(np);
02534f2f
KM
1166 goto rsnd_ssi_probe_done;
1167 }
ae5c3223 1168
51930295 1169 if (of_property_read_bool(np, "pio-transfer"))
ff8f30e6 1170 ops = &rsnd_ssi_pio_ops;
02534f2f
KM
1171 else
1172 ops = &rsnd_ssi_dma_ops;
ae5c3223 1173
b76e218a 1174 ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
5ba17b42 1175 rsnd_ssi_get_status, RSND_MOD_SSI, i);
53ba2aa3
JL
1176 if (ret) {
1177 of_node_put(np);
02534f2f 1178 goto rsnd_ssi_probe_done;
53ba2aa3 1179 }
9e9e95df 1180skip:
02534f2f 1181 i++;
ae5c3223
KM
1182 }
1183
02534f2f
KM
1184 ret = 0;
1185
1186rsnd_ssi_probe_done:
1187 of_node_put(node);
1188
1189 return ret;
ae5c3223 1190}
2f78dd7f 1191
2ea6b074 1192void rsnd_ssi_remove(struct rsnd_priv *priv)
2f78dd7f
KM
1193{
1194 struct rsnd_ssi *ssi;
1195 int i;
1196
1197 for_each_rsnd_ssi(ssi, priv, i) {
b76e218a 1198 rsnd_mod_quit(rsnd_mod_get(ssi));
2f78dd7f
KM
1199 }
1200}
This page took 0.764121 seconds and 4 git commands to generate.