snd_soc_platform_driver has snd_pcm_ops,
and it will be replaced into snd_soc_component_driver in the future.
To prepare it, component driver has it.

After this patch, rtd->platfrom is no longer mandatory

Signed-off-by: Kuninori Morimoto <kuninori.morimoto...@renesas.com>
---
 include/sound/soc.h  |   4 +-
 sound/soc/soc-core.c |  43 ++++++-
 sound/soc/soc-pcm.c  | 314 ++++++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 337 insertions(+), 24 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index ed613a7..f26897c 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -814,6 +814,8 @@ struct snd_soc_component_driver {
                int subseq);
        int (*stream_event)(struct snd_soc_component *, int event);
 
+       const struct snd_pcm_ops *ops;
+
        /* probe ordering - for components with runtime dependencies */
        int probe_order;
        int remove_order;
@@ -1247,7 +1249,7 @@ struct snd_soc_pcm_runtime {
        struct snd_pcm *pcm;
        struct snd_compr *compr;
        struct snd_soc_codec *codec;
-       struct snd_soc_platform *platform;
+       struct snd_soc_platform *platform; /* will be removed */
        struct snd_soc_dai *codec_dai;
        struct snd_soc_dai *cpu_dai;
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 287dec3..cdde8f7 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1079,6 +1079,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card,
        struct snd_soc_dai_link_component cpu_dai_component;
        struct snd_soc_dai **codec_dais;
        struct snd_soc_platform *platform;
+       struct snd_soc_component *component;
        struct device_node *platform_of_node;
        const char *platform_name;
        int i;
@@ -1128,6 +1129,22 @@ static int soc_bind_dai_link(struct snd_soc_card *card,
                platform_name = "snd-soc-dummy";
 
        /* find one from the set of registered platforms */
+       list_for_each_entry(component, &component_list, list) {
+               platform_of_node = component->dev->of_node;
+               if (!platform_of_node && component->dev->parent->of_node)
+                       platform_of_node = component->dev->parent->of_node;
+
+               if (dai_link->platform_of_node) {
+                       if (platform_of_node != dai_link->platform_of_node)
+                               continue;
+               } else {
+                       if (strcmp(component->name, platform_name))
+                               continue;
+               }
+
+               snd_soc_rtdcom_add(rtd, component);
+       }
+
        list_for_each_entry(platform, &platform_list, list) {
                platform_of_node = platform->dev->of_node;
                if (!platform_of_node && platform->dev->parent->of_node)
@@ -1143,11 +1160,6 @@ static int soc_bind_dai_link(struct snd_soc_card *card,
 
                rtd->platform = platform;
        }
-       if (!rtd->platform) {
-               dev_err(card->dev, "ASoC: platform %s not registered\n",
-                       dai_link->platform_name);
-               goto _err_defer;
-       }
 
        soc_add_pcm_runtime(card, rtd);
        return 0;
@@ -1215,12 +1227,20 @@ static void soc_remove_link_components(struct 
snd_soc_card *card,
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_platform *platform = rtd->platform;
        struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        int i;
 
        /* remove the platform */
        if (platform && platform->component.driver->remove_order == order)
                soc_remove_component(&platform->component);
 
+       /* remove the component */
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+               if (component->driver->remove_order == order)
+                       soc_remove_component(component);
+       }
+
        /* remove the CODEC-side CODEC */
        for (i = 0; i < rtd->num_codecs; i++) {
                component = rtd->codec_dais[i]->component;
@@ -1586,6 +1606,7 @@ static int soc_probe_link_components(struct snd_soc_card 
*card,
 {
        struct snd_soc_platform *platform = rtd->platform;
        struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        int i, ret;
 
        /* probe the CPU-side component, if it is a CODEC */
@@ -1607,12 +1628,22 @@ static int soc_probe_link_components(struct 
snd_soc_card *card,
        }
 
        /* probe the platform */
-       if (platform->component.driver->probe_order == order) {
+       if (platform && platform->component.driver->probe_order == order) {
                ret = soc_probe_component(card, &platform->component);
                if (ret < 0)
                        return ret;
        }
 
+       /* probe the component */
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+               if (component->driver->probe_order == order) {
+                       ret = soc_probe_component(card, component);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
        return 0;
 }
 
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index efc5831..b08ef16 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -450,10 +450,12 @@ static int soc_pcm_open(struct snd_pcm_substream 
*substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai;
        const char *codec_dai_name = "multicodec";
-       int i, ret = 0;
+       int i, ret = 0, __ret;
 
        pinctrl_pm_select_default_state(cpu_dai->dev);
        for (i = 0; i < rtd->num_codecs; i++)
@@ -461,7 +463,11 @@ static int soc_pcm_open(struct snd_pcm_substream 
*substream)
        pm_runtime_get_sync(cpu_dai->dev);
        for (i = 0; i < rtd->num_codecs; i++)
                pm_runtime_get_sync(rtd->codec_dais[i]->dev);
-       pm_runtime_get_sync(platform->dev);
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               pm_runtime_get_sync(component->dev);
+       }
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -475,7 +481,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                }
        }
 
-       if (platform->driver->ops && platform->driver->ops->open) {
+       if (platform && platform->driver->ops && platform->driver->ops->open) {
                ret = platform->driver->ops->open(substream);
                if (ret < 0) {
                        dev_err(platform->dev, "ASoC: can't open platform"
@@ -484,6 +490,25 @@ static int soc_pcm_open(struct snd_pcm_substream 
*substream)
                }
        }
 
+       ret = 0;
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (!component->driver->ops ||
+                   !component->driver->ops->open)
+                       continue;
+
+               __ret = component->driver->ops->open(substream);
+               if (__ret < 0) {
+                       dev_err(component->dev,
+                               "ASoC: can't open platform %s: %d\n",
+                               component->name, ret);
+                       ret = __ret;
+               }
+       }
+       if (ret < 0)
+               goto component_err;
+
        for (i = 0; i < rtd->num_codecs; i++) {
                codec_dai = rtd->codec_dais[i];
                if (codec_dai->driver->ops && codec_dai->driver->ops->startup) {
@@ -590,7 +615,16 @@ static int soc_pcm_open(struct snd_pcm_substream 
*substream)
                        codec_dai->driver->ops->shutdown(substream, codec_dai);
        }
 
-       if (platform->driver->ops && platform->driver->ops->close)
+component_err:
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (component->driver->ops &&
+                   component->driver->ops->close)
+                       component->driver->ops->close(substream);
+       }
+
+       if (platform && platform->driver->ops && platform->driver->ops->close)
                platform->driver->ops->close(substream);
 
 platform_err:
@@ -599,8 +633,13 @@ static int soc_pcm_open(struct snd_pcm_substream 
*substream)
 out:
        mutex_unlock(&rtd->pcm_mutex);
 
-       pm_runtime_mark_last_busy(platform->dev);
-       pm_runtime_put_autosuspend(platform->dev);
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               pm_runtime_mark_last_busy(component->dev);
+               pm_runtime_put_autosuspend(component->dev);
+       }
+
        for (i = 0; i < rtd->num_codecs; i++) {
                pm_runtime_mark_last_busy(rtd->codec_dais[i]->dev);
                pm_runtime_put_autosuspend(rtd->codec_dais[i]->dev);
@@ -655,6 +694,8 @@ static int soc_pcm_close(struct snd_pcm_substream 
*substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai;
        int i;
@@ -687,9 +728,17 @@ static int soc_pcm_close(struct snd_pcm_substream 
*substream)
        if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
                rtd->dai_link->ops->shutdown(substream);
 
-       if (platform->driver->ops && platform->driver->ops->close)
+       if (platform && platform->driver->ops && platform->driver->ops->close)
                platform->driver->ops->close(substream);
 
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (component->driver->ops &&
+                   component->driver->ops->close)
+                       component->driver->ops->close(substream);
+       }
+
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
                        /* powered down playback stream now */
@@ -711,8 +760,12 @@ static int soc_pcm_close(struct snd_pcm_substream 
*substream)
 
        mutex_unlock(&rtd->pcm_mutex);
 
-       pm_runtime_mark_last_busy(platform->dev);
-       pm_runtime_put_autosuspend(platform->dev);
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               pm_runtime_mark_last_busy(component->dev);
+               pm_runtime_put_autosuspend(component->dev);
+       }
 
        for (i = 0; i < rtd->num_codecs; i++) {
                pm_runtime_mark_last_busy(rtd->codec_dais[i]->dev);
@@ -741,6 +794,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream 
*substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai;
        int i, ret = 0;
@@ -756,7 +811,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream 
*substream)
                }
        }
 
-       if (platform->driver->ops && platform->driver->ops->prepare) {
+       if (platform && platform->driver->ops && 
platform->driver->ops->prepare) {
                ret = platform->driver->ops->prepare(substream);
                if (ret < 0) {
                        dev_err(platform->dev, "ASoC: platform prepare error:"
@@ -765,6 +820,21 @@ static int soc_pcm_prepare(struct snd_pcm_substream 
*substream)
                }
        }
 
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (!component->driver->ops ||
+                   !component->driver->ops->prepare)
+                       continue;
+
+               ret = component->driver->ops->prepare(substream);
+               if (ret < 0) {
+                       dev_err(component->dev, "ASoC: platform prepare error:"
+                               " %d\n", ret);
+                       goto out;
+               }
+       }
+
        for (i = 0; i < rtd->num_codecs; i++) {
                codec_dai = rtd->codec_dais[i];
                if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) {
@@ -847,8 +917,10 @@ static int soc_pcm_hw_params(struct snd_pcm_substream 
*substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-       int i, ret = 0;
+       int i, ret = 0, __ret;
 
        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
@@ -911,7 +983,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream 
*substream,
        if (ret < 0)
                goto interface_err;
 
-       if (platform->driver->ops && platform->driver->ops->hw_params) {
+       if (platform && platform->driver->ops && 
platform->driver->ops->hw_params) {
                ret = platform->driver->ops->hw_params(substream, params);
                if (ret < 0) {
                        dev_err(platform->dev, "ASoC: %s hw params failed: 
%d\n",
@@ -920,6 +992,25 @@ static int soc_pcm_hw_params(struct snd_pcm_substream 
*substream,
                }
        }
 
+       ret = 0;
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (!component->driver->ops ||
+                   !component->driver->ops->hw_params)
+                       continue;
+
+               __ret = component->driver->ops->hw_params(substream, params);
+               if (__ret < 0) {
+                       dev_err(component->dev,
+                               "ASoC: %s hw params failed: %d\n",
+                               component->name, ret);
+                       ret = __ret;
+               }
+       }
+       if (ret < 0)
+               goto component_err;
+
        /* store the parameters for each DAIs */
        cpu_dai->rate = params_rate(params);
        cpu_dai->channels = params_channels(params);
@@ -930,6 +1021,18 @@ static int soc_pcm_hw_params(struct snd_pcm_substream 
*substream,
        mutex_unlock(&rtd->pcm_mutex);
        return ret;
 
+component_err:
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (component->driver->ops &&
+                   component->driver->ops->hw_free)
+                       component->driver->ops->hw_free(substream);
+       }
+
+       if (platform && platform->driver->ops && platform->driver->ops->hw_free)
+               platform->driver->ops->hw_free(substream);
+
 platform_err:
        if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
                cpu_dai->driver->ops->hw_free(substream, cpu_dai);
@@ -959,6 +1062,8 @@ static int soc_pcm_hw_free(struct snd_pcm_substream 
*substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai;
        bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
@@ -995,9 +1100,18 @@ static int soc_pcm_hw_free(struct snd_pcm_substream 
*substream)
                rtd->dai_link->ops->hw_free(substream);
 
        /* free any DMA resources */
-       if (platform->driver->ops && platform->driver->ops->hw_free)
+       if (platform && platform->driver->ops && platform->driver->ops->hw_free)
                platform->driver->ops->hw_free(substream);
 
+       /* free any component resources */
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (component->driver->ops &&
+                   component->driver->ops->hw_free)
+                       component->driver->ops->hw_free(substream);
+       }
+
        /* now free hw params for the DAIs  */
        for (i = 0; i < rtd->num_codecs; i++) {
                codec_dai = rtd->codec_dais[i];
@@ -1016,6 +1130,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream 
*substream, int cmd)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai;
        int i, ret;
@@ -1030,12 +1146,23 @@ static int soc_pcm_trigger(struct snd_pcm_substream 
*substream, int cmd)
                }
        }
 
-       if (platform->driver->ops && platform->driver->ops->trigger) {
+       if (platform && platform->driver->ops && 
platform->driver->ops->trigger) {
                ret = platform->driver->ops->trigger(substream, cmd);
                if (ret < 0)
                        return ret;
        }
 
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (component->driver->ops &&
+                   component->driver->ops->trigger) {
+                       ret = component->driver->ops->trigger(substream, cmd);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
        if (cpu_dai->driver->ops && cpu_dai->driver->ops->trigger) {
                ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
                if (ret < 0)
@@ -1086,6 +1213,8 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_dai *codec_dai;
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1094,9 +1223,19 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
        snd_pcm_sframes_t codec_delay = 0;
        int i;
 
-       if (platform->driver->ops && platform->driver->ops->pointer)
+       if (platform && platform->driver->ops && platform->driver->ops->pointer)
                offset = platform->driver->ops->pointer(substream);
 
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (component->driver->ops &&
+                   component->driver->ops->pointer) {
+                       offset = component->driver->ops->pointer(substream);
+                       break;
+               }
+       }
+
        if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay)
                delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
 
@@ -2281,9 +2420,20 @@ static int soc_pcm_ioctl(struct snd_pcm_substream 
*substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
 
-       if (platform->driver->ops && platform->driver->ops->ioctl)
+       if (platform && platform->driver->ops && platform->driver->ops->ioctl)
                return platform->driver->ops->ioctl(substream, cmd, arg);
+
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (component->driver->ops &&
+                   component->driver->ops->ioctl)
+                       return component->driver->ops->ioctl(substream, cmd, 
arg);
+       }
+
        return snd_pcm_lib_ioctl(substream, cmd, arg);
 }
 
@@ -2640,6 +2790,116 @@ static void soc_pcm_free(struct snd_pcm *pcm)
        }
 }
 
+static int soc_rtdcom_ack(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_rtdcom_list *rtdcom;
+       struct snd_soc_component *component;
+
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (!component->driver->ops ||
+                   !component->driver->ops->ack)
+                       continue;
+
+               /* FIXME. it returns 1st ask now */
+               return component->driver->ops->ack(substream);
+       }
+
+       return -EINVAL;
+}
+
+static int soc_rtdcom_copy(struct snd_pcm_substream *substream, int channel,
+                          snd_pcm_uframes_t pos,
+                          void __user *buf, snd_pcm_uframes_t count)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_rtdcom_list *rtdcom;
+       struct snd_soc_component *component;
+
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (!component->driver->ops ||
+                   !component->driver->ops->copy)
+                       continue;
+
+               /* FIXME. it returns 1st copy now */
+               return component->driver->ops->copy(substream, channel,
+                                                  pos, buf, count);
+       }
+
+       return -EINVAL;
+}
+
+static int soc_rtdcom_silence(struct snd_pcm_substream *substream, int channel,
+                             snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_rtdcom_list *rtdcom;
+       struct snd_soc_component *component;
+
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (!component->driver->ops ||
+                   !component->driver->ops->silence)
+                       continue;
+
+               /* FIXME. it returns 1st silence now */
+               return component->driver->ops->silence(substream, channel,
+                                                     pos, count);
+       }
+
+       return -EINVAL;
+}
+
+static struct page* soc_rtdcom_page(struct snd_pcm_substream *substream,
+                                  unsigned long offset)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_rtdcom_list *rtdcom;
+       struct snd_soc_component *component;
+       struct page *page;
+
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (!component->driver->ops ||
+                   !component->driver->ops->page)
+                       continue;
+
+               /* FIXME. it returns 1st page now */
+               page = component->driver->ops->page(substream, offset);
+               if (page)
+                       return page;
+       }
+
+       return NULL;
+}
+
+static int soc_rtdcom_mmap(struct snd_pcm_substream *substream,
+                          struct vm_area_struct *vma)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_rtdcom_list *rtdcom;
+       struct snd_soc_component *component;
+
+       for_each_rtdcom(rtd, rtdcom) {
+               component = rtdcom->component;
+
+               if (!component->driver->ops ||
+                   !component->driver->ops->mmap)
+                       continue;
+
+               /* FIXME. it returns 1st mmap now */
+               return component->driver->ops->mmap(substream, vma);
+       }
+
+       return -EINVAL;
+}
+
 /* create a new pcm */
 int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 {
@@ -2647,6 +2907,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
        struct snd_soc_dai *codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_soc_component *component;
+       struct snd_soc_rtdcom_list *rtdcom;
        struct snd_pcm *pcm;
        char new_name[64];
        int ret = 0, playback = 0, capture = 0;
@@ -2741,7 +3002,26 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
                rtd->ops.ioctl          = soc_pcm_ioctl;
        }
 
-       if (platform->driver->ops) {
+       for_each_rtdcom(rtd, rtdcom) {
+               const struct snd_pcm_ops *ops = rtdcom->component->driver->ops;
+
+               if (!ops)
+                       continue;
+
+               if (ops->ack)
+                       rtd->ops.ack            = soc_rtdcom_ack;
+               if (ops->copy)
+                       rtd->ops.copy           = soc_rtdcom_copy;
+               if (ops->silence)
+                       rtd->ops.silence        = soc_rtdcom_silence;
+               if (ops->page)
+                       rtd->ops.page           = soc_rtdcom_page;
+               if (ops->mmap)
+                       rtd->ops.mmap           = soc_rtdcom_mmap;
+       }
+
+       /* overwrite */
+       if (platform && platform->driver->ops) {
                rtd->ops.ack            = platform->driver->ops->ack;
                rtd->ops.copy           = platform->driver->ops->copy;
                rtd->ops.silence        = platform->driver->ops->silence;
-- 
1.9.1

Reply via email to