ASoC: soc-compress: Add support for not memory mapped DSPs
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Tue, 5 Feb 2013 10:41:47 +0000 (10:41 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Tue, 5 Feb 2013 13:55:52 +0000 (13:55 +0000)
The ASoC compressed API did not implement the copy callback in its
compressed ops which is required for DSPs that are not memory mapped.

This patch creates a local copy of the compress ops for each runtime and
modifies them with a copy callback as appropriate.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Acked-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/soc-compress.c

index 3ea79564a99360006ad702104424ae731644a6d2..c81aeecec93677757642df341a65ba05bb70a135 100644 (file)
@@ -302,6 +302,22 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream,
        return 0;
 }
 
+static int soc_compr_copy(struct snd_compr_stream *cstream,
+                         const char __user *buf, size_t count)
+{
+       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+       struct snd_soc_platform *platform = rtd->platform;
+       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);
+
+       mutex_unlock(&rtd->pcm_mutex);
+       return ret;
+}
+
 /* ASoC Compress operations */
 static struct snd_compr_ops soc_compr_ops = {
        .open           = soc_compr_open,
@@ -319,6 +335,7 @@ static struct snd_compr_ops soc_compr_ops = {
 int 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;
@@ -335,14 +352,25 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
                return -ENOMEM;
        }
 
-       compr->ops = &soc_compr_ops;
+       compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
+                                 GFP_KERNEL);
+       if (compr->ops == NULL) {
+               dev_err(rtd->card->dev, "Cannot allocate compressed ops\n");
+               ret = -ENOMEM;
+               goto compr_err;
+       }
+       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;
+
        mutex_init(&compr->lock);
        ret = snd_compress_new(rtd->card->snd_card, num, direction, compr);
        if (ret < 0) {
                pr_err("compress asoc: can't create compress for codec %s\n",
                        codec->name);
-               kfree(compr);
-               return ret;
+               goto compr_err;
        }
 
        /* DAPM dai link stream work */
@@ -354,4 +382,8 @@ int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
        printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
                cpu_dai->name);
        return ret;
+
+compr_err:
+       kfree(compr);
+       return ret;
 }