Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[firefly-linux-kernel-4.4.55.git] / sound / soc / sh / rcar / ssi.c
index 4b8cf7ca9d19fb016b971cf9f0f1ddeb74fbb954..4b7e20603dd7be8032198291ee08ed9b95de88dd 100644 (file)
@@ -64,108 +64,29 @@ struct rsnd_ssi {
        struct rsnd_mod mod;
 
        struct rsnd_dai *rdai;
-       struct rsnd_dai_stream *io;
        u32 cr_own;
        u32 cr_clk;
        u32 cr_etc;
        int err;
-       int dma_offset;
        unsigned int usrcnt;
        unsigned int rate;
 };
 
-struct rsnd_ssiu {
-       u32 ssi_mode0;
-       u32 ssi_mode1;
-
-       int ssi_nr;
-       struct rsnd_ssi *ssi;
-};
-
 #define for_each_rsnd_ssi(pos, priv, i)                                        \
        for (i = 0;                                                     \
             (i < rsnd_ssi_nr(priv)) &&                                 \
-               ((pos) = ((struct rsnd_ssiu *)((priv)->ssiu))->ssi + i); \
+               ((pos) = ((struct rsnd_ssi *)(priv)->ssi + i));         \
             i++)
 
-#define rsnd_ssi_nr(priv) (((struct rsnd_ssiu *)((priv)->ssiu))->ssi_nr)
+#define rsnd_ssi_nr(priv) ((priv)->ssi_nr)
 #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod)
 #define rsnd_dma_to_ssi(dma)  rsnd_mod_to_ssi(rsnd_dma_to_mod(dma))
 #define rsnd_ssi_pio_available(ssi) ((ssi)->info->pio_irq > 0)
 #define rsnd_ssi_dma_available(ssi) \
        rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod))
 #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent)
-#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master)
 #define rsnd_ssi_mode_flags(p) ((p)->info->flags)
 #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
-#define rsnd_ssi_to_ssiu(ssi)\
-       (((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1)
-
-static void rsnd_ssi_mode_set(struct rsnd_priv *priv,
-                             struct rsnd_dai *rdai,
-                             struct rsnd_ssi *ssi)
-{
-       struct device *dev = rsnd_priv_to_dev(priv);
-       struct rsnd_mod *scu;
-       struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi);
-       int id = rsnd_mod_id(&ssi->mod);
-       u32 flags;
-       u32 val;
-
-       scu   = rsnd_scu_mod_get(priv, rsnd_mod_id(&ssi->mod));
-
-       /*
-        * SSI_MODE0
-        */
-
-       /* see also BUSIF_MODE */
-       if (rsnd_scu_hpbif_is_enable(scu)) {
-               ssiu->ssi_mode0 &= ~(1 << id);
-               dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", id);
-       } else {
-               ssiu->ssi_mode0 |= (1 << id);
-               dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", id);
-       }
-
-       /*
-        * SSI_MODE1
-        */
-#define ssi_parent_set(p, sync, adg, ext)              \
-       do {                                            \
-               ssi->parent = ssiu->ssi + p;            \
-               if (rsnd_rdai_is_clk_master(rdai))      \
-                       val = adg;                      \
-               else                                    \
-                       val = ext;                      \
-               if (flags & RSND_SSI_SYNC)              \
-                       val |= sync;                    \
-       } while (0)
-
-       flags = rsnd_ssi_mode_flags(ssi);
-       if (flags & RSND_SSI_CLK_PIN_SHARE) {
-
-               val = 0;
-               switch (id) {
-               case 1:
-                       ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0));
-                       break;
-               case 2:
-                       ssi_parent_set(0, (1 << 4), (0x2 << 2), (0x1 << 2));
-                       break;
-               case 4:
-                       ssi_parent_set(3, (1 << 20), (0x2 << 16), (0x1 << 16));
-                       break;
-               case 8:
-                       ssi_parent_set(7, 0, 0, 0);
-                       break;
-               }
-
-               ssiu->ssi_mode1 |= val;
-       }
-
-       rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0);
-       rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1);
-}
 
 static void rsnd_ssi_status_check(struct rsnd_mod *mod,
                                  u32 bit)
@@ -200,7 +121,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_ssi *ssi,
                1, 2, 4, 8, 16, 6, 12,
        };
        unsigned int main_rate;
-       unsigned int rate = rsnd_scu_get_ssi_rate(priv, &ssi->mod, runtime);
+       unsigned int rate = rsnd_src_get_ssi_rate(priv, io, runtime);
 
        /*
         * Find best clock, and try to start ADG
@@ -252,7 +173,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
        if (0 == ssi->usrcnt) {
                clk_enable(ssi->clk);
 
-               if (rsnd_rdai_is_clk_master(rdai)) {
+               if (rsnd_dai_is_clk_master(rdai)) {
                        if (rsnd_ssi_clk_from_parent(ssi))
                                rsnd_ssi_hw_start(ssi->parent, rdai, io);
                        else
@@ -302,7 +223,7 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi,
                rsnd_mod_write(&ssi->mod, SSICR, cr);   /* disabled all */
                rsnd_ssi_status_check(&ssi->mod, IIRQ);
 
-               if (rsnd_rdai_is_clk_master(rdai)) {
+               if (rsnd_dai_is_clk_master(rdai)) {
                        if (rsnd_ssi_clk_from_parent(ssi))
                                rsnd_ssi_hw_stop(ssi->parent, rdai);
                        else
@@ -323,8 +244,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
                         struct rsnd_dai_stream *io)
 {
        struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-       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);
        u32 cr;
 
@@ -365,13 +284,10 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
         * set ssi parameter
         */
        ssi->rdai       = rdai;
-       ssi->io         = io;
        ssi->cr_own     = cr;
        ssi->err        = -1; /* ignore 1st error */
 
-       rsnd_ssi_mode_set(priv, rdai, ssi);
-
-       dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
+       rsnd_src_ssi_mode_init(mod, rdai, io);
 
        return 0;
 }
@@ -384,13 +300,10 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
        struct device *dev = rsnd_priv_to_dev(priv);
 
-       dev_dbg(dev, "%s.%d quit\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
-
        if (ssi->err > 0)
                dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err);
 
        ssi->rdai       = NULL;
-       ssi->io         = NULL;
        ssi->cr_own     = 0;
        ssi->err        = 0;
 
@@ -414,8 +327,9 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
 static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data)
 {
        struct rsnd_ssi *ssi = data;
-       struct rsnd_dai_stream *io = ssi->io;
-       u32 status = rsnd_mod_read(&ssi->mod, SSISR);
+       struct rsnd_mod *mod = &ssi->mod;
+       struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+       u32 status = rsnd_mod_read(mod, SSISR);
        irqreturn_t ret = IRQ_NONE;
 
        if (io && (status & DIRQ)) {
@@ -432,9 +346,9 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data)
                 * see rsnd_ssi_init()
                 */
                if (rsnd_dai_is_play(rdai, io))
-                       rsnd_mod_write(&ssi->mod, SSITDR, *buf);
+                       rsnd_mod_write(mod, SSITDR, *buf);
                else
-                       *buf = rsnd_mod_read(&ssi->mod, SSIRDR);
+                       *buf = rsnd_mod_read(mod, SSIRDR);
 
                rsnd_dai_pointer_update(io, sizeof(*buf));
 
@@ -444,25 +358,39 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data)
        return ret;
 }
 
-static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
+static int rsnd_ssi_pio_probe(struct rsnd_mod *mod,
                              struct rsnd_dai *rdai,
                              struct rsnd_dai_stream *io)
 {
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-       struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
        struct device *dev = rsnd_priv_to_dev(priv);
+       struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+       int irq = ssi->info->pio_irq;
+       int ret;
+
+       ret = devm_request_irq(dev, irq,
+                              rsnd_ssi_pio_interrupt,
+                              IRQF_SHARED,
+                              dev_name(dev), ssi);
+       if (ret)
+               dev_err(dev, "SSI request interrupt failed\n");
+
+       return ret;
+}
+
+static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
+                             struct rsnd_dai *rdai,
+                             struct rsnd_dai_stream *io)
+{
+       struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
 
        /* enable PIO IRQ */
        ssi->cr_etc = UIEN | OIEN | DIEN;
 
-       /* enable PIO interrupt if gen2 */
-       if (rsnd_is_gen2(priv))
-               rsnd_mod_write(&ssi->mod, INT_ENABLE, 0x0f000000);
+       rsnd_src_enable_ssi_irq(mod, rdai, io);
 
        rsnd_ssi_hw_start(ssi, rdai, io);
 
-       dev_dbg(dev, "%s.%d start\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
-
        return 0;
 }
 
@@ -470,12 +398,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
                             struct rsnd_dai *rdai,
                             struct rsnd_dai_stream *io)
 {
-       struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-       struct device *dev = rsnd_priv_to_dev(priv);
        struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
 
-       dev_dbg(dev, "%s.%d stop\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
-
        ssi->cr_etc = 0;
 
        rsnd_ssi_hw_stop(ssi, rdai);
@@ -485,35 +409,46 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
 
 static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
        .name   = "ssi (pio)",
+       .probe  = rsnd_ssi_pio_probe,
        .init   = rsnd_ssi_init,
        .quit   = rsnd_ssi_quit,
        .start  = rsnd_ssi_pio_start,
        .stop   = rsnd_ssi_pio_stop,
 };
 
-static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len)
+static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
+                         struct rsnd_dai *rdai,
+                         struct rsnd_dai_stream *io)
 {
-       struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma);
-       struct rsnd_dai_stream *io = ssi->io;
-       struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+       struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+       struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+       struct rcar_snd_info *info = rsnd_priv_to_info(priv);
+       struct device *dev = rsnd_priv_to_dev(priv);
+       int dma_id = ssi->info->dma_id;
+       int is_play;
+       int ret;
 
-       *len = io->byte_per_period;
-       *buf = runtime->dma_addr +
-               rsnd_dai_pointer_offset(io, ssi->dma_offset + *len);
-       ssi->dma_offset = *len; /* it cares A/B plane */
+       if (info->dai_info)
+               is_play = rsnd_info_is_playback(priv, ssi);
+       else
+               is_play = rsnd_ssi_is_play(&ssi->mod);
 
-       return 0;
-}
+       ret = rsnd_dma_init(
+               priv, rsnd_mod_to_dma(mod),
+               is_play,
+               dma_id);
 
-static int rsnd_ssi_dma_complete(struct rsnd_dma *dma)
-{
-       struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma);
-       struct rsnd_dai_stream *io = ssi->io;
-       u32 status = rsnd_mod_read(&ssi->mod, SSISR);
+       if (ret < 0)
+               dev_err(dev, "SSI DMA failed\n");
 
-       rsnd_ssi_record_error(ssi, status);
+       return ret;
+}
 
-       rsnd_dai_pointer_update(ssi->io, io->byte_per_period);
+static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
+                              struct rsnd_dai *rdai,
+                              struct rsnd_dai_stream *io)
+{
+       rsnd_dma_quit(rsnd_mod_to_priv(mod), rsnd_mod_to_dma(mod));
 
        return 0;
 }
@@ -527,14 +462,13 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
 
        /* enable DMA transfer */
        ssi->cr_etc = DMEN;
-       ssi->dma_offset = 0;
 
        rsnd_dma_start(dma);
 
        rsnd_ssi_hw_start(ssi, ssi->rdai, io);
 
        /* enable WS continue */
-       if (rsnd_rdai_is_clk_master(rdai))
+       if (rsnd_dai_is_clk_master(rdai))
                rsnd_mod_write(&ssi->mod, SSIWSR, CONT);
 
        return 0;
@@ -549,6 +483,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
 
        ssi->cr_etc = 0;
 
+       rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR));
+
        rsnd_ssi_hw_stop(ssi, rdai);
 
        rsnd_dma_stop(dma);
@@ -558,6 +494,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
 
 static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
        .name   = "ssi (dma)",
+       .probe  = rsnd_ssi_dma_probe,
+       .remove = rsnd_ssi_dma_remove,
        .init   = rsnd_ssi_init,
        .quit   = rsnd_ssi_quit,
        .start  = rsnd_ssi_dma_start,
@@ -567,24 +505,8 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
 /*
  *             Non SSI
  */
-static int rsnd_ssi_non(struct rsnd_mod *mod,
-                       struct rsnd_dai *rdai,
-                       struct rsnd_dai_stream *io)
-{
-       struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-       struct device *dev = rsnd_priv_to_dev(priv);
-
-       dev_dbg(dev, "%s\n", __func__);
-
-       return 0;
-}
-
 static struct rsnd_mod_ops rsnd_ssi_non_ops = {
        .name   = "ssi (non)",
-       .init   = rsnd_ssi_non,
-       .quit   = rsnd_ssi_non,
-       .start  = rsnd_ssi_non,
-       .stop   = rsnd_ssi_non,
 };
 
 /*
@@ -593,16 +515,30 @@ static struct rsnd_mod_ops rsnd_ssi_non_ops = {
 struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
                                          int dai_id, int is_play)
 {
+       struct rsnd_dai_platform_info *dai_info = NULL;
+       struct rsnd_dai_path_info *path_info = NULL;
+       struct rsnd_ssi_platform_info *target_info = NULL;
        struct rsnd_ssi *ssi;
        int i, has_play;
 
+       if (priv->rdai)
+               dai_info = priv->rdai[dai_id].info;
+       if (dai_info)
+               path_info = (is_play) ? &dai_info->playback : &dai_info->capture;
+       if (path_info)
+               target_info = path_info->ssi;
+
        is_play = !!is_play;
 
        for_each_rsnd_ssi(ssi, priv, i) {
+               if (target_info == ssi->info)
+                       return &ssi->mod;
+
+               /* for compatible */
                if (rsnd_ssi_dai_id(ssi) != dai_id)
                        continue;
 
-               has_play = !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY);
+               has_play = rsnd_ssi_is_play(&ssi->mod);
 
                if (is_play == has_play)
                        return &ssi->mod;
@@ -616,36 +552,122 @@ struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
        if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
                id = 0;
 
