alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 1/2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure
@ 2013-12-19 15:48 Charles Keepax
  2013-12-19 15:48 ` [RFC PATCH 2/2] ASoC: wm_adsp: Start DSP booting earlier in the DAPM process Charles Keepax
  2013-12-19 20:21 ` [RFC PATCH 1/2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Mark Brown
  0 siblings, 2 replies; 3+ messages in thread
From: Charles Keepax @ 2013-12-19 15:48 UTC (permalink / raw)
  To: broonie; +Cc: alsa-devel, patches, lgirdwood

Move the ADSP2 boot proceedure into a work structure in preparation for
running it asynchronously with the rest of the audio path bring up.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
---
 sound/soc/codecs/wm_adsp.c |  186 +++++++++++++++++++++++++------------------
 sound/soc/codecs/wm_adsp.h |    5 +-
 2 files changed, 112 insertions(+), 79 deletions(-)

diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index fb0c678..4475790 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1497,107 +1497,136 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
 	return 0;
 }
 
-int wm_adsp2_event(struct snd_soc_dapm_widget *w,
-		   struct snd_kcontrol *kcontrol, int event)
+void wm_adsp2_boot_work(struct work_struct *work)
 {
-	struct snd_soc_codec *codec = w->codec;
-	struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
-	struct wm_adsp *dsp = &dsps[w->shift];
-	struct wm_adsp_alg_region *alg_region;
-	struct wm_coeff_ctl *ctl;
-	unsigned int val;
+	struct wm_adsp *dsp = container_of(work,
+					   struct wm_adsp,
+					   boot_work);
 	int ret;
+	unsigned int val;
 
-	dsp->card = codec->card;
+	/*
+	 * For simplicity set the DSP clock rate to be the
+	 * SYSCLK rate rather than making it configurable.
+	 */
+	ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
+	if (ret != 0) {
+		adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
+		return;
+	}
+	val = (val & ARIZONA_SYSCLK_FREQ_MASK)
+		>> ARIZONA_SYSCLK_FREQ_SHIFT;
 
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		/*
-		 * For simplicity set the DSP clock rate to be the
-		 * SYSCLK rate rather than making it configurable.
-		 */
-		ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
-		if (ret != 0) {
-			adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
-				 ret);
-			return ret;
-		}
-		val = (val & ARIZONA_SYSCLK_FREQ_MASK)
-			>> ARIZONA_SYSCLK_FREQ_SHIFT;
+	ret = regmap_update_bits_async(dsp->regmap,
+				       dsp->base + ADSP2_CLOCKING,
+				       ADSP2_CLK_SEL_MASK, val);
+	if (ret != 0) {
+		adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
+		return;
+	}
 
-		ret = regmap_update_bits_async(dsp->regmap,
-					       dsp->base + ADSP2_CLOCKING,
-					       ADSP2_CLK_SEL_MASK, val);
+	if (dsp->dvfs) {
+		ret = regmap_read(dsp->regmap,
+				  dsp->base + ADSP2_CLOCKING, &val);
 		if (ret != 0) {
-			adsp_err(dsp, "Failed to set clock rate: %d\n",
-				 ret);
-			return ret;
+			dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
+			return;
 		}
 
-		if (dsp->dvfs) {
-			ret = regmap_read(dsp->regmap,
-					  dsp->base + ADSP2_CLOCKING, &val);
+		if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
+			ret = regulator_enable(dsp->dvfs);
 			if (ret != 0) {
 				dev_err(dsp->dev,
-					"Failed to read clocking: %d\n", ret);
-				return ret;
+					"Failed to enable supply: %d\n",
+					ret);
+				return;
 			}
 
-			if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
-				ret = regulator_enable(dsp->dvfs);
-				if (ret != 0) {
-					dev_err(dsp->dev,
-						"Failed to enable supply: %d\n",
-						ret);
-					return ret;
-				}
-
-				ret = regulator_set_voltage(dsp->dvfs,
-							    1800000,
-							    1800000);
-				if (ret != 0) {
-					dev_err(dsp->dev,
-						"Failed to raise supply: %d\n",
-						ret);
-					return ret;
-				}
+			ret = regulator_set_voltage(dsp->dvfs,
+						    1800000,
+						    1800000);
+			if (ret != 0) {
+				dev_err(dsp->dev,
+					"Failed to raise supply: %d\n",
+					ret);
+				return;
 			}
 		}
+	}
 
-		ret = wm_adsp2_ena(dsp);
-		if (ret != 0)
-			return ret;
+	ret = wm_adsp2_ena(dsp);
+	if (ret != 0)
+		return;
 
-		ret = wm_adsp_load(dsp);
-		if (ret != 0)
-			goto err;
+	ret = wm_adsp_load(dsp);
+	if (ret != 0)
+		goto err;
 
-		ret = wm_adsp_setup_algs(dsp);
-		if (ret != 0)
-			goto err;
+	ret = wm_adsp_setup_algs(dsp);
+	if (ret != 0)
+		goto err;
 
-		ret = wm_adsp_load_coeff(dsp);
-		if (ret != 0)
-			goto err;
+	ret = wm_adsp_load_coeff(dsp);
+	if (ret != 0)
+		goto err;
 
-		/* Initialize caches for enabled and unset controls */
-		ret = wm_coeff_init_control_caches(dsp);
-		if (ret != 0)
-			goto err;
+	/* Initialize caches for enabled and unset controls */
+	ret = wm_coeff_init_control_caches(dsp);
+	if (ret != 0)
+		goto err;
 
-		/* Sync set controls */
-		ret = wm_coeff_sync_controls(dsp);
-		if (ret != 0)
-			goto err;
+	/* Sync set controls */
+	ret = wm_coeff_sync_controls(dsp);
+	if (ret != 0)
+		goto err;
+
+	ret = regmap_update_bits_async(dsp->regmap,
+				       dsp->base + ADSP2_CONTROL,
+				       ADSP2_CORE_ENA,
+				       ADSP2_CORE_ENA);
+	if (ret != 0)
+		goto err;
+
+	dsp->running = true;
+
+	return;
+
+err:
+	regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+			   ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+}
 
-		ret = regmap_update_bits_async(dsp->regmap,
-					       dsp->base + ADSP2_CONTROL,
-					       ADSP2_CORE_ENA | ADSP2_START,
-					       ADSP2_CORE_ENA | ADSP2_START);
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+		   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+	struct wm_adsp *dsp = &dsps[w->shift];
+	struct wm_adsp_alg_region *alg_region;
+	struct wm_coeff_ctl *ctl;
+	int ret;
+
+	dsp->card = codec->card;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		schedule_work(&dsp->boot_work);
+		flush_work(&dsp->boot_work);
+
+		if (!dsp->running)
+			return -EIO;
+		break;
+
+	case SND_SOC_DAPM_POST_PMU:
+		if (!dsp->running)
+			return -EIO;
+
+		ret = regmap_update_bits(dsp->regmap,
+					 dsp->base + ADSP2_CONTROL,
+					 ADSP2_START,
+					 ADSP2_START);
 		if (ret != 0)
 			goto err;
-
-		dsp->running = true;
 		break;
 
 	case SND_SOC_DAPM_PRE_PMD:
@@ -1668,6 +1697,7 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
 
 	INIT_LIST_HEAD(&adsp->alg_regions);
 	INIT_LIST_HEAD(&adsp->ctl_list);
+	INIT_WORK(&adsp->boot_work, wm_adsp2_boot_work);
 
 	if (dvfs) {
 		adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index d018dea..20b6b4b 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -59,6 +59,8 @@ struct wm_adsp {
 	struct regulator *dvfs;
 
 	struct list_head ctl_list;
+
+	struct work_struct boot_work;
 };
 
 #define WM_ADSP1(wname, num) \
@@ -67,7 +69,8 @@ struct wm_adsp {
 
 #define WM_ADSP2(wname, num) \
 	SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \
-		wm_adsp2_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
+		wm_adsp2_event, SND_SOC_DAPM_PRE_PMU | \
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
 
 extern const struct snd_kcontrol_new wm_adsp1_fw_controls[];
 extern const struct snd_kcontrol_new wm_adsp2_fw_controls[];
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [RFC PATCH 2/2] ASoC: wm_adsp: Start DSP booting earlier in the DAPM process
  2013-12-19 15:48 [RFC PATCH 1/2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Charles Keepax
@ 2013-12-19 15:48 ` Charles Keepax
  2013-12-19 20:21 ` [RFC PATCH 1/2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Mark Brown
  1 sibling, 0 replies; 3+ messages in thread
From: Charles Keepax @ 2013-12-19 15:48 UTC (permalink / raw)
  To: broonie; +Cc: alsa-devel, patches, lgirdwood

Move the start of booting the DSP to earlier in the DAPM process this
allows us to overlap some of the processing with other components of the
system being brought up.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
---
 sound/soc/codecs/arizona.h |   17 +++++++++--------
 sound/soc/codecs/wm_adsp.c |   24 +++++++++++++++++++++---
 sound/soc/codecs/wm_adsp.h |    5 +++++
 3 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 6641f3d..bd1b9d2 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -166,20 +166,21 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
 	ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
 
 #define ARIZONA_DSP_ROUTES(name) \
-	{ name, NULL, name " Aux 1" }, \
-	{ name, NULL, name " Aux 2" }, \
-	{ name, NULL, name " Aux 3" }, \
-	{ name, NULL, name " Aux 4" }, \
-	{ name, NULL, name " Aux 5" }, \
-	{ name, NULL, name " Aux 6" }, \
+	{ name, NULL, name " Preloader"}, \
+	{ name " Preloader", NULL, name " Aux 1" }, \
+	{ name " Preloader", NULL, name " Aux 2" }, \
+	{ name " Preloader", NULL, name " Aux 3" }, \
+	{ name " Preloader", NULL, name " Aux 4" }, \
+	{ name " Preloader", NULL, name " Aux 5" }, \
+	{ name " Preloader", NULL, name " Aux 6" }, \
 	ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \
 	ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \
 	ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \
 	ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \
 	ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \
 	ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \
-	ARIZONA_MIXER_ROUTES(name, name "L"), \
-	ARIZONA_MIXER_ROUTES(name, name "R")
+	ARIZONA_MIXER_ROUTES(name " Preloader", name "L"), \
+	ARIZONA_MIXER_ROUTES(name " Preloader", name "R")
 
 #define ARIZONA_RATE_ENUM_SIZE 4
 extern const char *arizona_rate_text[ARIZONA_RATE_ENUM_SIZE];
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 4475790..26de090 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1596,6 +1596,27 @@ err:
 			   ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
 }
 
+int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
+		   struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+	struct wm_adsp *dsp = &dsps[w->shift];
+
+	dsp->card = codec->card;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		schedule_work(&dsp->boot_work);
+		break;
+	default:
+		break;
+	};
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_early_event);
+
 int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 		   struct snd_kcontrol *kcontrol, int event)
 {
@@ -1606,11 +1627,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 	struct wm_coeff_ctl *ctl;
 	int ret;
 
-	dsp->card = codec->card;
-
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		schedule_work(&dsp->boot_work);
 		flush_work(&dsp->boot_work);
 
 		if (!dsp->running)
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index 20b6b4b..2b41694 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -68,6 +68,9 @@ struct wm_adsp {
 		wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
 
 #define WM_ADSP2(wname, num) \
+{	.id = snd_soc_dapm_dai_link, .name = wname " Preloader", \
+	.reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_early_event, \
+	.event_flags = SND_SOC_DAPM_PRE_PMU }, \
 	SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \
 		wm_adsp2_event, SND_SOC_DAPM_PRE_PMU | \
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
@@ -79,6 +82,8 @@ int wm_adsp1_init(struct wm_adsp *adsp);
 int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs);
 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
 		   struct snd_kcontrol *kcontrol, int event);
+int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol, int event);
 int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 		   struct snd_kcontrol *kcontrol, int event);
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [RFC PATCH 1/2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure
  2013-12-19 15:48 [RFC PATCH 1/2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Charles Keepax
  2013-12-19 15:48 ` [RFC PATCH 2/2] ASoC: wm_adsp: Start DSP booting earlier in the DAPM process Charles Keepax
@ 2013-12-19 20:21 ` Mark Brown
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Brown @ 2013-12-19 20:21 UTC (permalink / raw)
  To: Charles Keepax; +Cc: alsa-devel, patches, lgirdwood


[-- Attachment #1.1: Type: text/plain, Size: 717 bytes --]

On Thu, Dec 19, 2013 at 03:48:04PM +0000, Charles Keepax wrote:
> Move the ADSP2 boot proceedure into a work structure in preparation for
> running it asynchronously with the rest of the audio path bring up.

These look good at least for a first pass, though obviously the drivers
need updating and you need to pick times to run the events.  I had been
thinking about trying to do something to encourage things like firmware
download to happen during other delays or trying to arrange to initiate
things from the clock startup (this is one of the possible uses for the
_WILL_PMU event) but both are future work things.

You probably want to explicitly schedule these for WQ_UNBOUND though I
think that's the default.

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-12-19 20:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-19 15:48 [RFC PATCH 1/2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Charles Keepax
2013-12-19 15:48 ` [RFC PATCH 2/2] ASoC: wm_adsp: Start DSP booting earlier in the DAPM process Charles Keepax
2013-12-19 20:21 ` [RFC PATCH 1/2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).