From 208a1589db3e30767223d97e39e13237328e8a6e Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Wed, 5 Mar 2014 13:17:42 +0100
Subject: [PATCH 1/7] ASoC: Handle ignore_pmdown_time for CODEC to CODEC links

For CODEC to CODEC links we should only immediately power down if both CODECs
are configured to ignore the power down delay. Factor the logic for this
into a helper function that can be used for both compressed and normal PCMs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/soc.h      |  2 ++
 sound/soc/soc-compress.c |  3 +--
 sound/soc/soc-pcm.c      | 27 +++++++++++++++++++++++++--
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 9a001472b96a4..93c31c70b90a4 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -413,6 +413,8 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
 struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
 		const char *dai_link);
 
+bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
+
 /* Utility functions to get clock rates from various things */
 int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
 int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 5e9690c85d8f5..ef585af4081b0 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -235,8 +235,7 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
 	cpu_dai->runtime = NULL;
 
 	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
-		if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
-		    rtd->dai_link->ignore_pmdown_time) {
+		if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
 			snd_soc_dapm_stream_event(rtd,
 					SNDRV_PCM_STREAM_PLAYBACK,
 					SND_SOC_DAPM_STREAM_STOP);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 47e1ce771e65e..f098c8007cbe3 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -34,6 +34,30 @@
 
 #define DPCM_MAX_BE_USERS	8
 
+/**
+ * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay
+ * @rtd: The ASoC PCM runtime that should be checked.
+ *
+ * This function checks whether the power down delay should be ignored for a
+ * specific PCM runtime. Returns true if the delay is 0, if it the DAI link has
+ * been configured to ignore the delay, or if none of the components benefits
+ * from having the delay.
+ */
+bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
+{
+	bool ignore = true;
+
+	if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
+		return true;
+
+	if (rtd->cpu_dai->codec)
+		ignore &= rtd->cpu_dai->codec->ignore_pmdown_time;
+
+	ignore &= rtd->codec_dai->codec->ignore_pmdown_time;
+
+	return ignore;
+}
+
 /**
  * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
  * @substream: the pcm substream
@@ -496,8 +520,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 	cpu_dai->runtime = NULL;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
-		    rtd->dai_link->ignore_pmdown_time) {
+		if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
 			/* powered down playback stream now */
 			snd_soc_dapm_stream_event(rtd,
 						  SNDRV_PCM_STREAM_PLAYBACK,

From 24894b76468ed250d03f9718ddfe77b902995cbd Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Wed, 5 Mar 2014 13:17:43 +0100
Subject: [PATCH 2/7] ASoC: Add helper functions for PCM runtime 'active'
 management

We have the same code that increments and decrements the active field of the
various PCM runtime components (all with the same bugs). Factor this out into
common helper functions.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/soc.h      |  2 +
 sound/soc/soc-compress.c | 62 ++++++-----------------------
 sound/soc/soc-pcm.c      | 86 ++++++++++++++++++++++++++++++----------
 3 files changed, 78 insertions(+), 72 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 93c31c70b90a4..53d15e0e6e89b 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -414,6 +414,8 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card,
 		const char *dai_link);
 
 bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
+void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream);
+void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
 
 /* Utility functions to get clock rates from various things */
 int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index ef585af4081b0..91083e6a6b381 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -30,8 +30,6 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
 {
 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	int ret = 0;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
@@ -52,17 +50,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
 		}
 	}
 
-	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
-		cpu_dai->playback_active++;
-		codec_dai->playback_active++;
-	} else {
-		cpu_dai->capture_active++;
-		codec_dai->capture_active++;
-	}
-
-	cpu_dai->active++;
-	codec_dai->active++;
-	rtd->codec->active++;
+	snd_soc_runtime_activate(rtd, cstream->direction);
 
 	mutex_unlock(&rtd->pcm_mutex);
 
@@ -81,8 +69,6 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 	struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
 	struct snd_soc_platform *platform = fe->platform;
-	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
-	struct snd_soc_dai *codec_dai = fe->codec_dai;
 	struct snd_soc_dpcm *dpcm;
 	struct snd_soc_dapm_widget_list *list;
 	int stream;
@@ -140,17 +126,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 
-	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
-		cpu_dai->playback_active++;
-		codec_dai->playback_active++;
-	} else {
-		cpu_dai->capture_active++;
-		codec_dai->capture_active++;
-	}
-
-	cpu_dai->active++;
-	codec_dai->active++;
-	fe->codec->active++;
+	snd_soc_runtime_activate(fe, stream);
 
 	mutex_unlock(&fe->card->mutex);
 
