[alsa-devel] [RFC 4/x v2] ASoC: snd_soc_component_driver has snd_pcm_ops

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Mon Jun 26 10:53:22 CEST 2017


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.gx at 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



More information about the Alsa-devel mailing list