Commit 186152df authored by Simon Trimmer's avatar Simon Trimmer Committed by Mark Brown

ASoC: wm_adsp: Split DSP power operations into helper functions

This is preparation for moving the generic DSP support out of
ASoC. This change separates the generic handling of power and state
transitions from the DAPM API wrapper.
Signed-off-by: default avatarSimon Trimmer <simont@opensource.cirrus.com>
Signed-off-by: default avatarCharles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20210913160057.103842-9-simont@opensource.cirrus.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 25ca837b
......@@ -2808,23 +2808,13 @@ int wm_adsp1_init(struct wm_adsp *dsp)
}
EXPORT_SYMBOL_GPL(wm_adsp1_init);
int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
static int cs_dsp_adsp1_power_up(struct wm_adsp *dsp)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
struct wm_adsp *dsp = &dsps[w->shift];
struct wm_coeff_ctl *ctl;
int ret;
unsigned int val;
dsp->component = component;
int ret;
mutex_lock(&dsp->pwr_lock);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
ADSP1_SYS_ENA, ADSP1_SYS_ENA);
......@@ -2880,9 +2870,25 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
ADSP1_CORE_ENA | ADSP1_START);
dsp->running = true;
break;
case SND_SOC_DAPM_PRE_PMD:
mutex_unlock(&dsp->pwr_lock);
return 0;
err_ena:
regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
ADSP1_SYS_ENA, 0);
err_mutex:
mutex_unlock(&dsp->pwr_lock);
return ret;
}
static void cs_dsp_adsp1_power_down(struct wm_adsp *dsp)
{
struct wm_coeff_ctl *ctl;
mutex_lock(&dsp->pwr_lock);
dsp->running = false;
dsp->booted = false;
......@@ -2899,23 +2905,32 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
list_for_each_entry(ctl, &dsp->ctl_list, list)
ctl->enabled = 0;
cs_dsp_free_alg_regions(dsp);
break;
default:
break;
}
mutex_unlock(&dsp->pwr_lock);
}
return 0;
int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
struct wm_adsp *dsp = &dsps[w->shift];
int ret = 0;
err_ena:
regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
ADSP1_SYS_ENA, 0);
err_mutex:
mutex_unlock(&dsp->pwr_lock);
dsp->component = component;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
ret = cs_dsp_adsp1_power_up(dsp);
break;
case SND_SOC_DAPM_PRE_PMD:
cs_dsp_adsp1_power_down(dsp);
break;
default:
break;
}
return ret;
}
......@@ -3019,63 +3034,6 @@ static void cs_dsp_adsp2v2_disable_core(struct wm_adsp *dsp)
regmap_write(dsp->regmap, dsp->base + ADSP2V2_WDMA_CONFIG_2, 0);
}
static void wm_adsp_boot_work(struct work_struct *work)
{
struct wm_adsp *dsp = container_of(work,
struct wm_adsp,
boot_work);
int ret;
mutex_lock(&dsp->pwr_lock);
if (dsp->ops->enable_memory) {
ret = dsp->ops->enable_memory(dsp);
if (ret != 0)
goto err_mutex;
}
if (dsp->ops->enable_core) {
ret = dsp->ops->enable_core(dsp);
if (ret != 0)
goto err_mem;
}
ret = cs_dsp_load(dsp);
if (ret != 0)
goto err_ena;
ret = dsp->ops->setup_algs(dsp);
if (ret != 0)
goto err_ena;
ret = cs_dsp_load_coeff(dsp);
if (ret != 0)
goto err_ena;
/* Initialize caches for enabled and unset controls */
ret = cs_dsp_coeff_init_control_caches(dsp);
if (ret != 0)
goto err_ena;
if (dsp->ops->disable_core)
dsp->ops->disable_core(dsp);
dsp->booted = true;
mutex_unlock(&dsp->pwr_lock);
return;
err_ena:
if (dsp->ops->disable_core)
dsp->ops->disable_core(dsp);
err_mem:
if (dsp->ops->disable_memory)
dsp->ops->disable_memory(dsp);
err_mutex:
mutex_unlock(&dsp->pwr_lock);
}
static int cs_dsp_halo_configure_mpu(struct wm_adsp *dsp, unsigned int lock_regions)
{
struct reg_sequence config[] = {
......@@ -3185,19 +3143,64 @@ static void cs_dsp_halo_stop_watchdog(struct wm_adsp *dsp)
HALO_WDT_EN_MASK, 0);
}
int wm_adsp_early_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
static void cs_dsp_power_up(struct wm_adsp *dsp)
{
int ret;
mutex_lock(&dsp->pwr_lock);
if (dsp->ops->enable_memory) {
ret = dsp->ops->enable_memory(dsp);
if (ret != 0)
goto err_mutex;
}
if (dsp->ops->enable_core) {
ret = dsp->ops->enable_core(dsp);
if (ret != 0)
goto err_mem;
}
ret = cs_dsp_load(dsp);
if (ret != 0)
goto err_ena;
ret = dsp->ops->setup_algs(dsp);
if (ret != 0)
goto err_ena;
ret = cs_dsp_load_coeff(dsp);
if (ret != 0)
goto err_ena;
/* Initialize caches for enabled and unset controls */
ret = cs_dsp_coeff_init_control_caches(dsp);
if (ret != 0)
goto err_ena;
if (dsp->ops->disable_core)
dsp->ops->disable_core(dsp);
dsp->booted = true;
mutex_unlock(&dsp->pwr_lock);
return;
err_ena:
if (dsp->ops->disable_core)
dsp->ops->disable_core(dsp);
err_mem:
if (dsp->ops->disable_memory)
dsp->ops->disable_memory(dsp);
err_mutex:
mutex_unlock(&dsp->pwr_lock);
}
static void cs_dsp_power_down(struct wm_adsp *dsp)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
struct wm_adsp *dsp = &dsps[w->shift];
struct wm_coeff_ctl *ctl;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
queue_work(system_unbound_wq, &dsp->boot_work);
break;
case SND_SOC_DAPM_PRE_PMD:
mutex_lock(&dsp->pwr_lock);
cs_dsp_debugfs_clear(dsp);
......@@ -3218,6 +3221,30 @@ int wm_adsp_early_event(struct snd_soc_dapm_widget *w,
mutex_unlock(&dsp->pwr_lock);
cs_dsp_dbg(dsp, "Shutdown complete\n");
}
static void wm_adsp_boot_work(struct work_struct *work)
{
struct wm_adsp *dsp = container_of(work,
struct wm_adsp,
boot_work);
cs_dsp_power_up(dsp);
}
int wm_adsp_early_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
struct wm_adsp *dsp = &dsps[w->shift];
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
queue_work(system_unbound_wq, &dsp->boot_work);
break;
case SND_SOC_DAPM_PRE_PMD:
cs_dsp_power_down(dsp);
break;
default:
break;
......@@ -3240,17 +3267,25 @@ static void cs_dsp_adsp2_stop_core(struct wm_adsp *dsp)
ADSP2_CORE_ENA | ADSP2_START, 0);
}
int wm_adsp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
static int wm_adsp_event_post_run(struct wm_adsp *dsp)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
struct wm_adsp *dsp = &dsps[w->shift];
int ret;
if (wm_adsp_fw[dsp->fw].num_caps != 0)
return wm_adsp_buffer_init(dsp);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
flush_work(&dsp->boot_work);
return 0;
}
static void wm_adsp_event_post_stop(struct wm_adsp *dsp)
{
if (wm_adsp_fw[dsp->fw].num_caps != 0)
wm_adsp_buffer_free(dsp);
dsp->fatal_error = false;
}
static int cs_dsp_run(struct wm_adsp *dsp)
{
int ret;
mutex_lock(&dsp->pwr_lock);
......@@ -3286,16 +3321,26 @@ int wm_adsp_event(struct snd_soc_dapm_widget *w,
dsp->running = true;
if (wm_adsp_fw[dsp->fw].num_caps != 0) {
ret = wm_adsp_buffer_init(dsp);
ret = wm_adsp_event_post_run(dsp);
if (ret < 0)
goto err;
}
mutex_unlock(&dsp->pwr_lock);
break;
case SND_SOC_DAPM_PRE_PMD:
return 0;
err:
if (dsp->ops->stop_core)
dsp->ops->stop_core(dsp);
if (dsp->ops->disable_core)
dsp->ops->disable_core(dsp);
mutex_unlock(&dsp->pwr_lock);
return ret;
}
static void cs_dsp_stop(struct wm_adsp *dsp)
{
/* Tell the firmware to cleanup */
cs_dsp_signal_event_controls(dsp, CS_DSP_FW_EVENT_SHUTDOWN);
......@@ -3315,27 +3360,33 @@ int wm_adsp_event(struct snd_soc_dapm_widget *w,
if (dsp->ops->disable_core)
dsp->ops->disable_core(dsp);
if (wm_adsp_fw[dsp->fw].num_caps != 0)
wm_adsp_buffer_free(dsp);
dsp->fatal_error = false;
wm_adsp_event_post_stop(dsp);
mutex_unlock(&dsp->pwr_lock);
cs_dsp_dbg(dsp, "Execution stopped\n");
break;
}
int wm_adsp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
struct wm_adsp *dsp = &dsps[w->shift];
int ret = 0;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
flush_work(&dsp->boot_work);
ret = cs_dsp_run(dsp);
break;
case SND_SOC_DAPM_PRE_PMD:
cs_dsp_stop(dsp);
break;
default:
break;
}
return 0;
err:
if (dsp->ops->stop_core)
dsp->ops->stop_core(dsp);
if (dsp->ops->disable_core)
dsp->ops->disable_core(dsp);
mutex_unlock(&dsp->pwr_lock);
return ret;
}
EXPORT_SYMBOL_GPL(wm_adsp_event);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment