[5/6] ASoC: add Component level struct snd_compr_ops
diff mbox

Message ID 8737hk74l7.wl%kuninori.morimoto.gx@renesas.com
State New
Headers show

Commit Message

Kuninori Morimoto Dec. 19, 2016, 7:38 a.m. UTC
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

In current ALSA SoC, Platform has struct snd_compr_ops feature,
but it should be supported on Component level. This patch adds it.

If component level has it, many snd_pcm_ops can be called,
but, 1st ops function only will be used now. It should/will be
fixed in the future.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 include/sound/soc.h      |   4 +
 sound/soc/soc-compress.c | 246 ++++++++++++++++++++++++++++++++---------------
 sound/soc/soc-core.c     |   2 +
 3 files changed, 175 insertions(+), 77 deletions(-)

Comments

Charles Keepax Dec. 19, 2016, 11:12 a.m. UTC | #1
On Mon, Dec 19, 2016 at 07:38:18AM +0000, Kuninori Morimoto wrote:
> 
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> 
> In current ALSA SoC, Platform has struct snd_compr_ops feature,
> but it should be supported on Component level. This patch adds it.
> 
> If component level has it, many snd_pcm_ops can be called,
> but, 1st ops function only will be used now. It should/will be
> fixed in the future.
> 
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> ---
>  include/sound/soc.h      |   4 +
>  sound/soc/soc-compress.c | 246 ++++++++++++++++++++++++++++++++---------------
>  sound/soc/soc-core.c     |   2 +
>  3 files changed, 175 insertions(+), 77 deletions(-)
> 
> diff --git a/include/sound/soc.h b/include/sound/soc.h
> index 5db4a90..225e9b6 100644
> --- a/include/sound/soc.h
> +++ b/include/sound/soc.h
> @@ -777,6 +777,8 @@ struct snd_soc_component_driver {
>  	const struct snd_soc_dapm_route *dapm_routes;
>  	unsigned int num_dapm_routes;
>  
> +	const struct snd_compr_ops *compr_ops;
> +
>  	int (*probe)(struct snd_soc_component *);
>  	void (*remove)(struct snd_soc_component *);
>  	int (*suspend)(struct snd_soc_component *);
> @@ -855,6 +857,8 @@ struct snd_soc_component {
>  	unsigned int num_dapm_routes;
>  	struct snd_soc_codec *codec;
>  
> +	const struct snd_compr_ops *compr_ops;
> +
>  	int (*probe)(struct snd_soc_component *);
>  	void (*remove)(struct snd_soc_component *);
>  	int (*suspend)(struct snd_soc_component *);
> diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
> index bfd71b8..0362dd7 100644
> --- a/sound/soc/soc-compress.c
> +++ b/sound/soc/soc-compress.c
> @@ -29,7 +29,7 @@
>  static int soc_compr_open(struct snd_compr_stream *cstream)
>  {
>  	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
> -	struct snd_soc_platform *platform = rtd->platform;
> +	struct snd_soc_component *component;
>  	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>  	int ret = 0;
>  
> @@ -44,14 +44,22 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
>  		}
>  	}
>  
> -	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
> -		ret = platform->driver->compr_ops->open(cstream);
> -		if (ret < 0) {
> -			pr_err("compress asoc: can't open platform %s\n",
> -				platform->component.name);
> -			goto plat_err;
> +	ret = 0;
> +	for_each_component(component, rtd->card) {
> +		const struct snd_compr_ops *compr_ops = component->compr_ops;
> +
> +		if (compr_ops && compr_ops->open) {
> +			int _ret = compr_ops->open(cstream);
> +
> +			if (_ret < 0) {
> +				pr_err("compress asoc: can't open component %s\n",
> +				       component->name);
> +				ret |= _ret;
> +			}

Apologies if I am missing something but this really doesn't look
like equivalent code? The old code calls the ops for the platform
associated with the stream, the new code looks like it will call
the ops for every single component in the system that has
compressed ops, which would definitely cause issue. Am I missing
something here?

Thanks,
Charles
Kuninori Morimoto Dec. 20, 2016, 1:59 a.m. UTC | #2
Hi Charles

Thank you for your review

> > -	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
> > -		ret = platform->driver->compr_ops->open(cstream);
> > -		if (ret < 0) {
> > -			pr_err("compress asoc: can't open platform %s\n",
> > -				platform->component.name);
> > -			goto plat_err;
> > +	ret = 0;
> > +	for_each_component(component, rtd->card) {
> > +		const struct snd_compr_ops *compr_ops = component->compr_ops;
> > +
> > +		if (compr_ops && compr_ops->open) {
> > +			int _ret = compr_ops->open(cstream);
> > +
> > +			if (_ret < 0) {
> > +				pr_err("compress asoc: can't open component %s\n",
> > +				       component->name);
> > +				ret |= _ret;
> > +			}
> 
> Apologies if I am missing something but this really doesn't look
> like equivalent code? The old code calls the ops for the platform
> associated with the stream, the new code looks like it will call
> the ops for every single component in the system that has
> compressed ops, which would definitely cause issue. Am I missing
> something here?

Basically in *current* existing code, platform only has compr_ops.
So, converting existing code to new code should be OK.

Current ALSA SoC clearly separating CPU/Codec/Platform, but in these days,
new sound device has many features. Thus, it becaming difficult to
say "it is XXX" today. For example, some Codec has CPU feature,
some CPU has Platform feature etc.
So, our (= Me/Lars) plan is that remove current CPU/Codec/Platform separation,
and all will be Component connection.

Above code will call every component's compr_ops,
currently, it should be platform now.
But in the future device, Codec and/or CPU can have compr_ops.

If you want, currently, it can call 1st found compr_ops (= should be platform)
only with FIXME comment at this point.

Does this clear answer for you ?

	for_each_component(component, rtd->card) {
		const struct snd_compr_ops *compr_ops = component->compr_ops;

		/* FIXME: 1st compr_ops only at this point */
		if (compr_ops && compr_ops->open) {
			ret = compr_ops->open(cstream);
			if (ret < 0) {
				pr_err("compress asoc: can't open component %s\n",
				       component->name);
			}
			break;
		}
	}
Charles Keepax Dec. 20, 2016, 10:02 a.m. UTC | #3
On Tue, Dec 20, 2016 at 01:59:43AM +0000, Kuninori Morimoto wrote:
> > > +	for_each_component(component, rtd->card) {
> > > +		const struct snd_compr_ops *compr_ops = component->compr_ops;
> > > +
> > > +		if (compr_ops && compr_ops->open) {
> > > +			int _ret = compr_ops->open(cstream);
> > > +
> > > +			if (_ret < 0) {
> > > +				pr_err("compress asoc: can't open component %s\n",
> > > +				       component->name);
> > > +				ret |= _ret;
> > > +			}
> > 
> > Apologies if I am missing something but this really doesn't look
> > like equivalent code? The old code calls the ops for the platform
> > associated with the stream, the new code looks like it will call
> > the ops for every single component in the system that has
> > compressed ops, which would definitely cause issue. Am I missing
> > something here?
> 
> Basically in *current* existing code, platform only has compr_ops.
> So, converting existing code to new code should be OK.
> 
> Current ALSA SoC clearly separating CPU/Codec/Platform, but in these days,
> new sound device has many features. Thus, it becaming difficult to
> say "it is XXX" today. For example, some Codec has CPU feature,
> some CPU has Platform feature etc.
> So, our (= Me/Lars) plan is that remove current CPU/Codec/Platform separation,
> and all will be Component connection.
> 
> Above code will call every component's compr_ops,
> currently, it should be platform now.
> But in the future device, Codec and/or CPU can have compr_ops.
> 
> If you want, currently, it can call 1st found compr_ops (= should be platform)
> only with FIXME comment at this point.
> 
> Does this clear answer for you ?
> 
> 	for_each_component(component, rtd->card) {
> 		const struct snd_compr_ops *compr_ops = component->compr_ops;
> 
> 		/* FIXME: 1st compr_ops only at this point */
> 		if (compr_ops && compr_ops->open) {

But how do you know this is the correct compressed open here? The
system could have multiple platforms providing compressed ops and
you have just picked the first one in the card list. I think you
are making the assumption that there is only one platform
providing compressed ops and that seems like a very dangerous
assumption to me. Our CODECs provide some compressed features as
do many applications processors, which would easily give you at
two platforms. But I could even imagine APs registering multiple
compressed platforms for different DSPs or some such.

Thanks,
Charles

> 			ret = compr_ops->open(cstream);
> 			if (ret < 0) {
> 				pr_err("compress asoc: can't open component %s\n",
> 				       component->name);
> 			}
> 			break;
> 		}
> 	}
Kuninori Morimoto Dec. 21, 2016, 12:42 a.m. UTC | #4
Hi Charles

Thank you for your feedback

> > 	for_each_component(component, rtd->card) {
> > 		const struct snd_compr_ops *compr_ops = component->compr_ops;
> > 
> > 		/* FIXME: 1st compr_ops only at this point */
> > 		if (compr_ops && compr_ops->open) {
> 
> But how do you know this is the correct compressed open here? The
> system could have multiple platforms providing compressed ops and
> you have just picked the first one in the card list. I think you
> are making the assumption that there is only one platform
> providing compressed ops and that seems like a very dangerous
> assumption to me. Our CODECs provide some compressed features as
> do many applications processors, which would easily give you at
> two platforms. But I could even imagine APs registering multiple
> compressed platforms for different DSPs or some such.

I agree your opinion, and yes it can be issue in the future.
But, this is the reason why it has /* FIXME */ comment here
(will has in v2, not yet in v1).
I don't know which one should be solved first, but this
patch is focusing to part of platform -> component conversion now.
No existing code/card get damage at this point, I think ?

So, how about this in v2 ?
In comment and git log indicates
"It is still assumeing that system has 1 compressed,
same as current situation. Multi-compress is TBD."

Best regards
---
Kuninori Morimoto
Charles Keepax Dec. 21, 2016, 9:29 a.m. UTC | #5
On Wed, Dec 21, 2016 at 12:42:21AM +0000, Kuninori Morimoto wrote:
> 
> Hi Charles
> 
> Thank you for your feedback
> 
> > > 	for_each_component(component, rtd->card) {
> > > 		const struct snd_compr_ops *compr_ops = component->compr_ops;
> > > 
> > > 		/* FIXME: 1st compr_ops only at this point */
> > > 		if (compr_ops && compr_ops->open) {
> > 
> > But how do you know this is the correct compressed open here? The
> > system could have multiple platforms providing compressed ops and
> > you have just picked the first one in the card list. I think you
> > are making the assumption that there is only one platform
> > providing compressed ops and that seems like a very dangerous
> > assumption to me. Our CODECs provide some compressed features as
> > do many applications processors, which would easily give you at
> > two platforms. But I could even imagine APs registering multiple
> > compressed platforms for different DSPs or some such.
> 
> I agree your opinion, and yes it can be issue in the future.
> But, this is the reason why it has /* FIXME */ comment here
> (will has in v2, not yet in v1).
> I don't know which one should be solved first, but this
> patch is focusing to part of platform -> component conversion now.
> No existing code/card get damage at this point, I think ?
> 
> So, how about this in v2 ?
> In comment and git log indicates
> "It is still assumeing that system has 1 compressed,
> same as current situation. Multi-compress is TBD."

Admittedly there are no machines currently in mainline that do
this but it will basically break on every single one of our
customer integrations, as most AP systems are supporting some
sort of compressed stream stuff now and our CODEC does as well.

I would really rather see this issue fixed before these patches
are merged, as if it gets merged I basically have to fix it
straight away anyway, or face some very painful integrations in
the future. I will try to find some time to look at this and see
if I can come up with a better solution for these parts of the
code but given the current time frame it is likely to push into
the new year.

Thanks,
Charles
Kuninori Morimoto Dec. 21, 2016, 11:45 p.m. UTC | #6
Hi Charles

Thank you for your feedback

> Admittedly there are no machines currently in mainline that do
> this but it will basically break on every single one of our
> customer integrations, as most AP systems are supporting some
> sort of compressed stream stuff now and our CODEC does as well.
> 
> I would really rather see this issue fixed before these patches
> are merged, as if it gets merged I basically have to fix it
> straight away anyway, or face some very painful integrations in
> the future. I will try to find some time to look at this and see
> if I can come up with a better solution for these parts of the
> code but given the current time frame it is likely to push into
> the new year.

OK, Thanks.
Let's drop it at this point.

Best regards
---
Kuninori Morimoto

Patch
diff mbox

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 5db4a90..225e9b6 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -777,6 +777,8 @@  struct snd_soc_component_driver {
 	const struct snd_soc_dapm_route *dapm_routes;
 	unsigned int num_dapm_routes;
 
+	const struct snd_compr_ops *compr_ops;
+
 	int (*probe)(struct snd_soc_component *);
 	void (*remove)(struct snd_soc_component *);
 	int (*suspend)(struct snd_soc_component *);
@@ -855,6 +857,8 @@  struct snd_soc_component {
 	unsigned int num_dapm_routes;
 	struct snd_soc_codec *codec;
 
+	const struct snd_compr_ops *compr_ops;
+
 	int (*probe)(struct snd_soc_component *);
 	void (*remove)(struct snd_soc_component *);
 	int (*suspend)(struct snd_soc_component *);
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index bfd71b8..0362dd7 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -29,7 +29,7 @@ 
 static int soc_compr_open(struct snd_compr_stream *cstream)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret = 0;
 
@@ -44,14 +44,22 @@  static int soc_compr_open(struct snd_compr_stream *cstream)
 		}
 	}
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
-		ret = platform->driver->compr_ops->open(cstream);
-		if (ret < 0) {
-			pr_err("compress asoc: can't open platform %s\n",
-				platform->component.name);
-			goto plat_err;
+	ret = 0;
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->open) {
+			int _ret = compr_ops->open(cstream);
+
+			if (_ret < 0) {
+				pr_err("compress asoc: can't open component %s\n",
+				       component->name);
+				ret |= _ret;
+			}
 		}
 	}
+	if (ret < 0)
+		goto machine_err;
 
 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
 		ret = rtd->dai_link->compr_ops->startup(cstream);
@@ -68,9 +76,13 @@  static int soc_compr_open(struct snd_compr_stream *cstream)
 	return 0;
 
 machine_err:
-	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
-		platform->driver->compr_ops->free(cstream);
-plat_err:
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->free)
+			compr_ops->free(cstream);
+	}
+
 	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 out:
@@ -82,7 +94,7 @@  static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 {
 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 	struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
-	struct snd_soc_platform *platform = fe->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 	struct snd_soc_dpcm *dpcm;
 	struct snd_soc_dapm_widget_list *list;
@@ -105,15 +117,22 @@  static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 		}
 	}
 
+	ret = 0;
+	for_each_component(component, fe->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
-		ret = platform->driver->compr_ops->open(cstream);
-		if (ret < 0) {
-			pr_err("compress asoc: can't open platform %s\n",
-				platform->component.name);
-			goto plat_err;
+		if (compr_ops && compr_ops->open) {
+			int _ret = compr_ops->open(cstream);
+
+			if (_ret < 0) {
+				pr_err("compress asoc: can't open component %s\n",
+				       component->name);
+				ret |= _ret;
+			}
 		}
 	}
+	if (ret < 0)
+		goto machine_err;
 
 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
 		ret = fe->dai_link->compr_ops->startup(cstream);
@@ -166,9 +185,13 @@  static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
 		fe->dai_link->compr_ops->shutdown(cstream);
 machine_err:
-	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
-		platform->driver->compr_ops->free(cstream);
-plat_err:
+	for_each_component(component, fe->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->free)
+			compr_ops->free(cstream);
+	}
+
 	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 out:
@@ -208,7 +231,7 @@  static void close_delayed_work(struct work_struct *work)
 static int soc_compr_free(struct snd_compr_stream *cstream)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	int stream;
@@ -234,8 +257,12 @@  static int soc_compr_free(struct snd_compr_stream *cstream)
 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
 		rtd->dai_link->compr_ops->shutdown(cstream);
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
-		platform->driver->compr_ops->free(cstream);
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->free)
+			compr_ops->free(cstream);
+	}
 
 	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
@@ -265,7 +292,7 @@  static int soc_compr_free(struct snd_compr_stream *cstream)
 static int soc_compr_free_fe(struct snd_compr_stream *cstream)
 {
 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
-	struct snd_soc_platform *platform = fe->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 	struct snd_soc_dpcm *dpcm;
 	int stream, ret;
@@ -303,8 +330,12 @@  static int soc_compr_free_fe(struct snd_compr_stream *cstream)
 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
 		fe->dai_link->compr_ops->shutdown(cstream);
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
-		platform->driver->compr_ops->free(cstream);
+	for_each_component(component, fe->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->free)
+			compr_ops->free(cstream);
+	}
 
 	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
@@ -317,17 +348,21 @@  static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 {
 
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret = 0;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
-		ret = platform->driver->compr_ops->trigger(cstream, cmd);
-		if (ret < 0)
-			goto out;
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->trigger) {
+			ret = compr_ops->trigger(cstream, cmd);
+			if (ret < 0)
+				goto out;
+		}
 	}
 
 	if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
@@ -351,17 +386,20 @@  static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
 {
 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
-	struct snd_soc_platform *platform = fe->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 	int ret = 0, stream;
 
 	if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
 		cmd == SND_COMPR_TRIGGER_DRAIN) {
 
-		if (platform->driver->compr_ops &&
-		    platform->driver->compr_ops->trigger)
-			return platform->driver->compr_ops->trigger(cstream,
-								    cmd);
+		for_each_component(component, fe->card) {
+			const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+			/* FIXME: It uses 1st function only now */
+			if (compr_ops && compr_ops->trigger)
+				return compr_ops->trigger(cstream, cmd);
+		}
 	}
 
 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
@@ -378,10 +416,14 @@  static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
 			goto out;
 	}
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
-		ret = platform->driver->compr_ops->trigger(cstream, cmd);
-		if (ret < 0)
-			goto out;
+	for_each_component(component, fe->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->trigger) {
+			ret = compr_ops->trigger(cstream, cmd);
+			if (ret < 0)
+				goto out;
+		}
 	}
 
 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
@@ -413,7 +455,7 @@  static int soc_compr_set_params(struct snd_compr_stream *cstream,
 					struct snd_compr_params *params)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret = 0;
 
@@ -431,10 +473,14 @@  static int soc_compr_set_params(struct snd_compr_stream *cstream,
 			goto err;
 	}
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
-		ret = platform->driver->compr_ops->set_params(cstream, params);
-		if (ret < 0)
-			goto err;
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->set_params) {
+			ret = compr_ops->set_params(cstream, params);
+			if (ret < 0)
+				goto err;
+		}
 	}
 
 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
@@ -468,7 +514,7 @@  static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
 {
 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 	struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
-	struct snd_soc_platform *platform = fe->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 	int ret = 0, stream;
 
@@ -485,10 +531,14 @@  static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
 			goto out;
 	}
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
-		ret = platform->driver->compr_ops->set_params(cstream, params);
-		if (ret < 0)
-			goto out;
+	for_each_component(component, fe->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->set_params) {
+			ret = compr_ops->set_params(cstream, params);
+			if (ret < 0)
+				goto out;
+		}
 	}
 
 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
@@ -528,7 +578,7 @@  static int soc_compr_get_params(struct snd_compr_stream *cstream,
 					struct snd_codec *params)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret = 0;
 
@@ -540,8 +590,13 @@  static int soc_compr_get_params(struct snd_compr_stream *cstream,
 			goto err;
 	}
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->get_params)
-		ret = platform->driver->compr_ops->get_params(cstream, params);
+	ret = 0;
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->get_params)
+			ret |= compr_ops->get_params(cstream, params);
+	}
 
 err:
 	mutex_unlock(&rtd->pcm_mutex);
@@ -552,13 +607,17 @@  static int soc_compr_get_caps(struct snd_compr_stream *cstream,
 				struct snd_compr_caps *caps)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	int ret = 0;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps)
-		ret = platform->driver->compr_ops->get_caps(cstream, caps);
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->get_caps)
+			ret |= compr_ops->get_caps(cstream, caps);
+	}
 
 	mutex_unlock(&rtd->pcm_mutex);
 	return ret;
@@ -568,13 +627,17 @@  static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
 				struct snd_compr_codec_caps *codec)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	int ret = 0;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps)
-		ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->get_codec_caps)
+			ret |= compr_ops->get_codec_caps(cstream, codec);
+	}
 
 	mutex_unlock(&rtd->pcm_mutex);
 	return ret;
@@ -583,7 +646,7 @@  static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret = 0;
 
@@ -595,9 +658,13 @@  static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
 			goto err;
 	}
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->ack)
-		ret = platform->driver->compr_ops->ack(cstream, bytes);
+	ret = 0;
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
 
+		if (compr_ops && compr_ops->ack)
+			ret |= compr_ops->ack(cstream, bytes);
+	}
 err:
 	mutex_unlock(&rtd->pcm_mutex);
 	return ret;
@@ -607,7 +674,7 @@  static int soc_compr_pointer(struct snd_compr_stream *cstream,
 			struct snd_compr_tstamp *tstamp)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	int ret = 0;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
