* [PATCH 1/3] clk: sunxi-ng: Support fixed post-dividers on NM style clocks
2017-12-08 8:35 [PATCH 0/3] clk: sunxi-ng: sun8i: a83t: Use sigma-delta modulation for audio PLL Chen-Yu Tsai
@ 2017-12-08 8:35 ` Chen-Yu Tsai
2017-12-08 8:35 ` [PATCH 2/3] clk: sunxi-ng: sun8i: a83t: Add /2 fixed post divider to audio PLL Chen-Yu Tsai
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Chen-Yu Tsai @ 2017-12-08 8:35 UTC (permalink / raw)
To: Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, linux-clk, linux-kernel, linux-sunxi
On the A83T, the audio PLL should have its div1 set to 0, or /1, and
div2 set to 1, or /2. This setting is the default, and is required
to match the sigma-delta modulation parameters from the BSP kernel.
To do this, we first add fixed post-divider to the NM style clocks,
which is the type of clock the audio PLL clock is modeled into.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/clk/sunxi-ng/ccu_nm.c | 50 ++++++++++++++++++++++++++++++++-----------
drivers/clk/sunxi-ng/ccu_nm.h | 2 ++
2 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index 7620aa973a6e..a16de092bf94 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -70,11 +70,18 @@ static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ccu_nm *nm = hw_to_ccu_nm(hw);
+ unsigned long rate;
unsigned long n, m;
u32 reg;
- if (ccu_frac_helper_is_enabled(&nm->common, &nm->frac))
- return ccu_frac_helper_read_rate(&nm->common, &nm->frac);
+ if (ccu_frac_helper_is_enabled(&nm->common, &nm->frac)) {
+ rate = ccu_frac_helper_read_rate(&nm->common, &nm->frac);
+
+ if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
+ rate /= nm->fixed_post_div;
+
+ return rate;
+ }
reg = readl(nm->common.base + nm->common.reg);
@@ -90,15 +97,15 @@ static unsigned long ccu_nm_recalc_rate(struct clk_hw *hw,
if (!m)
m++;
- if (ccu_sdm_helper_is_enabled(&nm->common, &nm->sdm)) {
- unsigned long rate =
- ccu_sdm_helper_read_rate(&nm->common, &nm->sdm,
- m, n);
- if (rate)
- return rate;
- }
+ if (ccu_sdm_helper_is_enabled(&nm->common, &nm->sdm))
+ rate = ccu_sdm_helper_read_rate(&nm->common, &nm->sdm, m, n);
+ else
+ rate = parent_rate * n / m;
+
+ if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
+ rate /= nm->fixed_post_div;
- return parent_rate * n / m;
+ return rate;
}
static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -107,11 +114,20 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
struct ccu_nm *nm = hw_to_ccu_nm(hw);
struct _ccu_nm _nm;
- if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate))
+ if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
+ rate *= nm->fixed_post_div;
+
+ if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) {
+ if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
+ rate /= nm->fixed_post_div;
return rate;
+ }
- if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate))
+ if (ccu_sdm_helper_has_rate(&nm->common, &nm->sdm, rate)) {
+ if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
+ rate /= nm->fixed_post_div;
return rate;
+ }
_nm.min_n = nm->n.min ?: 1;
_nm.max_n = nm->n.max ?: 1 << nm->n.width;
@@ -119,8 +135,12 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
_nm.max_m = nm->m.max ?: 1 << nm->m.width;
ccu_nm_find_best(*parent_rate, rate, &_nm);
+ rate = *parent_rate * _nm.n / _nm.m;
+
+ if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
+ rate /= nm->fixed_post_div;
- return *parent_rate * _nm.n / _nm.m;
+ return rate;
}
static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -131,6 +151,10 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long flags;
u32 reg;
+ /* Adjust target rate according to post-dividers */
+ if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
+ rate = rate * nm->fixed_post_div;
+
if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) {
spin_lock_irqsave(nm->common.lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h
index c623b0c7a23c..eba586b4c7d0 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.h
+++ b/drivers/clk/sunxi-ng/ccu_nm.h
@@ -36,6 +36,8 @@ struct ccu_nm {
struct ccu_frac_internal frac;
struct ccu_sdm_internal sdm;
+ unsigned int fixed_post_div;
+
struct ccu_common common;
};
--
2.15.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/3] clk: sunxi-ng: sun8i: a83t: Add /2 fixed post divider to audio PLL
2017-12-08 8:35 [PATCH 0/3] clk: sunxi-ng: sun8i: a83t: Use sigma-delta modulation for audio PLL Chen-Yu Tsai
2017-12-08 8:35 ` [PATCH 1/3] clk: sunxi-ng: Support fixed post-dividers on NM style clocks Chen-Yu Tsai
@ 2017-12-08 8:35 ` Chen-Yu Tsai
2017-12-08 8:35 ` [PATCH 3/3] clk: sunxi-ng: sun8i: a83t: Use sigma-delta modulation for " Chen-Yu Tsai
2017-12-08 9:08 ` [PATCH 0/3] " Maxime Ripard
3 siblings, 0 replies; 5+ messages in thread
From: Chen-Yu Tsai @ 2017-12-08 8:35 UTC (permalink / raw)
To: Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, linux-clk, linux-kernel, linux-sunxi
On the A83T, the audio PLL should have its div1 set to 0, or /1, and
div2 set to 1, or /2. This setting is the default, and is required
to match the sigma-delta modulation parameters from the BSP kernel.
This patch adds a /2 fixed post divider to the audio PLL, and fixes
the enforced d1 & d2 values. This also resolves the mismatch between
the values mentioned in the comment for the audio PLL, and the actual
enforced values.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/clk/sunxi-ng/ccu-sun8i-a83t.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
index 5cedcd0d8be8..06b69e433d0f 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
@@ -81,10 +81,12 @@ static struct ccu_nm pll_audio_clk = {
.lock = BIT(2),
.n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
.m = _SUNXI_CCU_DIV(0, 6),
+ .fixed_post_div = 2,
.common = {
.reg = SUN8I_A83T_PLL_AUDIO_REG,
.lock_reg = CCU_SUN8I_A83T_LOCK_REG,
- .features = CCU_FEATURE_LOCK_REG,
+ .features = CCU_FEATURE_LOCK_REG |
+ CCU_FEATURE_FIXED_POSTDIV,
.hw.init = CLK_HW_INIT("pll-audio", "osc24M",
&ccu_nm_ops, CLK_SET_RATE_UNGATE),
},
@@ -889,9 +891,10 @@ static int sun8i_a83t_ccu_probe(struct platform_device *pdev)
if (IS_ERR(reg))
return PTR_ERR(reg);
- /* Enforce d1 = 0, d2 = 0 for Audio PLL */
+ /* Enforce d1 = 0, d2 = 1 for Audio PLL */
val = readl(reg + SUN8I_A83T_PLL_AUDIO_REG);
- val &= ~(BIT(16) | BIT(18));
+ val &= ~BIT(16);
+ val |= BIT(18);
writel(val, reg + SUN8I_A83T_PLL_AUDIO_REG);
/* Enforce P = 1 for both CPU cluster PLLs */
--
2.15.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/3] clk: sunxi-ng: sun8i: a83t: Use sigma-delta modulation for audio PLL
2017-12-08 8:35 [PATCH 0/3] clk: sunxi-ng: sun8i: a83t: Use sigma-delta modulation for audio PLL Chen-Yu Tsai
2017-12-08 8:35 ` [PATCH 1/3] clk: sunxi-ng: Support fixed post-dividers on NM style clocks Chen-Yu Tsai
2017-12-08 8:35 ` [PATCH 2/3] clk: sunxi-ng: sun8i: a83t: Add /2 fixed post divider to audio PLL Chen-Yu Tsai
@ 2017-12-08 8:35 ` Chen-Yu Tsai
2017-12-08 9:08 ` [PATCH 0/3] " Maxime Ripard
3 siblings, 0 replies; 5+ messages in thread
From: Chen-Yu Tsai @ 2017-12-08 8:35 UTC (permalink / raw)
To: Maxime Ripard, Michael Turquette, Stephen Boyd
Cc: Chen-Yu Tsai, linux-clk, linux-kernel, linux-sunxi
The audio blocks require specific clock rates. Until now we were using
the closest clock rate possible with integer N-M factors. This resulted
in audio playback being slightly slower than it should be.
The vendor kernel gets around this (for newer SoCs) by using sigma-delta
modulation to generate a fractional-N factor. This patch copies the
parameters for the A83T.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/clk/sunxi-ng/ccu-sun8i-a83t.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
index 06b69e433d0f..04a9c33f53f0 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
@@ -76,17 +76,26 @@ static struct ccu_mult pll_c1cpux_clk = {
*/
#define SUN8I_A83T_PLL_AUDIO_REG 0x008
+/* clock rates doubled for post divider */
+static struct ccu_sdm_setting pll_audio_sdm_table[] = {
+ { .rate = 45158400, .pattern = 0xc00121ff, .m = 29, .n = 54 },
+ { .rate = 49152000, .pattern = 0xc000e147, .m = 30, .n = 61 },
+};
+
static struct ccu_nm pll_audio_clk = {
.enable = BIT(31),
.lock = BIT(2),
.n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
.m = _SUNXI_CCU_DIV(0, 6),
.fixed_post_div = 2,
+ .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, BIT(24),
+ 0x284, BIT(31)),
.common = {
.reg = SUN8I_A83T_PLL_AUDIO_REG,
.lock_reg = CCU_SUN8I_A83T_LOCK_REG,
.features = CCU_FEATURE_LOCK_REG |
- CCU_FEATURE_FIXED_POSTDIV,
+ CCU_FEATURE_FIXED_POSTDIV |
+ CCU_FEATURE_SIGMA_DELTA_MOD,
.hw.init = CLK_HW_INIT("pll-audio", "osc24M",
&ccu_nm_ops, CLK_SET_RATE_UNGATE),
},
--
2.15.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 0/3] clk: sunxi-ng: sun8i: a83t: Use sigma-delta modulation for audio PLL
2017-12-08 8:35 [PATCH 0/3] clk: sunxi-ng: sun8i: a83t: Use sigma-delta modulation for audio PLL Chen-Yu Tsai
` (2 preceding siblings ...)
2017-12-08 8:35 ` [PATCH 3/3] clk: sunxi-ng: sun8i: a83t: Use sigma-delta modulation for " Chen-Yu Tsai
@ 2017-12-08 9:08 ` Maxime Ripard
3 siblings, 0 replies; 5+ messages in thread
From: Maxime Ripard @ 2017-12-08 9:08 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Michael Turquette, Stephen Boyd, linux-clk, linux-kernel,
linux-sunxi
[-- Attachment #1: Type: text/plain, Size: 1219 bytes --]
On Fri, Dec 08, 2017 at 04:35:09PM +0800, Chen-Yu Tsai wrote:
> Hi,
>
> This series follows previous improvements for the other Allwinner SoCs to
> improve audio quality, in particular the speed and pitch of audio playback.
> The audio PLLs in Allwinner SoCs cannot produce the correct frequency to
> match the audio sample rate families through integer factors. As such
> the audio is either too fast or too flow.
>
> This is dealt with by using sigma-delta modulation, a form of fractional-N
> synthesis, on the divider. The parameters used are copied from the BSP
> kernel.
>
> As these parameters assume that one of the untracked dividers is set to
> 2, we first add a fixed /2 post divider to the PLL, and force the
> untracked divider to /2. Then we introduce the sigma-delta modulation
> parameters.
>
> This has been tested with SPDIF playback on the Cubietruck Plus, and an
> external PCM5122 DAC from a PiFi DAC 2.0+, connected via I2S to the
> Banana Pi M3. The I2C and I2S support used in this latter test will be
> sent as a separate series later.
Applied, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread