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

Unverified Commit fc9cab05 authored by oder_chiou@realtek.com's avatar oder_chiou@realtek.com Committed by Mark Brown
Browse files

ASoC: rt5514: The DSP clock can be calibrated by the other clock source



Add the option for the DSP clock that can be calibrated by the other clock
source.

Signed-off-by: default avatarOder Chiou <oder_chiou@realtek.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 28aef24d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@

struct rt5514_platform_data {
	unsigned int dmic_init_delay;
	const char *dsp_calib_clk_name;
	unsigned int dsp_calib_clk_rate;
};

#endif
+1 −0
Original line number Diff line number Diff line
@@ -370,6 +370,7 @@ int rt5514_spi_burst_read(unsigned int addr, u8 *rxbuf, size_t len)

	return true;
}
EXPORT_SYMBOL_GPL(rt5514_spi_burst_read);

/**
 * rt5514_spi_burst_write - Write data to SPI by rt5514 address.
+85 −0
Original line number Diff line number Diff line
@@ -295,6 +295,33 @@ static int rt5514_dsp_voice_wake_up_get(struct snd_kcontrol *kcontrol,
	return 0;
}

static int rt5514_calibration(struct rt5514_priv *rt5514, bool on)
{
	if (on) {
		regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL3, 0x0000000a);
		regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf,
			0xa);
		regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301,
			0x301);
		regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL4,
			0x80000000 | rt5514->pll3_cal_value);
		regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL1,
			0x8bb80800);
		regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5,
			0xc0000000, 0x80000000);
		regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5,
			0xc0000000, 0xc0000000);
	} else {
		regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5,
			0xc0000000, 0x40000000);
		regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301, 0);
		regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf,
			0x4);
	}

	return 0;
}

static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
		struct snd_ctl_elem_value *ucontrol)
{
@@ -302,6 +329,7 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
	struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component);
	struct snd_soc_codec *codec = rt5514->codec;
	const struct firmware *fw = NULL;
	u8 buf[8];

	if (ucontrol->value.integer.value[0] == rt5514->dsp_enabled)
		return 0;
@@ -310,6 +338,35 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
		rt5514->dsp_enabled = ucontrol->value.integer.value[0];

		if (rt5514->dsp_enabled) {
			if (rt5514->pdata.dsp_calib_clk_name &&
				!IS_ERR(rt5514->dsp_calib_clk)) {
				if (clk_set_rate(rt5514->dsp_calib_clk,
					rt5514->pdata.dsp_calib_clk_rate))
					dev_err(codec->dev,
						"Can't set rate for mclk");

				if (clk_prepare_enable(rt5514->dsp_calib_clk))
					dev_err(codec->dev,
						"Can't enable dsp_calib_clk");

				rt5514_calibration(rt5514, true);

				msleep(20);
#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
				rt5514_spi_burst_read(RT5514_PLL3_CALIB_CTRL6 |
					RT5514_DSP_MAPPING,
					(u8 *)&buf, sizeof(buf));
#else
				dev_err(codec->dev, "There is no SPI driver for"
					" loading the firmware\n");
#endif
				rt5514->pll3_cal_value = buf[0] | buf[1] << 8 |
					buf[2] << 16 | buf[3] << 24;

				rt5514_calibration(rt5514, false);
				clk_disable_unprepare(rt5514->dsp_calib_clk);
			}

			rt5514_enable_dsp_prepare(rt5514);

			request_firmware(&fw, RT5514_FIRMWARE1, codec->dev);
@@ -341,6 +398,20 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
			/* DSP run */
			regmap_write(rt5514->i2c_regmap, 0x18002f00,
				0x00055148);

			if (rt5514->pdata.dsp_calib_clk_name &&
				!IS_ERR(rt5514->dsp_calib_clk)) {
				msleep(20);

				regmap_write(rt5514->i2c_regmap, 0x1800211c,
					rt5514->pll3_cal_value);
				regmap_write(rt5514->i2c_regmap, 0x18002124,
					0x00220012);
				regmap_write(rt5514->i2c_regmap, 0x18002124,
					0x80220042);
				regmap_write(rt5514->i2c_regmap, 0x18002124,
					0xe0220042);
			}
		} else {
			regmap_multi_reg_write(rt5514->i2c_regmap,
				rt5514_i2c_patch, ARRAY_SIZE(rt5514_i2c_patch));
@@ -1024,12 +1095,22 @@ static int rt5514_set_bias_level(struct snd_soc_codec *codec,
static int rt5514_probe(struct snd_soc_codec *codec)
{
	struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec);
	struct platform_device *pdev = container_of(codec->dev,
						   struct platform_device, dev);

	rt5514->mclk = devm_clk_get(codec->dev, "mclk");
	if (PTR_ERR(rt5514->mclk) == -EPROBE_DEFER)
		return -EPROBE_DEFER;

	if (rt5514->pdata.dsp_calib_clk_name) {
		rt5514->dsp_calib_clk = devm_clk_get(&pdev->dev,
				rt5514->pdata.dsp_calib_clk_name);
		if (PTR_ERR(rt5514->dsp_calib_clk) == -EPROBE_DEFER)
			return -EPROBE_DEFER;
	}

	rt5514->codec = codec;
	rt5514->pll3_cal_value = 0x0078b000;

	return 0;
}
@@ -1147,6 +1228,10 @@ static int rt5514_parse_dp(struct rt5514_priv *rt5514, struct device *dev)
{
	device_property_read_u32(dev, "realtek,dmic-init-delay-ms",
		&rt5514->pdata.dmic_init_delay);
	device_property_read_string(dev, "realtek,dsp-calib-clk-name",
		&rt5514->pdata.dsp_calib_clk_name);
	device_property_read_u32(dev, "realtek,dsp-calib-clk-rate",
		&rt5514->pdata.dsp_calib_clk_rate);

	return 0;
}
+4 −1
Original line number Diff line number Diff line
@@ -34,7 +34,9 @@
#define RT5514_CLK_CTRL1			0x2104
#define RT5514_CLK_CTRL2			0x2108
#define RT5514_PLL3_CALIB_CTRL1			0x2110
#define RT5514_PLL3_CALIB_CTRL4			0x2120
#define RT5514_PLL3_CALIB_CTRL5			0x2124
#define RT5514_PLL3_CALIB_CTRL6			0x2128
#define RT5514_DELAY_BUF_CTRL1			0x2140
#define RT5514_DELAY_BUF_CTRL3			0x2148
#define RT5514_ASRC_IN_CTRL1			0x2180
@@ -272,7 +274,7 @@ struct rt5514_priv {
	struct rt5514_platform_data pdata;
	struct snd_soc_codec *codec;
	struct regmap *i2c_regmap, *regmap;
	struct clk *mclk;
	struct clk *mclk, *dsp_calib_clk;
	int sysclk;
	int sysclk_src;
	int lrck;
@@ -281,6 +283,7 @@ struct rt5514_priv {
	int pll_in;
	int pll_out;
	int dsp_enabled;
	unsigned int pll3_cal_value;
};

#endif /* __RT5514_H__ */