Merge remote-tracking branch 'asoc/fix/rcar' into asoc-linus
authorMark Brown <broonie@kernel.org>
Fri, 26 May 2017 11:42:24 +0000 (12:42 +0100)
committerMark Brown <broonie@kernel.org>
Fri, 26 May 2017 11:42:24 +0000 (12:42 +0100)
sound/soc/sh/rcar/adg.c
sound/soc/sh/rcar/cmd.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/src.c
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssiu.c

index 66203d107a11e5ff17e150adb145b15a0d27934e..d3b0dc145a560c8a35ddc4320810039f481db5aa 100644 (file)
@@ -507,7 +507,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
                                rbga = rbgx;
                                adg->rbga_rate_for_441khz = rate / div;
                                ckr |= brg_table[i] << 20;
-                               if (req_441kHz_rate)
+                               if (req_441kHz_rate &&
+                                   !(adg_mode_flags(adg) & AUDIO_OUT_48))
                                        parent_clk_name = __clk_get_name(clk);
                        }
                }
@@ -522,7 +523,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
                                rbgb = rbgx;
                                adg->rbgb_rate_for_48khz = rate / div;
                                ckr |= brg_table[i] << 16;
-                               if (req_48kHz_rate)
+                               if (req_48kHz_rate &&
+                                   (adg_mode_flags(adg) & AUDIO_OUT_48))
                                        parent_clk_name = __clk_get_name(clk);
                        }
                }
index 7d92a24b7cfa558afbb8331401c974c59d5f1ae5..d879c010cf03c4607ebdab3c854a582d816ddf62 100644 (file)
@@ -89,6 +89,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod,
        dev_dbg(dev, "ctu/mix path = 0x%08x", data);
 
        rsnd_mod_write(mod, CMD_ROUTE_SLCT, data);
+       rsnd_mod_write(mod, CMD_BUSIF_MODE, rsnd_get_busif_shift(io, mod) | 1);
        rsnd_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
 
        rsnd_adg_set_cmd_timsel_gen2(mod, io);
index 1744015408c38f2ad530fbcbae9a22027f5f0828..8c1f4e2e0c4fb8c3ac09a641b4b8a928defb871c 100644 (file)
@@ -343,6 +343,57 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
                return 0x76543210;
 }
 
+u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
+{
+       enum rsnd_mod_type playback_mods[] = {
+               RSND_MOD_SRC,
+               RSND_MOD_CMD,
+               RSND_MOD_SSIU,
+       };
+       enum rsnd_mod_type capture_mods[] = {
+               RSND_MOD_CMD,
+               RSND_MOD_SRC,
+               RSND_MOD_SSIU,
+       };
+       struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+       struct rsnd_mod *tmod = NULL;
+       enum rsnd_mod_type *mods =
+               rsnd_io_is_play(io) ?
+               playback_mods : capture_mods;
+       int i;
+
+       /*
+        * This is needed for 24bit data
+        * We need to shift 8bit
+        *
+        * Linux 24bit data is located as 0x00******
+        * HW    24bit data is located as 0x******00
+        *
+        */
+       switch (runtime->sample_bits) {
+       case 16:
+               return 0;
+       case 32:
+               break;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(playback_mods); i++) {
+               tmod = rsnd_io_to_mod(io, mods[i]);
+               if (tmod)
+                       break;
+       }
+
+       if (tmod != mod)
+               return 0;
+
+       if (rsnd_io_is_play(io))
+               return  (0 << 20) | /* shift to Left */
+                       (8 << 16);  /* 8bit */
+       else
+               return  (1 << 20) | /* shift to Right */
+                       (8 << 16);  /* 8bit */
+}
+
 /*
  *     rsnd_dai functions
  */
index 63b6d3c28021024b1f06278c5c4f217a394faf8c..4b0980728e13ec75f18ac07135ab4971290b5310 100644 (file)
@@ -236,6 +236,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
                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),
+               RSND_GEN_M_REG(CMD_BUSIF_MODE,  0x184,  0x20),
                RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188,  0x20),
                RSND_GEN_M_REG(CMD_ROUTE_SLCT,  0x18c,  0x20),
                RSND_GEN_M_REG(CMD_CTRL,        0x190,  0x20),
