Lines Matching +full:io +full:- +full:width
1 // SPDX-License-Identifier: GPL-2.0
3 // Renesas R-Car SSIU/SSI support
109 ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \
112 #define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id)
113 #define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
115 #define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io))
116 #define rsnd_ssi_is_multi_secondary(mod, io) \
117 (rsnd_ssi_multi_secondaries(io) & (1 << rsnd_mod_id(mod)))
118 #define rsnd_ssi_is_run_mods(mod, io) \
119 (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod)))
122 int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
124 struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
133 if (rsnd_io_to_mod_src(io))
168 static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io)
179 struct rsnd_mod *mod = rsnd_io_to_mod(io, types[i]);
190 static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io)
192 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io);
193 struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
196 mods = rsnd_ssi_multi_secondaries_runtime(io) |
205 u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io)
207 if (rsnd_runtime_is_multi_ssi(io))
208 return rsnd_ssi_multi_secondaries(io);
217 int width = rsnd_rdai_width_get(rdai);
219 switch (width) {
225 dev_err(dev, "unsupported slot width value: %d\n", width);
238 int width = rsnd_rdai_width_get(rdai);
251 main_rate = width * param1 * param2 * ssi_clk_mul_table[j];
267 struct rsnd_dai_stream *io)
269 struct rsnd_priv *priv = rsnd_io_to_priv(io);
271 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
273 int chan = rsnd_runtime_channel_for_ssi(io);
276 unsigned int rate = rsnd_io_is_play(io) ?
277 rsnd_src_get_out_rate(priv, io) :
278 rsnd_src_get_in_rate(priv, io);
286 if (rsnd_ssi_is_multi_secondary(mod, io))
289 if (rsnd_runtime_is_tdm_split(io))
290 chan = rsnd_io_converted_chan(io);
294 if (ssi->usrcnt > 0) {
295 if (ssi->rate != rate) {
297 return -EINVAL;
300 if (ssi->chan != chan) {
302 return -EINVAL;
308 ret = -EIO;
327 ssi->cr_clk = FORCE | rsnd_rdai_width_to_swl(rdai) |
329 ssi->wsr = CONT;
330 ssi->rate = rate;
331 ssi->chan = chan;
345 struct rsnd_dai_stream *io)
347 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
356 if (ssi->usrcnt > 1)
359 ssi->cr_clk = 0;
360 ssi->rate = 0;
361 ssi->chan = 0;
367 struct rsnd_dai_stream *io)
369 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
372 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
374 u32 cr_own = ssi->cr_own;
375 u32 cr_mode = ssi->cr_mode;
376 u32 wsr = ssi->wsr;
377 int width;
380 is_tdm = rsnd_runtime_is_tdm(io);
381 is_tdm_split = rsnd_runtime_is_tdm_split(io);
390 if (rdai->bit_clk_inv)
392 if (rdai->frm_clk_inv && !is_tdm)
394 if (rdai->data_alignment)
396 if (rdai->sys_delay)
413 if (rsnd_ssi_is_parent(mod, io))
416 if (rsnd_io_is_play(io))
420 width = snd_pcm_format_width(runtime->format);
423 * The SWL and DWL bits in SSICR should be fixed at 32-bit
428 width = 32;
431 switch (width) {
454 ssi->cr_own = cr_own;
455 ssi->cr_mode = cr_mode;
456 ssi->wsr = wsr;
463 rsnd_mod_write(mod, SSIWSR, ssi->wsr);
464 rsnd_mod_write(mod, SSICR, ssi->cr_own |
465 ssi->cr_clk |
466 ssi->cr_mode |
467 ssi->cr_en);
474 struct rsnd_dai_stream *io,
480 if (!rsnd_ssi_is_run_mods(mod, io))
483 ret = rsnd_ssi_master_clk_start(mod, io);
487 ssi->usrcnt++;
493 rsnd_ssi_config_init(mod, io);
504 struct rsnd_dai_stream *io,
510 if (!rsnd_ssi_is_run_mods(mod, io))
513 if (!ssi->usrcnt) {
515 return -EIO;
518 rsnd_ssi_master_clk_stop(mod, io);
522 ssi->usrcnt--;
524 if (!ssi->usrcnt) {
525 ssi->cr_own = 0;
526 ssi->cr_mode = 0;
527 ssi->wsr = 0;
534 struct rsnd_dai_stream *io,
538 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
541 if (fmt_width > rdai->chan_width) {
542 struct rsnd_priv *priv = rsnd_io_to_priv(io);
545 dev_err(dev, "invalid combination of slot-width and format-data-width\n");
546 return -EINVAL;
553 struct rsnd_dai_stream *io,
558 if (!rsnd_ssi_is_run_mods(mod, io))
565 if (rsnd_ssi_multi_secondaries_runtime(io))
572 if (rsnd_ssi_is_parent(mod, io))
575 ssi->cr_en = EN;
577 rsnd_mod_write(mod, SSICR, ssi->cr_own |
578 ssi->cr_clk |
579 ssi->cr_mode |
580 ssi->cr_en);
586 struct rsnd_dai_stream *io,
592 if (!rsnd_ssi_is_run_mods(mod, io))
595 if (rsnd_ssi_is_parent(mod, io))
598 cr = ssi->cr_own |
599 ssi->cr_clk;
606 if (rsnd_io_is_play(io)) {
607 rsnd_mod_write(mod, SSICR, cr | ssi->cr_en);
611 /* In multi-SSI mode, stop is performed by setting ssi0129 in
614 if (rsnd_ssi_multi_secondaries_runtime(io))
624 ssi->cr_en = 0;
630 struct rsnd_dai_stream *io,
638 is_tdm = rsnd_runtime_is_tdm(io);
639 is_tdm_split = rsnd_runtime_is_tdm_split(io);
644 if (rsnd_ssi_is_parent(mod, io))
647 if (!rsnd_ssi_is_run_mods(mod, io))
672 struct rsnd_dai_stream *io);
674 struct rsnd_dai_stream *io)
683 scoped_guard(spinlock, &priv->lock) {
686 if (!rsnd_io_is_working(io))
693 elapsed = rsnd_ssi_pio_interrupt(mod, io);
709 snd_pcm_period_elapsed(io->substream);
712 snd_pcm_stop_xrun(io->substream);
726 struct rsnd_dai_stream *io,
734 * how many SSI requests parent SSI. Thus, it is localed on "io" now.
739 * 1) start Capture -> SSI0/SSI1 are started.
740 * 2) start Playback -> SSI0 doesn't work, because it is already
746 * IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0
748 * IO-1: SRC1 -> CTU2 -+
750 * 1) start IO-0 -> start SSI0
751 * 2) start IO-1 -> SSI0 doesn't need to start, because it is
755 return &io->parent_ssi_status;
757 return rsnd_mod_get_status(mod, io, type);
764 struct rsnd_dai_stream *io)
766 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
775 if (rsnd_ssi_is_multi_secondary(mod, io))
782 rsnd_dai_connect(rsnd_ssi_mod_get(priv, 0), io, RSND_MOD_SSIP);
785 rsnd_dai_connect(rsnd_ssi_mod_get(priv, 3), io, RSND_MOD_SSIP);
788 rsnd_dai_connect(rsnd_ssi_mod_get(priv, 7), io, RSND_MOD_SSIP);
794 struct rsnd_dai_stream *io,
802 rsnd_ssi_parent_attach(mod, io);
808 struct rsnd_dai_stream *io,
819 if (rsnd_ssi_is_multi_secondary(mod, io))
834 * mod->status.
839 ret = request_irq(ssi->irq,
851 struct rsnd_dai_stream *io,
855 struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io);
863 free_irq(ssi->irq, mod);
875 struct rsnd_dai_stream *io)
877 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
879 u32 *buf = (u32 *)(runtime->dma_area + ssi->byte_pos);
884 if (snd_pcm_format_width(runtime->format) == 24)
892 if (rsnd_io_is_play(io))
897 byte_pos = ssi->byte_pos + sizeof(*buf);
899 if (byte_pos >= ssi->next_period_byte) {
900 int period_pos = byte_pos / ssi->byte_per_period;
902 if (period_pos >= runtime->periods) {
907 ssi->next_period_byte = (period_pos + 1) * ssi->byte_per_period;
912 WRITE_ONCE(ssi->byte_pos, byte_pos);
918 struct rsnd_dai_stream *io,
921 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
924 if (!rsnd_ssi_is_parent(mod, io)) {
925 ssi->byte_pos = 0;
926 ssi->byte_per_period = runtime->period_size *
927 runtime->channels *
929 ssi->next_period_byte = ssi->byte_per_period;
932 return rsnd_ssi_init(mod, io, priv);
936 struct rsnd_dai_stream *io,
940 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
942 *pointer = bytes_to_frames(runtime, READ_ONCE(ssi->byte_pos));
963 struct rsnd_dai_stream *io,
972 if (rsnd_ssi_is_multi_secondary(mod, io))
975 ret = rsnd_ssi_common_probe(mod, io, priv);
980 ret = rsnd_dma_attach(io, mod, &io->dma);
986 struct rsnd_dai_stream *io,
998 mod->ops = &rsnd_ssi_pio_ops;
1005 static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io,
1009 int is_play = rsnd_io_is_play(io);
1023 if (rsnd_ssi_use_busif(io))
1034 struct rsnd_dai_stream *io,
1037 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
1042 seq_printf(m, "bit_clk_inv: %d\n", rdai->bit_clk_inv);
1043 seq_printf(m, "frm_clk_inv: %d\n", rdai->frm_clk_inv);
1046 seq_printf(m, "multi secondary: %d\n", rsnd_ssi_is_multi_secondary(mod, io));
1047 seq_printf(m, "tdm: %d, %d\n", rsnd_runtime_is_tdm(io),
1048 rsnd_runtime_is_tdm_split(io));
1049 seq_printf(m, "chan: %d\n", ssi->chan);
1050 seq_printf(m, "user: %d\n", ssi->usrcnt);
1079 return mod->ops == &rsnd_ssi_dma_ops;
1086 struct rsnd_dai_stream *io)
1088 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
1098 /* try SSI -> SSIM1 -> SSIM2 -> SSIM3 */
1101 if (!rsnd_io_to_mod(io, type)) {
1102 rsnd_dai_connect(mod, io, type);
1134 rsnd_ssi_connect(mod, &rdai->playback);
1136 rsnd_ssi_connect(mod, &rdai->capture);
1171 return -EINVAL;
1175 ret = -EINVAL;
1181 ret = -ENOMEM;
1185 priv->ssi = ssi;
1186 priv->ssi_nr = nr;
1195 ret = -EINVAL;
1210 if (of_property_read_bool(np, "shared-pin"))
1213 if (of_property_read_bool(np, "no-busif"))
1216 ssi->irq = irq_of_parse_and_map(np, 0);
1217 if (!ssi->irq) {
1218 ret = -EINVAL;
1222 if (of_property_read_bool(np, "pio-transfer"))