• Home
  • Raw
  • Download

Lines Matching +full:io +full:- +full:width

1 // SPDX-License-Identifier: GPL-2.0
3 // Renesas R-Car SSIU/SSI support
107 ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \
110 #define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id)
111 #define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
113 #define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io)) argument
114 #define rsnd_ssi_is_multi_secondary(mod, io) \ argument
115 (rsnd_ssi_multi_secondaries(io) & (1 << rsnd_mod_id(mod)))
116 #define rsnd_ssi_is_run_mods(mod, io) \ argument
117 (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod)))
120 int rsnd_ssi_use_busif(struct rsnd_dai_stream *io) in rsnd_ssi_use_busif() argument
122 struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io); in rsnd_ssi_use_busif()
131 if (rsnd_io_to_mod_src(io)) in rsnd_ssi_use_busif()
166 static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io) in rsnd_ssi_multi_secondaries() argument
177 struct rsnd_mod *mod = rsnd_io_to_mod(io, types[i]); in rsnd_ssi_multi_secondaries()
188 static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io) in rsnd_ssi_run_mods() argument
190 struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); in rsnd_ssi_run_mods()
191 struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); in rsnd_ssi_run_mods()
194 mods = rsnd_ssi_multi_secondaries_runtime(io) | in rsnd_ssi_run_mods()
203 u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io) in rsnd_ssi_multi_secondaries_runtime() argument
205 if (rsnd_runtime_is_multi_ssi(io)) in rsnd_ssi_multi_secondaries_runtime()
206 return rsnd_ssi_multi_secondaries(io); in rsnd_ssi_multi_secondaries_runtime()
215 int width = rsnd_rdai_width_get(rdai); in rsnd_rdai_width_to_swl() local
217 switch (width) { in rsnd_rdai_width_to_swl()
223 dev_err(dev, "unsupported slot width value: %d\n", width); in rsnd_rdai_width_to_swl()
236 int width = rsnd_rdai_width_get(rdai); in rsnd_ssi_clk_query() local
249 main_rate = width * param1 * param2 * ssi_clk_mul_table[j]; in rsnd_ssi_clk_query()
265 struct rsnd_dai_stream *io) in rsnd_ssi_master_clk_start() argument
267 struct rsnd_priv *priv = rsnd_io_to_priv(io); in rsnd_ssi_master_clk_start()
269 struct rsnd_dai *rdai = rsnd_io_to_rdai(io); in rsnd_ssi_master_clk_start()
271 int chan = rsnd_runtime_channel_for_ssi(io); in rsnd_ssi_master_clk_start()
274 unsigned int rate = rsnd_io_is_play(io) ? in rsnd_ssi_master_clk_start()
275 rsnd_src_get_out_rate(priv, io) : in rsnd_ssi_master_clk_start()
276 rsnd_src_get_in_rate(priv, io); in rsnd_ssi_master_clk_start()
284 if (rsnd_ssi_is_multi_secondary(mod, io)) in rsnd_ssi_master_clk_start()
287 if (rsnd_runtime_is_tdm_split(io)) in rsnd_ssi_master_clk_start()
288 chan = rsnd_io_converted_chan(io); in rsnd_ssi_master_clk_start()
292 if (ssi->usrcnt > 0) { in rsnd_ssi_master_clk_start()
293 if (ssi->rate != rate) { in rsnd_ssi_master_clk_start()
295 return -EINVAL; in rsnd_ssi_master_clk_start()
298 if (ssi->chan != chan) { in rsnd_ssi_master_clk_start()
300 return -EINVAL; in rsnd_ssi_master_clk_start()
306 ret = -EIO; in rsnd_ssi_master_clk_start()
325 ssi->cr_clk = FORCE | rsnd_rdai_width_to_swl(rdai) | in rsnd_ssi_master_clk_start()
327 ssi->wsr = CONT; in rsnd_ssi_master_clk_start()
328 ssi->rate = rate; in rsnd_ssi_master_clk_start()
329 ssi->chan = chan; in rsnd_ssi_master_clk_start()
343 struct rsnd_dai_stream *io) in rsnd_ssi_master_clk_stop() argument
345 struct rsnd_dai *rdai = rsnd_io_to_rdai(io); in rsnd_ssi_master_clk_stop()
354 if (ssi->usrcnt > 1) in rsnd_ssi_master_clk_stop()
357 ssi->cr_clk = 0; in rsnd_ssi_master_clk_stop()
358 ssi->rate = 0; in rsnd_ssi_master_clk_stop()
359 ssi->chan = 0; in rsnd_ssi_master_clk_stop()
365 struct rsnd_dai_stream *io) in rsnd_ssi_config_init() argument
367 struct rsnd_dai *rdai = rsnd_io_to_rdai(io); in rsnd_ssi_config_init()
370 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); in rsnd_ssi_config_init()
372 u32 cr_own = ssi->cr_own; in rsnd_ssi_config_init()
373 u32 cr_mode = ssi->cr_mode; in rsnd_ssi_config_init()
374 u32 wsr = ssi->wsr; in rsnd_ssi_config_init()
375 int width; in rsnd_ssi_config_init() local
378 is_tdm = rsnd_runtime_is_tdm(io); in rsnd_ssi_config_init()
379 is_tdm_split = rsnd_runtime_is_tdm_split(io); in rsnd_ssi_config_init()
388 if (rdai->bit_clk_inv) in rsnd_ssi_config_init()
390 if (rdai->frm_clk_inv && !is_tdm) in rsnd_ssi_config_init()
392 if (rdai->data_alignment) in rsnd_ssi_config_init()
394 if (rdai->sys_delay) in rsnd_ssi_config_init()
411 if (rsnd_ssi_is_parent(mod, io)) in rsnd_ssi_config_init()
414 if (rsnd_io_is_play(io)) in rsnd_ssi_config_init()
418 width = snd_pcm_format_width(runtime->format); in rsnd_ssi_config_init()
421 * The SWL and DWL bits in SSICR should be fixed at 32-bit in rsnd_ssi_config_init()
426 width = 32; in rsnd_ssi_config_init()
429 switch (width) { in rsnd_ssi_config_init()
452 ssi->cr_own = cr_own; in rsnd_ssi_config_init()
453 ssi->cr_mode = cr_mode; in rsnd_ssi_config_init()
454 ssi->wsr = wsr; in rsnd_ssi_config_init()
461 rsnd_mod_write(mod, SSIWSR, ssi->wsr); in rsnd_ssi_register_setup()
462 rsnd_mod_write(mod, SSICR, ssi->cr_own | in rsnd_ssi_register_setup()
463 ssi->cr_clk | in rsnd_ssi_register_setup()
464 ssi->cr_mode | in rsnd_ssi_register_setup()
465 ssi->cr_en); in rsnd_ssi_register_setup()
472 struct rsnd_dai_stream *io, in rsnd_ssi_init() argument
478 if (!rsnd_ssi_is_run_mods(mod, io)) in rsnd_ssi_init()
481 ret = rsnd_ssi_master_clk_start(mod, io); in rsnd_ssi_init()
485 ssi->usrcnt++; in rsnd_ssi_init()
491 rsnd_ssi_config_init(mod, io); in rsnd_ssi_init()
502 struct rsnd_dai_stream *io, in rsnd_ssi_quit() argument
508 if (!rsnd_ssi_is_run_mods(mod, io)) in rsnd_ssi_quit()
511 if (!ssi->usrcnt) { in rsnd_ssi_quit()
513 return -EIO; in rsnd_ssi_quit()
516 rsnd_ssi_master_clk_stop(mod, io); in rsnd_ssi_quit()
520 ssi->usrcnt--; in rsnd_ssi_quit()
522 if (!ssi->usrcnt) { in rsnd_ssi_quit()
523 ssi->cr_own = 0; in rsnd_ssi_quit()
524 ssi->cr_mode = 0; in rsnd_ssi_quit()
525 ssi->wsr = 0; in rsnd_ssi_quit()
532 struct rsnd_dai_stream *io, in rsnd_ssi_hw_params() argument
536 struct rsnd_dai *rdai = rsnd_io_to_rdai(io); in rsnd_ssi_hw_params()
539 if (fmt_width > rdai->chan_width) { in rsnd_ssi_hw_params()
540 struct rsnd_priv *priv = rsnd_io_to_priv(io); in rsnd_ssi_hw_params()
543 dev_err(dev, "invalid combination of slot-width and format-data-width\n"); in rsnd_ssi_hw_params()
544 return -EINVAL; in rsnd_ssi_hw_params()
551 struct rsnd_dai_stream *io, in rsnd_ssi_start() argument
556 if (!rsnd_ssi_is_run_mods(mod, io)) in rsnd_ssi_start()
563 if (rsnd_ssi_multi_secondaries_runtime(io)) in rsnd_ssi_start()
570 if (rsnd_ssi_is_parent(mod, io)) in rsnd_ssi_start()
573 ssi->cr_en = EN; in rsnd_ssi_start()
575 rsnd_mod_write(mod, SSICR, ssi->cr_own | in rsnd_ssi_start()
576 ssi->cr_clk | in rsnd_ssi_start()
577 ssi->cr_mode | in rsnd_ssi_start()
578 ssi->cr_en); in rsnd_ssi_start()
584 struct rsnd_dai_stream *io, in rsnd_ssi_stop() argument
590 if (!rsnd_ssi_is_run_mods(mod, io)) in rsnd_ssi_stop()
593 if (rsnd_ssi_is_parent(mod, io)) in rsnd_ssi_stop()
596 cr = ssi->cr_own | in rsnd_ssi_stop()
597 ssi->cr_clk; in rsnd_ssi_stop()
604 if (rsnd_io_is_play(io)) { in rsnd_ssi_stop()
605 rsnd_mod_write(mod, SSICR, cr | ssi->cr_en); in rsnd_ssi_stop()
609 /* In multi-SSI mode, stop is performed by setting ssi0129 in in rsnd_ssi_stop()
612 if (rsnd_ssi_multi_secondaries_runtime(io)) in rsnd_ssi_stop()
622 ssi->cr_en = 0; in rsnd_ssi_stop()
628 struct rsnd_dai_stream *io, in rsnd_ssi_irq() argument
636 is_tdm = rsnd_runtime_is_tdm(io); in rsnd_ssi_irq()
637 is_tdm_split = rsnd_runtime_is_tdm_split(io); in rsnd_ssi_irq()
642 if (rsnd_ssi_is_parent(mod, io)) in rsnd_ssi_irq()
645 if (!rsnd_ssi_is_run_mods(mod, io)) in rsnd_ssi_irq()
670 struct rsnd_dai_stream *io);
672 struct rsnd_dai_stream *io) in __rsnd_ssi_interrupt() argument
681 spin_lock(&priv->lock); in __rsnd_ssi_interrupt()
684 if (!rsnd_io_is_working(io)) in __rsnd_ssi_interrupt()
691 elapsed = rsnd_ssi_pio_interrupt(mod, io); in __rsnd_ssi_interrupt()
705 spin_unlock(&priv->lock); in __rsnd_ssi_interrupt()
708 rsnd_dai_period_elapsed(io); in __rsnd_ssi_interrupt()
711 snd_pcm_stop_xrun(io->substream); in __rsnd_ssi_interrupt()
725 struct rsnd_dai_stream *io, in rsnd_ssi_get_status() argument
733 * how many SSI requests parent SSI. Thus, it is localed on "io" now. in rsnd_ssi_get_status()
738 * 1) start Capture -> SSI0/SSI1 are started. in rsnd_ssi_get_status()
739 * 2) start Playback -> SSI0 doesn't work, because it is already in rsnd_ssi_get_status()
745 * IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0 in rsnd_ssi_get_status()
747 * IO-1: SRC1 -> CTU2 -+ in rsnd_ssi_get_status()
749 * 1) start IO-0 -> start SSI0 in rsnd_ssi_get_status()
750 * 2) start IO-1 -> SSI0 doesn't need to start, because it is in rsnd_ssi_get_status()
754 return &io->parent_ssi_status; in rsnd_ssi_get_status()
756 return rsnd_mod_get_status(mod, io, type); in rsnd_ssi_get_status()
763 struct rsnd_dai_stream *io) in rsnd_ssi_parent_attach() argument
765 struct rsnd_dai *rdai = rsnd_io_to_rdai(io); in rsnd_ssi_parent_attach()
774 if (rsnd_ssi_is_multi_secondary(mod, io)) in rsnd_ssi_parent_attach()
781 rsnd_dai_connect(rsnd_ssi_mod_get(priv, 0), io, RSND_MOD_SSIP); in rsnd_ssi_parent_attach()
784 rsnd_dai_connect(rsnd_ssi_mod_get(priv, 3), io, RSND_MOD_SSIP); in rsnd_ssi_parent_attach()
787 rsnd_dai_connect(rsnd_ssi_mod_get(priv, 7), io, RSND_MOD_SSIP); in rsnd_ssi_parent_attach()
793 struct rsnd_dai_stream *io, in rsnd_ssi_pcm_new() argument
801 rsnd_ssi_parent_attach(mod, io); in rsnd_ssi_pcm_new()
807 struct rsnd_dai_stream *io, in rsnd_ssi_common_probe() argument
818 if (rsnd_ssi_is_multi_secondary(mod, io)) in rsnd_ssi_common_probe()
833 * mod->status. in rsnd_ssi_common_probe()
838 ret = request_irq(ssi->irq, in rsnd_ssi_common_probe()
850 struct rsnd_dai_stream *io, in rsnd_ssi_common_remove() argument
854 struct rsnd_mod *pure_ssi_mod = rsnd_io_to_mod_ssi(io); in rsnd_ssi_common_remove()
862 free_irq(ssi->irq, mod); in rsnd_ssi_common_remove()
874 struct rsnd_dai_stream *io) in rsnd_ssi_pio_interrupt() argument
876 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); in rsnd_ssi_pio_interrupt()
878 u32 *buf = (u32 *)(runtime->dma_area + ssi->byte_pos); in rsnd_ssi_pio_interrupt()
883 if (snd_pcm_format_width(runtime->format) == 24) in rsnd_ssi_pio_interrupt()
891 if (rsnd_io_is_play(io)) in rsnd_ssi_pio_interrupt()
896 byte_pos = ssi->byte_pos + sizeof(*buf); in rsnd_ssi_pio_interrupt()
898 if (byte_pos >= ssi->next_period_byte) { in rsnd_ssi_pio_interrupt()
899 int period_pos = byte_pos / ssi->byte_per_period; in rsnd_ssi_pio_interrupt()
901 if (period_pos >= runtime->periods) { in rsnd_ssi_pio_interrupt()
906 ssi->next_period_byte = (period_pos + 1) * ssi->byte_per_period; in rsnd_ssi_pio_interrupt()
911 WRITE_ONCE(ssi->byte_pos, byte_pos); in rsnd_ssi_pio_interrupt()
917 struct rsnd_dai_stream *io, in rsnd_ssi_pio_init() argument
920 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); in rsnd_ssi_pio_init()
923 if (!rsnd_ssi_is_parent(mod, io)) { in rsnd_ssi_pio_init()
924 ssi->byte_pos = 0; in rsnd_ssi_pio_init()
925 ssi->byte_per_period = runtime->period_size * in rsnd_ssi_pio_init()
926 runtime->channels * in rsnd_ssi_pio_init()
928 ssi->next_period_byte = ssi->byte_per_period; in rsnd_ssi_pio_init()
931 return rsnd_ssi_init(mod, io, priv); in rsnd_ssi_pio_init()
935 struct rsnd_dai_stream *io, in rsnd_ssi_pio_pointer() argument
939 struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); in rsnd_ssi_pio_pointer()
941 *pointer = bytes_to_frames(runtime, READ_ONCE(ssi->byte_pos)); in rsnd_ssi_pio_pointer()
962 struct rsnd_dai_stream *io, in rsnd_ssi_dma_probe() argument
971 if (rsnd_ssi_is_multi_secondary(mod, io)) in rsnd_ssi_dma_probe()
974 ret = rsnd_ssi_common_probe(mod, io, priv); in rsnd_ssi_dma_probe()
979 ret = rsnd_dma_attach(io, mod, &io->dma); in rsnd_ssi_dma_probe()
985 struct rsnd_dai_stream *io, in rsnd_ssi_fallback() argument
997 mod->ops = &rsnd_ssi_pio_ops; in rsnd_ssi_fallback()
1004 static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io, in rsnd_ssi_dma_req() argument
1008 int is_play = rsnd_io_is_play(io); in rsnd_ssi_dma_req()
1022 if (rsnd_ssi_use_busif(io)) in rsnd_ssi_dma_req()
1033 struct rsnd_dai_stream *io, in rsnd_ssi_debug_info() argument
1036 struct rsnd_dai *rdai = rsnd_io_to_rdai(io); in rsnd_ssi_debug_info()
1041 seq_printf(m, "bit_clk_inv: %d\n", rdai->bit_clk_inv); in rsnd_ssi_debug_info()
1042 seq_printf(m, "frm_clk_inv: %d\n", rdai->frm_clk_inv); in rsnd_ssi_debug_info()
1045 seq_printf(m, "multi secondary: %d\n", rsnd_ssi_is_multi_secondary(mod, io)); in rsnd_ssi_debug_info()
1046 seq_printf(m, "tdm: %d, %d\n", rsnd_runtime_is_tdm(io), in rsnd_ssi_debug_info()
1047 rsnd_runtime_is_tdm_split(io)); in rsnd_ssi_debug_info()
1048 seq_printf(m, "chan: %d\n", ssi->chan); in rsnd_ssi_debug_info()
1049 seq_printf(m, "user: %d\n", ssi->usrcnt); in rsnd_ssi_debug_info()
1078 return mod->ops == &rsnd_ssi_dma_ops; in rsnd_ssi_is_dma_mode()
1085 struct rsnd_dai_stream *io) in rsnd_ssi_connect() argument
1087 struct rsnd_dai *rdai = rsnd_io_to_rdai(io); in rsnd_ssi_connect()
1097 /* try SSI -> SSIM1 -> SSIM2 -> SSIM3 */ in rsnd_ssi_connect()
1100 if (!rsnd_io_to_mod(io, type)) { in rsnd_ssi_connect()
1101 rsnd_dai_connect(mod, io, type); in rsnd_ssi_connect()
1136 rsnd_ssi_connect(mod, &rdai->playback); in rsnd_parse_connect_ssi()
1138 rsnd_ssi_connect(mod, &rdai->capture); in rsnd_parse_connect_ssi()
1174 return -EINVAL; in rsnd_ssi_probe()
1178 ret = -EINVAL; in rsnd_ssi_probe()
1184 ret = -ENOMEM; in rsnd_ssi_probe()
1188 priv->ssi = ssi; in rsnd_ssi_probe()
1189 priv->ssi_nr = nr; in rsnd_ssi_probe()
1198 ret = -EINVAL; in rsnd_ssi_probe()
1215 if (of_property_read_bool(np, "shared-pin")) in rsnd_ssi_probe()
1218 if (of_property_read_bool(np, "no-busif")) in rsnd_ssi_probe()
1221 ssi->irq = irq_of_parse_and_map(np, 0); in rsnd_ssi_probe()
1222 if (!ssi->irq) { in rsnd_ssi_probe()
1223 ret = -EINVAL; in rsnd_ssi_probe()
1228 if (of_property_read_bool(np, "pio-transfer")) in rsnd_ssi_probe()