diff options
author | oder_chiou@realtek.com <oder_chiou@realtek.com> | 2017-11-06 23:31:14 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-11-07 05:23:36 -0500 |
commit | fc9cab05837639ce3372870b09d26334fb15b157 (patch) | |
tree | 6e3ec46123eb50b4ea6c4063bc5c5128b547c4c4 | |
parent | 28aef24d726f8d503fde24ccf8a14b214355cfb5 (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.h | 2 | ||||
-rw-r--r-- | sound/soc/codecs/rt5514-spi.c | 1 | ||||
-rw-r--r-- | sound/soc/codecs/rt5514.c | 85 | ||||
-rw-r--r-- | sound/soc/codecs/rt5514.h | 5 |
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 | ||
15 | struct rt5514_platform_data { | 15 | struct 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 | } |
373 | EXPORT_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 | ||
298 | static 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 | |||
298 | static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol, | 325 | static 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, | |||
1024 | static int rt5514_probe(struct snd_soc_codec *codec) | 1095 | static 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__ */ |