aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroder_chiou@realtek.com <oder_chiou@realtek.com>2017-11-06 23:31:14 -0500
committerMark Brown <broonie@kernel.org>2017-11-07 05:23:36 -0500
commitfc9cab05837639ce3372870b09d26334fb15b157 (patch)
tree6e3ec46123eb50b4ea6c4063bc5c5128b547c4c4
parent28aef24d726f8d503fde24ccf8a14b214355cfb5 (diff)
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: Oder Chiou <oder_chiou@realtek.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--include/sound/rt5514.h2
-rw-r--r--sound/soc/codecs/rt5514-spi.c1
-rw-r--r--sound/soc/codecs/rt5514.c85
-rw-r--r--sound/soc/codecs/rt5514.h5
4 files changed, 92 insertions, 1 deletions
diff --git a/include/sound/rt5514.h b/include/sound/rt5514.h
index ef18494769ee..64d027dbaaca 100644
--- a/include/sound/rt5514.h
+++ b/include/sound/rt5514.h
@@ -14,6 +14,8 @@
14 14
15struct rt5514_platform_data { 15struct rt5514_platform_data {
16 unsigned int dmic_init_delay; 16 unsigned int dmic_init_delay;
17 const char *dsp_calib_clk_name;
18 unsigned int dsp_calib_clk_rate;
17}; 19};
18 20
19#endif 21#endif
diff --git a/sound/soc/codecs/rt5514-spi.c b/sound/soc/codecs/rt5514-spi.c
index 12f2ecf3a4fe..b90d6d5d7ff8 100644
--- a/sound/soc/codecs/rt5514-spi.c
+++ b/sound/soc/codecs/rt5514-spi.c
@@ -370,6 +370,7 @@ int rt5514_spi_burst_read(unsigned int addr, u8 *rxbuf, size_t len)
370 370
371 return true; 371 return true;
372} 372}
373EXPORT_SYMBOL_GPL(rt5514_spi_burst_read);
373 374
374/** 375/**
375 * rt5514_spi_burst_write - Write data to SPI by rt5514 address. 376 * rt5514_spi_burst_write - Write data to SPI by rt5514 address.
diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c
index 2a5b5d74e697..61ccbc62125b 100644
--- a/sound/soc/codecs/rt5514.c
+++ b/sound/soc/codecs/rt5514.c
@@ -295,6 +295,33 @@ static int rt5514_dsp_voice_wake_up_get(struct snd_kcontrol *kcontrol,
295 return 0; 295 return 0;
296} 296}
297 297
298static int rt5514_calibration(struct rt5514_priv *rt5514, bool on)
299{
300 if (on) {
301 regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL3, 0x0000000a);
302 regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf,
303 0xa);
304 regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301,
305 0x301);
306 regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL4,
307 0x80000000 | rt5514->pll3_cal_value);
308 regmap_write(rt5514->regmap, RT5514_PLL3_CALIB_CTRL1,
309 0x8bb80800);
310 regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5,
311 0xc0000000, 0x80000000);
312 regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5,
313 0xc0000000, 0xc0000000);
314 } else {
315 regmap_update_bits(rt5514->regmap, RT5514_PLL3_CALIB_CTRL5,
316 0xc0000000, 0x40000000);
317 regmap_update_bits(rt5514->regmap, RT5514_PWR_ANA1, 0x301, 0);
318 regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, 0xf,
319 0x4);
320 }
321
322 return 0;
323}
324
298static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol, 325static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_value *ucontrol) 326 struct snd_ctl_elem_value *ucontrol)
300{ 327{
@@ -302,6 +329,7 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
302 struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component); 329 struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component);
303 struct snd_soc_codec *codec = rt5514->codec; 330 struct snd_soc_codec *codec = rt5514->codec;
304 const struct firmware *fw = NULL; 331 const struct firmware *fw = NULL;
332 u8 buf[8];
305 333
306 if (ucontrol->value.integer.value[0] == rt5514->dsp_enabled) 334 if (ucontrol->value.integer.value[0] == rt5514->dsp_enabled)
307 return 0; 335 return 0;
@@ -310,6 +338,35 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
310 rt5514->dsp_enabled = ucontrol->value.integer.value[0]; 338 rt5514->dsp_enabled = ucontrol->value.integer.value[0];
311 339
312 if (rt5514->dsp_enabled) { 340 if (rt5514->dsp_enabled) {
341 if (rt5514->pdata.dsp_calib_clk_name &&
342 !IS_ERR(rt5514->dsp_calib_clk)) {
343 if (clk_set_rate(rt5514->dsp_calib_clk,
344 rt5514->pdata.dsp_calib_clk_rate))
345 dev_err(codec->dev,
346 "Can't set rate for mclk");
347
348 if (clk_prepare_enable(rt5514->dsp_calib_clk))
349 dev_err(codec->dev,
350 "Can't enable dsp_calib_clk");
351
352 rt5514_calibration(rt5514, true);
353
354 msleep(20);
355#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
356 rt5514_spi_burst_read(RT5514_PLL3_CALIB_CTRL6 |
357 RT5514_DSP_MAPPING,
358 (u8 *)&buf, sizeof(buf));
359#else
360 dev_err(codec->dev, "There is no SPI driver for"
361 " loading the firmware\n");
362#endif
363 rt5514->pll3_cal_value = buf[0] | buf[1] << 8 |
364 buf[2] << 16 | buf[3] << 24;
365
366 rt5514_calibration(rt5514, false);
367 clk_disable_unprepare(rt5514->dsp_calib_clk);
368 }
369
313 rt5514_enable_dsp_prepare(rt5514); 370 rt5514_enable_dsp_prepare(rt5514);
314 371
315 request_firmware(&fw, RT5514_FIRMWARE1, codec->dev); 372 request_firmware(&fw, RT5514_FIRMWARE1, codec->dev);
@@ -341,6 +398,20 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
341 /* DSP run */ 398 /* DSP run */
342 regmap_write(rt5514->i2c_regmap, 0x18002f00, 399 regmap_write(rt5514->i2c_regmap, 0x18002f00,
343 0x00055148); 400 0x00055148);
401
402 if (rt5514->pdata.dsp_calib_clk_name &&
403 !IS_ERR(rt5514->dsp_calib_clk)) {
404 msleep(20);
405
406 regmap_write(rt5514->i2c_regmap, 0x1800211c,
407 rt5514->pll3_cal_value);
408 regmap_write(rt5514->i2c_regmap, 0x18002124,
409 0x00220012);
410 regmap_write(rt5514->i2c_regmap, 0x18002124,
411 0x80220042);
412 regmap_write(rt5514->i2c_regmap, 0x18002124,
413 0xe0220042);
414 }
344 } else { 415 } else {
345 regmap_multi_reg_write(rt5514->i2c_regmap, 416 regmap_multi_reg_write(rt5514->i2c_regmap,
346 rt5514_i2c_patch, ARRAY_SIZE(rt5514_i2c_patch)); 417 rt5514_i2c_patch, ARRAY_SIZE(rt5514_i2c_patch));
@@ -1024,12 +1095,22 @@ static int rt5514_set_bias_level(struct snd_soc_codec *codec,
1024static int rt5514_probe(struct snd_soc_codec *codec) 1095static int rt5514_probe(struct snd_soc_codec *codec)
1025{ 1096{
1026 struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); 1097 struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec);
1098 struct platform_device *pdev = container_of(codec->dev,
1099 struct platform_device, dev);
1027 1100
1028 rt5514->mclk = devm_clk_get(codec->dev, "mclk"); 1101 rt5514->mclk = devm_clk_get(codec->dev, "mclk");
1029 if (PTR_ERR(rt5514->mclk) == -EPROBE_DEFER) 1102 if (PTR_ERR(rt5514->mclk) == -EPROBE_DEFER)
1030 return -EPROBE_DEFER; 1103 return -EPROBE_DEFER;
1031 1104
1105 if (rt5514->pdata.dsp_calib_clk_name) {
1106 rt5514->dsp_calib_clk = devm_clk_get(&pdev->dev,
1107 rt5514->pdata.dsp_calib_clk_name);
1108 if (PTR_ERR(rt5514->dsp_calib_clk) == -EPROBE_DEFER)
1109 return -EPROBE_DEFER;
1110 }
1111
1032 rt5514->codec = codec; 1112 rt5514->codec = codec;
1113 rt5514->pll3_cal_value = 0x0078b000;
1033 1114
1034 return 0; 1115 return 0;
1035} 1116}
@@ -1147,6 +1228,10 @@ static int rt5514_parse_dp(struct rt5514_priv *rt5514, struct device *dev)
1147{ 1228{
1148 device_property_read_u32(dev, "realtek,dmic-init-delay-ms", 1229 device_property_read_u32(dev, "realtek,dmic-init-delay-ms",
1149 &rt5514->pdata.dmic_init_delay); 1230 &rt5514->pdata.dmic_init_delay);
1231 device_property_read_string(dev, "realtek,dsp-calib-clk-name",
1232 &rt5514->pdata.dsp_calib_clk_name);
1233 device_property_read_u32(dev, "realtek,dsp-calib-clk-rate",
1234 &rt5514->pdata.dsp_calib_clk_rate);
1150 1235
1151 return 0; 1236 return 0;
1152} 1237}
diff --git a/sound/soc/codecs/rt5514.h b/sound/soc/codecs/rt5514.h
index 2dc40e6d8b3f..f0f3400ce6b1 100644
--- a/sound/soc/codecs/rt5514.h
+++ b/sound/soc/codecs/rt5514.h
@@ -34,7 +34,9 @@
34#define RT5514_CLK_CTRL1 0x2104 34#define RT5514_CLK_CTRL1 0x2104
35#define RT5514_CLK_CTRL2 0x2108 35#define RT5514_CLK_CTRL2 0x2108
36#define RT5514_PLL3_CALIB_CTRL1 0x2110 36#define RT5514_PLL3_CALIB_CTRL1 0x2110
37#define RT5514_PLL3_CALIB_CTRL4 0x2120
37#define RT5514_PLL3_CALIB_CTRL5 0x2124 38#define RT5514_PLL3_CALIB_CTRL5 0x2124
39#define RT5514_PLL3_CALIB_CTRL6 0x2128
38#define RT5514_DELAY_BUF_CTRL1 0x2140 40#define RT5514_DELAY_BUF_CTRL1 0x2140
39#define RT5514_DELAY_BUF_CTRL3 0x2148 41#define RT5514_DELAY_BUF_CTRL3 0x2148
40#define RT5514_ASRC_IN_CTRL1 0x2180 42#define RT5514_ASRC_IN_CTRL1 0x2180
@@ -272,7 +274,7 @@ struct rt5514_priv {
272 struct rt5514_platform_data pdata; 274 struct rt5514_platform_data pdata;
273 struct snd_soc_codec *codec; 275 struct snd_soc_codec *codec;
274 struct regmap *i2c_regmap, *regmap; 276 struct regmap *i2c_regmap, *regmap;
275 struct clk *mclk; 277 struct clk *mclk, *dsp_calib_clk;
276 int sysclk; 278 int sysclk;
277 int sysclk_src; 279 int sysclk_src;
278 int lrck; 280 int lrck;
@@ -281,6 +283,7 @@ struct rt5514_priv {
281 int pll_in; 283 int pll_in;
282 int pll_out; 284 int pll_out;
283 int dsp_enabled; 285 int dsp_enabled;
286 unsigned int pll3_cal_value;
284}; 287};
285 288
286#endif /* __RT5514_H__ */ 289#endif /* __RT5514_H__ */