static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_io_to_priv(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct device *dev = rsnd_priv_to_dev(priv); int i, j, ret; int adg_clk_div_table[] = { 1, 6, /* see adg.c */ }; int ssi_clk_mul_table[] = { 1, 2, 4, 8, 16, 6, 12, }; unsigned int main_rate; unsigned int rate = rsnd_src_get_ssi_rate(priv, io, runtime); /* * Find best clock, and try to start ADG */ for (i = 0; i < ARRAY_SIZE(adg_clk_div_table); i++) { for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) { /* * this driver is assuming that * system word is 64fs (= 2 x 32bit) * see rsnd_ssi_init() */ main_rate = rate / adg_clk_div_table[i] * 32 * 2 * ssi_clk_mul_table[j]; ret = rsnd_adg_ssi_clk_try_start(&ssi->mod, main_rate); if (0 == ret) { ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(j); dev_dbg(dev, "%s[%d] outputs %u Hz\n", rsnd_mod_name(&ssi->mod), rsnd_mod_id(&ssi->mod), rate); return 0; } } } dev_err(dev, "unsupported clock rate\n"); return -EIO; }
static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_io_to_priv(io); struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); int chan = rsnd_runtime_channel_for_ssi(io); int j, ret; int ssi_clk_mul_table[] = { 1, 2, 4, 8, 16, 6, 12, }; unsigned int main_rate; unsigned int rate = rsnd_io_is_play(io) ? rsnd_src_get_out_rate(priv, io) : rsnd_src_get_in_rate(priv, io); if (!rsnd_rdai_is_clk_master(rdai)) return 0; if (ssi_parent_mod && !rsnd_ssi_is_parent(mod, io)) return 0; if (rsnd_ssi_is_multi_slave(mod, io)) return 0; if (ssi->usrcnt > 1) { if (ssi->rate != rate) { dev_err(dev, "SSI parent/child should use same rate\n"); return -EINVAL; } return 0; } /* * Find best clock, and try to start ADG */ for (j = 0; j < ARRAY_SIZE(ssi_clk_mul_table); j++) { /* * this driver is assuming that * system word is 32bit x chan * see rsnd_ssi_init() */ main_rate = rate * 32 * chan * ssi_clk_mul_table[j]; ret = rsnd_adg_ssi_clk_try_start(mod, main_rate); if (0 == ret) { ssi->cr_clk = FORCE | SWL_32 | SCKD | SWSD | CKDV(j); ssi->wsr = CONT; ssi->rate = rate; dev_dbg(dev, "%s[%d] outputs %u Hz\n", rsnd_mod_name(mod), rsnd_mod_id(mod), rate); return 0; } } dev_err(dev, "unsupported clock rate\n"); return -EIO; }