Merge branch 'for-4.20' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[linux-2.6-block.git] / sound / soc / sh / rcar / ssi.c
index 6ec78f3096dd3e8158561535569e1f2502674d49..45ef295743ecdc2f6042e36b2c2f31edd619a3f9 100644 (file)
@@ -99,9 +99,7 @@ struct rsnd_ssi {
 /* flags */
 #define RSND_SSI_CLK_PIN_SHARE         (1 << 0)
 #define RSND_SSI_NO_BUSIF              (1 << 1) /* SSI+DMA without BUSIF */
-#define RSND_SSI_HDMI0                 (1 << 2) /* for HDMI0 */
-#define RSND_SSI_HDMI1                 (1 << 3) /* for HDMI1 */
-#define RSND_SSI_PROBED                        (1 << 4)
+#define RSND_SSI_PROBED                        (1 << 2)
 
 #define for_each_rsnd_ssi(pos, priv, i)                                        \
        for (i = 0;                                                     \
@@ -119,19 +117,7 @@ struct rsnd_ssi {
        (rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod)))
 #define rsnd_ssi_can_output_clk(mod) (!__rsnd_ssi_is_pin_sharing(mod))
 
-int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io)
-{
-       struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
-       struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-
-       if (rsnd_flags_has(ssi, RSND_SSI_HDMI0))
-               return RSND_SSI_HDMI_PORT0;
-
-       if (rsnd_flags_has(ssi, RSND_SSI_HDMI1))
-               return RSND_SSI_HDMI_PORT1;
-
-       return 0;
-}
+static int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
 
 int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
 {
@@ -150,11 +136,6 @@ int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
        return use_busif;
 }
 
-int rsnd_ssi_get_busif(struct rsnd_dai_stream *io)
-{
-       return 0; /* BUSIF0 only for now */
-}
-
 static void rsnd_ssi_status_clear(struct rsnd_mod *mod)
 {
        rsnd_mod_write(mod, SSISR, 0);
@@ -181,8 +162,7 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod,
                udelay(5);
        }
 
-       dev_warn(dev, "%s[%d] status check failed\n",
-                rsnd_mod_name(mod), rsnd_mod_id(mod));
+       dev_warn(dev, "%s status check failed\n", rsnd_mod_name(mod));
 }
 
 static u32 rsnd_ssi_multi_slaves(struct rsnd_dai_stream *io)
@@ -224,7 +204,7 @@ static u32 rsnd_ssi_run_mods(struct rsnd_dai_stream *io)
 
 u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io)
 {
-       if (rsnd_runtime_is_ssi_multi(io))
+       if (rsnd_runtime_is_multi_ssi(io))
                return rsnd_ssi_multi_slaves(io);
 
        return 0;
@@ -320,6 +300,9 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
                return 0;
        }
 
+       if (rsnd_runtime_is_tdm_split(io))
+               chan = rsnd_io_converted_chan(io);
+
        main_rate = rsnd_ssi_clk_query(rdai, rate, chan, &idx);
        if (!main_rate) {
                dev_err(dev, "unsupported clock rate\n");
@@ -346,9 +329,8 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
        ssi->rate = rate;
        ssi->chan = chan;
 
-       dev_dbg(dev, "%s[%d] outputs %u Hz\n",
-               rsnd_mod_name(mod),
-               rsnd_mod_id(mod), rate);
+       dev_dbg(dev, "%s outputs %d chan %u Hz\n",
+               rsnd_mod_name(mod), chan, rate);
 
        return 0;
 }
@@ -379,14 +361,23 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
                                struct rsnd_dai_stream *io)
 {
        struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+       struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai);
+       struct device *dev = rsnd_priv_to_dev(priv);
        struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
        struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
        u32 cr_own      = ssi->cr_own;
        u32 cr_mode     = ssi->cr_mode;
        u32 wsr         = ssi->wsr;
-       int is_tdm;
+       int width;
+       int is_tdm, is_tdm_split;
+
+       is_tdm          = rsnd_runtime_is_tdm(io);
+       is_tdm_split    = rsnd_runtime_is_tdm_split(io);
 
