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

Commit 3c43c695 authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: arizona: Use async writes



Where possible write to the device asynchronously, allowing better
performance when used with a bus like SPI which supports this by
minimising the need to context switch back to the driver to get the
next bit of data.

Signed-off-by: default avatarMark Brown <broonie@linaro.org>
Tested-by: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Reviewed-by: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
parent d733dc08
Loading
Loading
Loading
Loading
+89 −74
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		if (!priv->spk_ena && manual_ena) {
			snd_soc_write(codec, 0x4f5, 0x25a);
			regmap_write_async(arizona->regmap, 0x4f5, 0x25a);
			priv->spk_ena_pending = true;
		}
		break;
@@ -105,12 +105,13 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
			return -EBUSY;
		}

		snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
		regmap_update_bits_async(arizona->regmap,
					 ARIZONA_OUTPUT_ENABLES_1,
					 1 << w->shift, 1 << w->shift);

		if (priv->spk_ena_pending) {
			msleep(75);
			snd_soc_write(codec, 0x4f5, 0xda);
			regmap_write_async(arizona->regmap, 0x4f5, 0xda);
			priv->spk_ena_pending = false;
			priv->spk_ena++;
		}
@@ -119,16 +120,19 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w,
		if (manual_ena) {
			priv->spk_ena--;
			if (!priv->spk_ena)
				snd_soc_write(codec, 0x4f5, 0x25a);
				regmap_write_async(arizona->regmap,
						   0x4f5, 0x25a);
		}

		snd_soc_update_bits(codec, ARIZONA_OUTPUT_ENABLES_1,
		regmap_update_bits_async(arizona->regmap,
					 ARIZONA_OUTPUT_ENABLES_1,
					 1 << w->shift, 0);
		break;
	case SND_SOC_DAPM_POST_PMD:
		if (manual_ena) {
			if (!priv->spk_ena)
				snd_soc_write(codec, 0x4f5, 0x0da);
				regmap_write_async(arizona->regmap,
						   0x4f5, 0x0da);
		}
		break;
	}
@@ -687,6 +691,7 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
		   int event)
{
	struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec);
	struct arizona *arizona = priv->arizona;
	unsigned int mask = 1 << w->shift;
	unsigned int val;

@@ -709,7 +714,8 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
	if (priv->arizona->hpdet_magic)
		val = 0;

	snd_soc_update_bits(w->codec, ARIZONA_OUTPUT_ENABLES_1, mask, val);
	regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1,
				 mask, val);

	return arizona_out_ev(w, kcontrol, event);
}
@@ -864,6 +870,8 @@ EXPORT_SYMBOL_GPL(arizona_set_sysclk);
static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
	struct snd_soc_codec *codec = dai->codec;
	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
	struct arizona *arizona = priv->arizona;
	int lrclk, bclk, mode, base;

	base = dai->driver->base;
@@ -920,16 +928,18 @@ static int arizona_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
		return -EINVAL;
	}

	snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
			    ARIZONA_AIF1_BCLK_INV | ARIZONA_AIF1_BCLK_MSTR,
	regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_BCLK_CTRL,
				 ARIZONA_AIF1_BCLK_INV |
				 ARIZONA_AIF1_BCLK_MSTR,
				 bclk);
	snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_PIN_CTRL,
	regmap_update_bits_async(arizona->regmap, base + ARIZONA_AIF_TX_PIN_CTRL,
				 ARIZONA_AIF1TX_LRCLK_INV |
				 ARIZONA_AIF1TX_LRCLK_MSTR, lrclk);
	snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_PIN_CTRL,
	regmap_update_bits_async(arizona->regmap,
				 base + ARIZONA_AIF_RX_PIN_CTRL,
				 ARIZONA_AIF1RX_LRCLK_INV |
				 ARIZONA_AIF1RX_LRCLK_MSTR, lrclk);
	snd_soc_update_bits(codec, base + ARIZONA_AIF_FORMAT,
	regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FORMAT,
			   ARIZONA_AIF1_FMT_MASK, mode);

	return 0;
@@ -1182,16 +1192,20 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
	if (ret != 0)
		return ret;

	snd_soc_update_bits(codec, base + ARIZONA_AIF_BCLK_CTRL,
	regmap_update_bits_async(arizona->regmap,
				 base + ARIZONA_AIF_BCLK_CTRL,
				 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
	snd_soc_update_bits(codec, base + ARIZONA_AIF_TX_BCLK_RATE,
	regmap_update_bits_async(arizona->regmap,
				 base + ARIZONA_AIF_TX_BCLK_RATE,
				 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
	snd_soc_update_bits(codec, base + ARIZONA_AIF_RX_BCLK_RATE,
	regmap_update_bits_async(arizona->regmap,
				 base + ARIZONA_AIF_RX_BCLK_RATE,
				 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
	snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_1,
	regmap_update_bits_async(arizona->regmap,
				 base + ARIZONA_AIF_FRAME_CTRL_1,
				 ARIZONA_AIF1TX_WL_MASK |
				 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
	snd_soc_update_bits(codec, base + ARIZONA_AIF_FRAME_CTRL_2,
	regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2,
			   ARIZONA_AIF1RX_WL_MASK |
			   ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);

@@ -1446,29 +1460,29 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
			      struct arizona_fll_cfg *cfg, int source,
			      bool sync)
{
	regmap_update_bits(arizona->regmap, base + 3,
	regmap_update_bits_async(arizona->regmap, base + 3,
				 ARIZONA_FLL1_THETA_MASK, cfg->theta);
	regmap_update_bits(arizona->regmap, base + 4,
	regmap_update_bits_async(arizona->regmap, base + 4,
				 ARIZONA_FLL1_LAMBDA_MASK, cfg->lambda);
	regmap_update_bits(arizona->regmap, base + 5,
	regmap_update_bits_async(arizona->regmap, base + 5,
				 ARIZONA_FLL1_FRATIO_MASK,
				 cfg->fratio << ARIZONA_FLL1_FRATIO_SHIFT);
	regmap_update_bits(arizona->regmap, base + 6,
	regmap_update_bits_async(arizona->regmap, base + 6,
				 ARIZONA_FLL1_CLK_REF_DIV_MASK |
				 ARIZONA_FLL1_CLK_REF_SRC_MASK,
				 cfg->refdiv << ARIZONA_FLL1_CLK_REF_DIV_SHIFT |
				 source << ARIZONA_FLL1_CLK_REF_SRC_SHIFT);

	if (sync)
		regmap_update_bits(arizona->regmap, base + 0x7,
		regmap_update_bits_async(arizona->regmap, base + 0x7,
					 ARIZONA_FLL1_GAIN_MASK,
					 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);
	else
		regmap_update_bits(arizona->regmap, base + 0x9,
		regmap_update_bits_async(arizona->regmap, base + 0x9,
					 ARIZONA_FLL1_GAIN_MASK,
					 cfg->gain << ARIZONA_FLL1_GAIN_SHIFT);

	regmap_update_bits(arizona->regmap, base + 2,
	regmap_update_bits_async(arizona->regmap, base + 2,
				 ARIZONA_FLL1_CTRL_UPD | ARIZONA_FLL1_N_MASK,
				 ARIZONA_FLL1_CTRL_UPD | cfg->n);
}
@@ -1503,7 +1517,7 @@ static void arizona_enable_fll(struct arizona_fll *fll,
	 */
	if (fll->ref_src >= 0 && fll->ref_freq &&
	    fll->ref_src != fll->sync_src) {
		regmap_update_bits(arizona->regmap, fll->base + 5,
		regmap_update_bits_async(arizona->regmap, fll->base + 5,
					 ARIZONA_FLL1_OUTDIV_MASK,
					 ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);

@@ -1515,14 +1529,14 @@ static void arizona_enable_fll(struct arizona_fll *fll,
			use_sync = true;
		}
	} else if (fll->sync_src >= 0) {
		regmap_update_bits(arizona->regmap, fll->base + 5,
		regmap_update_bits_async(arizona->regmap, fll->base + 5,
					 ARIZONA_FLL1_OUTDIV_MASK,
					 sync->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);

		arizona_apply_fll(arizona, fll->base, sync,
				  fll->sync_src, false);

		regmap_update_bits(arizona->regmap, fll->base + 0x11,
		regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
					 ARIZONA_FLL1_SYNC_ENA, 0);
	} else {
		arizona_fll_err(fll, "No clocks provided\n");
@@ -1534,11 +1548,12 @@ static void arizona_enable_fll(struct arizona_fll *fll,
	 * sync source.
	 */
	if (use_sync && fll->sync_freq > 100000)
		regmap_update_bits(arizona->regmap, fll->base + 0x17,
		regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
					 ARIZONA_FLL1_SYNC_BW, 0);
	else
		regmap_update_bits(arizona->regmap, fll->base + 0x17,
				   ARIZONA_FLL1_SYNC_BW, ARIZONA_FLL1_SYNC_BW);
		regmap_update_bits_async(arizona->regmap, fll->base + 0x17,
					 ARIZONA_FLL1_SYNC_BW,
					 ARIZONA_FLL1_SYNC_BW);

	if (!arizona_is_enabled_fll(fll))
		pm_runtime_get(arizona->dev);
@@ -1546,12 +1561,12 @@ static void arizona_enable_fll(struct arizona_fll *fll,
	/* Clear any pending completions */
	try_wait_for_completion(&fll->ok);

	regmap_update_bits(arizona->regmap, fll->base + 1,
	regmap_update_bits_async(arizona->regmap, fll->base + 1,
				 ARIZONA_FLL1_FREERUN, 0);
	regmap_update_bits(arizona->regmap, fll->base + 1,
	regmap_update_bits_async(arizona->regmap, fll->base + 1,
				 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
	if (use_sync)
		regmap_update_bits(arizona->regmap, fll->base + 0x11,
		regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
					 ARIZONA_FLL1_SYNC_ENA,
					 ARIZONA_FLL1_SYNC_ENA);

@@ -1566,7 +1581,7 @@ static void arizona_disable_fll(struct arizona_fll *fll)
	struct arizona *arizona = fll->arizona;
	bool change;

	regmap_update_bits(arizona->regmap, fll->base + 1,
	regmap_update_bits_async(arizona->regmap, fll->base + 1,
				 ARIZONA_FLL1_FREERUN, ARIZONA_FLL1_FREERUN);
	regmap_update_bits_check(arizona->regmap, fll->base + 1,
				 ARIZONA_FLL1_ENA, 0, &change);