diff options
author | Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | 2017-01-06 17:24:41 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-01-06 21:09:01 +0300 |
commit | af813a6fd8740537bfa5801768e90cc95d9262a3 (patch) | |
tree | e083666c3b09a46e2dbec460b9c686fc57ec1dd4 /sound/soc/codecs/wm_adsp.c | |
parent | a5de5b74a50113564a1e0850e2da96c37c35e55d (diff) | |
download | linux-af813a6fd8740537bfa5801768e90cc95d9262a3.tar.xz |
ASoC: wm_adsp: Add mechanism to preload firmware on a core
As requirements to bring up audio paths are continuous getting tighter
and the DSP download to most ADSP devices happens over an external bus
it can become an important factor in the path bring up time. As such
sometimes it is a reasonable trade off to download the firmware ahead of
when it will be required and take a small hit on power consumption for
keeping the core powered up.
This "preloading" adds an additional control for each DSP core "DSPx
Preload Switch" that when set to true will power up the DSP core and
download the firmware currently selected in the "DSPx Firmware" control.
Whilst the core is preloaded the current firmware can not be changed and
the CODEC will be kept powered up and SYSCLK held on. Although future
improvements may allow the SYSCLK to be powered down as well because
the hardware only requires SYSCLK whilst the download is actually taking
place, but this is not covered in this series.
Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/wm_adsp.c')
-rw-r--r-- | sound/soc/codecs/wm_adsp.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 593b7d1aed46..ed615ce8a496 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2500,6 +2500,43 @@ static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq) adsp_err(dsp, "Failed to set clock rate: %d\n", ret); } +int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = dsp->preloaded; + + return 0; +} +EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get); + +int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + char preload[32]; + + snprintf(preload, ARRAY_SIZE(preload), "DSP%d Preload", mc->shift); + + dsp->preloaded = ucontrol->value.integer.value[0]; + + if (ucontrol->value.integer.value[0]) + snd_soc_dapm_force_enable_pin(dapm, preload); + else + snd_soc_dapm_disable_pin(dapm, preload); + + snd_soc_dapm_sync(dapm); + + return 0; +} +EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); + int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event, unsigned int freq) @@ -2631,10 +2668,16 @@ EXPORT_SYMBOL_GPL(wm_adsp2_event); int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec) { - dsp->codec = codec; + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + char preload[32]; + + snprintf(preload, ARRAY_SIZE(preload), "DSP%d Preload", dsp->num); + snd_soc_dapm_disable_pin(dapm, preload); wm_adsp2_init_debugfs(dsp, codec); + dsp->codec = codec; + return snd_soc_add_codec_controls(codec, &wm_adsp_fw_controls[dsp->num - 1], 1); |