diff options
Diffstat (limited to 'sound/soc/codecs/rt5514.c')
-rw-r--r-- | sound/soc/codecs/rt5514.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index 2dd6e9f990a4..198df016802f 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 | } |