Merge remote-tracking branch 'asoc/topic/core' into asoc-next
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 385c632..69e8e07 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -311,6 +311,8 @@
 #define SND_SOC_DAPM_POST_PMD	0x8		/* after widget power down */
 #define SND_SOC_DAPM_PRE_REG	0x10	/* before audio path setup */
 #define SND_SOC_DAPM_POST_REG	0x20	/* after audio path setup */
+#define SND_SOC_DAPM_WILL_PMU   0x40    /* called at start of sequence */
+#define SND_SOC_DAPM_WILL_PMD   0x80    /* called at start of sequence */
 #define SND_SOC_DAPM_PRE_POST_PMD \
 				(SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index d56bbea..4489c5b 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -272,8 +272,8 @@
 	codec->debugfs_codec_root = debugfs_create_dir(codec->name,
 						       debugfs_card_root);
 	if (!codec->debugfs_codec_root) {
-		dev_warn(codec->dev, "ASoC: Failed to create codec debugfs"
-			" directory\n");
+		dev_warn(codec->dev,
+			"ASoC: Failed to create codec debugfs directory\n");
 		return;
 	}
 
@@ -286,8 +286,8 @@
 						 codec->debugfs_codec_root,
 						 codec, &codec_reg_fops);
 	if (!codec->debugfs_reg)
-		dev_warn(codec->dev, "ASoC: Failed to create codec register"
-			" debugfs file\n");
+		dev_warn(codec->dev,
+			"ASoC: Failed to create codec register debugfs file\n");
 
 	snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
 }
@@ -631,8 +631,7 @@
 				 */
 				if (codec->dapm.idle_bias_off) {
 					dev_dbg(codec->dev,
-						"ASoC: idle_bias_off CODEC on"
-						" over suspend\n");
+						"ASoC: idle_bias_off CODEC on over suspend\n");
 					break;
 				}
 			case SND_SOC_BIAS_OFF:
@@ -643,8 +642,8 @@
 					regcache_mark_dirty(codec->control_data);
 				break;
 			default:
-				dev_dbg(codec->dev, "ASoC: CODEC is on"
-					" over suspend\n");
+				dev_dbg(codec->dev,
+					"ASoC: CODEC is on over suspend\n");
 				break;
 			}
 		}
@@ -713,8 +712,8 @@
 				codec->suspended = 0;
 				break;
 			default:
-				dev_dbg(codec->dev, "ASoC: CODEC was on over"
-					" suspend\n");
+				dev_dbg(codec->dev,
+					"ASoC: CODEC was on over suspend\n");
 				break;
 			}
 		}
@@ -1110,8 +1109,8 @@
 		}
 		WARN(codec->dapm.idle_bias_off &&
 			codec->dapm.bias_level != SND_SOC_BIAS_OFF,
-			"codec %s can not start from non-off bias"
-			" with idle_bias_off==1\n", codec->name);
+			"codec %s can not start from non-off bias with idle_bias_off==1\n",
+			codec->name);
 	}
 
 	/* If the driver didn't set I/O up try regmap */
@@ -1582,8 +1581,9 @@
 		codec->compress_type = compress_type;
 	ret = snd_soc_cache_init(codec);
 	if (ret < 0) {
-		dev_err(codec->dev, "ASoC: Failed to set cache compression"
-			" type: %d\n", ret);
+		dev_err(codec->dev,
+			"ASoC: Failed to set cache compression type: %d\n",
+			ret);
 		return ret;
 	}
 	codec->cache_init = 1;
@@ -1639,8 +1639,9 @@
 	ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
 			card->owner, 0, &card->snd_card);
 	if (ret < 0) {
-		dev_err(card->dev, "ASoC: can't create sound card for"
-			" card %s: %d\n", card->name, ret);
+		dev_err(card->dev,
+			"ASoC: can't create sound card for card %s: %d\n",
+			card->name, ret);
 		goto base_error;
 	}
 	card->snd_card->dev = card->dev;
@@ -1815,8 +1816,8 @@
 	for (i = 0; i < card->num_rtd; i++) {
 		ret = soc_register_ac97_dai_link(&card->rtd[i]);
 		if (ret < 0) {
-			dev_err(card->dev, "ASoC: failed to register AC97:"
-				" %d\n", ret);
+			dev_err(card->dev,
+				"ASoC: failed to register AC97: %d\n", ret);
 			while (--i >= 0)
 				soc_unregister_ac97_dai_link(card->rtd[i].codec);
 			goto probe_aux_dev_err;
@@ -2219,29 +2220,6 @@
 EXPORT_SYMBOL_GPL(snd_soc_test_bits);
 
 /**
- * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
- * @substream: the pcm substream
- * @hw: the hardware parameters
- *
- * Sets the substream runtime hardware parameters.
- */
-int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
-	const struct snd_pcm_hardware *hw)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	runtime->hw.info = hw->info;
-	runtime->hw.formats = hw->formats;
-	runtime->hw.period_bytes_min = hw->period_bytes_min;
-	runtime->hw.period_bytes_max = hw->period_bytes_max;
-	runtime->hw.periods_min = hw->periods_min;
-	runtime->hw.periods_max = hw->periods_max;
-	runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
-	runtime->hw.fifo_size = hw->fifo_size;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
-
-/**
  * snd_soc_cnew - create new control
  * @_template: control template
  * @data: control private data
@@ -2259,7 +2237,6 @@
 	struct snd_kcontrol_new template;
 	struct snd_kcontrol *kcontrol;
 	char *name = NULL;
-	int name_len;
 
 	memcpy(&template, _template, sizeof(template));
 	template.index = 0;
@@ -2268,13 +2245,10 @@
 		long_name = template.name;
 
 	if (prefix) {
-		name_len = strlen(long_name) + strlen(prefix) + 2;
-		name = kmalloc(name_len, GFP_KERNEL);
+		name = kasprintf(GFP_KERNEL, "%s %s", prefix, long_name);
 		if (!name)
 			return NULL;
 
-		snprintf(name, name_len, "%s %s", prefix, long_name);
-
 		template.name = name;
 	} else {
 		template.name = long_name;
@@ -3586,14 +3560,16 @@
 		 * not both or neither.
 		 */
 		if (!!link->codec_name == !!link->codec_of_node) {
-			dev_err(card->dev, "ASoC: Neither/both codec"
-				" name/of_node are set for %s\n", link->name);
+			dev_err(card->dev,
+				"ASoC: Neither/both codec name/of_node are set for %s\n",
+				link->name);
 			return -EINVAL;
 		}
 		/* Codec DAI name must be specified */
 		if (!link->codec_dai_name) {
-			dev_err(card->dev, "ASoC: codec_dai_name not"
-				" set for %s\n", link->name);
+			dev_err(card->dev,
+				"ASoC: codec_dai_name not set for %s\n",
+				link->name);
 			return -EINVAL;
 		}
 
@@ -3602,8 +3578,9 @@
 		 * can be left unspecified, and a dummy platform will be used.
 		 */
 		if (link->platform_name && link->platform_of_node) {
-			dev_err(card->dev, "ASoC: Both platform name/of_node"
-				" are set for %s\n", link->name);
+			dev_err(card->dev,
+				"ASoC: Both platform name/of_node are set for %s\n",
+				link->name);
 			return -EINVAL;
 		}
 
@@ -3613,8 +3590,9 @@
 		 * name alone..
 		 */
 		if (link->cpu_name && link->cpu_of_node) {
-			dev_err(card->dev, "ASoC: Neither/both "
-				"cpu name/of_node are set for %s\n",link->name);
+			dev_err(card->dev,
+				"ASoC: Neither/both cpu name/of_node are set for %s\n",
+				link->name);
 			return -EINVAL;
 		}
 		/*
@@ -3623,8 +3601,9 @@
 		 */
 		if (!link->cpu_dai_name &&
 		    !(link->cpu_name || link->cpu_of_node)) {
-			dev_err(card->dev, "ASoC: Neither cpu_dai_name nor "
-				"cpu_name/of_node are set for %s\n", link->name);
+			dev_err(card->dev,
+				"ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
+				link->name);
 			return -EINVAL;
 		}
 	}
