static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, struct rsnd_dai *rdai, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(&ssi->mod); struct device *dev = rsnd_priv_to_dev(priv); u32 cr; if (0 == ssi->usrcnt) { clk_enable(ssi->clk); if (rsnd_rdai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_start(ssi->parent, rdai, io); else rsnd_ssi_master_clk_start(ssi, io); } } cr = ssi->cr_own | ssi->cr_clk | ssi->cr_etc | EN; rsnd_mod_write(&ssi->mod, SSICR, cr); ssi->usrcnt++; dev_dbg(dev, "ssi%d hw started\n", rsnd_mod_id(&ssi->mod)); }
/* * SSI mod common functions */ static int rsnd_ssi_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); int ret; if (!rsnd_ssi_is_run_mods(mod, io)) return 0; ssi->usrcnt++; rsnd_mod_power_on(mod); ret = rsnd_ssi_master_clk_start(mod, io); if (ret < 0) return ret; if (!rsnd_ssi_is_parent(mod, io)) rsnd_ssi_config_init(mod, io); rsnd_ssi_register_setup(mod); /* clear error status */ rsnd_ssi_status_clear(mod); return 0; }
static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_io_to_priv(io); struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct device *dev = rsnd_priv_to_dev(priv); u32 cr_mode; u32 cr; if (0 == ssi->usrcnt) { rsnd_mod_hw_start(&ssi->mod); if (rsnd_rdai_is_clk_master(rdai)) { if (rsnd_ssi_clk_from_parent(ssi)) rsnd_ssi_hw_start(ssi->parent, io); else rsnd_ssi_master_clk_start(ssi, io); } } cr_mode = rsnd_ssi_is_dma_mode(&ssi->mod) ? DMEN : /* DMA : enable DMA */ DIEN; /* PIO : enable Data interrupt */ cr = ssi->cr_own | ssi->cr_clk | cr_mode | UIEN | OIEN | EN; rsnd_mod_write(&ssi->mod, SSICR, cr); /* enable WS continue */ if (rsnd_rdai_is_clk_master(rdai)) rsnd_mod_write(&ssi->mod, SSIWSR, CONT); /* clear error status */ rsnd_mod_write(&ssi->mod, SSISR, 0); ssi->usrcnt++; dev_dbg(dev, "%s[%d] hw started\n", rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod)); }