Lines Matching full:ssi

3 // Renesas R-Car SSIU/SSI support
13 * SSI interrupt status debug message when debugging
63 #define EN (1 << 0) /* SSI Module Enable */
79 #define SSI_NAME "ssi"
103 #define RSND_SSI_NO_BUSIF (1 << 1) /* SSI+DMA without BUSIF */
109 ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i)); \
112 #define rsnd_ssi_get(priv, id) ((struct rsnd_ssi *)(priv->ssi) + id)
115 #define rsnd_ssi_is_parent(ssi, io) ((ssi) == rsnd_io_to_mod_ssip(io)) argument
125 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_use_busif() local
131 if (!(rsnd_flags_has(ssi, RSND_SSI_NO_BUSIF))) in rsnd_ssi_use_busif()
272 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_master_clk_start() local
294 if (ssi->usrcnt > 0) { in rsnd_ssi_master_clk_start()
295 if (ssi->rate != rate) { in rsnd_ssi_master_clk_start()
296 dev_err(dev, "SSI parent/child should use same rate\n"); in rsnd_ssi_master_clk_start()
300 if (ssi->chan != chan) { in rsnd_ssi_master_clk_start()
301 dev_err(dev, "SSI parent/child should use same chan\n"); in rsnd_ssi_master_clk_start()
318 * SSI clock will be output contiguously in rsnd_ssi_master_clk_start()
322 * for SSI parent in rsnd_ssi_master_clk_start()
327 ssi->cr_clk = FORCE | rsnd_rdai_width_to_swl(rdai) | in rsnd_ssi_master_clk_start()
329 ssi->wsr = CONT; in rsnd_ssi_master_clk_start()
330 ssi->rate = rate; in rsnd_ssi_master_clk_start()
331 ssi->chan = chan; in rsnd_ssi_master_clk_start()
347 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_master_clk_stop() local
355 if (ssi->usrcnt > 1) in rsnd_ssi_master_clk_stop()
358 ssi->cr_clk = 0; in rsnd_ssi_master_clk_stop()
359 ssi->rate = 0; in rsnd_ssi_master_clk_stop()
360 ssi->chan = 0; in rsnd_ssi_master_clk_stop()
372 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_config_init() local
373 u32 cr_own = ssi->cr_own; in rsnd_ssi_config_init()
374 u32 cr_mode = ssi->cr_mode; in rsnd_ssi_config_init()
375 u32 wsr = ssi->wsr; in rsnd_ssi_config_init()
453 ssi->cr_own = cr_own; in rsnd_ssi_config_init()
454 ssi->cr_mode = cr_mode; in rsnd_ssi_config_init()
455 ssi->wsr = wsr; in rsnd_ssi_config_init()
460 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_register_setup() local
462 rsnd_mod_write(mod, SSIWSR, ssi->wsr); in rsnd_ssi_register_setup()
463 rsnd_mod_write(mod, SSICR, ssi->cr_own | in rsnd_ssi_register_setup()
464 ssi->cr_clk | in rsnd_ssi_register_setup()
465 ssi->cr_mode | in rsnd_ssi_register_setup()
466 ssi->cr_en); in rsnd_ssi_register_setup()
470 * SSI mod common functions
476 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_init() local
486 ssi->usrcnt++; in rsnd_ssi_init()
506 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_quit() local
512 if (!ssi->usrcnt) { in rsnd_ssi_quit()
521 ssi->usrcnt--; in rsnd_ssi_quit()
523 if (!ssi->usrcnt) { in rsnd_ssi_quit()
524 ssi->cr_own = 0; in rsnd_ssi_quit()
525 ssi->cr_mode = 0; in rsnd_ssi_quit()
526 ssi->wsr = 0; in rsnd_ssi_quit()
555 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_start() local
569 * SSI parent EN is not needed. in rsnd_ssi_start()
574 ssi->cr_en = EN; in rsnd_ssi_start()
576 rsnd_mod_write(mod, SSICR, ssi->cr_own | in rsnd_ssi_start()
577 ssi->cr_clk | in rsnd_ssi_start()
578 ssi->cr_mode | in rsnd_ssi_start()
579 ssi->cr_en); in rsnd_ssi_start()
588 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_stop() local
597 cr = ssi->cr_own | in rsnd_ssi_stop()
598 ssi->cr_clk; in rsnd_ssi_stop()
606 rsnd_mod_write(mod, SSICR, cr | ssi->cr_en); in rsnd_ssi_stop()
610 /* In multi-SSI mode, stop is performed by setting ssi0129 in in rsnd_ssi_stop()
617 * disable SSI, in rsnd_ssi_stop()
623 ssi->cr_en = 0; in rsnd_ssi_stop()
730 * SSIP (= SSI parent) needs to be special, otherwise, in rsnd_ssi_get_status()
731 * 2nd SSI might doesn't start. see also rsnd_mod_call() in rsnd_ssi_get_status()
733 * We can't include parent SSI status on SSI, because we don't know in rsnd_ssi_get_status()
734 * how many SSI requests parent SSI. Thus, it is localed on "io" now. in rsnd_ssi_get_status()
761 * SSI PIO
812 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_common_probe() local
817 * SSI Multi secondaries in rsnd_ssi_common_probe()
823 * It can't judge ssi parent at this point in rsnd_ssi_common_probe()
828 * SSI might be called again as PIO fallback in rsnd_ssi_common_probe()
838 if (!rsnd_flags_has(ssi, RSND_SSI_PROBED)) { in rsnd_ssi_common_probe()
839 ret = request_irq(ssi->irq, in rsnd_ssi_common_probe()
844 rsnd_flags_set(ssi, RSND_SSI_PROBED); in rsnd_ssi_common_probe()
854 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_common_remove() local
857 /* Do nothing if non SSI (= SSI parent, multi SSI) mod */ in rsnd_ssi_common_remove()
862 if (rsnd_flags_has(ssi, RSND_SSI_PROBED)) { in rsnd_ssi_common_remove()
863 free_irq(ssi->irq, mod); in rsnd_ssi_common_remove()
865 rsnd_flags_del(ssi, RSND_SSI_PROBED); in rsnd_ssi_common_remove()
872 * SSI PIO functions
878 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_pio_interrupt() local
879 u32 *buf = (u32 *)(runtime->dma_area + ssi->byte_pos); in rsnd_ssi_pio_interrupt()
897 byte_pos = ssi->byte_pos + sizeof(*buf); in rsnd_ssi_pio_interrupt()
899 if (byte_pos >= ssi->next_period_byte) { in rsnd_ssi_pio_interrupt()
900 int period_pos = byte_pos / ssi->byte_per_period; in rsnd_ssi_pio_interrupt()
907 ssi->next_period_byte = (period_pos + 1) * ssi->byte_per_period; in rsnd_ssi_pio_interrupt()
912 WRITE_ONCE(ssi->byte_pos, byte_pos); in rsnd_ssi_pio_interrupt()
922 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_pio_init() local
925 ssi->byte_pos = 0; in rsnd_ssi_pio_init()
926 ssi->byte_per_period = runtime->period_size * in rsnd_ssi_pio_init()
929 ssi->next_period_byte = ssi->byte_per_period; in rsnd_ssi_pio_init()
939 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_pio_pointer() local
942 *pointer = bytes_to_frames(runtime, READ_ONCE(ssi->byte_pos)); in rsnd_ssi_pio_pointer()
970 * SSI Multi secondaries in rsnd_ssi_dma_probe()
979 /* SSI probe might be called many times in MUX multi path */ in rsnd_ssi_dma_probe()
994 * SSI .probe might be called again. in rsnd_ssi_fallback()
1017 * If not, "rcar_sound.ssi" will be used. in rsnd_ssi_dma_req()
1038 struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); in rsnd_ssi_debug_info() local
1049 seq_printf(m, "chan: %d\n", ssi->chan); in rsnd_ssi_debug_info()
1050 seq_printf(m, "user: %d\n", ssi->usrcnt); in rsnd_ssi_debug_info()
1083 * ssi mod function
1098 /* try SSI -> SSIM1 -> SSIM2 -> SSIM3 */ in rsnd_ssi_connect()
1169 struct rsnd_ssi *ssi; in rsnd_ssi_probe() local
1183 ssi = devm_kcalloc(dev, nr, sizeof(*ssi), GFP_KERNEL); in rsnd_ssi_probe()
1184 if (!ssi) { in rsnd_ssi_probe()
1189 priv->ssi = ssi; in rsnd_ssi_probe()
1204 ssi = rsnd_ssi_get(priv, i); in rsnd_ssi_probe()
1217 rsnd_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE); in rsnd_ssi_probe()
1220 rsnd_flags_set(ssi, RSND_SSI_NO_BUSIF); in rsnd_ssi_probe()
1222 ssi->irq = irq_of_parse_and_map(np, 0); in rsnd_ssi_probe()
1223 if (!ssi->irq) { in rsnd_ssi_probe()
1234 ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk, in rsnd_ssi_probe()
1254 struct rsnd_ssi *ssi; in rsnd_ssi_remove() local
1257 for_each_rsnd_ssi(ssi, priv, i) { in rsnd_ssi_remove()
1258 rsnd_mod_quit(rsnd_mod_get(ssi)); in rsnd_ssi_remove()