ASoC: rsnd: add TDM Extend Mode support
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Mon, 30 Nov 2015 08:54:03 +0000 (08:54 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 30 Nov 2015 18:11:23 +0000 (18:11 +0000)
Renesas R-Car can out TDM by
1) 6ch x 1 DAI as TDM Extend Mode
2) 2ch x 4 x 1 DAI as TDM split Mode
3) 2ch x 3 DAI or
   2ch x 4 DAI as TDM Multichannel Mode

This patch adds 1) TDM Extend Mode. Because of HW design,
this 6ch data will be outputed via 8ch data width.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@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/ssi.c
sound/soc/sh/rcar/ssiu.c

index 7d364d7..b187a89 100644 (file)
@@ -247,9 +247,9 @@ 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)
 {
        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;
+       struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+       u32 chan = rsnd_get_slot_rdai(rdai);
 
        switch (chan) {
        case 1:
@@ -569,9 +569,31 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        return 0;
 }
 
+static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
+                                    u32 tx_mask, u32 rx_mask,
+                                    int slots, int slot_width)
+{
+       struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
+       struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
+       struct device *dev = rsnd_priv_to_dev(priv);
+
+       switch (slots) {
+       case 6:
+               /* TDM Extend Mode */
+               rdai->slots = slots;
+               break;
+       default:
+               dev_err(dev, "unsupported TDM slots (%d)\n", slots);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
        .trigger        = rsnd_soc_dai_trigger,
        .set_fmt        = rsnd_soc_dai_set_fmt,
+       .set_tdm_slot   = rsnd_soc_set_dai_tdm_slot,
 };
 
 static int rsnd_dai_probe(struct rsnd_priv *priv)
@@ -626,7 +648,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
                drv->playback.rates             = RSND_RATES;
                drv->playback.formats           = RSND_FMTS;
                drv->playback.channels_min      = 2;
-               drv->playback.channels_max      = 2;
+               drv->playback.channels_max      = 6;
                drv->playback.stream_name       = rdai->playback.name;
 
                snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE,
@@ -634,7 +656,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
                drv->capture.rates              = RSND_RATES;
                drv->capture.formats            = RSND_FMTS;
                drv->capture.channels_min       = 2;
-               drv->capture.channels_max       = 2;
+               drv->capture.channels_max       = 6;
                drv->capture.stream_name        = rdai->capture.name;
 
                rdai->playback.rdai             = rdai;
index 2151aa5..50fc730 100644 (file)
@@ -230,6 +230,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
                RSND_GEN_M_REG(SSI_BUSIF_MODE,  0x0,    0x80),
                RSND_GEN_M_REG(SSI_BUSIF_ADINR, 0x4,    0x80),
                RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8,    0x80),
+               RSND_GEN_M_REG(SSI_MODE,        0xc,    0x80),
                RSND_GEN_M_REG(SSI_CTRL,        0x10,   0x80),
                RSND_GEN_M_REG(SSI_INT_ENABLE,  0x18,   0x80),
        };
index 2111bf3..970e130 100644 (file)
@@ -44,6 +44,7 @@
  */
 enum rsnd_reg {
        /* SCU (SRC/SSIU/MIX/CTU/DVC) */
+       RSND_REG_SSI_MODE,              /* Gen2 only */
        RSND_REG_SSI_MODE0,
        RSND_REG_SSI_MODE1,
        RSND_REG_SSI_CTRL,              /* Gen2 only */
index 44e9141..628739f 100644 (file)
@@ -24,7 +24,9 @@
 #define        OIEN            (1 << 26)       /* Overflow Interrupt Enable */
 #define        IIEN            (1 << 25)       /* Idle Mode Interrupt Enable */
 #define        DIEN            (1 << 24)       /* Data Interrupt Enable */
-
+#define        CHNL_4          (1 << 22)       /* Channels */
+#define        CHNL_6          (2 << 22)       /* Channels */
+#define        CHNL_8          (3 << 22)       /* Channels */
 #define        DWL_8           (0 << 19)       /* Data Word Length */
 #define        DWL_16          (1 << 19)       /* Data Word Length */
 #define        DWL_18          (2 << 19)       /* Data Word Length */
@@ -57,6 +59,7 @@
  * SSIWSR
  */
 #define CONT           (1 << 8)        /* WS Continue Function */
+#define WS_MODE                (1 << 0)        /* WS Mode */
 
 #define SSI_NAME "ssi"
 
@@ -261,6 +264,7 @@ static int rsnd_ssi_config_init(struct rsnd_ssi *ssi,
        struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
        u32 cr_own;
        u32 cr_mode;
+       u32 wsr;
 
        /*
         * always use 32bit system word.
@@ -297,8 +301,20 @@ static int rsnd_ssi_config_init(struct rsnd_ssi *ssi,
                cr_mode = DIEN;         /* PIO : enable Data interrupt */
        }
 
+       /*
+        * TDM Extend Mode
+        * see
+        *      rsnd_ssiu_init_gen2()
+        */
+       wsr = ssi->wsr;
+       if (rsnd_get_slot_runtime(io) >= 6) {
+               wsr     |= WS_MODE;
+               cr_own  |= CHNL_8;
+       }
+
        ssi->cr_own     = cr_own;
        ssi->cr_mode    = cr_mode;
+       ssi->wsr        = wsr;
 
        return 0;
 }
index 6120b0a..3265501 100644 (file)
@@ -78,6 +78,15 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
        if (ret < 0)
                return ret;
 
+       if (rsnd_get_slot_runtime(io) >= 6) {
+               /*
+                * TDM Extend Mode
+                * see
+                *      rsnd_ssi_config_init()
+                */
+               rsnd_mod_write(mod, SSI_MODE, 0x1);
+       }
+
        if (rsnd_ssi_use_busif(io)) {
                u32 val = rsnd_get_dalign(mod, io);