@@ -202,23 +178,18 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = rtd->codec;
+	int stream;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
-	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
-		cpu_dai->playback_active--;
-		codec_dai->playback_active--;
-	} else {
-		cpu_dai->capture_active--;
-		codec_dai->capture_active--;
-	}
+	if (cstream->direction == SND_COMPRESS_PLAYBACK)
+		stream = SNDRV_PCM_STREAM_PLAYBACK;
+	else
+		stream = SNDRV_PCM_STREAM_CAPTURE;
 
-	snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
+	snd_soc_runtime_deactivate(rtd, stream);
 
-	cpu_dai->active--;
-	codec_dai->active--;
-	codec->active--;
+	snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
 
 	if (!cpu_dai->active)
 		cpu_dai->rate = 0;
@@ -260,26 +231,17 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)
 {
 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 	struct snd_soc_platform *platform = fe->platform;
-	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
-	struct snd_soc_dai *codec_dai = fe->codec_dai;
 	struct snd_soc_dpcm *dpcm;
 	int stream, ret;
 
 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 
-	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
+	if (cstream->direction == SND_COMPRESS_PLAYBACK)
 		stream = SNDRV_PCM_STREAM_PLAYBACK;
-		cpu_dai->playback_active--;
-		codec_dai->playback_active--;
-	} else {
+	else
 		stream = SNDRV_PCM_STREAM_CAPTURE;
-		cpu_dai->capture_active--;
-		codec_dai->capture_active--;
-	}
 
-	cpu_dai->active--;
-	codec_dai->active--;
-	fe->codec->active--;
+	snd_soc_runtime_deactivate(fe, stream);
 
 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index f098c8007cbe3..1a9857519d655 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -34,6 +34,66 @@
 
 #define DPCM_MAX_BE_USERS	8
 
+/**
+ * snd_soc_runtime_activate() - Increment active count for PCM runtime components
+ * @rtd: ASoC PCM runtime that is activated
+ * @stream: Direction of the PCM stream
+ *
+ * Increments the active count for all the DAIs and components attached to a PCM
+ * runtime. Should typically be called when a stream is opened.
+ *
+ * Must be called with the rtd->pcm_mutex being held
+ */
+void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
+{
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+	lockdep_assert_held(&rtd->pcm_mutex);
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		cpu_dai->playback_active++;
+		codec_dai->playback_active++;
+	} else {
+		cpu_dai->capture_active++;
+		codec_dai->capture_active++;
+	}
+
+	cpu_dai->active++;
+	codec_dai->active++;
+	rtd->codec->active++;
+}
+
+/**
+ * snd_soc_runtime_deactivate() - Decrement active count for PCM runtime components
+ * @rtd: ASoC PCM runtime that is deactivated
+ * @stream: Direction of the PCM stream
+ *
+ * Decrements the active count for all the DAIs and components attached to a PCM
+ * runtime. Should typically be called when a stream is closed.
+ *
+ * Must be called with the rtd->pcm_mutex being held
+ */
+void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
+{
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+	lockdep_assert_held(&rtd->pcm_mutex);
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		cpu_dai->playback_active--;
+		codec_dai->playback_active--;
+	} else {
+		cpu_dai->capture_active--;
+		codec_dai->capture_active--;
+	}
+
+	cpu_dai->active--;
+	codec_dai->active--;
+	rtd->codec->active--;
+}
+
 /**
  * snd_soc_runtime_ignore_pmdown_time() - Check whether to ignore the power down delay
  * @rtd: The ASoC PCM runtime that should be checked.
@@ -402,16 +462,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
 		 runtime->hw.rate_max);
 
 dynamic:
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		cpu_dai->playback_active++;
-		codec_dai->playback_active++;
-	} else {
-		cpu_dai->capture_active++;
-		codec_dai->capture_active++;
-	}
-	cpu_dai->active++;
-	codec_dai->active++;
-	rtd->codec->active++;
+
+	snd_soc_runtime_activate(rtd, substream->stream);
+
 	mutex_unlock(&rtd->pcm_mutex);
 	return 0;
 
@@ -483,21 +536,10 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
 	struct snd_soc_platform *platform = rtd->platform;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_codec *codec = rtd->codec;
 
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		cpu_dai->playback_active--;
-		codec_dai->playback_active--;
-	} else {
-		cpu_dai->capture_active--;
-		codec_dai->capture_active--;
-	}
-
-	cpu_dai->active--;
-	codec_dai->active--;
-	codec->active--;
+	snd_soc_runtime_deactivate(rtd, substream->stream);
 
 	/* clear the corresponding DAIs rate when inactive */
 	if (!cpu_dai->active)

From a1a0cc0646e38b41bfaac94f2b84422bb1df40e0 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Wed, 5 Mar 2014 13:17:44 +0100
Subject: [PATCH 3/7] ASoC: Fix active count tracking for CODEC to CODEC links

For CODEC to CODEC links we need to make sure to also manage the 'active' field
of the cpu_dai CODEC.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/soc-pcm.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 1a9857519d655..71a01dda1867e 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -61,7 +61,9 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
 
 	cpu_dai->active++;
 	codec_dai->active++;
-	rtd->codec->active++;
+	if (cpu_dai->codec)
+		cpu_dai->codec->active++;
+	codec_dai->codec->active++;
 }
 
 /**
@@ -91,7 +93,9 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
 
 	cpu_dai->active--;
 	codec_dai->active--;
-	rtd->codec->active--;
+	if (cpu_dai->codec)
+		cpu_dai->codec->active--;
+	codec_dai->codec->active--;
 }
 
 /**

From 5c898e74d135a23ce12e0263c1a3c78eeae1b52b Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Wed, 5 Mar 2014 13:17:45 +0100
Subject: [PATCH 4/7] ASoC: Add helper function to check whether a CODEC is
 active

Instead of directly checking the 'active' field of the CODEC struct add a new
helper function that will return either true or false depending on whether the
CODEC is active. This will make the migration to the component level easier.

The patch also updates all CODEC drivers that check the active attribute to use
the new helper function.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/soc.h            | 5 +++++
 sound/soc/codecs/adav80x.c     | 4 ++--
 sound/soc/codecs/tlv320aic23.c | 2 +-
 sound/soc/codecs/tlv320dac33.c | 2 +-
 sound/soc/codecs/uda1380.c     | 2 +-
 sound/soc/codecs/wl1273.c      | 2 +-
 sound/soc/codecs/wm8711.c      | 2 +-
 sound/soc/codecs/wm8753.c      | 4 ++--
 8 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 53d15e0e6e89b..5c2b4f4b5cfaa 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1172,6 +1172,11 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
 	return 1;
 }
 
+static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec)
+{
+	return codec->active != 0;
+}
+
 int snd_soc_util_init(void);
 void snd_soc_util_exit(void);
 
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index f78b27a7c461d..d50cf5b29a271 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -722,7 +722,7 @@ static int adav80x_dai_startup(struct snd_pcm_substream *substream,
 	struct snd_soc_codec *codec = dai->codec;
 	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-	if (!codec->active || !adav80x->rate)
+	if (!snd_soc_codec_is_active(codec) || !adav80x->rate)
 		return 0;
 
 	return snd_pcm_hw_constraint_minmax(substream->runtime,
@@ -735,7 +735,7 @@ static void adav80x_dai_shutdown(struct snd_pcm_substream *substream,
 	struct snd_soc_codec *codec = dai->codec;
 	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-	if (!codec->active)
+	if (!snd_soc_codec_is_active(codec))
 		adav80x->rate = 0;
 }
 
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 5d430cc56f51d..458a6aed203ed 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -400,7 +400,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
 	struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
 
 	/* deactivate */
-	if (!codec->active) {
+	if (!snd_soc_codec_is_active(codec)) {
 		udelay(50);
 		snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
 	}
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 4f358393d6d63..35b2d244e42e7 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -461,7 +461,7 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol,
 	if (dac33->fifo_mode == ucontrol->value.integer.value[0])
 		return 0;
 	/* Do not allow changes while stream is running*/
-	if (codec->active)
+	if (snd_soc_codec_is_active(codec))
 		return -EPERM;
 
 	if (ucontrol->value.integer.value[0] < 0 ||
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 726df6d43c2b6..8e3940dcff202 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -108,7 +108,7 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
 	/* the interpolator & decimator regs must only be written when the
 	 * codec DAI is active.
 	 */
-	if (!codec->active && (reg >= UDA1380_MVOL))
+	if (!snd_soc_codec_is_active(codec) && (reg >= UDA1380_MVOL))
 		return 0;
 	pr_debug("uda1380: hw write %x val %x\n", reg, value);
 	if (codec->hw_write(codec->control_data, data, 3) == 3) {
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index b7ab2ef567c88..47e96ff30064a 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -197,7 +197,7 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
 		return 0;
 
 	/* Do not allow changes while stream is running */
-	if (codec->active)
+	if (snd_soc_codec_is_active(codec))
 		return -EPERM;
 
 	if (ucontrol->value.integer.value[0] < 0 ||
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index d99f948c513cd..6efcc40a7cb3c 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -201,7 +201,7 @@ static void wm8711_shutdown(struct snd_pcm_substream *substream,
 	struct snd_soc_codec *codec = dai->codec;
 
 	/* deactivate */
-	if (!codec->active) {
+	if (!snd_soc_codec_is_active(codec)) {
 		udelay(50);
 		snd_soc_write(codec, WM8711_ACTIVE, 0x0);
 	}
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index be85da93a2682..5cf4bebc5d895 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -251,7 +251,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
 	if (wm8753->dai_func == ucontrol->value.integer.value[0])
 		return 0;
 
-	if (codec->active)
+	if (snd_soc_codec_is_active(codec))
 		return -EBUSY;
 
 	ioctl = snd_soc_read(codec, WM8753_IOCTL);
@@ -1314,7 +1314,7 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
 	/* the digital mute covers the HiFi and Voice DAC's on the WM8753.
 	 * make sure we check if they are not both active when we mute */
 	if (mute && wm8753->dai_func == 1) {
-		if (!codec->active)
+		if (!snd_soc_codec_is_active(codec))
 			snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
 	} else {
 		if (mute)

From 6106d12947d1b05dc15ca3933eb514347d6ed726 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Wed, 5 Mar 2014 13:17:46 +0100
Subject: [PATCH 5/7] ASoC: Add component pointer to the DAI struct

Keep track of which component registered a DAI. We'll need this as
componentization progresses.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/soc-dai.h |  1 +
 sound/soc/soc-core.c    | 18 ++++++++++++------
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 71f27c403194f..8763e539c4878 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -270,6 +270,7 @@ struct snd_soc_dai {
 	/* parent platform/codec */
 	struct snd_soc_platform *platform;
 	struct snd_soc_codec *codec;
+	struct snd_soc_component *component;
 
 	struct snd_soc_card *card;
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index fe1df50805a30..6401e97b2e685 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3884,11 +3884,13 @@ static inline char *fmt_multiple_name(struct device *dev,
 /**
  * snd_soc_register_dai - Register a DAI with the ASoC core
  *
- * @dai: DAI to register
+ * @component: The component the DAIs are registered for
+ * @dai_drv: DAI driver to use for the DAIs
  */
-static int snd_soc_register_dai(struct device *dev,
+static int snd_soc_register_dai(struct snd_soc_component *component,
 		struct snd_soc_dai_driver *dai_drv)
 {
+	struct device *dev = component->dev;
 	struct snd_soc_codec *codec;
 	struct snd_soc_dai *dai;
 
@@ -3905,6 +3907,7 @@ static int snd_soc_register_dai(struct device *dev,
 		return -ENOMEM;
 	}
 
+	dai->component = component;
 	dai->dev = dev;
 	dai->driver = dai_drv;
 	dai->dapm.dev = dev;
@@ -3962,12 +3965,14 @@ static void snd_soc_unregister_dai(struct device *dev)
 /**
  * snd_soc_register_dais - Register multiple DAIs with the ASoC core
  *
- * @dai: Array of DAIs to register
+ * @component: The component the DAIs are registered for
+ * @dai_drv: DAI driver to use for the DAIs
  * @count: Number of DAIs
  */
-static int snd_soc_register_dais(struct device *dev,
+static int snd_soc_register_dais(struct snd_soc_component *component,
 		struct snd_soc_dai_driver *dai_drv, size_t count)
 {
+	struct device *dev = component->dev;
 	struct snd_soc_codec *codec;
 	struct snd_soc_dai *dai;
 	int i, ret = 0;
@@ -3990,6 +3995,7 @@ static int snd_soc_register_dais(struct device *dev,
 			goto err;
 		}
 
+		dai->component = component;
 		dai->dev = dev;
 		dai->driver = &dai_drv[i];
 		if (dai->driver->id)
@@ -4086,9 +4092,9 @@ __snd_soc_register_component(struct device *dev,
 	 * since it had been used snd_soc_register_dais(),
 	 */
 	if ((1 == num_dai) && allow_single_dai)
-		ret = snd_soc_register_dai(dev, dai_drv);
+		ret = snd_soc_register_dai(cmpnt, dai_drv);
 	else
-		ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+		ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai);
 	if (ret < 0) {
 		dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
 		goto error_component_name;

From cdde4ccb14b4959bd1c96a07367bf02b746328d3 Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Wed, 5 Mar 2014 13:17:47 +0100
Subject: [PATCH 6/7] ASoC: Move active count from CODEC to component

There is no reason why active count tracking should only be done for CODECs but
not for other components. Moving the active count from the snd_soc_codec struct
to the snd_soc_component struct reduces the differences between CODECs and other
components and will eventually allow component to component DAI links (Which is
a prerequisite for converting CODECs to components).

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/soc.h | 12 ++++++++++--
 sound/soc/soc-pcm.c | 10 ++++------
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 5c2b4f4b5cfaa..0495b4aaeb701 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -660,6 +660,9 @@ struct snd_soc_component {
 	const char *name;
 	int id;
 	struct device *dev;
+
+	unsigned int active;
+
 	struct list_head list;
 
 	struct snd_soc_dai_driver *dai_drv;
@@ -687,7 +690,6 @@ struct snd_soc_codec {
 
 	/* runtime */
 	struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */
-	unsigned int active;
 	unsigned int cache_bypass:1; /* Suppress access to the cache */
 	unsigned int suspended:1; /* Codec is in suspend PM state */
 	unsigned int probed:1; /* Codec has been probed */
@@ -1172,9 +1174,15 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc)
 	return 1;
 }
 
+static inline bool snd_soc_component_is_active(
+	struct snd_soc_component *component)
+{
+	return component->active != 0;
+}
+
 static inline bool snd_soc_codec_is_active(struct snd_soc_codec *codec)
 {
-	return codec->active != 0;
+	return snd_soc_component_is_active(&codec->component);
 }
 
 int snd_soc_util_init(void);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 71a01dda1867e..98b46295785de 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -61,9 +61,8 @@ void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream)
 
 	cpu_dai->active++;
 	codec_dai->active++;
-	if (cpu_dai->codec)
-		cpu_dai->codec->active++;
-	codec_dai->codec->active++;
+	cpu_dai->component->active++;
+	codec_dai->component->active++;
 }
 
 /**
@@ -93,9 +92,8 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
 
 	cpu_dai->active--;
 	codec_dai->active--;
-	if (cpu_dai->codec)
-		cpu_dai->codec->active--;
-	codec_dai->codec->active--;
+	cpu_dai->component->active--;
+	codec_dai->component->active--;
 }
 
 /**

From 3d59400fe47e7e8bfb024cd1651433bef42e268e Mon Sep 17 00:00:00 2001
From: Lars-Peter Clausen <lars@metafoo.de>
Date: Wed, 5 Mar 2014 13:17:48 +0100
Subject: [PATCH 7/7] ASoC: Move ignore_pmdown_time from CODEC to component

In preparation for componentization move the ignore_pmdown_time field from the
snd_soc_codec struct to the snd_soc_component struct. Set it to true for non
CODEC components for now.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
---
 include/sound/soc.h  |  3 ++-
 sound/soc/soc-core.c |  4 +++-
 sound/soc/soc-pcm.c  | 10 ++--------
 3 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 0495b4aaeb701..b14acd8228ab1 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -663,6 +663,8 @@ struct snd_soc_component {
 
 	unsigned int active;
 
+	unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
+
 	struct list_head list;
 
 	struct snd_soc_dai_driver *dai_drv;
@@ -715,7 +717,6 @@ struct snd_soc_codec {
 
 	/* dapm */
 	struct snd_soc_dapm_context dapm;
-	unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
 
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_codec_root;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 6401e97b2e685..18aecd2841a84 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -4127,6 +4127,8 @@ int snd_soc_register_component(struct device *dev,
 		return -ENOMEM;
 	}
 
+	cmpnt->ignore_pmdown_time = true;
+
 	return __snd_soc_register_component(dev, cmpnt, cmpnt_drv,
 					    dai_drv, num_dai, true);
 }
@@ -4325,7 +4327,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->component.ignore_pmdown_time = codec_drv->ignore_pmdown_time;
 	codec->dapm.bias_level = SND_SOC_BIAS_OFF;
 	codec->dapm.dev = dev;
 	codec->dapm.codec = codec;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 98b46295785de..2cedf09f6d961 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -107,17 +107,11 @@ void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream)
  */
 bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd)
 {
-	bool ignore = true;
-
 	if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time)
 		return true;
 
-	if (rtd->cpu_dai->codec)
-		ignore &= rtd->cpu_dai->codec->ignore_pmdown_time;
-
-	ignore &= rtd->codec_dai->codec->ignore_pmdown_time;
-
-	return ignore;
+	return rtd->cpu_dai->component->ignore_pmdown_time &&
+			rtd->codec_dai->component->ignore_pmdown_time;
 }
 
 /**