Merge git://git.infradead.org/users/eparis/audit
[deliverable/linux.git] / sound / soc / soc-core.c
index ff4b45a5d796f0f16dcd09b7611ad6dc3bda5bb0..d56bbea6e75e60158405f45b1cf280f4d0fb9ac1 100644 (file)
@@ -58,6 +58,7 @@ static DEFINE_MUTEX(client_mutex);
 static LIST_HEAD(dai_list);
 static LIST_HEAD(platform_list);
 static LIST_HEAD(codec_list);
+static LIST_HEAD(component_list);
 
 /*
  * This is a timeout to do a DAPM powerdown after a stream is closed().
@@ -3740,7 +3741,7 @@ static inline char *fmt_multiple_name(struct device *dev,
  *
  * @dai: DAI to register
  */
-int snd_soc_register_dai(struct device *dev,
+static int snd_soc_register_dai(struct device *dev,
                struct snd_soc_dai_driver *dai_drv)
 {
        struct snd_soc_codec *codec;
@@ -3787,14 +3788,13 @@ int snd_soc_register_dai(struct device *dev,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(snd_soc_register_dai);
 
 /**
  * snd_soc_unregister_dai - Unregister a DAI from the ASoC core
  *
  * @dai: DAI to unregister
  */
-void snd_soc_unregister_dai(struct device *dev)
+static void snd_soc_unregister_dai(struct device *dev)
 {
        struct snd_soc_dai *dai;
 
@@ -3813,7 +3813,6 @@ found:
        kfree(dai->name);
        kfree(dai);
 }
-EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
 
 /**
  * snd_soc_register_dais - Register multiple DAIs with the ASoC core
@@ -3821,7 +3820,7 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
  * @dai: Array of DAIs to register
  * @count: Number of DAIs
  */
-int snd_soc_register_dais(struct device *dev,
+static int snd_soc_register_dais(struct device *dev,
                struct snd_soc_dai_driver *dai_drv, size_t count)
 {
        struct snd_soc_codec *codec;
@@ -3885,7 +3884,6 @@ err:
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(snd_soc_register_dais);
 
 /**
  * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
@@ -3893,31 +3891,23 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais);
  * @dai: Array of DAIs to unregister
  * @count: Number of DAIs
  */
-void snd_soc_unregister_dais(struct device *dev, size_t count)
+static void snd_soc_unregister_dais(struct device *dev, size_t count)
 {
        int i;
 
        for (i = 0; i < count; i++)
                snd_soc_unregister_dai(dev);
 }
-EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
 
 /**
- * snd_soc_register_platform - Register a platform with the ASoC core
- *
- * @platform: platform to register
+ * snd_soc_add_platform - Add a platform to the ASoC core
+ * @dev: The parent device for the platform
+ * @platform: The platform to add
+ * @platform_driver: The driver for the platform
  */
-int snd_soc_register_platform(struct device *dev,
-               struct snd_soc_platform_driver *platform_drv)
+int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
+               const struct snd_soc_platform_driver *platform_drv)
 {
-       struct snd_soc_platform *platform;
-
-       dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev));
-
-       platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
-       if (platform == NULL)
-               return -ENOMEM;
-
        /* create platform component name */
        platform->name = fmt_single_name(dev, &platform->id);
        if (platform->name == NULL) {
@@ -3940,30 +3930,76 @@ int snd_soc_register_platform(struct device *dev,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(snd_soc_register_platform);
+EXPORT_SYMBOL_GPL(snd_soc_add_platform);
 
 /**
- * snd_soc_unregister_platform - Unregister a platform from the ASoC core
+ * snd_soc_register_platform - Register a platform with the ASoC core
  *
- * @platform: platform to unregister
+ * @platform: platform to register
  */
-void snd_soc_unregister_platform(struct device *dev)
+int snd_soc_register_platform(struct device *dev,
+               const struct snd_soc_platform_driver *platform_drv)
 {
        struct snd_soc_platform *platform;
+       int ret;
 
-       list_for_each_entry(platform, &platform_list, list) {
-               if (dev == platform->dev)
-                       goto found;
-       }
-       return;
+       dev_dbg(dev, "ASoC: platform register %s\n", dev_name(dev));
 
-found:
+       platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
+       if (platform == NULL)
+               return -ENOMEM;
+
+       ret = snd_soc_add_platform(dev, platform, platform_drv);
+       if (ret)
+               kfree(platform);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_platform);
+
+/**
+ * snd_soc_remove_platform - Remove a platform from the ASoC core
+ * @platform: the platform to remove
+ */
+void snd_soc_remove_platform(struct snd_soc_platform *platform)
+{
        mutex_lock(&client_mutex);
        list_del(&platform->list);
        mutex_unlock(&client_mutex);
 
-       dev_dbg(dev, "ASoC: Unregistered platform '%s'\n", platform->name);
+       dev_dbg(platform->dev, "ASoC: Unregistered platform '%s'\n",
+               platform->name);
        kfree(platform->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_remove_platform);
+
+struct snd_soc_platform *snd_soc_lookup_platform(struct device *dev)
+{
+       struct snd_soc_platform *platform;
+
+       list_for_each_entry(platform, &platform_list, list) {
+               if (dev == platform->dev)
+                       return platform;
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_lookup_platform);
+
+/**
+ * snd_soc_unregister_platform - Unregister a platform from the ASoC core
+ *
+ * @platform: platform to unregister
+ */
+void snd_soc_unregister_platform(struct device *dev)
+{
+       struct snd_soc_platform *platform;
+
+       platform = snd_soc_lookup_platform(dev);
+       if (!platform)
+               return;
+
+       snd_soc_remove_platform(platform);
        kfree(platform);
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
@@ -4024,8 +4060,8 @@ int snd_soc_register_codec(struct device *dev,
        /* create CODEC component name */
        codec->name = fmt_single_name(dev, &codec->id);
        if (codec->name == NULL) {
-               kfree(codec);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail_codec;
        }
 
        if (codec_drv->compress_type)
@@ -4064,7 +4100,7 @@ int snd_soc_register_codec(struct device *dev,
                                                      reg_size, GFP_KERNEL);
                        if (!codec->reg_def_copy) {
                                ret = -ENOMEM;
-                               goto fail;
+                               goto fail_codec_name;
                        }
                }
        }
@@ -4088,18 +4124,22 @@ int snd_soc_register_codec(struct device *dev,
        mutex_unlock(&client_mutex);
 
        /* register any DAIs */
-       if (num_dai) {
-               ret = snd_soc_register_dais(dev, dai_drv, num_dai);
-               if (ret < 0)
-                       dev_err(codec->dev, "ASoC: Failed to regster"
-                               " DAIs: %d\n", ret);
+       ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+       if (ret < 0) {
+               dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+               goto fail_codec_name;
        }
 
        dev_dbg(codec->dev, "ASoC: Registered codec '%s'\n", codec->name);
        return 0;
 
-fail:
+fail_codec_name:
+       mutex_lock(&client_mutex);
+       list_del(&codec->list);
+       mutex_unlock(&client_mutex);
+
        kfree(codec->name);
+fail_codec:
        kfree(codec);
        return ret;
 }
@@ -4113,7 +4153,6 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec);
 void snd_soc_unregister_codec(struct device *dev)
 {
        struct snd_soc_codec *codec;
-       int i;
 
        list_for_each_entry(codec, &codec_list, list) {
                if (dev == codec->dev)
@@ -4122,9 +4161,7 @@ void snd_soc_unregister_codec(struct device *dev)
        return;
 
 found:
-       if (codec->num_dai)
-               for (i = 0; i < codec->num_dai; i++)
-                       snd_soc_unregister_dai(dev);
+       snd_soc_unregister_dais(dev, codec->num_dai);
 
        mutex_lock(&client_mutex);
        list_del(&codec->list);
@@ -4139,6 +4176,92 @@ found:
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
 
+
+/**
+ * snd_soc_register_component - Register a component with the ASoC core
+ *
+ */
+int snd_soc_register_component(struct device *dev,
+                        const struct snd_soc_component_driver *cmpnt_drv,
+                        struct snd_soc_dai_driver *dai_drv,
+                        int num_dai)
+{
+       struct snd_soc_component *cmpnt;
+       int ret;
+
+       dev_dbg(dev, "component register %s\n", dev_name(dev));
+
+       cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
+       if (!cmpnt) {
+               dev_err(dev, "ASoC: Failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       cmpnt->name = fmt_single_name(dev, &cmpnt->id);
+       if (!cmpnt->name) {
+               dev_err(dev, "ASoC: Failed to simplifying name\n");
+               return -ENOMEM;
+       }
+
+       cmpnt->dev      = dev;
+       cmpnt->driver   = cmpnt_drv;
+       cmpnt->num_dai  = num_dai;
+
+       /*
+        * snd_soc_register_dai()  uses fmt_single_name(), and
+        * snd_soc_register_dais() uses fmt_multiple_name()
+        * for dai->name which is used for name based matching
+        */
+       if (1 == num_dai)
+               ret = snd_soc_register_dai(dev, dai_drv);
+       else
+               ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+       if (ret < 0) {
+               dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+               goto error_component_name;
+       }
+
+       mutex_lock(&client_mutex);
+       list_add(&cmpnt->list, &component_list);
+       mutex_unlock(&client_mutex);
+
+       dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
+
+       return ret;
+
+error_component_name:
+       kfree(cmpnt->name);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_component);
+
+/**
+ * snd_soc_unregister_component - Unregister a component from the ASoC core
+ *
+ */
+void snd_soc_unregister_component(struct device *dev)
+{
+       struct snd_soc_component *cmpnt;
+
+       list_for_each_entry(cmpnt, &component_list, list) {
+               if (dev == cmpnt->dev)
+                       goto found;
+       }
+       return;
+
+found:
+       snd_soc_unregister_dais(dev, cmpnt->num_dai);
+
+       mutex_lock(&client_mutex);
+       list_del(&cmpnt->list);
+       mutex_unlock(&client_mutex);
+
+       dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
+       kfree(cmpnt->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
+
 /* Retrieve a card's name from device tree */
 int snd_soc_of_parse_card_name(struct snd_soc_card *card,
                               const char *propname)
This page took 0.047882 seconds and 5 git commands to generate.