From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
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 --- 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 a3637b9..0f9323f 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 5d3592df..a2d5df4 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 1296b35..6c10a8b 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 c45da61..89a18e1 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 *