-       is_tdm = rsnd_runtime_is_ssi_tdm(io);
+       if (is_tdm)
+               dev_dbg(dev, "TDM mode\n");
+       if (is_tdm_split)
+               dev_dbg(dev, "TDM Split mode\n");
 
        cr_own |= FORCE | rsnd_rdai_width_to_swl(rdai);
 
@@ -405,7 +396,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
         *      rsnd_ssiu_init_gen2()
         */
        wsr = ssi->wsr;
-       if (is_tdm) {
+       if (is_tdm || is_tdm_split) {
                wsr     |= WS_MODE;
                cr_own  |= CHNL_8;
        }
@@ -421,7 +412,18 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
                cr_own |= TRMD;
 
        cr_own &= ~DWL_MASK;
-       switch (snd_pcm_format_width(runtime->format)) {
+       width = snd_pcm_format_width(runtime->format);
+       if (is_tdm_split) {
+               /*
+                * The SWL and DWL bits in SSICR should be fixed at 32-bit
+                * setting when TDM split mode.
+                * see datasheet
+                *      Operation :: TDM Format Split Function (TDM Split Mode)
+                */
+               width = 32;
+       }
+
+       switch (width) {
        case 8:
                cr_own |= DWL_8;
                break;
@@ -431,6 +433,9 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
        case 24:
                cr_own |= DWL_24;
                break;
+       case 32:
+               cr_own |= DWL_32;
+               break;
        }
 
        if (rsnd_ssi_is_dma_mode(mod)) {
@@ -494,8 +499,7 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
                return 0;
 
        if (!ssi->usrcnt) {
-               dev_err(dev, "%s[%d] usrcnt error\n",
-                       rsnd_mod_name(mod), rsnd_mod_id(mod));
+               dev_err(dev, "%s usrcnt error\n", rsnd_mod_name(mod));
                return -EIO;
        }
 
@@ -654,8 +658,8 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
 
        /* DMA only */
        if (is_dma && (status & (UIRQ | OIRQ))) {
-               rsnd_dbg_irq_status(dev, "%s[%d] err status : 0x%08x\n",
-                       rsnd_mod_name(mod), rsnd_mod_id(mod), status);
+               rsnd_dbg_irq_status(dev, "%s err status : 0x%08x\n",
+                       rsnd_mod_name(mod), status);
 
                stop = true;
        }
@@ -681,6 +685,41 @@ static irqreturn_t rsnd_ssi_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static u32 *rsnd_ssi_get_status(struct rsnd_mod *mod,
+                               struct rsnd_dai_stream *io,
+                               enum rsnd_mod_type type)
+{
+       /*
+        * SSIP (= SSI parent) needs to be special, otherwise,
+        * 2nd SSI might doesn't start. see also rsnd_mod_call()
+        *
+        * We can't include parent SSI status on SSI, because we don't know
+        * how many SSI requests parent SSI. Thus, it is localed on "io" now.
+        * ex) trouble case
+        *      Playback: SSI0
+        *      Capture : SSI1 (needs SSI0)
+        *
+        * 1) start Capture  -> SSI0/SSI1 are started.
+        * 2) start Playback -> SSI0 doesn't work, because it is already
+        *                      marked as "started" on 1)
+        *
+        * OTOH, using each mod's status is good for MUX case.
+        * It doesn't need to start in 2nd start
+        * ex)
+        *      IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0
+        *                          |
+        *      IO-1: SRC1 -> CTU2 -+
+        *
+        * 1) start IO-0 ->     start SSI0
+        * 2) start IO-1 ->     SSI0 doesn't need to start, because it is
+        *                      already started on 1)
+        */
+       if (type == RSND_MOD_SSIP)
+               return &io->parent_ssi_status;
+
+       return rsnd_mod_get_status(mod, io, type);
+}
+
 /*
  *             SSI PIO
  */
@@ -730,7 +769,7 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
 {
        struct device *dev = rsnd_priv_to_dev(priv);
        struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-       int ret;
+       int ret = 0;
 
        /*
         * SSIP/SSIU/IRQ are not needed on
@@ -744,10 +783,6 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
         * see rsnd_ssi_pcm_new()
         */
 
-       ret = rsnd_ssiu_attach(io, mod);
-       if (ret < 0)
-               return ret;
-
        /*
         * SSI might be called again as PIO fallback
         * It is easy to manual handling for IRQ request/free
@@ -876,18 +911,19 @@ static int rsnd_ssi_prepare(struct rsnd_mod *mod,
 }
 
 static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
-       .name   = SSI_NAME,
-       .probe  = rsnd_ssi_common_probe,
-       .remove = rsnd_ssi_common_remove,
-       .init   = rsnd_ssi_pio_init,
-       .quit   = rsnd_ssi_quit,
-       .start  = rsnd_ssi_start,
-       .stop   = rsnd_ssi_stop,
-       .irq    = rsnd_ssi_irq,
-       .pointer = rsnd_ssi_pio_pointer,
-       .pcm_new = rsnd_ssi_pcm_new,
-       .hw_params = rsnd_ssi_hw_params,
-       .prepare = rsnd_ssi_prepare,
+       .name           = SSI_NAME,
+       .probe          = rsnd_ssi_common_probe,
+       .remove         = rsnd_ssi_common_remove,
+       .init           = rsnd_ssi_pio_init,
+       .quit           = rsnd_ssi_quit,
+       .start          = rsnd_ssi_start,
+       .stop           = rsnd_ssi_stop,
+       .irq            = rsnd_ssi_irq,
+       .pointer        = rsnd_ssi_pio_pointer,
+       .pcm_new        = rsnd_ssi_pcm_new,
+       .hw_params      = rsnd_ssi_hw_params,
+       .prepare        = rsnd_ssi_prepare,
+       .get_status     = rsnd_ssi_get_status,
 };
 
 static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
@@ -928,8 +964,7 @@ static int rsnd_ssi_fallback(struct rsnd_mod *mod,
         */
        mod->ops = &rsnd_ssi_pio_ops;
 
-       dev_info(dev, "%s[%d] fallback to PIO mode\n",
-                rsnd_mod_name(mod), rsnd_mod_id(mod));
+       dev_info(dev, "%s fallback to PIO mode\n", rsnd_mod_name(mod));
 
        return 0;
 }
@@ -941,6 +976,17 @@ static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io,
        int is_play = rsnd_io_is_play(io);
        char *name;
 
+       /*
+        * It should use "rcar_sound,ssiu" on DT.
+        * But, we need to keep compatibility for old version.
+        *
+        * If it has "rcar_sound.ssiu", it will be used.
+        * If not, "rcar_sound.ssi" will be used.
+        * see
+        *      rsnd_ssiu_dma_req()
+        *      rsnd_dma_of_path()
+        */
+
        if (rsnd_ssi_use_busif(io))
                name = is_play ? "rxu" : "txu";
        else
@@ -951,27 +997,27 @@ static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io,
 }
 
 static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
-       .name   = SSI_NAME,
-       .dma_req = rsnd_ssi_dma_req,
-       .probe  = rsnd_ssi_dma_probe,
-       .remove = rsnd_ssi_common_remove,
-       .init   = rsnd_ssi_init,
-       .quit   = rsnd_ssi_quit,
-       .start  = rsnd_ssi_start,
-       .stop   = rsnd_ssi_stop,
-       .irq    = rsnd_ssi_irq,
-       .pcm_new = rsnd_ssi_pcm_new,
-       .fallback = rsnd_ssi_fallback,
-       .hw_params = rsnd_ssi_hw_params,
-       .prepare = rsnd_ssi_prepare,
+       .name           = SSI_NAME,
+       .dma_req        = rsnd_ssi_dma_req,
+       .probe          = rsnd_ssi_dma_probe,
+       .remove         = rsnd_ssi_common_remove,
+       .init           = rsnd_ssi_init,
+       .quit           = rsnd_ssi_quit,
+       .start          = rsnd_ssi_start,
+       .stop           = rsnd_ssi_stop,
+       .irq            = rsnd_ssi_irq,
+       .pcm_new        = rsnd_ssi_pcm_new,
+       .fallback       = rsnd_ssi_fallback,
+       .hw_params      = rsnd_ssi_hw_params,
+       .prepare        = rsnd_ssi_prepare,
+       .get_status     = rsnd_ssi_get_status,
 };
 
-int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)
+static int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod)
 {
        return mod->ops == &rsnd_ssi_dma_ops;
 }
 
