]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - sound/soc/soc-core.c
ASoC: core: cleanup platform debugfs on probe failure.
[mirror_ubuntu-artful-kernel.git] / sound / soc / soc-core.c
index b5ecf6d2321446198551c6d2cc6d7728c81be07a..29dbbd793fc6267796e1f3a68109fa5295bb661d 100644 (file)
@@ -277,8 +277,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
        codec->debugfs_codec_root = debugfs_create_dir(codec->name,
                                                       debugfs_card_root);
        if (!codec->debugfs_codec_root) {
-               printk(KERN_WARNING
-                      "ASoC: Failed to create codec debugfs directory\n");
+               dev_warn(codec->dev, "Failed to create codec debugfs directory\n");
                return;
        }
 
@@ -291,8 +290,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
                                                 codec->debugfs_codec_root,
                                                 codec, &codec_reg_fops);
        if (!codec->debugfs_reg)
-               printk(KERN_WARNING
-                      "ASoC: Failed to create codec register debugfs file\n");
+               dev_warn(codec->dev, "Failed to create codec register debugfs file\n");
 
        snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
 }
@@ -302,6 +300,27 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
        debugfs_remove_recursive(codec->debugfs_codec_root);
 }
 
+static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+       struct dentry *debugfs_card_root = platform->card->debugfs_card_root;
+
+       platform->debugfs_platform_root = debugfs_create_dir(platform->name,
+                                                      debugfs_card_root);
+       if (!platform->debugfs_platform_root) {
+               dev_warn(platform->dev,
+                       "Failed to create platform debugfs directory\n");
+               return;
+       }
+
+       snd_soc_dapm_debugfs_init(&platform->dapm,
+               platform->debugfs_platform_root);
+}
+
+static void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+       debugfs_remove_recursive(platform->debugfs_platform_root);
+}
+
 static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
                                    size_t count, loff_t *ppos)
 {
@@ -435,6 +454,14 @@ static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
 {
 }
 
+static inline void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
+static inline void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
 static inline void soc_init_card_debugfs(struct snd_soc_card *card)
 {
 }
@@ -546,18 +573,20 @@ int snd_soc_suspend(struct device *dev)
        }
 
        for (i = 0; i < card->num_rtd; i++) {
-               struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+               struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
 
                if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (driver->playback.stream_name != NULL)
-                       snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
-                               SND_SOC_DAPM_STREAM_SUSPEND);
+               snd_soc_dapm_stream_event(&card->rtd[i],
+                                         SNDRV_PCM_STREAM_PLAYBACK,
+                                         codec_dai,
+                                         SND_SOC_DAPM_STREAM_SUSPEND);
 
-               if (driver->capture.stream_name != NULL)
-                       snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
-                               SND_SOC_DAPM_STREAM_SUSPEND);
+               snd_soc_dapm_stream_event(&card->rtd[i],
+                                         SNDRV_PCM_STREAM_CAPTURE,
+                                         codec_dai,
+                                         SND_SOC_DAPM_STREAM_SUSPEND);
        }
 
        /* suspend all CODECs */
@@ -567,6 +596,17 @@ int snd_soc_suspend(struct device *dev)
                if (!codec->suspended && codec->driver->suspend) {
                        switch (codec->dapm.bias_level) {
                        case SND_SOC_BIAS_STANDBY:
+                               /*
+                                * If the CODEC is capable of idle
+                                * bias off then being in STANDBY
+                                * means it's doing something,
+                                * otherwise fall through.
+                                */
+                               if (codec->dapm.idle_bias_off) {
+                                       dev_dbg(codec->dev,
+                                               "idle_bias_off CODEC on over suspend\n");
+                                       break;
+                               }
                        case SND_SOC_BIAS_OFF:
                                codec->driver->suspend(codec);
                                codec->suspended = 1;
@@ -649,18 +689,18 @@ static void soc_resume_deferred(struct work_struct *work)
        }
 
        for (i = 0; i < card->num_rtd; i++) {
-               struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+               struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
 
                if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (driver->playback.stream_name != NULL)
-                       snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
-                               SND_SOC_DAPM_STREAM_RESUME);
+               snd_soc_dapm_stream_event(&card->rtd[i],
+                                         SNDRV_PCM_STREAM_PLAYBACK, codec_dai,
+                                         SND_SOC_DAPM_STREAM_RESUME);
 
-               if (driver->capture.stream_name != NULL)
-                       snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
-                               SND_SOC_DAPM_STREAM_RESUME);
+               snd_soc_dapm_stream_event(&card->rtd[i],
+                                         SNDRV_PCM_STREAM_CAPTURE, codec_dai,
+                                         SND_SOC_DAPM_STREAM_RESUME);
        }
 
        /* unmute any active DACs */
@@ -893,7 +933,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
                if (codec_dai->driver->remove) {
                        err = codec_dai->driver->remove(codec_dai);
                        if (err < 0)
-                               printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name);
+                               pr_err("asoc: failed to remove %s: %d\n",
+                                                       codec_dai->name, err);
                }
                codec_dai->probed = 0;
                list_del(&codec_dai->card_list);
@@ -905,12 +946,14 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
                if (platform->driver->remove) {
                        err = platform->driver->remove(platform);
                        if (err < 0)
-                               printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
+                               pr_err("asoc: failed to remove %s: %d\n",
+                                                       platform->name, err);
                }
 
                /* Make sure all DAPM widgets are freed */
                snd_soc_dapm_free(&platform->dapm);
 
+               soc_cleanup_platform_debugfs(platform);
                platform->probed = 0;
                list_del(&platform->card_list);
                module_put(platform->dev->driver->owner);
@@ -927,7 +970,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
                if (cpu_dai->driver->remove) {
                        err = cpu_dai->driver->remove(cpu_dai);
                        if (err < 0)
-                               printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name);
+                               pr_err("asoc: failed to remove %s: %d\n",
+                                                       cpu_dai->name, err);
                }
                cpu_dai->probed = 0;
                list_del(&cpu_dai->card_list);
@@ -969,6 +1013,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
 {
        int ret = 0;
        const struct snd_soc_codec_driver *driver = codec->driver;
+       struct snd_soc_dai *dai;
 
        codec->card = card;
        codec->dapm.card = card;
@@ -983,6 +1028,14 @@ static int soc_probe_codec(struct snd_soc_card *card,
                snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
                                          driver->num_dapm_widgets);
 
+       /* Create DAPM widgets for each DAI stream */
+       list_for_each_entry(dai, &dai_list, list) {
+               if (dai->dev != codec->dev)
+                       continue;
+
+               snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
+       }
+
        codec->dapm.idle_bias_off = driver->idle_bias_off;
 
        if (driver->probe) {
@@ -996,7 +1049,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
        }
 
        if (driver->controls)
-               snd_soc_add_controls(codec, driver->controls,
+               snd_soc_add_codec_controls(codec, driver->controls,
                                     driver->num_controls);
        if (driver->dapm_routes)
                snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes,
@@ -1028,6 +1081,8 @@ static int soc_probe_platform(struct snd_soc_card *card,
        if (!try_module_get(platform->dev->driver->owner))
                return -ENODEV;
 
+       soc_init_platform_debugfs(platform);
+
        if (driver->dapm_widgets)
                snd_soc_dapm_new_controls(&platform->dapm,
                        driver->dapm_widgets, driver->num_dapm_widgets);
@@ -1057,6 +1112,7 @@ static int soc_probe_platform(struct snd_soc_card *card,
        return 0;
 
 err_probe:
+       soc_cleanup_platform_debugfs(platform);
        module_put(platform->dev->driver->owner);
 
        return ret;
@@ -1172,8 +1228,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
                if (cpu_dai->driver->probe) {
                        ret = cpu_dai->driver->probe(cpu_dai);
                        if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n",
-                                               cpu_dai->name);
+                               pr_err("asoc: failed to probe CPU DAI %s: %d\n",
+                                                       cpu_dai->name, ret);
                                module_put(cpu_dai->dev->driver->owner);
                                return ret;
                        }
@@ -1204,8 +1260,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
                if (codec_dai->driver->probe) {
                        ret = codec_dai->driver->probe(codec_dai);
                        if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
-                                               codec_dai->name);
+                               pr_err("asoc: failed to probe CODEC DAI %s: %d\n",
+                                                       codec_dai->name, ret);
                                return ret;
                        }
                }
@@ -1225,12 +1281,13 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
 
        ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
        if (ret < 0)
-               printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
+               pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
 
        /* create the pcm */
        ret = soc_new_pcm(rtd, num);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name);
+               pr_err("asoc: can't create pcm %s :%d\n",
+                               dai_link->stream_name, ret);
                return ret;
        }
 
@@ -1263,7 +1320,7 @@ static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
 
                ret = soc_ac97_dev_register(rtd->codec);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: AC97 device register failed\n");
+                       pr_err("asoc: AC97 device register failed:%d\n", ret);
                        return ret;
                }
 
@@ -1403,8 +1460,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
        ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
                        card->owner, 0, &card->snd_card);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: can't create sound card for card %s\n",
-                       card->name);
+               pr_err("asoc: can't create sound card for card %s: %d\n",
+                       card->name, ret);
                mutex_unlock(&card->mutex);
                return;
        }
@@ -1457,13 +1514,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
                }
        }
 
-       /* We should have a non-codec control add function but we don't */
+       snd_soc_dapm_link_dai_widgets(card);
+
        if (card->controls)
-               snd_soc_add_controls(list_first_entry(&card->codec_dev_list,
-                                                     struct snd_soc_codec,
-                                                     card_list),
-                                    card->controls,
-                                    card->num_controls);
+               snd_soc_add_card_controls(card, card->controls, card->num_controls);
 
        if (card->dapm_routes)
                snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
@@ -1527,7 +1581,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 
        ret = snd_card_register(card->snd_card);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
+               pr_err("asoc: failed to register soundcard for %s: %d\n",
+                                                       card->name, ret);
                goto probe_aux_dev_err;
        }
 
@@ -1536,7 +1591,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
        for (i = 0; i < card->num_rtd; i++) {
                ret = soc_register_ac97_dai_link(&card->rtd[i]);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+                       pr_err("asoc: failed to register AC97 %s: %d\n",
+                                                       card->name, ret);
                        while (--i >= 0)
                                soc_unregister_ac97_dai_link(card->rtd[i].codec);
                        goto probe_aux_dev_err;
@@ -1665,7 +1721,10 @@ EXPORT_SYMBOL_GPL(snd_soc_poweroff);
 const struct dev_pm_ops snd_soc_pm_ops = {
        .suspend = snd_soc_suspend,
        .resume = snd_soc_resume,
+       .freeze = snd_soc_suspend,
+       .thaw = snd_soc_resume,
        .poweroff = snd_soc_poweroff,
+       .restore = snd_soc_resume,
 };
 EXPORT_SYMBOL_GPL(snd_soc_pm_ops);
 
@@ -1869,23 +1928,28 @@ EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
                                unsigned int mask, unsigned int value)
 {
-       int change;
+       bool change;
        unsigned int old, new;
        int ret;
 
-       ret = snd_soc_read(codec, reg);
-       if (ret < 0)
-               return ret;
-
-       old = ret;
-       new = (old & ~mask) | (value & mask);
-       change = old != new;
-       if (change) {
-               ret = snd_soc_write(codec, reg, new);
+       if (codec->using_regmap) {
+               ret = regmap_update_bits_check(codec->control_data, reg,
+                                              mask, value, &change);
+       } else {
+               ret = snd_soc_read(codec, reg);
                if (ret < 0)
                        return ret;
+
+               old = ret;
+               new = (old & ~mask) | (value & mask);
+               change = old != new;
+               if (change)
+                       ret = snd_soc_write(codec, reg, new);
        }
 
+       if (ret < 0)
+               return ret;
+
        return change;
 }
 EXPORT_SYMBOL_GPL(snd_soc_update_bits);
@@ -1976,7 +2040,7 @@ EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
  * Returns 0 for success, else error.
  */
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
-                                 void *data, char *long_name,
+                                 void *data, const char *long_name,
                                  const char *prefix)
 {
        struct snd_kcontrol_new template;
@@ -2011,9 +2075,28 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 }
 EXPORT_SYMBOL_GPL(snd_soc_cnew);
 
+static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
+       const struct snd_kcontrol_new *controls, int num_controls,
+       const char *prefix, void *data)
+{
+       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, data,
+                                                    control->name, prefix));
+               if (err < 0) {
+                       dev_err(dev, "Failed to add %s: %d\n", control->name, err);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
 /**
- * snd_soc_add_controls - add an array of controls to a codec.
- * Convienience function to add a list of controls. Many codecs were
+ * snd_soc_add_codec_controls - add an array of controls to a codec.
+ * Convenience function to add a list of controls. Many codecs were
  * duplicating this code.
  *
  * @codec: codec to add controls to
@@ -2022,31 +2105,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);
  *
  * Return 0 for success, else error.
  */
-int snd_soc_add_controls(struct snd_soc_codec *codec,
+int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
        const struct snd_kcontrol_new *controls, int num_controls)
 {
        struct snd_card *card = codec->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, codec,
-                                                    control->name,
-                                                    codec->name_prefix));
-               if (err < 0) {
-                       dev_err(codec->dev, "%s: Failed to add %s: %d\n",
-                               codec->name, control->name, err);
-                       return err;
-               }
-       }
 
-       return 0;
+       return snd_soc_add_controls(card, codec->dev, controls, num_controls,
+                       codec->name_prefix, codec);
 }
-EXPORT_SYMBOL_GPL(snd_soc_add_controls);
+EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
 
 /**
  * snd_soc_add_platform_controls - add an array of controls to a platform.
- * Convienience function to add a list of controls.
+ * Convenience function to add a list of controls.
  *
  * @platform: platform to add controls to
  * @controls: array of controls to add
@@ -2058,22 +2129,52 @@ 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;
+       return snd_soc_add_controls(card, platform->dev, controls, num_controls,
+                       NULL, platform);
 }
 EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
 
+/**
+ * snd_soc_add_card_controls - add an array of controls to a SoC card.
+ * Convenience function to add a list of controls.
+ *
+ * @soc_card: SoC card 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_card_controls(struct snd_soc_card *soc_card,
+       const struct snd_kcontrol_new *controls, int num_controls)
+{
+       struct snd_card *card = soc_card->snd_card;
+
+       return snd_soc_add_controls(card, soc_card->dev, controls, num_controls,
+                       NULL, soc_card);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
+
+/**
+ * snd_soc_add_dai_controls - add an array of controls to a DAI.
+ * Convienience function to add a list of controls.
+ *
+ * @dai: DAI 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_dai_controls(struct snd_soc_dai *dai,
+       const struct snd_kcontrol_new *controls, int num_controls)
+{
+       struct snd_card *card = dai->card->snd_card;
+
+       return snd_soc_add_controls(card, dai->dev, controls, num_controls,
+                       NULL, dai);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
+
 /**
  * snd_soc_info_enum_double - enumerated double mixer info callback
  * @kcontrol: mixer control
@@ -2640,6 +2741,115 @@ int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
 
+int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
+                      struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct soc_bytes *params = (void *)kcontrol->private_value;
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+       uinfo->count = params->num_regs * codec->val_bytes;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
+
+int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
+                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_bytes *params = (void *)kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       int ret;
+
+       if (codec->using_regmap)
+               ret = regmap_raw_read(codec->control_data, params->base,
+                                     ucontrol->value.bytes.data,
+                                     params->num_regs * codec->val_bytes);
+       else
+               ret = -EINVAL;
+
+       /* Hide any masked bytes to ensure consistent data reporting */
+       if (ret == 0 && params->mask) {
+               switch (codec->val_bytes) {
+               case 1:
+                       ucontrol->value.bytes.data[0] &= ~params->mask;
+                       break;
+               case 2:
+                       ((u16 *)(&ucontrol->value.bytes.data))[0]
+                               &= ~params->mask;
+                       break;
+               case 4:
+                       ((u32 *)(&ucontrol->value.bytes.data))[0]
+                               &= ~params->mask;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
+
+int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
+                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_bytes *params = (void *)kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       int ret, len;
+       unsigned int val;
+       void *data;
+
+       if (!codec->using_regmap)
+               return -EINVAL;
+
+       data = ucontrol->value.bytes.data;
+       len = params->num_regs * codec->val_bytes;
+
+       /*
+        * If we've got a mask then we need to preserve the register
+        * bits.  We shouldn't modify the incoming data so take a
+        * copy.
+        */
+       if (params->mask) {
+               ret = regmap_read(codec->control_data, params->base, &val);
+               if (ret != 0)
+                       return ret;
+
+               val &= params->mask;
+
+               data = kmemdup(data, len, GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+
+               switch (codec->val_bytes) {
+               case 1:
+                       ((u8 *)data)[0] &= ~params->mask;
+                       ((u8 *)data)[0] |= val;
+                       break;
+               case 2:
+                       ((u16 *)data)[0] &= cpu_to_be16(~params->mask);
+                       ((u16 *)data)[0] |= cpu_to_be16(val);
+                       break;
+               case 4:
+                       ((u32 *)data)[0] &= cpu_to_be32(~params->mask);
+                       ((u32 *)data)[0] |= cpu_to_be32(val);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       ret = regmap_raw_write(codec->control_data, params->base,
+                              data, len);
+
+       if (params->mask)
+               kfree(data);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
+
 /**
  * snd_soc_dai_set_sysclk - configure DAI system or master clock.
  * @dai: DAI
@@ -2864,7 +3074,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 */
                if (!!link->codec_name == !!link->codec_of_node) {
                        dev_err(card->dev,
-                               "Neither/both codec name/of_node are set\n");
+                               "Neither/both codec name/of_node are set for %s\n",
+                               link->name);
                        return -EINVAL;
                }
 
@@ -2874,7 +3085,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 */
                if (link->platform_name && link->platform_of_node) {
                        dev_err(card->dev,
-                               "Both platform name/of_node are set\n");
+                               "Both platform name/of_node are set for %s\n", link->name);
                        return -EINVAL;
                }
 
@@ -2884,7 +3095,8 @@ int snd_soc_register_card(struct snd_soc_card *card)
                 */
                if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) {
                        dev_err(card->dev,
-                               "Neither/both cpu_dai name/of_node are set\n");
+                               "Neither/both cpu_dai name/of_node are set for %s\n",
+                               link->name);
                        return -EINVAL;
                }
        }
@@ -2991,7 +3203,7 @@ static inline char *fmt_multiple_name(struct device *dev,
                struct snd_soc_dai_driver *dai_drv)
 {
        if (dai_drv->name == NULL) {
-               printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n",
+               pr_err("asoc: error - multiple DAI %s registered with no name\n",
                                dev_name(dev));
                return NULL;
        }
@@ -3274,6 +3486,7 @@ int snd_soc_register_codec(struct device *dev,
        codec->volatile_register = codec_drv->volatile_register;
        codec->readable_register = codec_drv->readable_register;
        codec->writable_register = codec_drv->writable_register;
+       codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time;
        codec->dapm.bias_level = SND_SOC_BIAS_OFF;
        codec->dapm.dev = dev;
        codec->dapm.codec = codec;
@@ -3462,8 +3675,7 @@ static int __init snd_soc_init(void)
 #ifdef CONFIG_DEBUG_FS
        snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
        if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
-               printk(KERN_WARNING
-                      "ASoC: Failed to create debugfs directory\n");
+               pr_warn("ASoC: Failed to create debugfs directory\n");
                snd_soc_debugfs_root = NULL;
        }