@@ -616,8 +683,13 @@  static int soc_compr_pointer(struct snd_compr_stream *cstream,
 	if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
 		cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->pointer)
-		ret = platform->driver->compr_ops->pointer(cstream, tstamp);
+	ret = 0;
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->pointer)
+			ret |= compr_ops->pointer(cstream, tstamp);
+	}
 
 	mutex_unlock(&rtd->pcm_mutex);
 	return ret;
@@ -627,13 +699,17 @@  static int soc_compr_copy(struct snd_compr_stream *cstream,
 			  char __user *buf, size_t count)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	int ret = 0;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
-		ret = platform->driver->compr_ops->copy(cstream, buf, count);
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->copy)
+			ret |= compr_ops->copy(cstream, buf, count);
+	}
 
 	mutex_unlock(&rtd->pcm_mutex);
 	return ret;
@@ -643,7 +719,7 @@  static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
 				struct snd_compr_metadata *metadata)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret = 0;
 
@@ -653,8 +729,13 @@  static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
 			return ret;
 	}
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata)
-		ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
+	ret = 0;
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->set_metadata)
+			ret |= compr_ops->set_metadata(cstream, metadata);
+	}
 
 	return ret;
 }
@@ -663,7 +744,7 @@  static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
 				struct snd_compr_metadata *metadata)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
-	struct snd_soc_platform *platform = rtd->platform;
+	struct snd_soc_component *component;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	int ret = 0;
 
@@ -673,8 +754,13 @@  static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
 			return ret;
 	}
 
-	if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata)
-		ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
+	ret = 0;
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->get_metadata)
+			ret |= compr_ops->get_metadata(cstream, metadata);
+	}
 
 	return ret;
 }
@@ -720,11 +806,11 @@  static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
 {
 	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_compr *compr;
 	struct snd_pcm *be_pcm;
+	struct snd_soc_component *component;
 	char new_name[64];
 	int ret = 0, direction = 0;
 	int playback = 0, capture = 0;
@@ -799,8 +885,14 @@  int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
 		memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
 
 	/* Add copy callback for not memory mapped DSPs */
-	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
-		compr->ops->copy = soc_compr_copy;
+	for_each_component(component, rtd->card) {
+		const struct snd_compr_ops *compr_ops = component->compr_ops;
+
+		if (compr_ops && compr_ops->copy) {
+			compr->ops->copy = soc_compr_copy;
+			break;
+		}
+	}
 
 	mutex_init(&compr->lock);
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 9f2b9e1..ecadebe 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3200,6 +3200,8 @@  int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
 		platform->component.pcm_new = snd_soc_platform_drv_pcm_new;
 	if (platform_drv->pcm_free)
 		platform->component.pcm_free = snd_soc_platform_drv_pcm_free;
+	if (platform_drv->compr_ops)
+		platform->component.compr_ops = platform_drv->compr_ops;
 
 #ifdef CONFIG_DEBUG_FS
 	platform->component.debugfs_prefix = "platform";