ASoC: rsnd: tidyup data align position
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Wed, 15 Jul 2015 07:14:47 +0000 (07:14 +0000)
committerMark Brown <broonie@kernel.org>
Thu, 16 Jul 2015 21:29:21 +0000 (22:29 +0100)
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>
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/src.c

index a3637b92b187639376703297d3476149ad5a7dce..0f9323f2c04953e6eda10a73ffade623bce268c5 100644 (file)
@@ -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
  */
index 5d3592dfc3824d2bf8a6f2f9d33459fd8d3e51b1..a2d5df4d5d176f4c9f8e44abe86bb9626fc16551 100644 (file)
@@ -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),
index 1296b3525fa69e55cc1b54c28b1e470696652996..6c10a8b9210e3514fd5be734feb7ef7383d578ad 100644 (file)
@@ -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);
 
index c45da610fedac66f286ae99e1a623fd7d64cc4b1..89a18e102feb100b57350024a3d548261e91243e 100644 (file)
@@ -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
         *