ASoC: dapm: Use DAPM mutex for DAPM ops instead of codec mutex
[linux-2.6.git] / sound / soc / soc-core.c
index d08abf4..db2e0f0 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/bitops.h>
 #include <linux/debugfs.h>
 #include <linux/platform_device.h>
+#include <linux/ctype.h>
 #include <linux/slab.h>
 #include <sound/ac97_codec.h>
 #include <sound/core.h>
@@ -577,6 +578,7 @@ int snd_soc_suspend(struct device *dev)
                        case SND_SOC_BIAS_OFF:
                                codec->driver->suspend(codec, PMSG_SUSPEND);
                                codec->suspended = 1;
+                               codec->cache_sync = 1;
                                break;
                        default:
                                dev_dbg(codec->dev, "CODEC is on over suspend\n");
@@ -993,10 +995,15 @@ static int soc_probe_platform(struct snd_soc_card *card,
        const struct snd_soc_platform_driver *driver = platform->driver;
 
        platform->card = card;
+       platform->dapm.card = card;
 
        if (!try_module_get(platform->dev->driver->owner))
                return -ENODEV;
 
+       if (driver->dapm_widgets)
+               snd_soc_dapm_new_controls(&platform->dapm,
+                       driver->dapm_widgets, driver->num_dapm_widgets);
+
        if (driver->probe) {
                ret = driver->probe(platform);
                if (ret < 0) {
@@ -1007,9 +1014,17 @@ static int soc_probe_platform(struct snd_soc_card *card,
                }
        }
 
+       if (driver->controls)
+               snd_soc_add_platform_controls(platform, driver->controls,
+                                    driver->num_controls);
+       if (driver->dapm_routes)
+               snd_soc_dapm_add_routes(&platform->dapm, driver->dapm_routes,
+                                       driver->num_dapm_routes);
+
        /* mark platform as probed and add to card platform list */
        platform->probed = 1;
        list_add(&platform->card_list, &card->platform_dev_list);
+       list_add(&platform->dapm.list, &card->dapm_list);
 
        return 0;
 
@@ -1127,7 +1142,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
                        }
                }
                cpu_dai->probed = 1;
-               /* mark cpu_dai as probed and add to card cpu_dai list */
+               /* mark cpu_dai as probed and add to card dai list */
                list_add(&cpu_dai->card_list, &card->dai_dev_list);
        }
 
@@ -1158,7 +1173,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
                        }
                }
 
-               /* mark cpu_dai as probed and add to card cpu_dai list */
+               /* mark codec_dai as probed and add to card dai list */
                codec_dai->probed = 1;
                list_add(&codec_dai->card_list, &card->dai_dev_list);
        }
@@ -1422,6 +1437,18 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
                 "%s", card->long_name ? card->long_name : card->name);
        snprintf(card->snd_card->driver, sizeof(card->snd_card->driver),
                 "%s", card->driver_name ? card->driver_name : card->name);
+       for (i = 0; i < ARRAY_SIZE(card->snd_card->driver); i++) {
+               switch (card->snd_card->driver[i]) {
+               case '_':
+               case '-':
+               case '\0':
+                       break;
+               default:
+                       if (!isalnum(card->snd_card->driver[i]))
+                               card->snd_card->driver[i] = '_';
+                       break;
+               }
+       }
 
        if (card->late_probe) {
                ret = card->late_probe(card);
@@ -1618,7 +1645,7 @@ int snd_soc_codec_readable_register(struct snd_soc_codec *codec,
        if (codec->readable_register)
                return codec->readable_register(codec, reg);
        else
-               return 0;
+               return 1;
 }
 EXPORT_SYMBOL_GPL(snd_soc_codec_readable_register);
 
@@ -1636,7 +1663,7 @@ int snd_soc_codec_writable_register(struct snd_soc_codec *codec,
        if (codec->writable_register)
                return codec->writable_register(codec, reg);
        else
-               return 0;
+               return 1;
 }
 EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register);
 
@@ -1652,6 +1679,7 @@ int snd_soc_platform_read(struct snd_soc_platform *platform,
 
        ret = platform->driver->read(platform, reg);
        dev_dbg(platform->dev, "read %x => %x\n", reg, ret);
+       trace_snd_soc_preg_read(platform, reg, ret);
 
        return ret;
 }
@@ -1666,6 +1694,7 @@ int snd_soc_platform_write(struct snd_soc_platform *platform,
        }
 
        dev_dbg(platform->dev, "write %x = %x\n", reg, val);
+       trace_snd_soc_preg_write(platform, reg, val);
        return platform->driver->write(platform, reg, val);
 }
 EXPORT_SYMBOL_GPL(snd_soc_platform_write);
@@ -1896,7 +1925,7 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 
        if (prefix) {
                name_len = strlen(long_name) + strlen(prefix) + 2;
-               name = kmalloc(name_len, GFP_ATOMIC);
+               name = kmalloc(name_len, GFP_KERNEL);
                if (!name)
                        return NULL;
 
@@ -1949,6 +1978,36 @@ int snd_soc_add_controls(struct snd_soc_codec *codec,
 EXPORT_SYMBOL_GPL(snd_soc_add_controls);
 
 /**
+ * snd_soc_add_platform_controls - add an array of controls to a platform.
+ * Convienience function to add a list of controls.
+ *
+ * @platform: platform to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
+       const struct snd_kcontrol_new *controls, int num_controls)
+{
+       struct snd_card *card = platform->card->snd_card;
+       int err, i;
+
+       for (i = 0; i < num_controls; i++) {
+               const struct snd_kcontrol_new *control = &controls[i];
+               err = snd_ctl_add(card, snd_soc_cnew(control, platform,
+                               control->name, NULL));
+               if (err < 0) {
+                       dev_err(platform->dev, "Failed to add %s %d\n",control->name, err);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
+
+/**
  * snd_soc_info_enum_double - enumerated double mixer info callback
  * @kcontrol: mixer control
  * @uinfo: control element information
@@ -2838,6 +2897,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
        INIT_LIST_HEAD(&card->list);
        card->instantiated = 0;
        mutex_init(&card->mutex);
+       mutex_init(&card->dapm_mutex);
 
        mutex_lock(&client_mutex);
        list_add(&card->list, &card_list);
@@ -3092,6 +3152,8 @@ int snd_soc_register_platform(struct device *dev,
 
        platform->dev = dev;
        platform->driver = platform_drv;
+       platform->dapm.dev = dev;
+       platform->dapm.platform = platform;
 
        mutex_lock(&client_mutex);
        list_add(&platform->list, &platform_list);