Allow ADSPs to be preloaded with firmware
Subsystems (5)
cover Allow ADSPs to be preloaded with firmware
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 patch chain adds such functionality to the wm_adsp driver, broadly speaking there are three parts to the chain. Firstly we setup the existing preloader widgets such that they will be easier to power up independently. Secondly, we setup the ALSA controls such that they will gracefully handle the DSP being in a low power state between loading the firmware and starting the core. Finally, we actually add the preloading features itself.
Thanks,
Charles
Charles Keepax (7):
ASoC: arizona: Attach SYSCLK to DSP preloaders
ASoC: wm_adsp: Make DSP preloader a supply widget
ASoC: wm_adsp: Separate concept of booted and running
ASoC: wm_adsp: Move control cache sync out of preloader
ASoC: wm_adsp: Put DSP into low power state between loading and
running
ASoC: wm_adsp: Allow preloader to do the final shutdown of the DSP
ASoC: wm_adsp: Add mechanism to preload firmware on a core
sound/soc/codecs/arizona.h | 18 ++++--- sound/soc/codecs/cs47l24.c | 5 +- sound/soc/codecs/wm5102.c | 3 +- sound/soc/codecs/wm5110.c | 7 ++- sound/soc/codecs/wm_adsp.c | 126 ++++++++++++++++++++++++++++++++++++--------- sound/soc/codecs/wm_adsp.h | 18 ++++++- 6 files changed, 138 insertions(+), 39 deletions(-)
Signature · 1 line
2.1.4
PATCH 1/7 ASoC: arizona: Attach SYSCLK to DSP preloaders
Currently SYSCLK is attached to every compressed DAI as this follows the pattern of attaching clocks to the chips inputs and outputs, however, it is really the DSP that requires the clock here. As firmware download can be a significant part of the path startup time for these devices occasionally it would be desirable to download the firmware in advance of the path being brought up.
To help facilitate this early firmware loading this patch attaches the SYSCLK to the DSP preloader widget. This also saves us adding a new route to SYSCLK every time a new compressed DAI is created.
--- sound/soc/codecs/arizona.h | 1 + sound/soc/codecs/cs47l24.c | 2 -- sound/soc/codecs/wm5102.c | 1 - sound/soc/codecs/wm5110.c | 2 -- 4 files changed, 1 insertion(+), 5 deletions(-)
sound/soc/codecs/arizona.h +1 -0
@@ -190,6 +190,7 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];#define ARIZONA_DSP_ROUTES (name) \ { name, NULL, name " Preloader"}, \ + { name " Preloader", NULL, "SYSCLK" }, \ { name " Preloader", NULL, name " Aux 1" }, \ { name " Preloader", NULL, name " Aux 2" }, \ { name " Preloader", NULL, name " Aux 3" }, \
sound/soc/codecs/cs47l24.c +0 -2
@@ -816,7 +816,6 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "AIF3 Capture", NULL, "SYSCLK" }, { "Voice Control DSP", NULL, "DSP3" }, - { "Voice Control DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" },
@@ -825,7 +824,6 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "IN2R PGA", NULL, "IN2R" }, { "Audio Trace DSP", NULL, "DSP2" }, - { "Audio Trace DSP", NULL, "SYSCLK" },ARIZONA_MIXER_ROUTES ("OUT1L" ,"HPOUT1L" ), ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
sound/soc/codecs/wm5102.c +0 -1
@@ -1615,7 +1615,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "Slim3 Capture", NULL, "SYSCLK" }, { "Audio Trace DSP", NULL, "DSP1" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" },
sound/soc/codecs/wm5110.c +0 -2
@@ -1846,10 +1846,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "Slim3 Capture", NULL, "SYSCLK" }, { "Voice Control DSP", NULL, "DSP3" }, - { "Voice Control DSP", NULL, "SYSCLK" }, { "Audio Trace DSP", NULL, "DSP1" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" },
Signature · 1 line
2.1.4
Mark Brown
maintainerApplied "ASoC: arizona: Attach SYSCLK to DSP preloaders" to the asoc tree
The patch
ASoC: arizona: Attach SYSCLK to DSP preloaders
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
Quoted 1 line
From
3577357a1680543b8acb98d69d23e87c1175db2bMon Sep 17 00:00:00 2001
From: Charles Keepax <[email protected]>
Date: Tue, 20 Sep 2016 13:52:30 +0100
Subject: [PATCH] ASoC: arizona: Attach SYSCLK to DSP preloaders
Currently SYSCLK is attached to every compressed DAI as this follows the pattern of attaching clocks to the chips inputs and outputs, however, it is really the DSP that requires the clock here. As firmware download can be a significant part of the path startup time for these devices occasionally it would be desirable to download the firmware in advance of the path being brought up.
To help facilitate this early firmware loading this patch attaches the SYSCLK to the DSP preloader widget. This also saves us adding a new route to SYSCLK every time a new compressed DAI is created.
--- sound/soc/codecs/arizona.h | 1 + sound/soc/codecs/cs47l24.c | 2 -- sound/soc/codecs/wm5102.c | 1 - sound/soc/codecs/wm5110.c | 2 -- 4 files changed, 1 insertion(+), 5 deletions(-)
sound/soc/codecs/arizona.h +1 -0
@@ -190,6 +190,7 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];#define ARIZONA_DSP_ROUTES (name) \ { name, NULL, name " Preloader"}, \ + { name " Preloader", NULL, "SYSCLK" }, \ { name " Preloader", NULL, name " Aux 1" }, \ { name " Preloader", NULL, name " Aux 2" }, \ { name " Preloader", NULL, name " Aux 3" }, \
sound/soc/codecs/cs47l24.c +0 -2
@@ -814,7 +814,6 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "AIF3 Capture", NULL, "SYSCLK" }, { "Voice Control DSP", NULL, "DSP3" }, - { "Voice Control DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" },
@@ -823,7 +822,6 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "IN2R PGA", NULL, "IN2R" }, { "Audio Trace DSP", NULL, "DSP2" }, - { "Audio Trace DSP", NULL, "SYSCLK" },ARIZONA_MIXER_ROUTES ("OUT1L" ,"HPOUT1L" ), ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),
sound/soc/codecs/wm5102.c +0 -1
@@ -1610,7 +1610,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "Slim3 Capture", NULL, "SYSCLK" }, { "Audio Trace DSP", NULL, "DSP1" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" },
sound/soc/codecs/wm5110.c +0 -2
@@ -1842,10 +1842,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "Slim3 Capture", NULL, "SYSCLK" }, { "Voice Control DSP", NULL, "DSP3" }, - { "Voice Control DSP", NULL, "SYSCLK" }, { "Audio Trace DSP", NULL, "DSP1" }, - { "Audio Trace DSP", NULL, "SYSCLK" }, { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" },
Signature · 1 line
2.9.3
PATCH 2/7 ASoC: wm_adsp: Make DSP preloader a supply widget
In reply to Charles KeepaxCurrently the DSP loading is split into two widgets, the preloader that is a snd_soc_dapm_dai_link widget which starts a thread to download the firmware, and the DSP itself which is a snd_soc_dapm_out_drv and synchronises the thread back in to the DAPM sequence. This allows the firmware download to be overlapped with the rest of the path bring up.
The use of a snd_soc_dapm_dai_link widget requires the preloader to be part of the audio path in DAPM, really a supply widget is a better fit for the preloader. The preloader is something that needs to be done for the DSP to function, not a part of the audio path itself.
This change makes the DSP preloader widget a supply widget, which as well as probably being a better fit will also make it much simpler to power up the preloader widget to trigger firmware download to the core independently of the audio path coming up.
--- sound/soc/codecs/arizona.h | 16 ++++++++-------- sound/soc/codecs/wm_adsp.h | 5 +++-- 2 files changed, 11 insertions(+), 10 deletions(-)
sound/soc/codecs/arizona.h +8 -8
@@ -191,20 +191,20 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];#define ARIZONA_DSP_ROUTES (name) \ { name, NULL, name " Preloader"}, \ { name " Preloader", NULL, "SYSCLK" }, \ - { 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" }, \ + { 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" }, \ 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 " Preloader", name "L"), \ - ARIZONA_MIXER_ROUTES(name " Preloader", name "R") + ARIZONA_MIXER_ROUTES(name, name "L"), \ + ARIZONA_MIXER_ROUTES(name, name "R")#define ARIZONA_EQ_CONTROL (xname, xbase) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
sound/soc/codecs/wm_adsp.h +3 -2
@@ -85,9 +85,10 @@ struct wm_adsp { wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) #define WM_ADSP2(wname, num, event_fn) \ -{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ +{ .id = snd_soc_dapm_supply, .name = wname " Preloader", \ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ - .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \ + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ + .subseq = 100, /* Ensure we run after SYSCLK supply widget */ }, \ { .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 }
Signature · 1 line
2.1.4
Mark Brown
maintainerApplied "ASoC: wm_adsp: Make DSP preloader a supply widget" to the asoc tree
The patch
ASoC: wm_adsp: Make DSP preloader a supply widget
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
Quoted 1 line
From
5ca7e170e331781fe71acb4919667993bb9fbab6Mon Sep 17 00:00:00 2001
From: Charles Keepax <[email protected]>
Date: Tue, 20 Sep 2016 13:52:31 +0100
Subject: [PATCH] ASoC: wm_adsp: Make DSP preloader a supply widget
Currently the DSP loading is split into two widgets, the preloader that is a snd_soc_dapm_dai_link widget which starts a thread to download the firmware, and the DSP itself which is a snd_soc_dapm_out_drv and synchronises the thread back in to the DAPM sequence. This allows the firmware download to be overlapped with the rest of the path bring up.
The use of a snd_soc_dapm_dai_link widget requires the preloader to be part of the audio path in DAPM, really a supply widget is a better fit for the preloader. The preloader is something that needs to be done for the DSP to function, not a part of the audio path itself.
This change makes the DSP preloader widget a supply widget, which as well as probably being a better fit will also make it much simpler to power up the preloader widget to trigger firmware download to the core independently of the audio path coming up.
--- sound/soc/codecs/arizona.h | 16 ++++++++-------- sound/soc/codecs/wm_adsp.h | 5 +++-- 2 files changed, 11 insertions(+), 10 deletions(-)
sound/soc/codecs/arizona.h +8 -8
@@ -191,20 +191,20 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];#define ARIZONA_DSP_ROUTES (name) \ { name, NULL, name " Preloader"}, \ { name " Preloader", NULL, "SYSCLK" }, \ - { 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" }, \ + { 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" }, \ 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 " Preloader", name "L"), \ - ARIZONA_MIXER_ROUTES(name " Preloader", name "R") + ARIZONA_MIXER_ROUTES(name, name "L"), \ + ARIZONA_MIXER_ROUTES(name, name "R")#define ARIZONA_EQ_CONTROL (xname, xbase) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
sound/soc/codecs/wm_adsp.h +3 -2
@@ -87,9 +87,10 @@ struct wm_adsp { wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) #define WM_ADSP2(wname, num, event_fn) \ -{ .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ +{ .id = snd_soc_dapm_supply, .name = wname " Preloader", \ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ - .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \ + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ + .subseq = 100, /* Ensure we run after SYSCLK supply widget */ }, \ { .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 }
Signature · 1 line
2.9.3
PATCH 3/7 ASoC: wm_adsp: Separate concept of booted and running
In reply to Charles KeepaxCurrently the wm_adsp driver has a flag that indicates the DSP is "running", this flag is used to gate access to the hardware. However this flag is actually set in the firmware download thread after the firmware has been downloaded, but this is before the core is actually started running, so really it currently indicates that the core has been booted and is perhaps running.
This patch clearly separates out the concepts of booted (firmware is downloaded) and running (code is executing on the DSP) within the wm_adsp driver.
--- sound/soc/codecs/wm_adsp.c | 36 +++++++++++++++++++++++++----------- sound/soc/codecs/wm_adsp.h | 2 ++ 2 files changed, 27 insertions(+), 11 deletions(-)
sound/soc/codecs/wm_adsp.c +25 -11
@@ -480,7 +480,7 @@ static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,mutex_lock (&dsp->pwr_lock); -if (!dsp->wmfw_file_name || !dsp->running) +if (!dsp->wmfw_file_name || !dsp->booted) ret =0 ;else ret = simple_read_from_buffer(user_buf, count, ppos,
@@ -500,7 +500,7 @@ static ssize_t wm_adsp_debugfs_bin_read(struct file *file,mutex_lock (&dsp->pwr_lock); -if (!dsp->bin_file_name || !dsp->running) +if (!dsp->bin_file_name || !dsp->booted) ret =0 ;else ret = simple_read_from_buffer(user_buf, count, ppos,
@@ -554,6 +554,9 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,if (!root) goto err; +if (!debugfs_create_bool ("booted" ,S_IRUGO , root, &dsp->booted)) + goto err; +if (!debugfs_create_bool ("running" ,S_IRUGO , root, &dsp->running)) goto err;
@@ -637,7 +640,7 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,mutex_lock (&dsp[e->shift_l].pwr_lock); -if (dsp[e->shift_l].running || dsp[e->shift_l].compr) +if (dsp[e->shift_l].booted || dsp[e->shift_l].compr) ret = -EBUSY ;else dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0 ];
@@ -789,7 +792,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl,memcpy (ctl->cache, p, ctl->len); ctl->set =1 ; -if (ctl->enabled) +if (ctl->enabled && ctl->dsp->booted) ret =wm_coeff_write_control (ctl, p, ctl->len);mutex_unlock (&ctl->dsp->pwr_lock);
@@ -811,7 +814,7 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, ret = -EFAULT ; }else { ctl->set =1 ; -if (ctl->enabled) +if (ctl->enabled && ctl->dsp->booted) ret =wm_coeff_write_control (ctl, ctl->cache, size); }
@@ -871,12 +874,12 @@ static int wm_coeff_get(struct snd_kcontrol *kctl,mutex_lock (&ctl->dsp->pwr_lock);if (ctl->flags &WMFW_CTL_FLAG_VOLATILE ) { -if (ctl->enabled) +if (ctl->enabled && ctl->dsp->booted) ret =wm_coeff_read_control (ctl, p, ctl->len);else ret = -EPERM ; }else { -if (!ctl->flags && ctl->enabled) +if (!ctl->flags && ctl->enabled && ctl->dsp->booted) ret =wm_coeff_read_control (ctl, ctl->cache, ctl->len);memcpy (p, ctl->cache, ctl->len);
@@ -898,12 +901,12 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,mutex_lock (&ctl->dsp->pwr_lock);if (ctl->flags &WMFW_CTL_FLAG_VOLATILE ) { -if (ctl->enabled) +if (ctl->enabled && ctl->dsp->booted) ret =wm_coeff_read_control (ctl, ctl->cache, size);else ret = -EPERM ; }else { -if (!ctl->flags && ctl->enabled) +if (!ctl->flags && ctl->enabled && ctl->dsp->booted) ret =wm_coeff_read_control (ctl, ctl->cache, size); }
@@ -2166,13 +2169,20 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,if (ret !=0 ) goto err_ena; + dsp->booted = true; +/* Start the core running */ regmap_update_bits (dsp->regmap, dsp->base +ADSP1_CONTROL_30 ,ADSP1_CORE_ENA |ADSP1_START ,ADSP1_CORE_ENA |ADSP1_START ); + + dsp->running = true;break ;case SND_SOC_DAPM_PRE_PMD : + dsp->running = false; + dsp->booted = false; +/* Halt the core */ regmap_update_bits (dsp->regmap, dsp->base +ADSP1_CONTROL_30 ,ADSP1_CORE_ENA |ADSP1_START ,0 );
@@ -2275,7 +2285,7 @@ static void wm_adsp2_boot_work(struct work_struct *work)if (ret !=0 ) goto err_ena; - dsp->running = true; + dsp->booted = true;mutex_unlock (&dsp->pwr_lock);
@@ -2336,7 +2346,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,case SND_SOC_DAPM_POST_PMU :flush_work (&dsp->boot_work); -if (!dsp->running) +if (!dsp->booted)return -EIO ; ret = regmap_update_bits(dsp->regmap,
@@ -2346,6 +2356,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,if (ret !=0 ) goto err; + dsp->running = true; +mutex_lock (&dsp->pwr_lock);if (wm_adsp_fw[dsp->fw].num_caps !=0 )
@@ -2365,7 +2377,9 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, dsp->fw_id =0 ; dsp->fw_id_version =0 ; + dsp->running = false; + dsp->booted = false;regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL ,ADSP2_CORE_ENA |ADSP2_START ,0 );
sound/soc/codecs/wm_adsp.h +2 -0
@@ -61,6 +61,8 @@ struct wm_adsp {int fw;int fw_ver; + +bool booted;bool running;struct list_head ctl_list;
Signature · 1 line
2.1.4
Mark Brown
maintainerApplied "ASoC: wm_adsp: Separate concept of booted and running" to the asoc tree
The patch
ASoC: wm_adsp: Separate concept of booted and running
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
Quoted 1 line
From
28823ebad5e73bd717ca820929de2d18415d9822Mon Sep 17 00:00:00 2001
From: Charles Keepax <[email protected]>
Date: Tue, 20 Sep 2016 13:52:32 +0100
Subject: [PATCH] ASoC: wm_adsp: Separate concept of booted and running
Currently the wm_adsp driver has a flag that indicates the DSP is "running", this flag is used to gate access to the hardware. However this flag is actually set in the firmware download thread after the firmware has been downloaded, but this is before the core is actually started running, so really it currently indicates that the core has been booted and is perhaps running.
This patch clearly separates out the concepts of booted (firmware is downloaded) and running (code is executing on the DSP) within the wm_adsp driver.
--- sound/soc/codecs/wm_adsp.c | 36 +++++++++++++++++++++++++----------- sound/soc/codecs/wm_adsp.h | 2 ++ 2 files changed, 27 insertions(+), 11 deletions(-)
sound/soc/codecs/wm_adsp.c +25 -11
@@ -480,7 +480,7 @@ static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,mutex_lock (&dsp->pwr_lock); -if (!dsp->wmfw_file_name || !dsp->running) +if (!dsp->wmfw_file_name || !dsp->booted) ret =0 ;else ret = simple_read_from_buffer(user_buf, count, ppos,
@@ -500,7 +500,7 @@ static ssize_t wm_adsp_debugfs_bin_read(struct file *file,mutex_lock (&dsp->pwr_lock); -if (!dsp->bin_file_name || !dsp->running) +if (!dsp->bin_file_name || !dsp->booted) ret =0 ;else ret = simple_read_from_buffer(user_buf, count, ppos,
@@ -554,6 +554,9 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,if (!root) goto err; +if (!debugfs_create_bool ("booted" ,S_IRUGO , root, &dsp->booted)) + goto err; +if (!debugfs_create_bool ("running" ,S_IRUGO , root, &dsp->running)) goto err;
@@ -637,7 +640,7 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,mutex_lock (&dsp[e->shift_l].pwr_lock); -if (dsp[e->shift_l].running || dsp[e->shift_l].compr) +if (dsp[e->shift_l].booted || dsp[e->shift_l].compr) ret = -EBUSY ;else dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0 ];
@@ -789,7 +792,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl,memcpy (ctl->cache, p, ctl->len); ctl->set =1 ; -if (ctl->enabled) +if (ctl->enabled && ctl->dsp->booted) ret =wm_coeff_write_control (ctl, p, ctl->len);mutex_unlock (&ctl->dsp->pwr_lock);
@@ -811,7 +814,7 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, ret = -EFAULT ; }else { ctl->set =1 ; -if (ctl->enabled) +if (ctl->enabled && ctl->dsp->booted) ret =wm_coeff_write_control (ctl, ctl->cache, size); }
@@ -871,12 +874,12 @@ static int wm_coeff_get(struct snd_kcontrol *kctl,mutex_lock (&ctl->dsp->pwr_lock);if (ctl->flags &WMFW_CTL_FLAG_VOLATILE ) { -if (ctl->enabled) +if (ctl->enabled && ctl->dsp->booted) ret =wm_coeff_read_control (ctl, p, ctl->len);else ret = -EPERM ; }else { -if (!ctl->flags && ctl->enabled) +if (!ctl->flags && ctl->enabled && ctl->dsp->booted) ret =wm_coeff_read_control (ctl, ctl->cache, ctl->len);memcpy (p, ctl->cache, ctl->len);
@@ -898,12 +901,12 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,mutex_lock (&ctl->dsp->pwr_lock);if (ctl->flags &WMFW_CTL_FLAG_VOLATILE ) { -if (ctl->enabled) +if (ctl->enabled && ctl->dsp->booted) ret =wm_coeff_read_control (ctl, ctl->cache, size);else ret = -EPERM ; }else { -if (!ctl->flags && ctl->enabled) +if (!ctl->flags && ctl->enabled && ctl->dsp->booted) ret =wm_coeff_read_control (ctl, ctl->cache, size); }
@@ -2166,13 +2169,20 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,if (ret !=0 ) goto err_ena; + dsp->booted = true; +/* Start the core running */ regmap_update_bits (dsp->regmap, dsp->base +ADSP1_CONTROL_30 ,ADSP1_CORE_ENA |ADSP1_START ,ADSP1_CORE_ENA |ADSP1_START ); + + dsp->running = true;break ;case SND_SOC_DAPM_PRE_PMD : + dsp->running = false; + dsp->booted = false; +/* Halt the core */ regmap_update_bits (dsp->regmap, dsp->base +ADSP1_CONTROL_30 ,ADSP1_CORE_ENA |ADSP1_START ,0 );
@@ -2275,7 +2285,7 @@ static void wm_adsp2_boot_work(struct work_struct *work)if (ret !=0 ) goto err_ena; - dsp->running = true; + dsp->booted = true;mutex_unlock (&dsp->pwr_lock);
@@ -2336,7 +2346,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,case SND_SOC_DAPM_POST_PMU :flush_work (&dsp->boot_work); -if (!dsp->running) +if (!dsp->booted)return -EIO ; ret = regmap_update_bits(dsp->regmap,
@@ -2346,6 +2356,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,if (ret !=0 ) goto err; + dsp->running = true; +mutex_lock (&dsp->pwr_lock);if (wm_adsp_fw[dsp->fw].num_caps !=0 )
@@ -2365,7 +2377,9 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, dsp->fw_id =0 ; dsp->fw_id_version =0 ; + dsp->running = false; + dsp->booted = false;regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL ,ADSP2_CORE_ENA |ADSP2_START ,0 );
sound/soc/codecs/wm_adsp.h +2 -0
@@ -61,6 +61,8 @@ struct wm_adsp {int fw;int fw_ver; + +bool booted;bool running;struct list_head ctl_list;
Signature · 1 line
2.9.3
PATCH 4/7 ASoC: wm_adsp: Move control cache sync out of preloader
In reply to Charles KeepaxAs part of the work to download firmware before the audio path is brought up the DSP will be put into a low power state between downloading firmware to the core and starting it running. This will mean that the firmware ALSA controls are not accessible in the hardware during this period of time.
To prepare for this change we gate access to the hardware in the ALSA control handlers on the DSP being running rather than simply booted and move the synchronisation of the control caches out of the preloader delayed work and into the main DAPM thread after the DSP will have been brought out of its low power state.
--- sound/soc/codecs/wm_adsp.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
sound/soc/codecs/wm_adsp.c +11 -11
@@ -792,7 +792,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl,memcpy (ctl->cache, p, ctl->len); ctl->set =1 ; -if (ctl->enabled && ctl->dsp->booted) +if (ctl->enabled && ctl->dsp->running) ret =wm_coeff_write_control (ctl, p, ctl->len);mutex_unlock (&ctl->dsp->pwr_lock);
@@ -814,7 +814,7 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, ret = -EFAULT ; }else { ctl->set =1 ; -if (ctl->enabled && ctl->dsp->booted) +if (ctl->enabled && ctl->dsp->running) ret =wm_coeff_write_control (ctl, ctl->cache, size); }
@@ -874,12 +874,12 @@ static int wm_coeff_get(struct snd_kcontrol *kctl,mutex_lock (&ctl->dsp->pwr_lock);if (ctl->flags &WMFW_CTL_FLAG_VOLATILE ) { -if (ctl->enabled && ctl->dsp->booted) +if (ctl->enabled && ctl->dsp->running) ret =wm_coeff_read_control (ctl, p, ctl->len);else ret = -EPERM ; }else { -if (!ctl->flags && ctl->enabled && ctl->dsp->booted) +if (!ctl->flags && ctl->enabled && ctl->dsp->running) ret =wm_coeff_read_control (ctl, ctl->cache, ctl->len);memcpy (p, ctl->cache, ctl->len);
@@ -901,12 +901,12 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,mutex_lock (&ctl->dsp->pwr_lock);if (ctl->flags &WMFW_CTL_FLAG_VOLATILE ) { -if (ctl->enabled && ctl->dsp->booted) +if (ctl->enabled && ctl->dsp->running) ret =wm_coeff_read_control (ctl, ctl->cache, size);else ret = -EPERM ; }else { -if (!ctl->flags && ctl->enabled && ctl->dsp->booted) +if (!ctl->flags && ctl->enabled && ctl->dsp->running) ret =wm_coeff_read_control (ctl, ctl->cache, size); }
@@ -2280,11 +2280,6 @@ static void wm_adsp2_boot_work(struct work_struct *work)if (ret !=0 ) goto err_ena; -/* Sync set controls */ - ret =wm_coeff_sync_controls (dsp); -if (ret !=0 ) - goto err_ena; - dsp->booted = true;mutex_unlock (&dsp->pwr_lock);
@@ -2349,6 +2344,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,if (!dsp->booted)return -EIO ; +/* Sync set controls */ + ret =wm_coeff_sync_controls (dsp); +if (ret !=0 ) + goto err; + ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, ADSP2_CORE_ENA | ADSP2_START,
Signature · 1 line
2.1.4
Mark Brown
maintainerApplied "ASoC: wm_adsp: Move control cache sync out of preloader" to the asoc tree
The patch
ASoC: wm_adsp: Move control cache sync out of preloader
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
Quoted 1 line
From
cef45771c141fdccebe4cb7e0ce79f4687275494Mon Sep 17 00:00:00 2001
From: Charles Keepax <[email protected]>
Date: Tue, 20 Sep 2016 13:52:33 +0100
Subject: [PATCH] ASoC: wm_adsp: Move control cache sync out of preloader
As part of the work to download firmware before the audio path is brought up the DSP will be put into a low power state between downloading firmware to the core and starting it running. This will mean that the firmware ALSA controls are not accessible in the hardware during this period of time.
To prepare for this change we gate access to the hardware in the ALSA control handlers on the DSP being running rather than simply booted and move the synchronisation of the control caches out of the preloader delayed work and into the main DAPM thread after the DSP will have been brought out of its low power state.
--- sound/soc/codecs/wm_adsp.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
sound/soc/codecs/wm_adsp.c +11 -11
@@ -792,7 +792,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl,memcpy (ctl->cache, p, ctl->len); ctl->set =1 ; -if (ctl->enabled && ctl->dsp->booted) +if (ctl->enabled && ctl->dsp->running) ret =wm_coeff_write_control (ctl, p, ctl->len);mutex_unlock (&ctl->dsp->pwr_lock);
@@ -814,7 +814,7 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, ret = -EFAULT ; }else { ctl->set =1 ; -if (ctl->enabled && ctl->dsp->booted) +if (ctl->enabled && ctl->dsp->running) ret =wm_coeff_write_control (ctl, ctl->cache, size); }
@@ -874,12 +874,12 @@ static int wm_coeff_get(struct snd_kcontrol *kctl,mutex_lock (&ctl->dsp->pwr_lock);if (ctl->flags &WMFW_CTL_FLAG_VOLATILE ) { -if (ctl->enabled && ctl->dsp->booted) +if (ctl->enabled && ctl->dsp->running) ret =wm_coeff_read_control (ctl, p, ctl->len);else ret = -EPERM ; }else { -if (!ctl->flags && ctl->enabled && ctl->dsp->booted) +if (!ctl->flags && ctl->enabled && ctl->dsp->running) ret =wm_coeff_read_control (ctl, ctl->cache, ctl->len);memcpy (p, ctl->cache, ctl->len);
@@ -901,12 +901,12 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,mutex_lock (&ctl->dsp->pwr_lock);if (ctl->flags &WMFW_CTL_FLAG_VOLATILE ) { -if (ctl->enabled && ctl->dsp->booted) +if (ctl->enabled && ctl->dsp->running) ret =wm_coeff_read_control (ctl, ctl->cache, size);else ret = -EPERM ; }else { -if (!ctl->flags && ctl->enabled && ctl->dsp->booted) +if (!ctl->flags && ctl->enabled && ctl->dsp->running) ret =wm_coeff_read_control (ctl, ctl->cache, size); }
@@ -2280,11 +2280,6 @@ static void wm_adsp2_boot_work(struct work_struct *work)if (ret !=0 ) goto err_ena; -/* Sync set controls */ - ret =wm_coeff_sync_controls (dsp); -if (ret !=0 ) - goto err_ena; - dsp->booted = true;mutex_unlock (&dsp->pwr_lock);
@@ -2349,6 +2344,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,if (!dsp->booted)return -EIO ; +/* Sync set controls */ + ret =wm_coeff_sync_controls (dsp); +if (ret !=0 ) + goto err; + ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, ADSP2_CORE_ENA | ADSP2_START,
Signature · 1 line
2.9.3
PATCH 5/7 ASoC: wm_adsp: Put DSP into low power state between loading and running
In reply to Charles KeepaxBetween when we load the DSP and when it actually starts running put the core into a lower power state where the memory is retained but nothing is clocked.
--- sound/soc/codecs/wm_adsp.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
sound/soc/codecs/wm_adsp.c +18 -1
@@ -2223,6 +2223,11 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)unsigned int val;int ret, count; + ret =regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL , +ADSP2_MEM_ENA ,ADSP2_MEM_ENA ); +if (ret !=0 ) +return ret; + ret =regmap_update_bits_async (dsp->regmap, dsp->base +ADSP2_CONTROL ,ADSP2_SYS_ENA ,ADSP2_SYS_ENA );if (ret !=0 )
@@ -2282,6 +2287,12 @@ static void wm_adsp2_boot_work(struct work_struct *work) dsp->booted = true; +/* Turn DSP back off until we are ready to run */ + ret =regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL , +ADSP2_SYS_ENA ,0 ); +if (ret !=0 ) + goto err_ena; +mutex_unlock (&dsp->pwr_lock);return ;
@@ -2344,6 +2355,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,if (!dsp->booted)return -EIO ; + ret =regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL , +ADSP2_SYS_ENA ,ADSP2_SYS_ENA ); +if (ret !=0 ) + goto err; +/* Sync set controls */ ret =wm_coeff_sync_controls (dsp);if (ret !=0 )
@@ -2382,7 +2398,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, dsp->booted = false;regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL , -ADSP2_CORE_ENA |ADSP2_START ,0 ); +ADSP2_MEM_ENA |ADSP2_CORE_ENA |ADSP2_START , +0 );/* Make sure DMAs are quiesced */ regmap_write (dsp->regmap, dsp->base +ADSP2_RDMA_CONFIG_1 ,0 );
Signature · 1 line
2.1.4
Re: [PATCH 5/7] ASoC: wm_adsp: Put DSP into low power state between loading and running
Quoted 7 lines · Charles Keepax
Between when we load the DSP and when it actually starts running put the core into a lower power state where the memory is retained but nothing is clocked.
Signed-off-by Charles Keepax <[email protected]>---
sound/soc/codecs/wm_adsp.c int wm_adsp2_event(struct snd_soc_dapm_widget *w, · line 2362
Quoted 8 lines
sound/soc/codecs/wm_adsp.c +5
-0@@ -2344,6 +2355,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,if (!dsp->booted)return -EIO ; + ret =regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL , +ADSP2_SYS_ENA ,ADSP2_SYS_ENA ); +if (ret !=0 ) + goto err; +
We actually need to wait for RAM_RDY again here, I will fire out a new version of the patches in the next day or two.
Thanks,
Charles
PATCH 6/7 ASoC: wm_adsp: Allow preloader to do the final shutdown of the DSP
In reply to Charles KeepaxThe booting process for the DSP is clearly separated into two parts, the preloader brings up the core and downloads code, then the main widget starts the code actually executing. However the shutdown sequence is all handled with the main widget.
To allow the preloading to be run independently of the main audio bring up it makes sense, and is generally just cleaner, for the preloader widget to shutdown those things it initialised. This patch moves the appropriate parts of the shutdown process into the preloader widget.
--- sound/soc/codecs/wm_adsp.c | 32 ++++++++++++++++++-------------- sound/soc/codecs/wm_adsp.h | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-)
sound/soc/codecs/wm_adsp.c +18 -14
@@ -2323,6 +2323,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,struct snd_soc_codec *codec =snd_soc_dapm_to_codec (w->dapm);struct wm_adsp *dsps =snd_soc_codec_get_drvdata (codec);struct wm_adsp *dsp = &dsps[w->shift]; +struct wm_coeff_ctl *ctl; dsp->card = codec->component.card;
@@ -2331,6 +2332,22 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,wm_adsp2_set_dspclk (dsp, freq);queue_work (system_unbound_wq, &dsp->boot_work);break ; +case SND_SOC_DAPM_PRE_PMD : +wm_adsp_debugfs_clear (dsp); + + dsp->fw_id =0 ; + dsp->fw_id_version =0 ; + + dsp->booted = false; + +regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL , +ADSP2_MEM_ENA ,0 ); + +list_for_each_entry (ctl, &dsp->ctl_list, list) + ctl->enabled =0 ; + +wm_adsp_free_alg_regions (dsp); +break ;default :break ; }
@@ -2345,7 +2362,6 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,struct snd_soc_codec *codec =snd_soc_dapm_to_codec (w->dapm);struct wm_adsp *dsps =snd_soc_codec_get_drvdata (codec);struct wm_adsp *dsp = &dsps[w->shift]; -struct wm_coeff_ctl *ctl;int ret;switch (event) {
@@ -2389,17 +2405,10 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,mutex_lock (&dsp->pwr_lock); -wm_adsp_debugfs_clear (dsp); - - dsp->fw_id =0 ; - dsp->fw_id_version =0 ; - dsp->running = false; - dsp->booted = false;regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL , -ADSP2_MEM_ENA |ADSP2_CORE_ENA |ADSP2_START , -0 ); +ADSP2_CORE_ENA |ADSP2_START ,0 );/* Make sure DMAs are quiesced */ regmap_write (dsp->regmap, dsp->base +ADSP2_RDMA_CONFIG_1 ,0 );
@@ -2409,11 +2418,6 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,regmap_update_bits (dsp->regmap, dsp->base +ADSP2_CONTROL ,ADSP2_SYS_ENA ,0 ); -list_for_each_entry (ctl, &dsp->ctl_list, list) - ctl->enabled =0 ; - -wm_adsp_free_alg_regions (dsp); -if (wm_adsp_fw[dsp->fw].num_caps !=0 )wm_adsp_buffer_free (dsp);
sound/soc/codecs/wm_adsp.h +1 -1
@@ -89,7 +89,7 @@ struct wm_adsp { #define WM_ADSP2(wname, num, event_fn) \ { .id = snd_soc_dapm_supply, .name = wname " Preloader", \ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ - .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ + .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD, \ .subseq = 100, /* Ensure we run after SYSCLK supply widget */ }, \ { .id = snd_soc_dapm_out_drv, .name = wname, \ .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \
Signature · 1 line
2.1.4
PATCH 7/7 ASoC: wm_adsp: Add mechanism to preload firmware on a core
In reply to Charles KeepaxAs 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.
--- sound/soc/codecs/arizona.h | 1 + sound/soc/codecs/cs47l24.c | 3 +++ sound/soc/codecs/wm5102.c | 2 ++ sound/soc/codecs/wm5110.c | 5 +++++ sound/soc/codecs/wm_adsp.c | 43 +++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/wm_adsp.h | 11 +++++++++++ 6 files changed, 65 insertions(+)
sound/soc/codecs/arizona.h +1 -0
@@ -191,6 +191,7 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];#define ARIZONA_DSP_ROUTES (name) \ { name, NULL, name " Preloader"}, \ { name " Preloader", NULL, "SYSCLK" }, \ + { name " Preload", NULL, name " Preloader"}, \ { name, NULL, name " Aux 1" }, \ { name, NULL, name " Aux 2" }, \ { name, NULL, name " Aux 3" }, \
sound/soc/codecs/cs47l24.c +3 -0
@@ -173,6 +173,9 @@ SOC_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]),SOC_ENUM ("ISRC3 FSH" , arizona_isrc_fsh[2 ]),SOC_ENUM ("ASRC RATE 1" , arizona_asrc_rate1), +WM_ADSP2_PRELOAD_SWITCH ("DSP2" ,2 ), +WM_ADSP2_PRELOAD_SWITCH ("DSP3" ,3 ), +ARIZONA_MIXER_CONTROLS ("DSP2L" ,ARIZONA_DSP2LMIX_INPUT_1_SOURCE ),ARIZONA_MIXER_CONTROLS ("DSP2R" ,ARIZONA_DSP2RMIX_INPUT_1_SOURCE ), ARIZONA_MIXER_CONTROLS("DSP3L", ARIZONA_DSP3LMIX_INPUT_1_SOURCE),
sound/soc/codecs/wm5102.c +2 -0
@@ -855,6 +855,8 @@ ARIZONA_LHPF_CONTROL("LHPF2 Coefficients", ARIZONA_HPLPF2_2),ARIZONA_LHPF_CONTROL ("LHPF3 Coefficients" ,ARIZONA_HPLPF3_2 ),ARIZONA_LHPF_CONTROL ("LHPF4 Coefficients" ,ARIZONA_HPLPF4_2 ), +WM_ADSP2_PRELOAD_SWITCH ("DSP1" ,1 ), +ARIZONA_MIXER_CONTROLS ("DSP1L" ,ARIZONA_DSP1LMIX_INPUT_1_SOURCE ), ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
sound/soc/codecs/wm5110.c +5 -0
@@ -778,6 +778,11 @@ SOC_ENUM("ISRC2 FSH", arizona_isrc_fsh[1]),SOC_ENUM ("ISRC3 FSH" , arizona_isrc_fsh[2 ]),SOC_ENUM ("ASRC RATE 1" , arizona_asrc_rate1), +WM_ADSP2_PRELOAD_SWITCH ("DSP1" ,1 ), +WM_ADSP2_PRELOAD_SWITCH ("DSP2" ,2 ), +WM_ADSP2_PRELOAD_SWITCH ("DSP3" ,3 ), +WM_ADSP2_PRELOAD_SWITCH ("DSP4" ,4 ), +ARIZONA_MIXER_CONTROLS ("DSP1L" ,ARIZONA_DSP1LMIX_INPUT_1_SOURCE ),ARIZONA_MIXER_CONTROLS ("DSP1R" ,ARIZONA_DSP1RMIX_INPUT_1_SOURCE ), ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE),
sound/soc/codecs/wm_adsp.c +43 -0
55 lines not on this page · raw message
sound/soc/codecs/wm_adsp.h +11 -0
@@ -62,6 +62,7 @@ struct wm_adsp {int fw;int fw_ver; +bool preloaded;bool booted;bool running;
@@ -86,7 +87,12 @@ struct wm_adsp {SND_SOC_DAPM_PGA_E (wname,SND_SOC_NOPM , num,0 ,NULL ,0 , \ wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) +#define WM_ADSP2_PRELOAD_SWITCH (wname, num) \ + SOC_SINGLE_EXT(wname " Preload Switch", SND_SOC_NOPM, num, 1, 0, \ + wm_adsp2_preloader_get, wm_adsp2_preloader_put) +#define WM_ADSP2 (wname, num, event_fn) \ + SND_SOC_DAPM_SPK(wname " Preload", NULL), \ { .id = snd_soc_dapm_supply, .name = wname " Preloader", \ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD, \
@@ -110,6 +116,11 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,int wm_adsp2_event (struct snd_soc_dapm_widget *w,struct snd_kcontrol *kcontrol,int event); +int wm_adsp2_preloader_get (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol); +int wm_adsp2_preloader_put (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol); +extern int wm_adsp_compr_open (struct wm_adsp *dsp,struct snd_compr_stream *stream);extern int wm_adsp_compr_free (struct snd_compr_stream *stream);
Signature · 1 line
2.1.4