Merge branch 'x86-trace-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-starfive.git] / sound / soc / soc-core.c
index 1a38be0..4e53d87 100644 (file)
@@ -662,6 +662,8 @@ int snd_soc_suspend(struct device *dev)
                                codec->cache_sync = 1;
                                if (codec->using_regmap)
                                        regcache_mark_dirty(codec->control_data);
+                               /* deactivate pins to sleep state */
+                               pinctrl_pm_select_sleep_state(codec->dev);
                                break;
                        default:
                                dev_dbg(codec->dev,
@@ -679,6 +681,9 @@ int snd_soc_suspend(struct device *dev)
 
                if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control)
                        cpu_dai->driver->suspend(cpu_dai);
+
+               /* deactivate pins to sleep state */
+               pinctrl_pm_select_sleep_state(cpu_dai->dev);
        }
 
        if (card->suspend_post)
@@ -807,6 +812,16 @@ int snd_soc_resume(struct device *dev)
        if (list_empty(&card->codec_dev_list))
                return 0;
 
+       /* activate pins from sleep state */
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+               struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
+               if (cpu_dai->active)
+                       pinctrl_pm_select_default_state(cpu_dai->dev);
+               if (codec_dai->active)
+                       pinctrl_pm_select_default_state(codec_dai->dev);
+       }
+
        /* AC97 devices might have other drivers hanging off them so
         * need to resume immediately.  Other drivers don't have that
         * problem and may take a substantial amount of time to resume
@@ -1589,17 +1604,13 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
                soc_remove_codec(codec);
 }
 
-static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
-                                   enum snd_soc_compress_type compress_type)
+static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
 {
        int ret;
 
        if (codec->cache_init)
                return 0;
 
-       /* override the compress_type if necessary */
-       if (compress_type && codec->compress_type != compress_type)
-               codec->compress_type = compress_type;
        ret = snd_soc_cache_init(codec);
        if (ret < 0) {
                dev_err(codec->dev,
@@ -1614,8 +1625,6 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
 static int snd_soc_instantiate_card(struct snd_soc_card *card)
 {
        struct snd_soc_codec *codec;
-       struct snd_soc_codec_conf *codec_conf;
-       enum snd_soc_compress_type compress_type;
        struct snd_soc_dai_link *dai_link;
        int ret, i, order, dai_fmt;
 
@@ -1639,19 +1648,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        list_for_each_entry(codec, &codec_list, list) {
                if (codec->cache_init)
                        continue;
-               /* by default we don't override the compress_type */
-               compress_type = 0;
-               /* check to see if we need to override the compress_type */
-               for (i = 0; i < card->num_configs; ++i) {
-                       codec_conf = &card->codec_conf[i];
-                       if (!strcmp(codec->name, codec_conf->dev_name)) {
-                               compress_type = codec_conf->compress_type;
-                               if (compress_type && compress_type
-                                   != codec->compress_type)
-                                       break;
-                       }
-               }
-               ret = snd_soc_init_codec_cache(codec, compress_type);
+               ret = snd_soc_init_codec_cache(codec);
                if (ret < 0)
                        goto base_error;
        }
@@ -1947,6 +1944,14 @@ int snd_soc_poweroff(struct device *dev)
 
        snd_soc_dapm_shutdown(card);
 
+       /* deactivate pins to sleep state */
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+               struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
+               pinctrl_pm_select_sleep_state(codec_dai->dev);
+               pinctrl_pm_select_sleep_state(cpu_dai->dev);
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_poweroff);
@@ -2297,13 +2302,6 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec,
 }
 EXPORT_SYMBOL_GPL(snd_soc_write);
 
-unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec,
-                                   unsigned int reg, const void *data, size_t len)
-{
-       return codec->bulk_write_raw(codec, reg, data, len);
-}
-EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
-
 /**
  * snd_soc_update_bits - update codec register bits
  * @codec: audio codec
@@ -2576,8 +2574,9 @@ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
 
        if (uinfo->value.enumerated.item > e->max - 1)
                uinfo->value.enumerated.item = e->max - 1;
-       strcpy(uinfo->value.enumerated.name,
-               e->texts[uinfo->value.enumerated.item]);
+       strlcpy(uinfo->value.enumerated.name,
+               e->texts[uinfo->value.enumerated.item],
+               sizeof(uinfo->value.enumerated.name));
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
@@ -3576,6 +3575,22 @@ int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
 EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
 
 /**
+ * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
+ * @dai: DAI
+ * @ratio Ratio of BCLK to Sample rate.
+ *
+ * Configures the DAI for a preset BCLK to sample rate ratio.
+ */
+int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+       if (dai->driver && dai->driver->ops->set_bclk_ratio)
+               return dai->driver->ops->set_bclk_ratio(dai, ratio);
+       else
+               return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
+
+/**
  * snd_soc_dai_set_fmt - configure DAI hardware audio format.
  * @dai: DAI
  * @fmt: SND_SOC_DAIFMT_ format value.
@@ -3775,6 +3790,16 @@ int snd_soc_register_card(struct snd_soc_card *card)
        if (ret != 0)
                soc_cleanup_card_debugfs(card);
 
+       /* deactivate pins to sleep state */
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+               struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
+               if (!codec_dai->active)
+                       pinctrl_pm_select_sleep_state(codec_dai->dev);
+               if (!cpu_dai->active)
+                       pinctrl_pm_select_sleep_state(cpu_dai->dev);
+       }
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_register_card);
@@ -4020,6 +4045,113 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count)
 }
 
 /**
+ * snd_soc_register_component - Register a component with the ASoC core
+ *
+ */
+static int
+__snd_soc_register_component(struct device *dev,
+                            struct snd_soc_component *cmpnt,
+                            const struct snd_soc_component_driver *cmpnt_drv,
+                            struct snd_soc_dai_driver *dai_drv,
+                            int num_dai, bool allow_single_dai)
+{
+       int ret;
+
+       dev_dbg(dev, "component register %s\n", dev_name(dev));
+
+       if (!cmpnt) {
+               dev_err(dev, "ASoC: Failed to connecting component\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->dai_drv  = dai_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
+        *
+        * this function is used from cpu/codec.
+        * allow_single_dai flag can ignore "codec" driver reworking
+        * since it had been used snd_soc_register_dais(),
+        */
+       if ((1 == num_dai) && allow_single_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;
+}
+
+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;
+
+       cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
+       if (!cmpnt) {
+               dev_err(dev, "ASoC: Failed to allocate memory\n");
+               return -ENOMEM;
+       }
+
+       return __snd_soc_register_component(dev, cmpnt, cmpnt_drv,
+                                           dai_drv, num_dai, true);
+}
+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);
+
+/**
  * snd_soc_add_platform - Add a platform to the ASoC core
  * @dev: The parent device for the platform
  * @platform: The platform to add
@@ -4165,7 +4297,6 @@ int snd_soc_register_codec(struct device *dev,
                           struct snd_soc_dai_driver *dai_drv,
                           int num_dai)
 {
-       size_t reg_size;
        struct snd_soc_codec *codec;
        int ret, i;
 
@@ -4182,11 +4313,6 @@ int snd_soc_register_codec(struct device *dev,
                goto fail_codec;
        }
 
-       if (codec_drv->compress_type)
-               codec->compress_type = codec_drv->compress_type;
-       else
-               codec->compress_type = SND_SOC_FLAT_COMPRESSION;
-
        codec->write = codec_drv->write;
        codec->read = codec_drv->read;
        codec->volatile_register = codec_drv->volatile_register;
@@ -4203,35 +4329,6 @@ int snd_soc_register_codec(struct device *dev,
        codec->num_dai = num_dai;
        mutex_init(&codec->mutex);
 
-       /* allocate CODEC register cache */
-       if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
-               reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
-               codec->reg_size = reg_size;
-               /* it is necessary to make a copy of the default register cache
-                * because in the case of using a compression type that requires
-                * the default register cache to be marked as the
-                * kernel might have freed the array by the time we initialize
-                * the cache.
-                */
-               if (codec_drv->reg_cache_default) {
-                       codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
-                                                     reg_size, GFP_KERNEL);
-                       if (!codec->reg_def_copy) {
-                               ret = -ENOMEM;
-                               goto fail_codec_name;
-                       }
-               }
-       }
-
-       if (codec_drv->reg_access_size && codec_drv->reg_access_default) {
-               if (!codec->volatile_register)
-                       codec->volatile_register = snd_soc_default_volatile_register;
-               if (!codec->readable_register)
-                       codec->readable_register = snd_soc_default_readable_register;
-               if (!codec->writable_register)
-                       codec->writable_register = snd_soc_default_writable_register;
-       }
-
        for (i = 0; i < num_dai; i++) {
                fixup_codec_formats(&dai_drv[i].playback);
                fixup_codec_formats(&dai_drv[i].capture);
@@ -4241,10 +4338,12 @@ int snd_soc_register_codec(struct device *dev,
        list_add(&codec->list, &codec_list);
        mutex_unlock(&client_mutex);
 
-       /* register any DAIs */
-       ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+       /* register component */
+       ret = __snd_soc_register_component(dev, &codec->component,
+                                          &codec_drv->component_driver,
+                                          dai_drv, num_dai, false);
        if (ret < 0) {
-               dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+               dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret);
                goto fail_codec_name;
        }
 
@@ -4279,7 +4378,7 @@ void snd_soc_unregister_codec(struct device *dev)
        return;
 
 found:
-       snd_soc_unregister_dais(dev, codec->num_dai);
+       snd_soc_unregister_component(dev);
 
        mutex_lock(&client_mutex);
        list_del(&codec->list);
@@ -4288,98 +4387,11 @@ found:
        dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name);
 
        snd_soc_cache_exit(codec);
-       kfree(codec->reg_def_copy);
        kfree(codec->name);
        kfree(codec);
 }
 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)
@@ -4567,6 +4579,60 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
 }
 EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
 
+int snd_soc_of_get_dai_name(struct device_node *of_node,
+                           const char **dai_name)
+{
+       struct snd_soc_component *pos;
+       struct of_phandle_args args;
+       int ret;
+
+       ret = of_parse_phandle_with_args(of_node, "sound-dai",
+                                        "#sound-dai-cells", 0, &args);
+       if (ret)
+               return ret;
+
+       ret = -EPROBE_DEFER;
+
+       mutex_lock(&client_mutex);
+       list_for_each_entry(pos, &component_list, list) {
+               if (pos->dev->of_node != args.np)
+                       continue;
+
+               if (pos->driver->of_xlate_dai_name) {
+                       ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name);
+               } else {
+                       int id = -1;
+
+                       switch (args.args_count) {
+                       case 0:
+                               id = 0; /* same as dai_drv[0] */
+                               break;
+                       case 1:
+                               id = args.args[0];
+                               break;
+                       default:
+                               /* not supported */
+                               break;
+                       }
+
+                       if (id < 0 || id >= pos->num_dai) {
+                               ret = -EINVAL;
+                       } else {
+                               *dai_name = pos->dai_drv[id].name;
+                               ret = 0;
+                       }
+               }
+
+               break;
+       }
+       mutex_unlock(&client_mutex);
+
+       of_node_put(args.np);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name);
+
 static int __init snd_soc_init(void)
 {
 #ifdef CONFIG_DEBUG_FS