[alsa-devel] [PATCH 0/6] ASoC: rsnd: add CTU support
Hi Mark
These patches adds CTU (= Channel Transfer Unit) support to Renesas R-Car sound driver. It can exchange channel order ex) channel {0,1,2,3} -> channel {3,2,1,0} And it can add/reduce each channels sound ex) (input 0th ch x 0.5) + (input 2nd ch x 0.5) = output 1st ch You need to check R-Car datasheet for each detail settings, or check 6) patch
Kuninori Morimoto (6): 1) ASoC: rsnd: don't call update callback if it was NULL 2) ASoC: rsrc-card: add convert channels support 3) ASoC: rsnd: tidyup rsnd_ssiu_init_gen2() 4) ASoC: rsnd: add CTU basic support 5) ASoC: rsnd: add rsnd_runtime_channel_xxx() 6) ASoC: rsnd: add CTU support
Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt | 1 + sound/soc/sh/rcar/core.c | 71 ++++++++++++++---------- sound/soc/sh/rcar/ctu.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- sound/soc/sh/rcar/dvc.c | 2 +- sound/soc/sh/rcar/mix.c | 2 +- sound/soc/sh/rcar/rsnd.h | 9 +++- sound/soc/sh/rcar/rsrc-card.c | 22 +++++--- sound/soc/sh/rcar/src.c | 2 +- sound/soc/sh/rcar/ssi.c | 15 +++--- sound/soc/sh/rcar/ssiu.c | 11 ++-- 10 files changed, 330 insertions(+), 92 deletions(-)
Best regards --- Kuninori Morimoto
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 21e13b3..769d34c 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -927,7 +927,7 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl, } }
- if (change) + if (change && cfg->update) cfg->update(cfg->io, mod);
return change;
The patch
ASoC: rsnd: don't call update callback if it was NULL
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From d7289565483c65094d0473555625a4acd89567d3 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Thu, 25 Feb 2016 05:51:12 +0000 Subject: [PATCH] ASoC: rsnd: don't call update callback if it was NULL
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/sh/rcar/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ba37b0d55b21..3a3dc2ff18c9 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -927,7 +927,7 @@ static int rsnd_kctrl_put(struct snd_kcontrol *kctrl, } }
- if (change) + if (change && cfg->update) cfg->update(cfg->io, mod);
return change;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Renesas sound device has CTU (= Channel Transfer Unit), and sound card needs its support.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- .../bindings/sound/renesas,rsrc-card.txt | 1 + sound/soc/sh/rcar/rsrc-card.c | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt index 2b2caa2..5abebf7 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt @@ -30,6 +30,7 @@ Optional subnode properties: - frame-inversion : bool property. Add this if the dai-link uses frame clock inversion. - convert-rate : platform specified sampling rate convert +- convert-channels : platform specified channel size convert - audio-prefix : see audio-routing - audio-routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 8a357fd..ecf5d47 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -66,6 +66,7 @@ struct rsrc_card_priv { struct snd_soc_dai_link *dai_link; int dai_num; u32 convert_rate; + u32 convert_channels; };
#define rsrc_priv_to_dev(priv) ((priv)->snd_card.dev) @@ -145,11 +146,16 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS);
- if (!priv->convert_rate) - return 0; + if (priv->convert_rate) + rate->min = + rate->max = priv->convert_rate;
- rate->min = rate->max = priv->convert_rate; + if (priv->convert_channels) + channels->min = + channels->max = priv->convert_channels;
return 0; } @@ -437,9 +443,13 @@ static int rsrc_card_parse_of(struct device_node *node, /* sampling rate convert */ of_property_read_u32(node, "convert-rate", &priv->convert_rate);
- dev_dbg(dev, "New rsrc-audio-card: %s (%d)\n", - priv->snd_card.name ? priv->snd_card.name : "", - priv->convert_rate); + /* channels transfer */ + of_property_read_u32(node, "convert-channels", &priv->convert_channels); + + dev_dbg(dev, "New rsrc-audio-card: %s\n", + priv->snd_card.name ? priv->snd_card.name : ""); + dev_dbg(dev, "SRC : convert_rate %d\n", priv->convert_rate); + dev_dbg(dev, "CTU : convert_channels %d\n", priv->convert_channels);
ret = rsrc_card_dai_link_of(node, priv); if (ret < 0)
On Thu, Feb 25, 2016 at 05:51:44AM +0000, Kuninori Morimoto wrote:
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Renesas sound device has CTU (= Channel Transfer Unit), and sound card needs its support.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
.../bindings/sound/renesas,rsrc-card.txt | 1 + sound/soc/sh/rcar/rsrc-card.c | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt index 2b2caa2..5abebf7 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt @@ -30,6 +30,7 @@ Optional subnode properties:
- frame-inversion : bool property. Add this if the dai-link uses frame clock inversion.
- convert-rate : platform specified sampling rate convert
+- convert-channels : platform specified channel size convert
This needs a better description (as did convert-rate). What is the type? What are valid values?
- audio-prefix : see audio-routing
- audio-routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink,
Hi Mark, Rob
thank you for your review
- convert-rate : platform specified sampling rate convert
+- convert-channels : platform specified channel size convert
This needs a better description (as did convert-rate). What is the type? What are valid values?
OK, I will fixit
Mark, can I send additional patch ? or is v2 patch better ?
The patch
ASoC: rsrc-card: add convert channels support
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From f90432fc6ec41c5bb1d7b75edc1f2bc58799ece3 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Thu, 25 Feb 2016 05:51:44 +0000 Subject: [PATCH] ASoC: rsrc-card: add convert channels support
Renesas sound device has CTU (= Channel Transfer Unit), and sound card needs its support.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org --- .../bindings/sound/renesas,rsrc-card.txt | 1 + sound/soc/sh/rcar/rsrc-card.c | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt index 2b2caa281ce3..5abebf7898d9 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsrc-card.txt @@ -30,6 +30,7 @@ Optional subnode properties: - frame-inversion : bool property. Add this if the dai-link uses frame clock inversion. - convert-rate : platform specified sampling rate convert +- convert-channels : platform specified channel size convert - audio-prefix : see audio-routing - audio-routing : A list of the connections between audio components. Each entry is a pair of strings, the first being the connection's sink, diff --git a/sound/soc/sh/rcar/rsrc-card.c b/sound/soc/sh/rcar/rsrc-card.c index 545e94245e62..1bc7ecfc42a9 100644 --- a/sound/soc/sh/rcar/rsrc-card.c +++ b/sound/soc/sh/rcar/rsrc-card.c @@ -66,6 +66,7 @@ struct rsrc_card_priv { struct snd_soc_dai_link *dai_link; int dai_num; u32 convert_rate; + u32 convert_channels; };
#define rsrc_priv_to_dev(priv) ((priv)->snd_card.dev) @@ -144,11 +145,16 @@ static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct rsrc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS);
- if (!priv->convert_rate) - return 0; + if (priv->convert_rate) + rate->min = + rate->max = priv->convert_rate;
- rate->min = rate->max = priv->convert_rate; + if (priv->convert_channels) + channels->min = + channels->max = priv->convert_channels;
return 0; } @@ -436,9 +442,13 @@ static int rsrc_card_parse_of(struct device_node *node, /* sampling rate convert */ of_property_read_u32(node, "convert-rate", &priv->convert_rate);
- dev_dbg(dev, "New rsrc-audio-card: %s (%d)\n", - priv->snd_card.name ? priv->snd_card.name : "", - priv->convert_rate); + /* channels transfer */ + of_property_read_u32(node, "convert-channels", &priv->convert_channels); + + dev_dbg(dev, "New rsrc-audio-card: %s\n", + priv->snd_card.name ? priv->snd_card.name : ""); + dev_dbg(dev, "SRC : convert_rate %d\n", priv->convert_rate); + dev_dbg(dev, "CTU : convert_channels %d\n", priv->convert_channels);
ret = rsrc_card_dai_link_of(node, priv); if (ret < 0)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
remove unnecessary variable
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/ssiu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 1b8ea0e..0d964a0 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -115,13 +115,12 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, }
if (rsnd_ssi_use_busif(io)) { - u32 val = rsnd_get_dalign(mod, io); - rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_get_adinr_bit(mod, io) | rsnd_get_adinr_chan(mod, io)); rsnd_mod_write(mod, SSI_BUSIF_MODE, 1); - rsnd_mod_write(mod, SSI_BUSIF_DALIGN, val); + rsnd_mod_write(mod, SSI_BUSIF_DALIGN, + rsnd_get_dalign(mod, io)); }
return 0;
The patch
ASoC: rsnd: tidyup rsnd_ssiu_init_gen2()
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 135bb7d5c7b3fa40cd0559b5500a50d4e3663f6e Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Thu, 25 Feb 2016 05:52:13 +0000 Subject: [PATCH] ASoC: rsnd: tidyup rsnd_ssiu_init_gen2()
remove unnecessary variable
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/sh/rcar/ssiu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 1b8ea0e09bc2..0d964a0a3e31 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -115,13 +115,12 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, }
if (rsnd_ssi_use_busif(io)) { - u32 val = rsnd_get_dalign(mod, io); - rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_get_adinr_bit(mod, io) | rsnd_get_adinr_chan(mod, io)); rsnd_mod_write(mod, SSI_BUSIF_MODE, 1); - rsnd_mod_write(mod, SSI_BUSIF_DALIGN, val); + rsnd_mod_write(mod, SSI_BUSIF_DALIGN, + rsnd_get_dalign(mod, io)); }
return 0;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
This patch adds Renesas R-Car sound CTU (= Channel Transfer Unit) very basic support, but not yet enough feature at this point. Because CTU support needs more complex channel function for each modules. To avoid complex patch reviewing, this patch picked up very basic part only.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/ctu.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/rsnd.h | 1 + 2 files changed, 50 insertions(+)
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index a10d0f7..784515a 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -14,6 +14,7 @@
struct rsnd_ctu { struct rsnd_mod mod; + int channels; };
#define rsnd_ctu_nr(priv) ((priv)->ctu_nr) @@ -23,6 +24,9 @@ struct rsnd_ctu { ((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \ i++)
+#define rsnd_mod_to_ctu(_mod) \ + container_of((_mod), struct rsnd_ctu, mod) + #define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id)
static void rsnd_ctu_activation(struct rsnd_mod *mod) @@ -37,6 +41,13 @@ static void rsnd_ctu_halt(struct rsnd_mod *mod) rsnd_mod_write(mod, CTU_SWRSR, 0); }
+int rsnd_ctu_converted_channel(struct rsnd_mod *mod) +{ + struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); + + return ctu->channels; +} + static int rsnd_ctu_probe_(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) @@ -116,11 +127,49 @@ static int rsnd_ctu_quit(struct rsnd_mod *mod, return 0; }
+static int rsnd_ctu_hw_params(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *fe_params) +{ + struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); + struct snd_soc_pcm_runtime *fe = substream->private_data; + + /* + * CTU assumes that it is used under DPCM if user want to use + * channel transfer. Then, CTU should be FE. + * And then, this function will be called *after* BE settings. + * this means, each BE already has fixuped hw_params. + * see + * dpcm_fe_dai_hw_params() + * dpcm_be_dai_hw_params() + */ + ctu->channels = 0; + if (fe->dai_link->dynamic) { + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + struct snd_soc_dpcm *dpcm; + struct snd_pcm_hw_params *be_params; + int stream = substream->stream; + + list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { + be_params = &dpcm->hw_params; + if (params_channels(fe_params) != params_channels(be_params)) + ctu->channels = params_channels(be_params); + } + + dev_dbg(dev, "CTU convert channels %d\n", ctu->channels); + } + + return 0; +} + static struct rsnd_mod_ops rsnd_ctu_ops = { .name = CTU_NAME, .probe = rsnd_ctu_probe_, .init = rsnd_ctu_init, .quit = rsnd_ctu_quit, + .hw_params = rsnd_ctu_hw_params, };
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 305cc08..bbc89bd 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -638,6 +638,7 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, */ int rsnd_ctu_probe(struct rsnd_priv *priv); void rsnd_ctu_remove(struct rsnd_priv *priv); +int rsnd_ctu_converted_channel(struct rsnd_mod *mod); struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id); #define rsnd_ctu_of_node(priv) \ of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ctu")
The patch
ASoC: rsnd: add CTU basic support
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 8a3a2211e97395694827f12552bbad7f2caf11ef Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Thu, 25 Feb 2016 05:53:00 +0000 Subject: [PATCH] ASoC: rsnd: add CTU basic support
This patch adds Renesas R-Car sound CTU (= Channel Transfer Unit) very basic support, but not yet enough feature at this point. Because CTU support needs more complex channel function for each modules. To avoid complex patch reviewing, this patch picked up very basic part only.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/sh/rcar/ctu.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ sound/soc/sh/rcar/rsnd.h | 1 + 2 files changed, 50 insertions(+)
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index a10d0f7b73fa..784515afefaf 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -14,6 +14,7 @@
struct rsnd_ctu { struct rsnd_mod mod; + int channels; };
#define rsnd_ctu_nr(priv) ((priv)->ctu_nr) @@ -23,6 +24,9 @@ struct rsnd_ctu { ((pos) = (struct rsnd_ctu *)(priv)->ctu + i); \ i++)
+#define rsnd_mod_to_ctu(_mod) \ + container_of((_mod), struct rsnd_ctu, mod) + #define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id)
static void rsnd_ctu_activation(struct rsnd_mod *mod) @@ -37,6 +41,13 @@ static void rsnd_ctu_halt(struct rsnd_mod *mod) rsnd_mod_write(mod, CTU_SWRSR, 0); }
+int rsnd_ctu_converted_channel(struct rsnd_mod *mod) +{ + struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); + + return ctu->channels; +} + static int rsnd_ctu_probe_(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) @@ -116,11 +127,49 @@ static int rsnd_ctu_quit(struct rsnd_mod *mod, return 0; }
+static int rsnd_ctu_hw_params(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *fe_params) +{ + struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); + struct snd_soc_pcm_runtime *fe = substream->private_data; + + /* + * CTU assumes that it is used under DPCM if user want to use + * channel transfer. Then, CTU should be FE. + * And then, this function will be called *after* BE settings. + * this means, each BE already has fixuped hw_params. + * see + * dpcm_fe_dai_hw_params() + * dpcm_be_dai_hw_params() + */ + ctu->channels = 0; + if (fe->dai_link->dynamic) { + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + struct snd_soc_dpcm *dpcm; + struct snd_pcm_hw_params *be_params; + int stream = substream->stream; + + list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) { + be_params = &dpcm->hw_params; + if (params_channels(fe_params) != params_channels(be_params)) + ctu->channels = params_channels(be_params); + } + + dev_dbg(dev, "CTU convert channels %d\n", ctu->channels); + } + + return 0; +} + static struct rsnd_mod_ops rsnd_ctu_ops = { .name = CTU_NAME, .probe = rsnd_ctu_probe_, .init = rsnd_ctu_init, .quit = rsnd_ctu_quit, + .hw_params = rsnd_ctu_hw_params, };
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 305cc086a0bc..bbc89bd1e918 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -638,6 +638,7 @@ unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv, */ int rsnd_ctu_probe(struct rsnd_priv *priv); void rsnd_ctu_remove(struct rsnd_priv *priv); +int rsnd_ctu_converted_channel(struct rsnd_mod *mod); struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id); #define rsnd_ctu_of_node(priv) \ of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ctu")
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
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: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/core.c | 69 +++++++++++++++++++++++++++++------------------- sound/soc/sh/rcar/ctu.c | 2 +- sound/soc/sh/rcar/dvc.c | 2 +- sound/soc/sh/rcar/mix.c | 2 +- sound/soc/sh/rcar/rsnd.h | 8 ++++-- sound/soc/sh/rcar/src.c | 2 +- sound/soc/sh/rcar/ssi.c | 15 +++++------ sound/soc/sh/rcar/ssiu.c | 6 +++-- 8 files changed, 62 insertions(+), 44 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 769d34c..2481b8f 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -224,13 +224,36 @@ int rsnd_get_slot_num(struct rsnd_dai_stream *io) 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); - int chan = runtime->channels;
- /* Multi channel Mode */ - if (rsnd_ssi_multi_slaves_runtime(io)) + return runtime->channels; +} + +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);
/* TDM Extend Mode needs 8ch */ @@ -240,6 +263,21 @@ int rsnd_get_slot_width(struct rsnd_dai_stream *io) 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 */ @@ -261,29 +299,6 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io) 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 */ diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 784515a..b326966 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -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_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_SCMDR, 0); diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index d757f13..93b11e1 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -116,7 +116,7 @@ static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io, u32 vrdbr = 0;
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 */ dvucr |= 0x101; diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index e0e337a..195fc7b 100644 --- a/sound/soc/sh/rcar/mix.c +++ b/sound/soc/sh/rcar/mix.c @@ -51,7 +51,7 @@ static void rsnd_mix_volume_init(struct rsnd_dai_stream *io, rsnd_mod_write(mod, MIX_MIXIR, 1);
/* 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 */ rsnd_mod_write(mod, MIX_MIXMR, 0); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index bbc89bd..ff53f96 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -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, u32 mask, u32 data); 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);
/* @@ -356,9 +355,14 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, void rsnd_set_slot(struct rsnd_dai *rdai, int slots, int slots_total); 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_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 */ diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 03c6314..8e1177a 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -205,7 +205,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, * SRC_ADINR */ adinr = rsnd_get_adinr_bit(mod, io) | - rsnd_get_adinr_chan(mod, io); + rsnd_runtime_channel_original(io);
/* * SRC_IFSCR / SRC_IFSVR diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0979db8..5404897 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -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) { - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - u32 mask = rsnd_ssi_multi_slaves(io); - - if (mask && (runtime->channels >= 6)) - return mask; + if (rsnd_runtime_is_ssi_multi(io)) + return rsnd_ssi_multi_slaves(io);
return 0; } @@ -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_ssi *ssi = rsnd_mod_to_ssi(mod); 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 ssi_clk_mul_table[] = { 1, 2, 4, 8, 16, 6, 12, @@ -231,10 +228,10 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
/* * this driver is assuming that - * system word is 32bit x slots + * system word is 32bit x chan * 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); if (0 == ret) { @@ -289,7 +286,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, u32 wsr; 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. diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 0d964a0..6f9b388 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -105,7 +105,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, if (ret < 0) return ret;
- if (rsnd_get_slot_width(io) >= 6) { + if (rsnd_runtime_is_ssi_tdm(io)) { /* * TDM Extend Mode * see @@ -117,7 +117,9 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, if (rsnd_ssi_use_busif(io)) { rsnd_mod_write(mod, SSI_BUSIF_ADINR, 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_DALIGN, rsnd_get_dalign(mod, io));
The patch
ASoC: rsnd: add rsnd_runtime_channel_xxx()
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From eed76bb811cd143119b4bdeca88606685222e687 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Thu, 25 Feb 2016 05:54:58 +0000 Subject: [PATCH] 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: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/sh/rcar/core.c | 69 +++++++++++++++++++++++++++++------------------- sound/soc/sh/rcar/ctu.c | 2 +- sound/soc/sh/rcar/dvc.c | 2 +- sound/soc/sh/rcar/mix.c | 2 +- sound/soc/sh/rcar/rsnd.h | 8 ++++-- sound/soc/sh/rcar/src.c | 2 +- sound/soc/sh/rcar/ssi.c | 15 +++++------ sound/soc/sh/rcar/ssiu.c | 6 +++-- 8 files changed, 62 insertions(+), 44 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 3a3dc2ff18c9..3351a701c60e 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -224,13 +224,36 @@ int rsnd_get_slot_num(struct rsnd_dai_stream *io) 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); - int chan = runtime->channels;
- /* Multi channel Mode */ - if (rsnd_ssi_multi_slaves_runtime(io)) + return runtime->channels; +} + +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);
/* TDM Extend Mode needs 8ch */ @@ -240,6 +263,21 @@ int rsnd_get_slot_width(struct rsnd_dai_stream *io) 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 */ @@ -261,29 +299,6 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io) 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 */ diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 784515afefaf..b326966ea407 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -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_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_SCMDR, 0); diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index d757f1316385..93b11e1c5d7f 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -116,7 +116,7 @@ static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io, u32 vrdbr = 0;
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 */ dvucr |= 0x101; diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index e0e337ad4206..195fc7bb22af 100644 --- a/sound/soc/sh/rcar/mix.c +++ b/sound/soc/sh/rcar/mix.c @@ -51,7 +51,7 @@ static void rsnd_mix_volume_init(struct rsnd_dai_stream *io, rsnd_mod_write(mod, MIX_MIXIR, 1);
/* 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 */ rsnd_mod_write(mod, MIX_MIXMR, 0); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index bbc89bd1e918..ff53f96e5006 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -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, u32 mask, u32 data); 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);
/* @@ -356,9 +355,14 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, void rsnd_set_slot(struct rsnd_dai *rdai, int slots, int slots_total); 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_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 */ diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 03c6314871ff..8e1177aea6b1 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -205,7 +205,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, * SRC_ADINR */ adinr = rsnd_get_adinr_bit(mod, io) | - rsnd_get_adinr_chan(mod, io); + rsnd_runtime_channel_original(io);
/* * SRC_IFSCR / SRC_IFSVR diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0979db8af8f9..540489755367 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -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) { - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - u32 mask = rsnd_ssi_multi_slaves(io); - - if (mask && (runtime->channels >= 6)) - return mask; + if (rsnd_runtime_is_ssi_multi(io)) + return rsnd_ssi_multi_slaves(io);
return 0; } @@ -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_ssi *ssi = rsnd_mod_to_ssi(mod); 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 ssi_clk_mul_table[] = { 1, 2, 4, 8, 16, 6, 12, @@ -231,10 +228,10 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
/* * this driver is assuming that - * system word is 32bit x slots + * system word is 32bit x chan * 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); if (0 == ret) { @@ -289,7 +286,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, u32 wsr; 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. diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 0d964a0a3e31..6f9b388ec5a8 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -105,7 +105,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, if (ret < 0) return ret;
- if (rsnd_get_slot_width(io) >= 6) { + if (rsnd_runtime_is_ssi_tdm(io)) { /* * TDM Extend Mode * see @@ -117,7 +117,9 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, if (rsnd_ssi_use_busif(io)) { rsnd_mod_write(mod, SSI_BUSIF_ADINR, 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_DALIGN, rsnd_get_dalign(mod, io));
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
This patch adds CTU (= Channel Transfer Unit) support on Renesas R-Car sound driver. It can Down/Up mixing and splitter. You need to check R-Car datasheet especially CTUn_CPMDR/CTUn_SV0xR/CTUn_SV1xR/CTUn_SV2xR/CTUn_SV3xR for setting parameter.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/rcar/ctu.c | 234 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 197 insertions(+), 37 deletions(-)
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index b326966..9dcc1f9 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -12,8 +12,74 @@ #define CTU_NAME_SIZE 16 #define CTU_NAME "ctu"
+/* + * User needs to setup CTU by amixer, and its settings are + * based on below registers + * + * CTUn_CPMDR : amixser set "CTU Pass" + * CTUn_SV0xR : amixser set "CTU SV0" + * CTUn_SV1xR : amixser set "CTU SV1" + * CTUn_SV2xR : amixser set "CTU SV2" + * CTUn_SV3xR : amixser set "CTU SV3" + * + * [CTU Pass] + * 0000: default + * 0001: Connect input data of channel 0 + * 0010: Connect input data of channel 1 + * 0011: Connect input data of channel 2 + * 0100: Connect input data of channel 3 + * 0101: Connect input data of channel 4 + * 0110: Connect input data of channel 5 + * 0111: Connect input data of channel 6 + * 1000: Connect input data of channel 7 + * 1001: Connect calculated data by scale values of matrix row 0 + * 1010: Connect calculated data by scale values of matrix row 1 + * 1011: Connect calculated data by scale values of matrix row 2 + * 1100: Connect calculated data by scale values of matrix row 3 + * + * [CTU SVx] + * [Output0] = [SV00, SV01, SV02, SV03, SV04, SV05, SV06, SV07] + * [Output1] = [SV10, SV11, SV12, SV13, SV14, SV15, SV16, SV17] + * [Output2] = [SV20, SV21, SV22, SV23, SV24, SV25, SV26, SV27] + * [Output3] = [SV30, SV31, SV32, SV33, SV34, SV35, SV36, SV37] + * [Output4] = [ 0, 0, 0, 0, 0, 0, 0, 0 ] + * [Output5] = [ 0, 0, 0, 0, 0, 0, 0, 0 ] + * [Output6] = [ 0, 0, 0, 0, 0, 0, 0, 0 ] + * [Output7] = [ 0, 0, 0, 0, 0, 0, 0, 0 ] + * + * [SVxx] + * Plus Minus + * value time dB value time dB + * ----------------------------------------------------------------------- + * H'7F_FFFF 2 6 H'80_0000 2 6 + * ... + * H'40_0000 1 0 H'C0_0000 1 0 + * ... + * H'00_0001 2.38 x 10^-7 -132 + * H'00_0000 0 Mute H'FF_FFFF 2.38 x 10^-7 -132 + * + * + * Ex) Input ch -> Output ch + * 1ch -> 0ch + * 0ch -> 1ch + * + * amixer set "CTU Reset" on + * amixer set "CTU Pass" 9,10 + * amixer set "CTU SV0" 0,4194304 + * amixer set "CTU SV1" 4194304,0 + * or + * amixer set "CTU Reset" on + * amixer set "CTU Pass" 2,1 + */ + struct rsnd_ctu { struct rsnd_mod mod; + struct rsnd_kctrl_cfg_m pass; + struct rsnd_kctrl_cfg_m sv0; + struct rsnd_kctrl_cfg_m sv1; + struct rsnd_kctrl_cfg_m sv2; + struct rsnd_kctrl_cfg_m sv3; + struct rsnd_kctrl_cfg_s reset; int channels; };
@@ -58,51 +124,91 @@ static int rsnd_ctu_probe_(struct rsnd_mod *mod, static void rsnd_ctu_value_init(struct rsnd_dai_stream *io, struct rsnd_mod *mod) { + struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); + u32 cpmdr = 0; + u32 scmdr = 0; + int i; + + for (i = 0; i < RSND_MAX_CHANNELS; i++) { + u32 val = ctu->pass.val[i]; + + cpmdr |= val << (28 - (i * 4)); + + if ((val > 0x8) && (scmdr < (val - 0x8))) + scmdr = val - 0x8; + } + rsnd_mod_write(mod, CTU_CTUIR, 1);
rsnd_mod_write(mod, CTU_ADINR, rsnd_runtime_channel_original(io));
- rsnd_mod_write(mod, CTU_CPMDR, 0); - rsnd_mod_write(mod, CTU_SCMDR, 0); - rsnd_mod_write(mod, CTU_SV00R, 0); - rsnd_mod_write(mod, CTU_SV01R, 0); - rsnd_mod_write(mod, CTU_SV02R, 0); - rsnd_mod_write(mod, CTU_SV03R, 0); - rsnd_mod_write(mod, CTU_SV04R, 0); - rsnd_mod_write(mod, CTU_SV05R, 0); - rsnd_mod_write(mod, CTU_SV06R, 0); - rsnd_mod_write(mod, CTU_SV07R, 0); - - rsnd_mod_write(mod, CTU_SV10R, 0); - rsnd_mod_write(mod, CTU_SV11R, 0); - rsnd_mod_write(mod, CTU_SV12R, 0); - rsnd_mod_write(mod, CTU_SV13R, 0); - rsnd_mod_write(mod, CTU_SV14R, 0); - rsnd_mod_write(mod, CTU_SV15R, 0); - rsnd_mod_write(mod, CTU_SV16R, 0); - rsnd_mod_write(mod, CTU_SV17R, 0); - - rsnd_mod_write(mod, CTU_SV20R, 0); - rsnd_mod_write(mod, CTU_SV21R, 0); - rsnd_mod_write(mod, CTU_SV22R, 0); - rsnd_mod_write(mod, CTU_SV23R, 0); - rsnd_mod_write(mod, CTU_SV24R, 0); - rsnd_mod_write(mod, CTU_SV25R, 0); - rsnd_mod_write(mod, CTU_SV26R, 0); - rsnd_mod_write(mod, CTU_SV27R, 0); - - rsnd_mod_write(mod, CTU_SV30R, 0); - rsnd_mod_write(mod, CTU_SV31R, 0); - rsnd_mod_write(mod, CTU_SV32R, 0); - rsnd_mod_write(mod, CTU_SV33R, 0); - rsnd_mod_write(mod, CTU_SV34R, 0); - rsnd_mod_write(mod, CTU_SV35R, 0); - rsnd_mod_write(mod, CTU_SV36R, 0); - rsnd_mod_write(mod, CTU_SV37R, 0); + rsnd_mod_write(mod, CTU_CPMDR, cpmdr); + + rsnd_mod_write(mod, CTU_SCMDR, scmdr); + + if (scmdr > 0) { + rsnd_mod_write(mod, CTU_SV00R, ctu->sv0.val[0]); + rsnd_mod_write(mod, CTU_SV01R, ctu->sv0.val[1]); + rsnd_mod_write(mod, CTU_SV02R, ctu->sv0.val[2]); + rsnd_mod_write(mod, CTU_SV03R, ctu->sv0.val[3]); + rsnd_mod_write(mod, CTU_SV04R, ctu->sv0.val[4]); + rsnd_mod_write(mod, CTU_SV05R, ctu->sv0.val[5]); + rsnd_mod_write(mod, CTU_SV06R, ctu->sv0.val[6]); + rsnd_mod_write(mod, CTU_SV07R, ctu->sv0.val[7]); + } + if (scmdr > 1) { + rsnd_mod_write(mod, CTU_SV10R, ctu->sv1.val[0]); + rsnd_mod_write(mod, CTU_SV11R, ctu->sv1.val[1]); + rsnd_mod_write(mod, CTU_SV12R, ctu->sv1.val[2]); + rsnd_mod_write(mod, CTU_SV13R, ctu->sv1.val[3]); + rsnd_mod_write(mod, CTU_SV14R, ctu->sv1.val[4]); + rsnd_mod_write(mod, CTU_SV15R, ctu->sv1.val[5]); + rsnd_mod_write(mod, CTU_SV16R, ctu->sv1.val[6]); + rsnd_mod_write(mod, CTU_SV17R, ctu->sv1.val[7]); + } + if (scmdr > 2) { + rsnd_mod_write(mod, CTU_SV20R, ctu->sv2.val[0]); + rsnd_mod_write(mod, CTU_SV21R, ctu->sv2.val[1]); + rsnd_mod_write(mod, CTU_SV22R, ctu->sv2.val[2]); + rsnd_mod_write(mod, CTU_SV23R, ctu->sv2.val[3]); + rsnd_mod_write(mod, CTU_SV24R, ctu->sv2.val[4]); + rsnd_mod_write(mod, CTU_SV25R, ctu->sv2.val[5]); + rsnd_mod_write(mod, CTU_SV26R, ctu->sv2.val[6]); + rsnd_mod_write(mod, CTU_SV27R, ctu->sv2.val[7]); + } + if (scmdr > 3) { + rsnd_mod_write(mod, CTU_SV30R, ctu->sv3.val[0]); + rsnd_mod_write(mod, CTU_SV31R, ctu->sv3.val[1]); + rsnd_mod_write(mod, CTU_SV32R, ctu->sv3.val[2]); + rsnd_mod_write(mod, CTU_SV33R, ctu->sv3.val[3]); + rsnd_mod_write(mod, CTU_SV34R, ctu->sv3.val[4]); + rsnd_mod_write(mod, CTU_SV35R, ctu->sv3.val[5]); + rsnd_mod_write(mod, CTU_SV36R, ctu->sv3.val[6]); + rsnd_mod_write(mod, CTU_SV37R, ctu->sv3.val[7]); + }
rsnd_mod_write(mod, CTU_CTUIR, 0); }
+static void rsnd_ctu_value_reset(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) +{ + struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); + int i; + + if (!ctu->reset.val) + return; + + for (i = 0; i < RSND_MAX_CHANNELS; i++) { + ctu->pass.val[i] = 0; + ctu->sv0.val[i] = 0; + ctu->sv1.val[i] = 0; + ctu->sv2.val[i] = 0; + ctu->sv3.val[i] = 0; + } + ctu->reset.val = 0; +} + static int rsnd_ctu_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) @@ -164,12 +270,66 @@ static int rsnd_ctu_hw_params(struct rsnd_mod *mod, return 0; }
+static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct snd_soc_pcm_runtime *rtd) +{ + struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod); + int ret; + + /* CTU Pass */ + ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass", + NULL, + &ctu->pass, RSND_MAX_CHANNELS, + 0xC); + + /* ROW0 */ + ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0", + NULL, + &ctu->sv0, RSND_MAX_CHANNELS, + 0x00FFFFFF); + if (ret < 0) + return ret; + + /* ROW1 */ + ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1", + NULL, + &ctu->sv1, RSND_MAX_CHANNELS, + 0x00FFFFFF); + if (ret < 0) + return ret; + + /* ROW2 */ + ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2", + NULL, + &ctu->sv2, RSND_MAX_CHANNELS, + 0x00FFFFFF); + if (ret < 0) + return ret; + + /* ROW3 */ + ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3", + NULL, + &ctu->sv3, RSND_MAX_CHANNELS, + 0x00FFFFFF); + if (ret < 0) + return ret; + + /* Reset */ + ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset", + rsnd_ctu_value_reset, + &ctu->reset, 1); + + return ret; +} + static struct rsnd_mod_ops rsnd_ctu_ops = { .name = CTU_NAME, .probe = rsnd_ctu_probe_, .init = rsnd_ctu_init, .quit = rsnd_ctu_quit, .hw_params = rsnd_ctu_hw_params, + .pcm_new = rsnd_ctu_pcm_new, };
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
participants (3)
-
Kuninori Morimoto
-
Mark Brown
-
Rob Herring