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

Commit 480d060b authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'asoc/topic/da7218', 'asoc/topic/da7219' and...

Merge remote-tracking branches 'asoc/topic/da7218', 'asoc/topic/da7219' and 'asoc/topic/dpcm' into asoc-next
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ enum da7219_mic_amp_in_sel {
struct da7219_aad_pdata;

struct da7219_pdata {
	bool wakeup_source;

	/* Mic */
	enum da7219_micbias_voltage micbias_lvl;
	enum da7219_mic_amp_in_sel mic_amp_in_sel;
+15 −19
Original line number Diff line number Diff line
@@ -1819,7 +1819,7 @@ static int da7218_set_dai_sysclk(struct snd_soc_dai *codec_dai,
	if (da7218->mclk_rate == freq)
		return 0;

	if (((freq < 2000000) && (freq != 32768)) || (freq > 54000000)) {
	if ((freq < 2000000) || (freq > 54000000)) {
		dev_err(codec_dai->dev, "Unsupported MCLK value %d\n",
			freq);
		return -EINVAL;
@@ -1866,11 +1866,8 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
	u32 freq_ref;
	u64 frac_div;

	/* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */
	if (da7218->mclk_rate == 32768) {
		indiv_bits = DA7218_PLL_INDIV_9_TO_18_MHZ;
		indiv = DA7218_PLL_INDIV_9_TO_18_MHZ_VAL;
	} else if (da7218->mclk_rate < 2000000) {
	/* Verify 2MHz - 54MHz MCLK provided, and set input divider */
	if (da7218->mclk_rate < 2000000) {
		dev_err(codec->dev, "PLL input clock %d below valid range\n",
			da7218->mclk_rate);
		return -EINVAL;
@@ -1911,9 +1908,6 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
	case DA7218_SYSCLK_PLL_SRM:
		pll_ctrl |= DA7218_PLL_MODE_SRM;
		break;
	case DA7218_SYSCLK_PLL_32KHZ:
		pll_ctrl |= DA7218_PLL_MODE_32KHZ;
		break;
	default:
		dev_err(codec->dev, "Invalid PLL config\n");
		return -EINVAL;
@@ -2589,20 +2583,22 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec,

	switch (level) {
	case SND_SOC_BIAS_ON:
	case SND_SOC_BIAS_PREPARE:
		break;
	case SND_SOC_BIAS_STANDBY:
		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
			/* MCLK */
	case SND_SOC_BIAS_PREPARE:
		/* Enable MCLK for transition to ON state */
		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) {
			if (da7218->mclk) {
				ret = clk_prepare_enable(da7218->mclk);
				if (ret) {
					dev_err(codec->dev,
						"Failed to enable mclk\n");
					dev_err(codec->dev, "Failed to enable mclk\n");
					return ret;
				}
			}
		}

		break;
	case SND_SOC_BIAS_STANDBY:
		if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
			/* Master bias */
			snd_soc_update_bits(codec, DA7218_REFERENCES,
					    DA7218_BIAS_EN_MASK,
@@ -2612,6 +2608,10 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec,
			snd_soc_update_bits(codec, DA7218_LDO_CTRL,
					    DA7218_LDO_EN_MASK,
					    DA7218_LDO_EN_MASK);
		} else {
			/* Remove MCLK */
			if (da7218->mclk)
				clk_disable_unprepare(da7218->mclk);
		}
		break;
	case SND_SOC_BIAS_OFF:
@@ -2625,10 +2625,6 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec,
			snd_soc_update_bits(codec, DA7218_REFERENCES,
					    DA7218_BIAS_EN_MASK, 0);
		}

		/* MCLK */
		if (da7218->mclk)
			clk_disable_unprepare(da7218->mclk);
		break;
	}

+0 −2
Original line number Diff line number Diff line
@@ -888,7 +888,6 @@
#define DA7218_PLL_MODE_BYPASS		(0x0 << 6)
#define DA7218_PLL_MODE_NORMAL		(0x1 << 6)
#define DA7218_PLL_MODE_SRM		(0x2 << 6)
#define DA7218_PLL_MODE_32KHZ		(0x3 << 6)

/* DA7218_PLL_FRAC_TOP = 0x92 */
#define DA7218_PLL_FBDIV_FRAC_TOP_SHIFT	0
@@ -1371,7 +1370,6 @@ enum da7218_sys_clk {
	DA7218_SYSCLK_MCLK = 0,
	DA7218_SYSCLK_PLL,
	DA7218_SYSCLK_PLL_SRM,
	DA7218_SYSCLK_PLL_32KHZ
};

enum da7218_dev_id {
+105 −3
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/property.h>
#include <linux/pm_wakeirq.h>
@@ -114,13 +115,38 @@ static void da7219_aad_hptest_work(struct work_struct *work)
	struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);

	u16 tonegen_freq_hptest;
	u8 accdet_cfg8;
	int report = 0;
	u8 pll_srm_sts, gain_ramp_ctrl, accdet_cfg8;
	int report = 0, ret = 0;

	/* Lock DAPM and any Kcontrols that are affected by this test */
	snd_soc_dapm_mutex_lock(dapm);
	mutex_lock(&da7219->lock);

	/* Ensure MCLK is available for HP test procedure */
	if (da7219->mclk) {
		ret = clk_prepare_enable(da7219->mclk);
		if (ret) {
			dev_err(codec->dev, "Failed to enable mclk - %d\n", ret);
			mutex_unlock(&da7219->lock);
			snd_soc_dapm_mutex_unlock(dapm);
			return;
		}
	}

	/*
	 * If MCLK not present, then we're using the internal oscillator and
	 * require different frequency settings to achieve the same result.
	 */
	pll_srm_sts = snd_soc_read(codec, DA7219_PLL_SRM_STS);
	if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK)
		tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ);
	else
		tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC);

	/* Ensure gain ramping at fastest rate */
	gain_ramp_ctrl = snd_soc_read(codec, DA7219_GAIN_RAMP_CTRL);
	snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_X8);

	/* Bypass cache so it saves current settings */
	regcache_cache_bypass(da7219->regmap, true);

@@ -183,9 +209,15 @@ static void da7219_aad_hptest_work(struct work_struct *work)
	snd_soc_write(codec, DA7219_HP_R_CTRL,
		      DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK);

	/*
	 * If we're running from the internal oscillator then give audio paths
	 * time to settle before running test.
	 */
	if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
		msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);

	/* Configure & start Tone Generator */
	snd_soc_write(codec, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK);
	tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ);
	regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L,
			 &tonegen_freq_hptest, sizeof(tonegen_freq_hptest));
	snd_soc_update_bits(codec, DA7219_TONE_GEN_CFG2,
@@ -244,12 +276,26 @@ static void da7219_aad_hptest_work(struct work_struct *work)
	snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8,
			    DA7219_HPTEST_EN_MASK, 0);

	/*
	 * If we're running from the internal oscillator then give audio paths
	 * time to settle before allowing headphones to be driven as required.
	 */
	if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
		msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);

	/* Restore gain ramping rate */
	snd_soc_write(codec, DA7219_GAIN_RAMP_CTRL, gain_ramp_ctrl);

	/* Drive Headphones/lineout */
	snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK,
			    DA7219_HP_L_AMP_OE_MASK);
	snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK,
			    DA7219_HP_R_AMP_OE_MASK);

	/* Remove MCLK, if previously enabled */
	if (da7219->mclk)
		clk_disable_unprepare(da7219->mclk);

	mutex_unlock(&da7219->lock);
	snd_soc_dapm_mutex_unlock(dapm);

