| From 742e8653d61715a65cfec6a179f922eb260b199d Mon Sep 17 00:00:00 2001 |
| From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Date: Wed, 15 Jul 2015 07:14:47 +0000 |
| Subject: [PATCH 297/326] ASoC: rsnd: tidyup data align position |
| |
| Sound L/R order of SSI is different from Linux sound data order. |
| So current rsnd driver is using DALIGN (= data align) to exchange data |
| align on SSIU. OTOH, CMD/SRC/SSIU have DALIGN register. Now inverted |
| sound volume will be exchanged if user used volume control on DVC. |
| Because SSIU which exchanges data align is located after DVC. |
| |
| MEM -> SRC -> DVC -> SSI |
| |
| This patch exchanges data align SRC if possible |
| |
| Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Tested-by: Keita Kobayashi <keita.kobayashi.ym@renesas.com> |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| (cherry picked from commit 4689032b11d1af10e5eb755eb575f9761a455a72) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| sound/soc/sh/rcar/core.c | 36 ++++++++++++++++++++++++++++++++++++ |
| sound/soc/sh/rcar/gen.c | 1 + |
| sound/soc/sh/rcar/rsnd.h | 3 +++ |
| sound/soc/sh/rcar/src.c | 20 +++++--------------- |
| 4 files changed, 45 insertions(+), 15 deletions(-) |
| |
| diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c |
| index a3637b92b187..0f9323f2c049 100644 |
| --- a/sound/soc/sh/rcar/core.c |
| +++ b/sound/soc/sh/rcar/core.c |
| @@ -249,6 +249,42 @@ u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io) |
| |
| return chan; |
| } |
| + |
| +/* |
| + * DALIGN function |
| + */ |
| +u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) |
| +{ |
| + struct rsnd_mod *src = rsnd_io_to_mod_src(io); |
| + struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); |
| + struct rsnd_mod *target = src ? src : ssi; |
| + struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
| + u32 val = 0x76543210; |
| + u32 mask = ~0; |
| + |
| + mask <<= runtime->channels * 4; |
| + val = val & mask; |
| + |
| + switch (runtime->sample_bits) { |
| + case 16: |
| + val |= 0x67452301 & ~mask; |
| + break; |
| + case 32: |
| + val |= 0x76543210 & ~mask; |
| + break; |
| + } |
| + |
| + /* |
| + * exchange channeles on SRC if possible, |
| + * otherwise, R/L volume settings on DVC |
| + * changes inverted channels |
| + */ |
| + if (mod == target) |
| + return val; |
| + else |
| + return 0x76543210; |
| +} |
| + |
| /* |
| * rsnd_dai functions |
| */ |
| diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c |
| index 5d3592dfc382..a2d5df4d5d17 100644 |
| --- a/sound/soc/sh/rcar/gen.c |
| +++ b/sound/soc/sh/rcar/gen.c |
| @@ -222,6 +222,7 @@ static int rsnd_gen2_probe(struct platform_device *pdev, |
| }; |
| struct rsnd_regmap_field_conf conf_scu[] = { |
| RSND_GEN_M_REG(SRC_BUSIF_MODE, 0x0, 0x20), |
| + RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20), |
| RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), |
| RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), |
| RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), |
| diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h |
| index 1296b3525fa6..6c10a8b9210e 100644 |
| --- a/sound/soc/sh/rcar/rsnd.h |
| +++ b/sound/soc/sh/rcar/rsnd.h |
| @@ -99,6 +99,7 @@ enum rsnd_reg { |
| RSND_REG_SHARE26, |
| RSND_REG_SHARE27, |
| RSND_REG_SHARE28, |
| + RSND_REG_SHARE29, |
| |
| RSND_REG_MAX, |
| }; |
| @@ -143,6 +144,7 @@ enum rsnd_reg { |
| #define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26 |
| #define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27 |
| #define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28 |
| +#define RSND_REG_SRC_BUSIF_DALIGN RSND_REG_SHARE29 |
| |
| struct rsnd_of_data; |
| struct rsnd_priv; |
| @@ -171,6 +173,7 @@ 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); |
| void rsnd_path_parse(struct rsnd_priv *priv, |
| struct rsnd_dai_stream *io); |
| |
| diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c |
| index c45da610feda..89a18e102feb 100644 |
| --- a/sound/soc/sh/rcar/src.c |
| +++ b/sound/soc/sh/rcar/src.c |
| @@ -148,7 +148,6 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
| int use_busif) |
| { |
| struct rsnd_dai *rdai = rsnd_io_to_rdai(io); |
| - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); |
| int ssi_id = rsnd_mod_id(ssi_mod); |
| |
| /* |
| @@ -185,27 +184,14 @@ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, |
| * DMA settings for SSIU |
| */ |
| if (use_busif) { |
| - u32 val = 0x76543210; |
| - u32 mask = ~0; |
| + u32 val = rsnd_get_dalign(ssi_mod, io); |
| |
| rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, |
| rsnd_get_adinr_bit(ssi_mod, io)); |
| rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); |
| rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); |
| |
| - mask <<= runtime->channels * 4; |
| - val = val & mask; |
| - |
| - switch (runtime->sample_bits) { |
| - case 16: |
| - val |= 0x67452301 & ~mask; |
| - break; |
| - case 32: |
| - val |= 0x76543210 & ~mask; |
| - break; |
| - } |
| rsnd_mod_write(ssi_mod, SSI_BUSIF_DALIGN, val); |
| - |
| } |
| |
| return 0; |
| @@ -678,6 +664,10 @@ static int _rsnd_src_start_gen2(struct rsnd_mod *mod, |
| struct rsnd_src *src = rsnd_mod_to_src(mod); |
| u32 val; |
| |
| + val = rsnd_get_dalign(mod, io); |
| + |
| + rsnd_mod_write(mod, SRC_BUSIF_DALIGN, val); |
| + |
| /* |
| * WORKAROUND |
| * |
| -- |
| 2.6.2 |
| |