Skip to content

Commit

Permalink
clk: sunxi-ng: sun8i: h3: Use sigma-delta modulation for audio PLL
Browse files Browse the repository at this point in the history
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 H3.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
  • Loading branch information
Chen-Yu Tsai authored and Maxime Ripard committed Oct 13, 2017
1 parent 392ba5f commit a5e3e2b
Showing 1 changed file with 25 additions and 13 deletions.
38 changes: 25 additions & 13 deletions drivers/clk/sunxi-ng/ccu-sun8i-h3.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "ccu_nkmp.h"
#include "ccu_nm.h"
#include "ccu_phase.h"
#include "ccu_sdm.h"

#include "ccu-sun8i-h3.h"

Expand All @@ -44,18 +45,29 @@ static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux",
* the base (2x, 4x and 8x), and one variable divider (the one true
* pll audio).
*
* We don't have any need for the variable divider for now, so we just
* hardcode it to match with the clock names
* With sigma-delta modulation for fractional-N on the audio PLL,
* we have to use specific dividers. This means the variable divider
* can no longer be used, as the audio codec requests the exact clock
* rates we support through this mechanism. So we now hard code the
* variable divider to 1. This means the clock rates will no longer
* match the clock names.
*/
#define SUN8I_H3_PLL_AUDIO_REG 0x008

static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
"osc24M", 0x008,
8, 7, /* N */
0, 5, /* M */
BIT(31), /* gate */
BIT(28), /* lock */
CLK_SET_RATE_UNGATE);
static struct ccu_sdm_setting pll_audio_sdm_table[] = {
{ .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 },
{ .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 },
};

static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
"osc24M", 0x008,
8, 7, /* N */
0, 5, /* M */
pll_audio_sdm_table, BIT(24),
0x284, BIT(31),
BIT(31), /* gate */
BIT(28), /* lock */
CLK_SET_RATE_UNGATE);

static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video",
"osc24M", 0x0010,
Expand Down Expand Up @@ -707,9 +719,9 @@ static struct ccu_common *sun50i_h5_ccu_clks[] = {
&gpu_clk.common,
};

/* We hardcode the divider to 4 for now */
/* We hardcode the divider to 1 for now */
static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
"pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
"pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
"pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
Expand Down Expand Up @@ -1129,10 +1141,10 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node,
return;
}

/* Force the PLL-Audio-1x divider to 4 */
/* Force the PLL-Audio-1x divider to 1 */
val = readl(reg + SUN8I_H3_PLL_AUDIO_REG);
val &= ~GENMASK(19, 16);
writel(val | (3 << 16), reg + SUN8I_H3_PLL_AUDIO_REG);
writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG);

sunxi_ccu_probe(node, reg, desc);

Expand Down

0 comments on commit a5e3e2b

Please sign in to comment.