@@ -750,6 +796,62 @@ static void da7219_aad_handle_pdata(struct snd_soc_codec *codec)
}


/*
 * Suspend/Resume
 */

void da7219_aad_suspend(struct snd_soc_codec *codec)
{
	struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
	struct da7219_aad_priv *da7219_aad = da7219->aad;
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
	u8 micbias_ctrl;

	if (da7219_aad->jack) {
		/* Disable jack detection during suspend */
		snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
				    DA7219_ACCDET_EN_MASK, 0);

		/*
		 * If we have a 4-pole jack inserted, then micbias will be
		 * enabled. We can disable micbias here, and keep a note to
		 * re-enable it on resume. If jack removal occurred during
		 * suspend then this will be dealt with through the IRQ handler.
		 */
		if (da7219_aad->jack_inserted) {
			micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL);
			if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) {
				snd_soc_dapm_disable_pin(dapm, "Mic Bias");
				snd_soc_dapm_sync(dapm);
				da7219_aad->micbias_resume_enable = true;
			}
		}
	}
}

void da7219_aad_resume(struct snd_soc_codec *codec)
{
	struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec);
	struct da7219_aad_priv *da7219_aad = da7219->aad;
	struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);

	if (da7219_aad->jack) {
		/* Re-enable micbias if previously enabled for 4-pole jack */
		if (da7219_aad->jack_inserted &&
		    da7219_aad->micbias_resume_enable) {
			snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
			snd_soc_dapm_sync(dapm);
			da7219_aad->micbias_resume_enable = false;
		}

		/* Re-enable jack detection */
		snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1,
				    DA7219_ACCDET_EN_MASK,
				    DA7219_ACCDET_EN_MASK);
	}
}


/*
 * Init/Exit
 */
+9 −2
Original line number Diff line number Diff line
@@ -177,7 +177,9 @@
#define DA7219_AAD_MICBIAS_CHK_RETRIES	5

#define DA7219_AAD_HPTEST_RAMP_FREQ		0x28
#define DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC	0x4D
#define DA7219_AAD_HPTEST_PERIOD		65
#define DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY	20

enum da7219_aad_event_regs {
	DA7219_AAD_IRQ_REG_A = 0,
@@ -199,12 +201,17 @@ struct da7219_aad_priv {
	struct work_struct hptest_work;

	struct snd_soc_jack *jack;
	bool micbias_resume_enable;
	bool jack_inserted;
};

/* AAD control */
void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack);

/* Suspend/Resume */
void da7219_aad_suspend(struct snd_soc_codec *codec);
void da7219_aad_resume(struct snd_soc_codec *codec);

/* Init/Exit */
int da7219_aad_init(struct snd_soc_codec *codec);
void da7219_aad_exit(struct snd_soc_codec *codec);
Loading