-       return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod;
+       return &((struct rsnd_ssi *)(priv->ssi) + id)->mod;
+}
+
+int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
+{
+       struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+
+       return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE);
+}
+
+int rsnd_ssi_is_play(struct rsnd_mod *mod)
+{
+       struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+
+       return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY);
+}
+
+static void rsnd_ssi_parent_clk_setup(struct rsnd_priv *priv, struct rsnd_ssi *ssi)
+{
+       if (!rsnd_ssi_is_pin_sharing(&ssi->mod))
+               return;
+
+       switch (rsnd_mod_id(&ssi->mod)) {
+       case 1:
+       case 2:
+               ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 0));
+               break;
+       case 4:
+               ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 3));
+               break;
+       case 8:
+               ssi->parent = rsnd_mod_to_ssi(rsnd_ssi_mod_get(priv, 7));
+               break;
+       }
+}
+
+
+static void rsnd_of_parse_ssi(struct platform_device *pdev,
+                             const struct rsnd_of_data *of_data,
+                             struct rsnd_priv *priv)
+{
+       struct device_node *node;
+       struct device_node *np;
+       struct rsnd_ssi_platform_info *ssi_info;
+       struct rcar_snd_info *info = rsnd_priv_to_info(priv);
+       struct device *dev = &pdev->dev;
+       int nr, i;
+
+       if (!of_data)
+               return;
+
+       node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi");
+       if (!node)
+               return;
+
+       nr = of_get_child_count(node);
+       if (!nr)
+               return;
+
+       ssi_info = devm_kzalloc(dev,
+                               sizeof(struct rsnd_ssi_platform_info) * nr,
+                               GFP_KERNEL);
+       if (!ssi_info) {
+               dev_err(dev, "ssi info allocation error\n");
+               return;
+       }
+
+       info->ssi_info          = ssi_info;
+       info->ssi_info_nr       = nr;
+
+       i = -1;
+       for_each_child_of_node(node, np) {
+               i++;
+
+               ssi_info = info->ssi_info + i;
+
+               /*
+                * pin settings
+                */
+               if (of_get_property(np, "shared-pin", NULL))
+                       ssi_info->flags |= RSND_SSI_CLK_PIN_SHARE;
+
+               /*
+                * irq
+                */
+               ssi_info->pio_irq = irq_of_parse_and_map(np, 0);
+       }
 }
 
 int rsnd_ssi_probe(struct platform_device *pdev,
-                  struct rcar_snd_info *info,
+                  const struct rsnd_of_data *of_data,
                   struct rsnd_priv *priv)
 {
+       struct rcar_snd_info *info = rsnd_priv_to_info(priv);
        struct rsnd_ssi_platform_info *pinfo;
        struct device *dev = rsnd_priv_to_dev(priv);
        struct rsnd_mod_ops *ops;
        struct clk *clk;
-       struct rsnd_ssiu *ssiu;
        struct rsnd_ssi *ssi;
        char name[RSND_SSI_NAME_SIZE];
-       int i, nr, ret;
+       int i, nr;
+
+       rsnd_of_parse_ssi(pdev, of_data, priv);
 
        /*
         *      init SSI
         */
        nr      = info->ssi_info_nr;
-       ssiu    = devm_kzalloc(dev, sizeof(*ssiu) + (sizeof(*ssi) * nr),
-                              GFP_KERNEL);
-       if (!ssiu) {
+       ssi     = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL);
+       if (!ssi) {
                dev_err(dev, "SSI allocate failed\n");
                return -ENOMEM;
        }
 
-       priv->ssiu      = ssiu;
-       ssiu->ssi       = (struct rsnd_ssi *)(ssiu + 1);
-       ssiu->ssi_nr    = nr;
+       priv->ssi       = ssi;
+       priv->ssi_nr    = nr;
 
        for_each_rsnd_ssi(ssi, priv, i) {
                pinfo = &info->ssi_info[i];
@@ -660,61 +682,15 @@ int rsnd_ssi_probe(struct platform_device *pdev,
                ssi->clk        = clk;
 
                ops = &rsnd_ssi_non_ops;
+               if (pinfo->dma_id > 0)
+                       ops = &rsnd_ssi_dma_ops;
+               else if (rsnd_ssi_pio_available(ssi))
+                       ops = &rsnd_ssi_pio_ops;
 
-               /*
-                * SSI DMA case
-                */
-               if (pinfo->dma_id > 0) {
-                       ret = rsnd_dma_init(
-                               priv, rsnd_mod_to_dma(&ssi->mod),
-                               (rsnd_ssi_mode_flags(ssi) & RSND_SSI_PLAY),
-                               pinfo->dma_id,
-                               rsnd_ssi_dma_inquiry,
-                               rsnd_ssi_dma_complete);
-                       if (ret < 0)
-                               dev_info(dev, "SSI DMA failed. try PIO transter\n");
-                       else
-                               ops     = &rsnd_ssi_dma_ops;
-
-                       dev_dbg(dev, "SSI%d use DMA transfer\n", i);
-               }
-
-               /*
-                * SSI PIO case
-                */
-               if (!rsnd_ssi_dma_available(ssi) &&
-                    rsnd_ssi_pio_available(ssi)) {
-                       ret = devm_request_irq(dev, pinfo->pio_irq,
-                                              &rsnd_ssi_pio_interrupt,
-                                              IRQF_SHARED,
-                                              dev_name(dev), ssi);
-                       if (ret) {
-                               dev_err(dev, "SSI request interrupt failed\n");
-                               return ret;
-                       }
-
-                       ops     = &rsnd_ssi_pio_ops;
-
-                       dev_dbg(dev, "SSI%d use PIO transfer\n", i);
-               }
+               rsnd_mod_init(priv, &ssi->mod, ops, RSND_MOD_SSI, i);
 
-               rsnd_mod_init(priv, &ssi->mod, ops, i);
+               rsnd_ssi_parent_clk_setup(priv, ssi);
        }
 
-       dev_dbg(dev, "ssi probed\n");
-
        return 0;
 }
-
-void rsnd_ssi_remove(struct platform_device *pdev,
-                  struct rsnd_priv *priv)
-{
-       struct rsnd_ssi *ssi;
-       int i;
-
-       for_each_rsnd_ssi(ssi, priv, i) {
-               if (rsnd_ssi_dma_available(ssi))
-                       rsnd_dma_quit(priv, rsnd_mod_to_dma(&ssi->mod));
-       }
-
-}