Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8a64d6a authored by Charles Keepax's avatar Charles Keepax Committed by Mark Brown
Browse files

ASoC: wm_adsp: Factor out ADSP2 boot proceedure



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: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 5095f55d
Loading
Loading
Loading
Loading
+103 −78
Original line number Diff line number Diff line
@@ -1492,30 +1492,22 @@ 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;

	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;
		adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
		return;
	}
	val = (val & ARIZONA_SYSCLK_FREQ_MASK)
		>> ARIZONA_SYSCLK_FREQ_SHIFT;
@@ -1524,18 +1516,16 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
				       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;
		adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
		return;
	}

	if (dsp->dvfs) {
		ret = regmap_read(dsp->regmap,
				  dsp->base + ADSP2_CLOCKING, &val);
		if (ret != 0) {
				dev_err(dsp->dev,
					"Failed to read clocking: %d\n", ret);
				return ret;
			dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
			return;
		}

		if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
@@ -1544,7 +1534,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
				dev_err(dsp->dev,
					"Failed to enable supply: %d\n",
					ret);
					return ret;
				return;
			}

			ret = regulator_set_voltage(dsp->dvfs,
@@ -1554,14 +1544,14 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
				dev_err(dsp->dev,
					"Failed to raise supply: %d\n",
					ret);
					return ret;
				return;
			}
		}
	}

	ret = wm_adsp2_ena(dsp);
	if (ret != 0)
			return ret;
		return;

	ret = wm_adsp_load(dsp);
	if (ret != 0)
@@ -1587,12 +1577,46 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,

	ret = regmap_update_bits_async(dsp->regmap,
				       dsp->base + ADSP2_CONTROL,
					       ADSP2_CORE_ENA | ADSP2_START,
					       ADSP2_CORE_ENA | ADSP2_START);
				       ADSP2_CORE_ENA,
				       ADSP2_CORE_ENA);
	if (ret != 0)
		goto err;

	dsp->running = true;

	return;

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;
		break;

	case SND_SOC_DAPM_PRE_PMD:
@@ -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");
+2 −0
Original line number Diff line number Diff line
@@ -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) \