@@ -3728,8 +3707,9 @@
 		struct snd_soc_dai_driver *dai_drv)
 {
 	if (dai_drv->name == NULL) {
-		dev_err(dev, "ASoC: error - multiple DAI %s registered with"
-				" no name\n", dev_name(dev));
+		dev_err(dev,
+			"ASoC: error - multiple DAI %s registered with no name\n",
+			dev_name(dev));
 		return NULL;
 	}
 
@@ -3859,8 +3839,9 @@
 
 		list_for_each_entry(codec, &codec_list, list) {
 			if (codec->dev == dev) {
-				dev_dbg(dev, "ASoC: Mapped DAI %s to "
-					"CODEC %s\n", dai->name, codec->name);
+				dev_dbg(dev,
+					"ASoC: Mapped DAI %s to CODEC %s\n",
+					dai->name, codec->name);
 				dai->codec = codec;
 				break;
 			}
@@ -4296,8 +4277,9 @@
 
 	num_routes = of_property_count_strings(np, propname);
 	if (num_routes < 0 || num_routes & 1) {
-		dev_err(card->dev, "ASoC: Property '%s' does not exist or its"
-			" length is not even\n", propname);
+		dev_err(card->dev,
+			"ASoC: Property '%s' does not exist or its length is not even\n",
+			propname);
 		return -EINVAL;
 	}
 	num_routes /= 2;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index fe2be28..10290c7 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -526,7 +526,6 @@
 	int wlistentries;
 	size_t wlistsize;
 	bool wname_in_long_name, kcname_in_long_name;
-	size_t name_len;
 	char *long_name;
 	const char *name;
 	int ret;
@@ -591,25 +590,19 @@
 		}
 
 		if (wname_in_long_name && kcname_in_long_name) {
-			name_len = strlen(w->name) - prefix_len + 1 +
-				   strlen(w->kcontrol_news[kci].name) + 1;
-
-			long_name = kmalloc(name_len, GFP_KERNEL);
-			if (long_name == NULL) {
-				kfree(wlist);
-				return -ENOMEM;
-			}
-
 			/*
 			 * The control will get a prefix from the control
 			 * creation process but we're also using the same
 			 * prefix for widgets so cut the prefix off the
 			 * front of the widget name.
 			 */
-			snprintf(long_name, name_len, "%s %s",
+			long_name = kasprintf(GFP_KERNEL, "%s %s",
 				 w->name + prefix_len,
 				 w->kcontrol_news[kci].name);
-			long_name[name_len - 1] = '\0';
+			if (long_name == NULL) {
+				kfree(wlist);
+				return -ENOMEM;
+			}
 
 			name = long_name;
 		} else if (wname_in_long_name) {
@@ -1272,6 +1265,14 @@
 		ev_name = "POST_PMD";
 		power = 0;
 		break;
+	case SND_SOC_DAPM_WILL_PMU:
+		ev_name = "WILL_PMU";
+		power = 1;
+		break;
+	case SND_SOC_DAPM_WILL_PMD:
+		ev_name = "WILL_PMD";
+		power = 0;
+		break;
 	default:
 		BUG();
 		return;
@@ -1732,6 +1733,14 @@
 					&async_domain);
 	async_synchronize_full_domain(&async_domain);
 
+	list_for_each_entry(w, &down_list, power_list) {
+		dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMD);
+	}
+
+	list_for_each_entry(w, &up_list, power_list) {
+		dapm_seq_check_event(dapm, w, SND_SOC_DAPM_WILL_PMU);
+	}
+
 	/* Power down widgets first; try to avoid amplifying pops. */
 	dapm_seq_run(dapm, &down_list, event, false);
 
@@ -3057,7 +3066,6 @@
 			 const struct snd_soc_dapm_widget *widget)
 {
 	struct snd_soc_dapm_widget *w;
-	size_t name_len;
 	int ret;
 
 	if ((w = dapm_cnew_widget(widget)) == NULL)
@@ -3098,19 +3106,16 @@
 		break;
 	}
 
-	name_len = strlen(widget->name) + 1;
 	if (dapm->codec && dapm->codec->name_prefix)
-		name_len += 1 + strlen(dapm->codec->name_prefix);
-	w->name = kmalloc(name_len, GFP_KERNEL);
+		w->name = kasprintf(GFP_KERNEL, "%s %s",
+			dapm->codec->name_prefix, widget->name);
+	else
+		w->name = kasprintf(GFP_KERNEL, "%s", widget->name);
+
 	if (w->name == NULL) {
 		kfree(w);
 		return NULL;
 	}
-	if (dapm->codec && dapm->codec->name_prefix)
-		snprintf((char *)w->name, name_len, "%s %s",
-			dapm->codec->name_prefix, widget->name);
-	else
-		snprintf((char *)w->name, name_len, "%s", widget->name);
 
 	switch (w->id) {
 	case snd_soc_dapm_switch:
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ccb6be4..b6c6403 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -33,6 +33,29 @@
 
 #define DPCM_MAX_BE_USERS	8
 
+/**
+ * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
+ * @substream: the pcm substream
+ * @hw: the hardware parameters
+ *
+ * Sets the substream runtime hardware parameters.
+ */
+int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
+	const struct snd_pcm_hardware *hw)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	runtime->hw.info = hw->info;
+	runtime->hw.formats = hw->formats;
+	runtime->hw.period_bytes_min = hw->period_bytes_min;
+	runtime->hw.period_bytes_max = hw->period_bytes_max;
+	runtime->hw.periods_min = hw->periods_min;
+	runtime->hw.periods_max = hw->periods_max;
+	runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
+	runtime->hw.fifo_size = hw->fifo_size;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
+
 /* DPCM stream event, send event to FE and all active BEs. */
 static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
 	int event)
@@ -124,6 +147,26 @@
 	}
 }
 
+static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw,
+	struct snd_soc_pcm_stream *codec_stream,
+	struct snd_soc_pcm_stream *cpu_stream)
+{
+	hw->rate_min = max(codec_stream->rate_min, cpu_stream->rate_min);
+	hw->rate_max = max(codec_stream->rate_max, cpu_stream->rate_max);
+	hw->channels_min = max(codec_stream->channels_min,
+		cpu_stream->channels_min);
+	hw->channels_max = min(codec_stream->channels_max,
+		cpu_stream->channels_max);
+	hw->formats = codec_stream->formats & cpu_stream->formats;
+	hw->rates = codec_stream->rates & cpu_stream->rates;
+	if (codec_stream->rates
+		& (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
+		hw->rates |= cpu_stream->rates;
+	if (cpu_stream->rates
+		& (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
+		hw->rates |= codec_stream->rates;
+}
+
 /*
  * Called by ALSA when a PCM substream is opened, the runtime->hw record is
  * then initialized and any private data can be allocated. This also calls
@@ -189,51 +232,11 @@
 
 	/* Check that the codec and cpu DAIs are compatible */
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		runtime->hw.rate_min =
-			max(codec_dai_drv->playback.rate_min,
-			    cpu_dai_drv->playback.rate_min);
-		runtime->hw.rate_max =
-			min(codec_dai_drv->playback.rate_max,
-			    cpu_dai_drv->playback.rate_max);
-		runtime->hw.channels_min =
-			max(codec_dai_drv->playback.channels_min,
-				cpu_dai_drv->playback.channels_min);
-		runtime->hw.channels_max =
-			min(codec_dai_drv->playback.channels_max,
-				cpu_dai_drv->playback.channels_max);
-		runtime->hw.formats =
-			codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
-		runtime->hw.rates =
-			codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
-		if (codec_dai_drv->playback.rates
-			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-			runtime->hw.rates |= cpu_dai_drv->playback.rates;
-		if (cpu_dai_drv->playback.rates
-			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-			runtime->hw.rates |= codec_dai_drv->playback.rates;
+		soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->playback,
+			&cpu_dai_drv->playback);
 	} else {
-		runtime->hw.rate_min =
-			max(codec_dai_drv->capture.rate_min,
-			    cpu_dai_drv->capture.rate_min);
-		runtime->hw.rate_max =
-			min(codec_dai_drv->capture.rate_max,
-			    cpu_dai_drv->capture.rate_max);
-		runtime->hw.channels_min =
-			max(codec_dai_drv->capture.channels_min,
-				cpu_dai_drv->capture.channels_min);
-		runtime->hw.channels_max =
-			min(codec_dai_drv->capture.channels_max,
-				cpu_dai_drv->capture.channels_max);
-		runtime->hw.formats =
-			codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
-		runtime->hw.rates =
-			codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
-		if (codec_dai_drv->capture.rates
-			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-			runtime->hw.rates |= cpu_dai_drv->capture.rates;
-		if (cpu_dai_drv->capture.rates
-			   & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-			runtime->hw.rates |= codec_dai_drv->capture.rates;
+		soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->capture,
+			&cpu_dai_drv->capture);
 	}
 
 	ret = -EINVAL;
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 4b3be6c..29b211e 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -159,15 +159,10 @@
 {
 	int ret;
 
-	soc_dummy_dev = platform_device_alloc("snd-soc-dummy", -1);
-	if (!soc_dummy_dev)
-		return -ENOMEM;
-
-	ret = platform_device_add(soc_dummy_dev);
-	if (ret != 0) {
-		platform_device_put(soc_dummy_dev);
-		return ret;
-	}
+	soc_dummy_dev =
+		platform_device_register_simple("snd-soc-dummy", -1, NULL, 0);
+	if (IS_ERR(soc_dummy_dev))
+		return PTR_ERR(soc_dummy_dev);
 
 	ret = platform_driver_register(&soc_dummy_driver);
 	if (ret != 0)