Skip to content

Commit

Permalink
ASoC: rt5514: The DSP clock can be calibrated by the other clock source
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
oder_chiou@realtek.com authored and Mark Brown committed Nov 7, 2017
1 parent 28aef24 commit fc9cab0
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 1 deletion.
2 changes: 2 additions & 0 deletions include/sound/rt5514.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions sound/soc/codecs/rt5514-spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
85 changes: 85 additions & 0 deletions sound/soc/codecs/rt5514.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,41 @@ 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)
{
struct snd_soc_component *component = snd_kcontrol_chip(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;
Expand All @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
5 changes: 4 additions & 1 deletion sound/soc/codecs/rt5514.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -281,6 +283,7 @@ struct rt5514_priv {
int pll_in;
int pll_out;
int dsp_enabled;
unsigned int pll3_cal_value;
};

#endif /* __RT5514_H__ */

0 comments on commit fc9cab0

Please sign in to comment.