Merge tag 'selinux-pr-20201214' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / sound / soc / soc-component.c
index 728e93f..7605233 100644 (file)
@@ -421,6 +421,260 @@ EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
 
 #endif
 
+int snd_soc_component_compr_open(struct snd_compr_stream *cstream)
+{
+       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+       struct snd_soc_component *component;
+       int i, ret;
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->open) {
+                       ret = component->driver->compress_ops->open(component, cstream);
+                       if (ret < 0)
+                               return soc_component_ret(component, ret);
+               }
+               soc_component_mark_push(component, cstream, compr_open);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_open);
+
+void snd_soc_component_compr_free(struct snd_compr_stream *cstream,
+                                 int rollback)
+{
+       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+       struct snd_soc_component *component;
+       int i;
+
+       for_each_rtd_components(rtd, i, component) {
+               if (rollback && !soc_component_mark_match(component, cstream, compr_open))
+                       continue;
+
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->free)
+                       component->driver->compress_ops->free(component, cstream);
+
+               soc_component_mark_pop(component, cstream, compr_open);
+       }
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_free);
+
+int snd_soc_component_compr_trigger(struct snd_compr_stream *cstream, int cmd)
+{
+       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+       struct snd_soc_component *component;
+       int i, ret;
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->trigger) {
+                       ret = component->driver->compress_ops->trigger(
+                               component, cstream, cmd);
+                       if (ret < 0)
+                               return soc_component_ret(component, ret);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_trigger);
+
+int snd_soc_component_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_component *component;
+       int i, ret;
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->set_params) {
+                       ret = component->driver->compress_ops->set_params(
+                               component, cstream, params);
+                       if (ret < 0)
+                               return soc_component_ret(component, ret);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_params);
+
+int snd_soc_component_compr_get_params(struct snd_compr_stream *cstream,
+                                      struct snd_codec *params)
+{
+       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+       struct snd_soc_component *component;
+       int i, ret;
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->get_params) {
+                       ret = component->driver->compress_ops->get_params(
+                               component, cstream, params);
+                       return soc_component_ret(component, ret);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_params);
+
+int snd_soc_component_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_component *component;
+       int i, ret = 0;
+
+       mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->get_caps) {
+                       ret = component->driver->compress_ops->get_caps(
+                               component, cstream, caps);
+                       break;
+               }
+       }
+
+       mutex_unlock(&rtd->card->pcm_mutex);
+
+       return soc_component_ret(component, ret);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_caps);
+
+int snd_soc_component_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_component *component;
+       int i, ret = 0;
+
+       mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->get_codec_caps) {
+                       ret = component->driver->compress_ops->get_codec_caps(
+                               component, cstream, codec);
+                       break;
+               }
+       }
+
+       mutex_unlock(&rtd->card->pcm_mutex);
+
+       return soc_component_ret(component, ret);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_codec_caps);
+
+int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
+{
+       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+       struct snd_soc_component *component;
+       int i, ret;
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->ack) {
+                       ret = component->driver->compress_ops->ack(
+                               component, cstream, bytes);
+                       if (ret < 0)
+                               return soc_component_ret(component, ret);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack);
+
+int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream,
+                                   struct snd_compr_tstamp *tstamp)
+{
+       struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+       struct snd_soc_component *component;
+       int i, ret;
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->pointer) {
+                       ret = component->driver->compress_ops->pointer(
+                               component, cstream, tstamp);
+                       return soc_component_ret(component, ret);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_pointer);
+
+int snd_soc_component_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_component *component;
+       int i, ret = 0;
+
+       mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->copy) {
+                       ret = component->driver->compress_ops->copy(
+                               component, cstream, buf, count);
+                       break;
+               }
+       }
+
+       mutex_unlock(&rtd->card->pcm_mutex);
+
+       return soc_component_ret(component, ret);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_copy);
+
+int snd_soc_component_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_component *component;
+       int i, ret;
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->set_metadata) {
+                       ret = component->driver->compress_ops->set_metadata(
+                               component, cstream, metadata);
+                       if (ret < 0)
+                               return soc_component_ret(component, ret);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_metadata);
+
+int snd_soc_component_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_component *component;
+       int i, ret;
+
+       for_each_rtd_components(rtd, i, component) {
+               if (component->driver->compress_ops &&
+                   component->driver->compress_ops->get_metadata) {
+                       ret = component->driver->compress_ops->get_metadata(
+                               component, cstream, metadata);
+                       return soc_component_ret(component, ret);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_metadata);
+
 static unsigned int soc_component_read_no_lock(
        struct snd_soc_component *component,
        unsigned int reg)
@@ -779,8 +1033,7 @@ int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream)
 }
 
 int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
-                                   struct snd_pcm_hw_params *params,
-                                   struct snd_soc_component **last)
+                                   struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
        struct snd_soc_component *component;
@@ -790,52 +1043,83 @@ int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
                if (component->driver->hw_params) {
                        ret = component->driver->hw_params(component,
                                                           substream, params);
-                       if (ret < 0) {
-                               *last = component;
+                       if (ret < 0)
                                return soc_component_ret(component, ret);
-                       }
                }
+               /* mark substream if succeeded */
+               soc_component_mark_push(component, substream, hw_params);
        }
 
-       *last = NULL;
        return 0;
 }
 
 void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
-                                  struct snd_soc_component *last)
+                                  int rollback)
 {
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
        struct snd_soc_component *component;
        int i, ret;
 
        for_each_rtd_components(rtd, i, component) {
-               if (component == last)
-                       break;
+               if (rollback && !soc_component_mark_match(component, substream, hw_params))
+                       continue;
 
                if (component->driver->hw_free) {
                        ret = component->driver->hw_free(component, substream);
                        if (ret < 0)
                                soc_component_ret(component, ret);
                }
+
+               /* remove marked substream */
+               soc_component_mark_pop(component, substream, hw_params);
        }
 }
 
+static int soc_component_trigger(struct snd_soc_component *component,
+                                struct snd_pcm_substream *substream,
+                                int cmd)
+{
+       int ret = 0;
+
+       if (component->driver->trigger)
+               ret = component->driver->trigger(component, substream, cmd);
+
+       return soc_component_ret(component, ret);
+}
+
 int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
-                                 int cmd)
+                                 int cmd, int rollback)
 {
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
        struct snd_soc_component *component;
-       int i, ret;
-
-       for_each_rtd_components(rtd, i, component) {
-               if (component->driver->trigger) {
-                       ret = component->driver->trigger(component, substream, cmd);
+       int i, r, ret = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               for_each_rtd_components(rtd, i, component) {
+                       ret = soc_component_trigger(component, substream, cmd);
                        if (ret < 0)
-                               return soc_component_ret(component, ret);
+                               break;
+                       soc_component_mark_push(component, substream, trigger);
+               }
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               for_each_rtd_components(rtd, i, component) {
+                       if (rollback && !soc_component_mark_match(component, substream, trigger))
+                               continue;
+
+                       r = soc_component_trigger(component, substream, cmd);
+                       if (r < 0)
+                               ret = r; /* use last ret */
+                       soc_component_mark_pop(component, substream, trigger);
                }
        }
 
-       return 0;
+       return ret;
 }
 
 int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,