-
 /*
  *             ssi mod function
  */
@@ -1027,54 +1073,6 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
        of_node_put(node);
 }
 
-static void __rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
-                                            struct rsnd_dai_stream *io,
-                                            struct device_node *remote_ep)
-{
-       struct device *dev = rsnd_priv_to_dev(priv);
-       struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
-       struct rsnd_ssi *ssi;
-       struct device_node *remote_node = of_graph_get_port_parent(remote_ep);
-
-       /* support Gen3 only */
-       if (!rsnd_is_gen3(priv))
-               return;
-
-       if (!mod)
-               return;
-
-       ssi  = rsnd_mod_to_ssi(mod);
-
-       /* HDMI0 */
-       if (strstr(remote_node->full_name, "hdmi@fead0000")) {
-               rsnd_flags_set(ssi, RSND_SSI_HDMI0);
-               dev_dbg(dev, "%s[%d] connected to HDMI0\n",
-                        rsnd_mod_name(mod), rsnd_mod_id(mod));
-       }
-
-       /* HDMI1 */
-       if (strstr(remote_node->full_name, "hdmi@feae0000")) {
-               rsnd_flags_set(ssi, RSND_SSI_HDMI1);
-               dev_dbg(dev, "%s[%d] connected to HDMI1\n",
-                       rsnd_mod_name(mod), rsnd_mod_id(mod));
-       }
-}
-
-void rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
-                                   struct device_node *endpoint,
-                                   int dai_i)
-{
-       struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i);
-       struct device_node *remote_ep;
-
-       remote_ep = of_graph_get_remote_endpoint(endpoint);
-       if (!remote_ep)
-               return;
-
-       __rsnd_ssi_parse_hdmi_connection(priv, &rdai->playback, remote_ep);
-       __rsnd_ssi_parse_hdmi_connection(priv, &rdai->capture,  remote_ep);
-}
-
 struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
 {
        if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
@@ -1091,41 +1089,6 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
        return !!(rsnd_flags_has(rsnd_mod_to_ssi(mod), RSND_SSI_CLK_PIN_SHARE));
 }
 