index dbf4163427e808d62dbc37aa62f64b482e65e7c4..323af41ecfcb8ffea222f25fbe6c524968f29fd5 100644 (file)
@@ -73,6 +73,7 @@ enum rsnd_reg {
        RSND_REG_SCU_SYS_INT_EN0,
        RSND_REG_SCU_SYS_INT_EN1,
        RSND_REG_CMD_CTRL,
+       RSND_REG_CMD_BUSIF_MODE,
        RSND_REG_CMD_BUSIF_DALIGN,
        RSND_REG_CMD_ROUTE_SLCT,
        RSND_REG_CMDOUT_TIMSEL,
@@ -204,6 +205,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_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
+u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
 
 /*
  *     R-Car DMA
index 20b5b2ec625ea7b1e1812ea83d07d35b48b948ea..76a477a3ccb5d88e18fd8398d9ad2b2616a99f48 100644 (file)
@@ -190,11 +190,13 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
        struct device *dev = rsnd_priv_to_dev(priv);
        struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+       int is_play = rsnd_io_is_play(io);
        int use_src = 0;
        u32 fin, fout;
        u32 ifscr, fsrate, adinr;
        u32 cr, route;
        u32 bsdsr, bsisr;
+       u32 i_busif, o_busif, tmp;
        uint ratio;
 
        if (!runtime)
@@ -270,6 +272,11 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
                break;
        }
 
+       /* BUSIF_MODE */
+       tmp = rsnd_get_busif_shift(io, mod);
+       i_busif = ( is_play ? tmp : 0) | 1;
+       o_busif = (!is_play ? tmp : 0) | 1;
+
        rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
 
        rsnd_mod_write(mod, SRC_SRCIR, 1);      /* initialize */
@@ -281,8 +288,9 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
        rsnd_mod_write(mod, SRC_BSISR, bsisr);
        rsnd_mod_write(mod, SRC_SRCIR, 0);      /* cancel initialize */
 
-       rsnd_mod_write(mod, SRC_I_BUSIF_MODE, 1);
-       rsnd_mod_write(mod, SRC_O_BUSIF_MODE, 1);
+       rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif);
+       rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif);
+
        rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
 
        rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
index 135c5669f7963bd228c9a1187bc6f5dfd13bc04e..91e5c07911b4a5b14364becf64c568d7a61cc1c4 100644 (file)
@@ -302,7 +302,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
         * always use 32bit system word.
         * see also rsnd_ssi_master_clk_enable()
         */
-       cr_own = FORCE | SWL_32 | PDTA;
+       cr_own = FORCE | SWL_32;
 
        if (rdai->bit_clk_inv)
                cr_own |= SCKP;
@@ -550,6 +550,13 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
                struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
                u32 *buf = (u32 *)(runtime->dma_area +
                                   rsnd_dai_pointer_offset(io, 0));
+               int shift = 0;
+
+               switch (runtime->sample_bits) {
+               case 32:
+                       shift = 8;
+                       break;
+               }
 
                /*
                 * 8/16/32 data can be assesse to TDR/RDR register
@@ -557,9 +564,9 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
                 * see rsnd_ssi_init()
                 */
                if (rsnd_io_is_play(io))
-                       rsnd_mod_write(mod, SSITDR, *buf);
+                       rsnd_mod_write(mod, SSITDR, (*buf) << shift);
                else
-                       *buf = rsnd_mod_read(mod, SSIRDR);
+                       *buf = (rsnd_mod_read(mod, SSIRDR) >> shift);
 
                elapsed = rsnd_dai_pointer_update(io, sizeof(*buf));
        }
@@ -709,6 +716,11 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
                               struct rsnd_priv *priv)
 {
        struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+       struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
+
+       /* Do nothing for SSI parent mod */
+       if (ssi_parent_mod == mod)
+               return 0;
 
        /* PIO will request IRQ again */
        free_irq(ssi->irq, mod);
index 14fafdaf1395f9737191df18599ee58fc4f858fd..512d238b79e2895f13a4b1b7be3e145859a65280 100644 (file)
@@ -144,7 +144,8 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
                               (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,
+                              rsnd_get_busif_shift(io, mod) | 1);
                rsnd_mod_write(mod, SSI_BUSIF_DALIGN,
                               rsnd_get_dalign(mod, io));
        }