mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
ASoC: rockchip: pdm: Shift rate back to 0 ppm when restart
Change-Id: Ibb867e8b1a9a553a3077a7c91d415eea82cc76ba Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com> Signed-off-by: XiaoTan Luo <lxt@rock-chips.com>
This commit is contained in:
@@ -229,13 +229,46 @@ static void rockchip_pdm_rxctrl(struct rk_pdm_dev *pdm, int on)
|
||||
}
|
||||
}
|
||||
|
||||
static int rockchip_pdm_clk_set_rate(struct rk_pdm_dev *pdm,
|
||||
struct clk *clk, unsigned long rate,
|
||||
int ppm)
|
||||
{
|
||||
unsigned long rate_target;
|
||||
int delta, ret;
|
||||
|
||||
if (ppm == pdm->clk_ppm)
|
||||
return 0;
|
||||
|
||||
ret = rockchip_pll_clk_compensation(clk, ppm);
|
||||
if (ret != -ENOSYS)
|
||||
goto out;
|
||||
|
||||
delta = (ppm < 0) ? -1 : 1;
|
||||
delta *= (int)div64_u64((uint64_t)rate * (uint64_t)abs(ppm) + 500000, 1000000);
|
||||
|
||||
rate_target = rate + delta;
|
||||
|
||||
if (!rate_target)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_set_rate(clk, rate_target);
|
||||
if (ret)
|
||||
return ret;
|
||||
out:
|
||||
if (!ret)
|
||||
pdm->clk_ppm = ppm;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_pdm_set_samplerate(struct rk_pdm_dev *pdm, unsigned int samplerate)
|
||||
{
|
||||
|
||||
unsigned int val = 0, div = 0;
|
||||
unsigned int clk_rate, clk_div, rate;
|
||||
unsigned int clk_rate, clk_div, rate, delta;
|
||||
unsigned int clk_src = 0, clk_out = 0, signoff = PDM_SIGNOFF_CLK_100M;
|
||||
unsigned long m, n;
|
||||
uint64_t ppm;
|
||||
bool change;
|
||||
int ret;
|
||||
|
||||
@@ -250,14 +283,21 @@ static int rockchip_pdm_set_samplerate(struct rk_pdm_dev *pdm, unsigned int samp
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rockchip_pdm_clk_set_rate(pdm, pdm->clk_root,
|
||||
pdm->clk_root_rate, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rate = pdm->clk_root_rate;
|
||||
if (rate % clk_src) {
|
||||
delta = abs(rate % clk_src - clk_src);
|
||||
ppm = div64_u64((uint64_t)delta * 1000000, (uint64_t)rate);
|
||||
|
||||
if (ppm) {
|
||||
div = DIV_ROUND_CLOSEST(pdm->clk_root_initial_rate, clk_src);
|
||||
if (!div)
|
||||
return -EINVAL;
|
||||
|
||||
rate = clk_src * round_up(div, 2);
|
||||
pdm->clk_ppm = 0;
|
||||
ret = clk_set_rate(pdm->clk_root, rate);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -530,29 +570,6 @@ static const struct snd_kcontrol_new rockchip_pdm_controls[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int rockchip_pdm_clk_set_rate(struct rk_pdm_dev *pdm,
|
||||
struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long rate_target;
|
||||
int delta, ret;
|
||||
|
||||
ret = rockchip_pll_clk_compensation(clk, pdm->clk_ppm);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
delta = (pdm->clk_ppm < 0) ? -1 : 1;
|
||||
delta *= (int)div64_u64((uint64_t)rate * (uint64_t)abs(pdm->clk_ppm) + 500000, 1000000);
|
||||
|
||||
rate_target = rate + delta;
|
||||
|
||||
if (!rate_target)
|
||||
return -EINVAL;
|
||||
|
||||
ret = clk_set_rate(clk, rate_target);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_pdm_clk_compensation_info(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_info *uinfo)
|
||||
{
|
||||
@@ -578,22 +595,19 @@ static int rockchip_pdm_clk_compensation_get(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int rockchip_pdm_clk_compensation_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
|
||||
{
|
||||
struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
|
||||
struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
|
||||
|
||||
int ppm = ucontrol->value.integer.value[0];
|
||||
|
||||
if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) ||
|
||||
(ucontrol->value.integer.value[0] > CLK_PPM_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
pdm->clk_ppm = ucontrol->value.integer.value[0];
|
||||
|
||||
return rockchip_pdm_clk_set_rate(pdm, pdm->clk_root, pdm->clk_root_rate);
|
||||
return rockchip_pdm_clk_set_rate(pdm, pdm->clk_root, pdm->clk_root_rate, ppm);
|
||||
}
|
||||
|
||||
static struct snd_kcontrol_new rockchip_pdm_compensation_control = {
|
||||
|
||||
Reference in New Issue
Block a user