Commit eed76bb8 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown

ASoC: rsnd: add rsnd_runtime_channel_xxx()

Current SSI is supporting Normal SSI/Multi mode SSI/TDM mode SSI
and its behavior is based on input channels.
This input channel might be converted by CTU,
and SSI needs to be Multi SSI mode / TDM SSI mode if 6ch input

EX) 6ch input, CTU for 2ch, playback

 6ch    6ch    2ch    2ch    2ch     2ch
 -> SRC -> CTU -> MIX -> DVC -> SSIU -> SSI

EX) 6ch input, no CTU, Multi SSI, playback

 6ch    6ch    6ch    6ch    6ch     2ch
 -> SRC -> CTU -> MIX -> DVC -> SSIU -> SSI0/SSI1/SSI2

Current driver is using rsnd_get_adinr_chan() / rsnd_get_slot_width()
for this purpose, but it is complicated enough without meaning.
This patch adds new rsnd_runtime_channel_xxx() which is caring
CTU/Multi SSI.
Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 8a3a2211
...@@ -224,13 +224,36 @@ int rsnd_get_slot_num(struct rsnd_dai_stream *io) ...@@ -224,13 +224,36 @@ int rsnd_get_slot_num(struct rsnd_dai_stream *io)
return rdai->slots_num; return rdai->slots_num;
} }
int rsnd_get_slot_width(struct rsnd_dai_stream *io) int rsnd_runtime_channel_original(struct rsnd_dai_stream *io)
{ {
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
int chan = runtime->channels;
/* Multi channel Mode */ return runtime->channels;
if (rsnd_ssi_multi_slaves_runtime(io)) }
int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io)
{
int chan = rsnd_runtime_channel_original(io);
struct rsnd_mod *ctu_mod = rsnd_io_to_mod_ctu(io);
if (ctu_mod) {
u32 converted_chan = rsnd_ctu_converted_channel(ctu_mod);
if (converted_chan)
return converted_chan;
}
return chan;
}
int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io)
{
int chan = rsnd_io_is_play(io) ?
rsnd_runtime_channel_after_ctu(io) :
rsnd_runtime_channel_original(io);
/* Use Multi SSI */
if (rsnd_runtime_is_ssi_multi(io))
chan /= rsnd_get_slot_num(io); chan /= rsnd_get_slot_num(io);
/* TDM Extend Mode needs 8ch */ /* TDM Extend Mode needs 8ch */
...@@ -240,6 +263,21 @@ int rsnd_get_slot_width(struct rsnd_dai_stream *io) ...@@ -240,6 +263,21 @@ int rsnd_get_slot_width(struct rsnd_dai_stream *io)
return chan; return chan;
} }
int rsnd_runtime_is_ssi_multi(struct rsnd_dai_stream *io)
{
int slots = rsnd_get_slot_num(io);
int chan = rsnd_io_is_play(io) ?
rsnd_runtime_channel_after_ctu(io) :
rsnd_runtime_channel_original(io);
return (chan >= 6) && (slots > 1);
}
int rsnd_runtime_is_ssi_tdm(struct rsnd_dai_stream *io)
{
return rsnd_runtime_channel_for_ssi(io) >= 6;
}
/* /*
* ADINR function * ADINR function
*/ */
...@@ -261,29 +299,6 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io) ...@@ -261,29 +299,6 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
return 0; return 0;
} }
u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
{
struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct device *dev = rsnd_priv_to_dev(priv);
u32 chan = runtime->channels;
switch (chan) {
case 1:
case 2:
case 4:
case 6:
case 8:
break;
default:
dev_warn(dev, "not supported channel\n");
chan = 0;
break;
}
return chan;
}
/* /*
* DALIGN function * DALIGN function
*/ */
......
...@@ -60,7 +60,7 @@ static void rsnd_ctu_value_init(struct rsnd_dai_stream *io, ...@@ -60,7 +60,7 @@ static void rsnd_ctu_value_init(struct rsnd_dai_stream *io,
{ {
rsnd_mod_write(mod, CTU_CTUIR, 1); rsnd_mod_write(mod, CTU_CTUIR, 1);
rsnd_mod_write(mod, CTU_ADINR, rsnd_get_adinr_chan(mod, io)); rsnd_mod_write(mod, CTU_ADINR, rsnd_runtime_channel_original(io));
rsnd_mod_write(mod, CTU_CPMDR, 0); rsnd_mod_write(mod, CTU_CPMDR, 0);
rsnd_mod_write(mod, CTU_SCMDR, 0); rsnd_mod_write(mod, CTU_SCMDR, 0);
......
...@@ -116,7 +116,7 @@ static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io, ...@@ -116,7 +116,7 @@ static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io,
u32 vrdbr = 0; u32 vrdbr = 0;
adinr = rsnd_get_adinr_bit(mod, io) | adinr = rsnd_get_adinr_bit(mod, io) |
rsnd_get_adinr_chan(mod, io); rsnd_runtime_channel_after_ctu(io);
/* Enable Digital Volume, Zero Cross Mute Mode */ /* Enable Digital Volume, Zero Cross Mute Mode */
dvucr |= 0x101; dvucr |= 0x101;
......
...@@ -51,7 +51,7 @@ static void rsnd_mix_volume_init(struct rsnd_dai_stream *io, ...@@ -51,7 +51,7 @@ static void rsnd_mix_volume_init(struct rsnd_dai_stream *io,
rsnd_mod_write(mod, MIX_MIXIR, 1); rsnd_mod_write(mod, MIX_MIXIR, 1);
/* General Information */ /* General Information */
rsnd_mod_write(mod, MIX_ADINR, rsnd_get_adinr_chan(mod, io)); rsnd_mod_write(mod, MIX_ADINR, rsnd_runtime_channel_after_ctu(io));
/* volume step */ /* volume step */
rsnd_mod_write(mod, MIX_MIXMR, 0); rsnd_mod_write(mod, MIX_MIXMR, 0);
......
...@@ -193,7 +193,6 @@ void rsnd_force_write(struct rsnd_priv *priv, struct rsnd_mod *mod, ...@@ -193,7 +193,6 @@ void rsnd_force_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg, void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
u32 mask, u32 data); u32 mask, u32 data);
u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io); u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io); u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
/* /*
...@@ -356,9 +355,14 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, ...@@ -356,9 +355,14 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai,
void rsnd_set_slot(struct rsnd_dai *rdai, void rsnd_set_slot(struct rsnd_dai *rdai,
int slots, int slots_total); int slots, int slots_total);
int rsnd_get_slot(struct rsnd_dai_stream *io); int rsnd_get_slot(struct rsnd_dai_stream *io);
int rsnd_get_slot_width(struct rsnd_dai_stream *io);
int rsnd_get_slot_num(struct rsnd_dai_stream *io); int rsnd_get_slot_num(struct rsnd_dai_stream *io);
int rsnd_runtime_channel_original(struct rsnd_dai_stream *io);
int rsnd_runtime_channel_after_ctu(struct rsnd_dai_stream *io);
int rsnd_runtime_channel_for_ssi(struct rsnd_dai_stream *io);
int rsnd_runtime_is_ssi_multi(struct rsnd_dai_stream *io);
int rsnd_runtime_is_ssi_tdm(struct rsnd_dai_stream *io);
/* /*
* R-Car sound DAI * R-Car sound DAI
*/ */
......
...@@ -205,7 +205,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, ...@@ -205,7 +205,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
* SRC_ADINR * SRC_ADINR
*/ */
adinr = rsnd_get_adinr_bit(mod, io) | adinr = rsnd_get_adinr_bit(mod, io) |
rsnd_get_adinr_chan(mod, io); rsnd_runtime_channel_original(io);
/* /*
* SRC_IFSCR / SRC_IFSVR * SRC_IFSCR / SRC_IFSVR
......
...@@ -180,11 +180,8 @@ static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io) ...@@ -180,11 +180,8 @@ static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io)
u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io) u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io)
{ {
struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); if (rsnd_runtime_is_ssi_multi(io))
u32 mask = rsnd_ssi_multi_slaves(io); return rsnd_ssi_multi_slaves(io);
if (mask && (runtime->channels >= 6))
return mask;
return 0; return 0;
} }
...@@ -198,7 +195,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, ...@@ -198,7 +195,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
int slots = rsnd_get_slot_width(io); int chan = rsnd_runtime_channel_for_ssi(io);
int j, ret; int j, ret;
int ssi_clk_mul_table[] = { int ssi_clk_mul_table[] = {
1, 2, 4, 8, 16, 6, 12, 1, 2, 4, 8, 16, 6, 12,
...@@ -231,10 +228,10 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, ...@@ -231,10 +228,10 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
/* /*
* this driver is assuming that * this driver is assuming that
* system word is 32bit x slots * system word is 32bit x chan
* see rsnd_ssi_init() * see rsnd_ssi_init()
*/ */
main_rate = rate * 32 * slots * ssi_clk_mul_table[j]; main_rate = rate * 32 * chan * ssi_clk_mul_table[j];
ret = rsnd_adg_ssi_clk_try_start(mod, main_rate); ret = rsnd_adg_ssi_clk_try_start(mod, main_rate);
if (0 == ret) { if (0 == ret) {
...@@ -289,7 +286,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, ...@@ -289,7 +286,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
u32 wsr; u32 wsr;
int is_tdm; int is_tdm;
is_tdm = (rsnd_get_slot_width(io) >= 6) ? 1 : 0; is_tdm = rsnd_runtime_is_ssi_tdm(io);
/* /*
* always use 32bit system word. * always use 32bit system word.
......
...@@ -105,7 +105,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, ...@@ -105,7 +105,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
if (ret < 0) if (ret < 0)
return ret; return ret;
if (rsnd_get_slot_width(io) >= 6) { if (rsnd_runtime_is_ssi_tdm(io)) {
/* /*
* TDM Extend Mode * TDM Extend Mode
* see * see
...@@ -117,7 +117,9 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, ...@@ -117,7 +117,9 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
if (rsnd_ssi_use_busif(io)) { if (rsnd_ssi_use_busif(io)) {
rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_write(mod, SSI_BUSIF_ADINR,
rsnd_get_adinr_bit(mod, io) | rsnd_get_adinr_bit(mod, io) |
rsnd_get_adinr_chan(mod, io)); (rsnd_io_is_play(io) ?
rsnd_runtime_channel_after_ctu(io) :
rsnd_runtime_channel_original(io)));
rsnd_mod_write(mod, SSI_BUSIF_MODE, 1); rsnd_mod_write(mod, SSI_BUSIF_MODE, 1);
rsnd_mod_write(mod, SSI_BUSIF_DALIGN, rsnd_mod_write(mod, SSI_BUSIF_DALIGN,
rsnd_get_dalign(mod, io)); rsnd_get_dalign(mod, io));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment