* [PATCH 1/2 v2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure
@ 2014-01-08 17:42 Charles Keepax
2014-01-08 17:42 ` [PATCH 2/2 v2] ASoC: wm_adsp: Start DSP booting earlier in the DAPM process Charles Keepax
2014-01-08 18:27 ` [PATCH 1/2 v2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Mark Brown
0 siblings, 2 replies; 3+ messages in thread
From: Charles Keepax @ 2014-01-08 17:42 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 reset of the audio path bring up.
Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
---
sound/soc/codecs/wm_adsp.c | 181 +++++++++++++++++++++++++-------------------
sound/soc/codecs/wm_adsp.h | 2 +
2 files changed, 105 insertions(+), 78 deletions(-)
Changes since v1:
- Schedule to the system unbound work queue since it is
likely to be a fairly long task.
- Move final start signal to the DSP to be an out_drv
widget such that the download is overlapped with the
output enables.
Thanks,
Charles
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index fb0c678..41bbac9 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1497,107 +1497,131 @@ 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;
- ret = regmap_update_bits_async(dsp->regmap,
- dsp->base + ADSP2_CONTROL,
- ADSP2_CORE_ENA | ADSP2_START,
- ADSP2_CORE_ENA | ADSP2_START);
+err:
+ regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+ ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
+}
+
+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_POST_PMU:
+ queue_work(system_unbound_wq, &dsp->boot_work);
+ flush_work(&dsp->boot_work);
+
+ 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 +1692,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..b172c1d 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) \
--
1.7.2.5
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2 v2] ASoC: wm_adsp: Start DSP booting earlier in the DAPM process
2014-01-08 17:42 [PATCH 1/2 v2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Charles Keepax
@ 2014-01-08 17:42 ` Charles Keepax
2014-01-08 18:27 ` [PATCH 1/2 v2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Mark Brown
1 sibling, 0 replies; 3+ messages in thread
From: Charles Keepax @ 2014-01-08 17:42 UTC (permalink / raw)
To: broonie; +Cc: alsa-devel, patches, lgirdwood
Move the start of booting the DSP to earlier in the DAPM process, and
move the final starting of the DSP to later 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 | 10 ++++++++--
3 files changed, 38 insertions(+), 13 deletions(-)
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 10b3984..16df0f9 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 41bbac9..41669ad 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:
+ queue_work(system_unbound_wq, &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_POST_PMU:
- queue_work(system_unbound_wq, &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 b172c1d..a4f6b64 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -68,8 +68,12 @@ struct wm_adsp {
wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)
#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)
+{ .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 }, \
+{ .id = snd_soc_dapm_out_drv, .name = wname, \
+ .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
+ .event_flags = 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[];
@@ -78,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: [PATCH 1/2 v2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure
2014-01-08 17:42 [PATCH 1/2 v2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Charles Keepax
2014-01-08 17:42 ` [PATCH 2/2 v2] ASoC: wm_adsp: Start DSP booting earlier in the DAPM process Charles Keepax
@ 2014-01-08 18:27 ` Mark Brown
1 sibling, 0 replies; 3+ messages in thread
From: Mark Brown @ 2014-01-08 18:27 UTC (permalink / raw)
To: Charles Keepax; +Cc: alsa-devel, patches, lgirdwood
[-- Attachment #1.1: Type: text/plain, Size: 443 bytes --]
On Wed, Jan 08, 2014 at 05:42:18PM +0000, Charles Keepax wrote:
> Move the ADSP2 boot proceedure into a work structure in preparation for
> running it asynchronously with the reset of the audio path bring up.
Applied both, thanks. Might be worth considering pushing the RAM enable
into the context of the initiating thread so that the time taken to poll
is eaten up in the scheduling delay, or at least you end up with bigger
chains of I/O.
[-- 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:[~2014-01-08 18:28 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-08 17:42 [PATCH 1/2 v2] ASoC: wm_adsp: Factor out ADSP2 boot proceedure Charles Keepax
2014-01-08 17:42 ` [PATCH 2/2 v2] ASoC: wm_adsp: Start DSP booting earlier in the DAPM process Charles Keepax
2014-01-08 18:27 ` [PATCH 1/2 v2] 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