Skip to content

Commit

Permalink
ASoC: wm_adsp: Factor out ADSP2 boot proceedure
Browse files Browse the repository at this point in the history
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>
Signed-off-by: Mark Brown <broonie@linaro.org>
  • Loading branch information
Charles Keepax authored and Mark Brown committed Jan 8, 2014
1 parent 5095f55 commit d8a64d6
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 78 deletions.
181 changes: 103 additions & 78 deletions sound/soc/codecs/wm_adsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1492,107 +1492,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:
Expand Down Expand Up @@ -1663,6 +1687,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");
Expand Down
2 changes: 2 additions & 0 deletions sound/soc/codecs/wm_adsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down

0 comments on commit d8a64d6

Please sign in to comment.