-static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io,
-                               struct rsnd_mod *mod,
-                               enum rsnd_mod_type type)
-{
-       /*
-        * SSIP (= SSI parent) needs to be special, otherwise,
-        * 2nd SSI might doesn't start. see also rsnd_mod_call()
-        *
-        * We can't include parent SSI status on SSI, because we don't know
-        * how many SSI requests parent SSI. Thus, it is localed on "io" now.
-        * ex) trouble case
-        *      Playback: SSI0
-        *      Capture : SSI1 (needs SSI0)
-        *
-        * 1) start Capture  -> SSI0/SSI1 are started.
-        * 2) start Playback -> SSI0 doesn't work, because it is already
-        *                      marked as "started" on 1)
-        *
-        * OTOH, using each mod's status is good for MUX case.
-        * It doesn't need to start in 2nd start
-        * ex)
-        *      IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0
-        *                          |
-        *      IO-1: SRC1 -> CTU2 -+
-        *
-        * 1) start IO-0 ->     start SSI0
-        * 2) start IO-1 ->     SSI0 doesn't need to start, because it is
-        *                      already started on 1)
-        */
-       if (type == RSND_MOD_SSIP)
-               return &io->parent_ssi_status;
-
-       return rsnd_mod_get_status(io, mod, type);
-}
-
 int rsnd_ssi_probe(struct rsnd_priv *priv)
 {
        struct device_node *node;
@@ -1192,7 +1155,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
                        ops = &rsnd_ssi_dma_ops;
 
                ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
-                                   rsnd_ssi_get_status, RSND_MOD_SSI, i);
+                                   RSND_MOD_SSI, i);
                if (ret) {
                        of_node_put(np);
                        goto rsnd_ssi_probe_done;