diff mbox series

[v3,1/7] clk: sunxi-ng: h616: Add sigma-delta modulation settings for audio PLL

Message ID 20241023075917.186835-2-ryan@testtoast.com (mailing list archive)
State Awaiting Upstream, archived
Headers show
Series ASoC: add Allwinner H616 audio codec support | expand

Commit Message

Ryan Walklin Oct. 23, 2024, 7:56 a.m. UTC
Allwinner has previously released a H616 audio driver which also
provides sigma-delta modulation for the audio PLL clocks. This approach
is used in other Allwinner SoCs, including the H3 and A64.

The manual-provided clock values are:
PLL_AUDIO(hs) = 24 MHz*N/M1
PLL_AUDIO(4X) = 24 MHz*N/M0/M1/P
PLL_AUDIO(2X) = 24 MHz*N/M0/M1/P/2
PLL_AUDIO(1X) = 24 MHz*N/M0/M1/P/4

A fixed post-divider of 2 is used to account for a M0 divider of
2, which cannot be modelled by the existing macros and ccu_nm struct.

Add SDM to the H616 clock control unit driver.

Signed-off-by: Ryan Walklin <ryan@testtoast.com>

---
Changelog v1..v2:
- Add fixed_post_div to high-speed audio clock to correct M0 value to 1 (ie divide by 2) based on manual
- Correct PLL_AUDIO_(4/2/1)X clocks to manual-provided values
- Add/correct inline comments for the above.
- add CCU_FEATURE_FIXED_POSTDIV to pll_audio_hs_clk.common.features

Changelog v2..v3:
- Update comments and commit message to more accurately reflect SDM changes and rationale
---
 drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 46 +++++++++++++++++---------
 1 file changed, 30 insertions(+), 16 deletions(-)

Comments

Andre Przywara Oct. 25, 2024, 9:38 a.m. UTC | #1
On Wed, 23 Oct 2024 20:56:57 +1300
Ryan Walklin <ryan@testtoast.com> wrote:

Hi Ryan,

> Allwinner has previously released a H616 audio driver which also
> provides sigma-delta modulation for the audio PLL clocks. This approach
> is used in other Allwinner SoCs, including the H3 and A64.
> 
> The manual-provided clock values are:
> PLL_AUDIO(hs) = 24 MHz*N/M1
> PLL_AUDIO(4X) = 24 MHz*N/M0/M1/P
> PLL_AUDIO(2X) = 24 MHz*N/M0/M1/P/2
> PLL_AUDIO(1X) = 24 MHz*N/M0/M1/P/4
> 
> A fixed post-divider of 2 is used to account for a M0 divider of
> 2, which cannot be modelled by the existing macros and ccu_nm struct.
> 
> Add SDM to the H616 clock control unit driver.

Thanks for the changes in the comments, that looks all good to me. I am
still scratching my head on why Allwinner promotes odd dividers, when
they somewhat warn about them in the manual, but I trust the wisdom of the
BSP here, and it certainly works. If any issues arise, we can always fix
that later.

> Signed-off-by: Ryan Walklin <ryan@testtoast.com>

Confirmed that the registers and bits match the manual, and the SDM values
also add up to reach those frequencies:

Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Cheers,
Andre

> 
> ---
> Changelog v1..v2:
> - Add fixed_post_div to high-speed audio clock to correct M0 value to 1 (ie divide by 2) based on manual
> - Correct PLL_AUDIO_(4/2/1)X clocks to manual-provided values
> - Add/correct inline comments for the above.
> - add CCU_FEATURE_FIXED_POSTDIV to pll_audio_hs_clk.common.features
> 
> Changelog v2..v3:
> - Update comments and commit message to more accurately reflect SDM changes and rationale
> ---
>  drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 46 +++++++++++++++++---------
>  1 file changed, 30 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> index 6c7623d4c59ea..05727fa1ee46e 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> @@ -215,20 +215,30 @@ static struct ccu_nkmp pll_de_clk = {
>  	},
>  };
>  
> -/*
> - * TODO: Determine SDM settings for the audio PLL. The manual suggests
> - * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b
> - * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2,
> - * pattern=0xe001288c for 22.5792 MHz.
> - * This clashes with our fixed PLL_POST_DIV_P.
> +/* 
> + * Sigma-delta modulation settings table obtained from the vendor SDK driver.
> + * There are additional M0 and M1 divider bits not modelled here, so forced to
> + * fixed values in the probe routine. Sigma-delta modulation allows providing a
> + * fractional-N divider in the PLL, to help reaching those specific
> + * frequencies with less error.
>   */
> +static struct ccu_sdm_setting pll_audio_sdm_table[] = {
> +	{ .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
> +	{ .rate = 98304000, .pattern = 0xc001eb85, .m = 5, .n = 40 },
> +};
> +
>  #define SUN50I_H616_PLL_AUDIO_REG	0x078
>  static struct ccu_nm pll_audio_hs_clk = {
>  	.enable		= BIT(31),
>  	.lock		= BIT(28),
>  	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
> -	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
> +	.m		= _SUNXI_CCU_DIV(16, 6),
> +	.sdm		= _SUNXI_CCU_SDM(pll_audio_sdm_table,
> +					 BIT(24), 0x178, BIT(31)),
> +	.fixed_post_div = 2,
>  	.common		= {
> +		.features	= CCU_FEATURE_FIXED_POSTDIV | 
> +				  CCU_FEATURE_SIGMA_DELTA_MOD,
>  		.reg		= 0x078,
>  		.hw.init	= CLK_HW_INIT("pll-audio-hs", "osc24M",
>  					      &ccu_nm_ops,
> @@ -701,18 +711,20 @@ static const struct clk_hw *clk_parent_pll_audio[] = {
>  };
>  
>  /*
> - * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
> - * rates can be set exactly in conjunction with sigma-delta modulation.
> + * The PLL_AUDIO_4X clock defaults to 24.5714 MHz according to the manual, with 
> + * a final divider of 1. The 2X and 1X clocks use 2 and 4 respectively. The 1x 
> + * clock is set to either 24576000 or 22579200 for 48Khz and 44.1Khz (and 
> + * multiples).
>   */
>  static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x",
>  			    clk_parent_pll_audio,
> -			    96, 1, CLK_SET_RATE_PARENT);
> +			    4, 1, CLK_SET_RATE_PARENT);
>  static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
>  			    clk_parent_pll_audio,
> -			    48, 1, CLK_SET_RATE_PARENT);
> +			    2, 1, CLK_SET_RATE_PARENT);
>  static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
>  			    clk_parent_pll_audio,
> -			    24, 1, CLK_SET_RATE_PARENT);
> +			    1, 1, CLK_SET_RATE_PARENT);
>  
>  static const struct clk_hw *pll_periph0_parents[] = {
>  	&pll_periph0_clk.common.hw
> @@ -1162,12 +1174,14 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev)
>  	}
>  
>  	/*
> -	 * Force the post-divider of pll-audio to 12 and the output divider
> -	 * of it to 2, so 24576000 and 22579200 rates can be set exactly.
> +	 * Set the output-divider for the pll-audio clocks (M0) to 2 and the
> +	 * input divider (M1) to 1 as recommended by the manual when using 
> +	 * SDM. 
>  	 */
>  	val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
> -	val &= ~(GENMASK(21, 16) | BIT(0));
> -	writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
> +	val &= ~BIT(1);
> +	val |= BIT(0);
> +	writel(val, reg + SUN50I_H616_PLL_AUDIO_REG);
>  
>  	/*
>  	 * First clock parent (osc32K) is unusable for CEC. But since there
Code Kipper Oct. 25, 2024, 1:20 p.m. UTC | #2
On Wed, 23 Oct 2024 at 09:59, Ryan Walklin <ryan@testtoast.com> wrote:
>
> Allwinner has previously released a H616 audio driver which also
> provides sigma-delta modulation for the audio PLL clocks. This approach
> is used in other Allwinner SoCs, including the H3 and A64.
>
> The manual-provided clock values are:
> PLL_AUDIO(hs) = 24 MHz*N/M1
> PLL_AUDIO(4X) = 24 MHz*N/M0/M1/P
> PLL_AUDIO(2X) = 24 MHz*N/M0/M1/P/2
> PLL_AUDIO(1X) = 24 MHz*N/M0/M1/P/4
>
> A fixed post-divider of 2 is used to account for a M0 divider of
> 2, which cannot be modelled by the existing macros and ccu_nm struct.
>
> Add SDM to the H616 clock control unit driver.
>
> Signed-off-by: Ryan Walklin <ryan@testtoast.com>
>
> ---
> Changelog v1..v2:
> - Add fixed_post_div to high-speed audio clock to correct M0 value to 1 (ie divide by 2) based on manual
> - Correct PLL_AUDIO_(4/2/1)X clocks to manual-provided values
> - Add/correct inline comments for the above.
> - add CCU_FEATURE_FIXED_POSTDIV to pll_audio_hs_clk.common.features
>
> Changelog v2..v3:
> - Update comments and commit message to more accurately reflect SDM changes and rationale
> ---
>  drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 46 +++++++++++++++++---------
>  1 file changed, 30 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> index 6c7623d4c59ea..05727fa1ee46e 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> @@ -215,20 +215,30 @@ static struct ccu_nkmp pll_de_clk = {
>         },
>  };
>
> -/*
> - * TODO: Determine SDM settings for the audio PLL. The manual suggests
> - * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b
> - * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2,
> - * pattern=0xe001288c for 22.5792 MHz.
> - * This clashes with our fixed PLL_POST_DIV_P.
> +/*
> + * Sigma-delta modulation settings table obtained from the vendor SDK driver.
> + * There are additional M0 and M1 divider bits not modelled here, so forced to
> + * fixed values in the probe routine. Sigma-delta modulation allows providing a
> + * fractional-N divider in the PLL, to help reaching those specific
> + * frequencies with less error.
>   */
> +static struct ccu_sdm_setting pll_audio_sdm_table[] = {
> +       { .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
> +       { .rate = 98304000, .pattern = 0xc001eb85, .m = 5, .n = 40 },
> +};
> +
>  #define SUN50I_H616_PLL_AUDIO_REG      0x078
>  static struct ccu_nm pll_audio_hs_clk = {
>         .enable         = BIT(31),
>         .lock           = BIT(28),
>         .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> -       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
> +       .m              = _SUNXI_CCU_DIV(16, 6),
> +       .sdm            = _SUNXI_CCU_SDM(pll_audio_sdm_table,
> +                                        BIT(24), 0x178, BIT(31)),
> +       .fixed_post_div = 2,
>         .common         = {
> +               .features       = CCU_FEATURE_FIXED_POSTDIV |
> +                                 CCU_FEATURE_SIGMA_DELTA_MOD,
>                 .reg            = 0x078,
>                 .hw.init        = CLK_HW_INIT("pll-audio-hs", "osc24M",
>                                               &ccu_nm_ops,
> @@ -701,18 +711,20 @@ static const struct clk_hw *clk_parent_pll_audio[] = {
>  };
>
>  /*
> - * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
> - * rates can be set exactly in conjunction with sigma-delta modulation.
> + * The PLL_AUDIO_4X clock defaults to 24.5714 MHz according to the manual, with
> + * a final divider of 1. The 2X and 1X clocks use 2 and 4 respectively. The 1x
> + * clock is set to either 24576000 or 22579200 for 48Khz and 44.1Khz (and
> + * multiples).
>   */
>  static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x",
>                             clk_parent_pll_audio,
> -                           96, 1, CLK_SET_RATE_PARENT);
> +                           4, 1, CLK_SET_RATE_PARENT);
>  static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
>                             clk_parent_pll_audio,
> -                           48, 1, CLK_SET_RATE_PARENT);
> +                           2, 1, CLK_SET_RATE_PARENT);
>  static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
>                             clk_parent_pll_audio,
> -                           24, 1, CLK_SET_RATE_PARENT);
> +                           1, 1, CLK_SET_RATE_PARENT);
>
>  static const struct clk_hw *pll_periph0_parents[] = {
>         &pll_periph0_clk.common.hw
> @@ -1162,12 +1174,14 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev)
>         }
>
>         /*
> -        * Force the post-divider of pll-audio to 12 and the output divider
> -        * of it to 2, so 24576000 and 22579200 rates can be set exactly.
> +        * Set the output-divider for the pll-audio clocks (M0) to 2 and the
> +        * input divider (M1) to 1 as recommended by the manual when using
> +        * SDM.
>          */
>         val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
> -       val &= ~(GENMASK(21, 16) | BIT(0));
> -       writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
> +       val &= ~BIT(1);
> +       val |= BIT(0);
> +       writel(val, reg + SUN50I_H616_PLL_AUDIO_REG);
>
>         /*
>          * First clock parent (osc32K) is unusable for CEC. But since there
Hi Ryan,
I noticed some white-space issues when cherry-picking this change from
your repo.
scripts/checkpatch.pl
0001-clk-sunxi-ng-h616-Add-sigma-delta-modulation-setting.patch
ERROR: trailing whitespace
#51: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:218:
+/* $

ERROR: trailing whitespace
#74: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:240:
+^I^I.features^I= CCU_FEATURE_FIXED_POSTDIV | $

ERROR: trailing whitespace
#85: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:698:
+ * The PLL_AUDIO_4X clock defaults to 24.5714 MHz according to the
manual, with $

ERROR: trailing whitespace
#86: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:699:
+ * a final divider of 1. The 2X and 1X clocks use 2 and 4
respectively. The 1x $

ERROR: trailing whitespace
#87: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:700:
+ * clock is set to either 24576000 or 22579200 for 48Khz and 44.1Khz (and $

ERROR: trailing whitespace
#112: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:1152:
+^I * input divider (M1) to 1 as recommended by the manual when using $

ERROR: trailing whitespace
#113: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:1153:
+^I * SDM. $

total: 7 errors, 0 warnings, 80 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

NOTE: Whitespace errors detected.
      You may wish to use scripts/cleanpatch or scripts/cleanfile

but that didn't stop it from singing beautifully!,

Tested-by: Marcus Cooper <codekipper@gmail.com>
BR,
CK
> --
> 2.47.0
>
>
Chen-Yu Tsai Oct. 25, 2024, 2:59 p.m. UTC | #3
On Fri, Oct 25, 2024 at 9:20 PM Code Kipper <codekipper@gmail.com> wrote:
>
> On Wed, 23 Oct 2024 at 09:59, Ryan Walklin <ryan@testtoast.com> wrote:
> >
> > Allwinner has previously released a H616 audio driver which also
> > provides sigma-delta modulation for the audio PLL clocks. This approach
> > is used in other Allwinner SoCs, including the H3 and A64.
> >
> > The manual-provided clock values are:
> > PLL_AUDIO(hs) = 24 MHz*N/M1
> > PLL_AUDIO(4X) = 24 MHz*N/M0/M1/P
> > PLL_AUDIO(2X) = 24 MHz*N/M0/M1/P/2
> > PLL_AUDIO(1X) = 24 MHz*N/M0/M1/P/4
> >
> > A fixed post-divider of 2 is used to account for a M0 divider of
> > 2, which cannot be modelled by the existing macros and ccu_nm struct.
> >
> > Add SDM to the H616 clock control unit driver.
> >
> > Signed-off-by: Ryan Walklin <ryan@testtoast.com>
> >
> > ---
> > Changelog v1..v2:
> > - Add fixed_post_div to high-speed audio clock to correct M0 value to 1 (ie divide by 2) based on manual
> > - Correct PLL_AUDIO_(4/2/1)X clocks to manual-provided values
> > - Add/correct inline comments for the above.
> > - add CCU_FEATURE_FIXED_POSTDIV to pll_audio_hs_clk.common.features
> >
> > Changelog v2..v3:
> > - Update comments and commit message to more accurately reflect SDM changes and rationale
> > ---
> >  drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 46 +++++++++++++++++---------
> >  1 file changed, 30 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> > index 6c7623d4c59ea..05727fa1ee46e 100644
> > --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> > @@ -215,20 +215,30 @@ static struct ccu_nkmp pll_de_clk = {
> >         },
> >  };
> >
> > -/*
> > - * TODO: Determine SDM settings for the audio PLL. The manual suggests
> > - * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b
> > - * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2,
> > - * pattern=0xe001288c for 22.5792 MHz.
> > - * This clashes with our fixed PLL_POST_DIV_P.
> > +/*
> > + * Sigma-delta modulation settings table obtained from the vendor SDK driver.
> > + * There are additional M0 and M1 divider bits not modelled here, so forced to
> > + * fixed values in the probe routine. Sigma-delta modulation allows providing a
> > + * fractional-N divider in the PLL, to help reaching those specific
> > + * frequencies with less error.
> >   */
> > +static struct ccu_sdm_setting pll_audio_sdm_table[] = {
> > +       { .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
> > +       { .rate = 98304000, .pattern = 0xc001eb85, .m = 5, .n = 40 },
> > +};
> > +
> >  #define SUN50I_H616_PLL_AUDIO_REG      0x078
> >  static struct ccu_nm pll_audio_hs_clk = {
> >         .enable         = BIT(31),
> >         .lock           = BIT(28),
> >         .n              = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> > -       .m              = _SUNXI_CCU_DIV(1, 1), /* input divider */
> > +       .m              = _SUNXI_CCU_DIV(16, 6),
> > +       .sdm            = _SUNXI_CCU_SDM(pll_audio_sdm_table,
> > +                                        BIT(24), 0x178, BIT(31)),
> > +       .fixed_post_div = 2,
> >         .common         = {
> > +               .features       = CCU_FEATURE_FIXED_POSTDIV |
> > +                                 CCU_FEATURE_SIGMA_DELTA_MOD,
> >                 .reg            = 0x078,
> >                 .hw.init        = CLK_HW_INIT("pll-audio-hs", "osc24M",
> >                                               &ccu_nm_ops,
> > @@ -701,18 +711,20 @@ static const struct clk_hw *clk_parent_pll_audio[] = {
> >  };
> >
> >  /*
> > - * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
> > - * rates can be set exactly in conjunction with sigma-delta modulation.
> > + * The PLL_AUDIO_4X clock defaults to 24.5714 MHz according to the manual, with
> > + * a final divider of 1. The 2X and 1X clocks use 2 and 4 respectively. The 1x
> > + * clock is set to either 24576000 or 22579200 for 48Khz and 44.1Khz (and
> > + * multiples).
> >   */
> >  static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x",
> >                             clk_parent_pll_audio,
> > -                           96, 1, CLK_SET_RATE_PARENT);
> > +                           4, 1, CLK_SET_RATE_PARENT);
> >  static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
> >                             clk_parent_pll_audio,
> > -                           48, 1, CLK_SET_RATE_PARENT);
> > +                           2, 1, CLK_SET_RATE_PARENT);
> >  static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
> >                             clk_parent_pll_audio,
> > -                           24, 1, CLK_SET_RATE_PARENT);
> > +                           1, 1, CLK_SET_RATE_PARENT);
> >
> >  static const struct clk_hw *pll_periph0_parents[] = {
> >         &pll_periph0_clk.common.hw
> > @@ -1162,12 +1174,14 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev)
> >         }
> >
> >         /*
> > -        * Force the post-divider of pll-audio to 12 and the output divider
> > -        * of it to 2, so 24576000 and 22579200 rates can be set exactly.
> > +        * Set the output-divider for the pll-audio clocks (M0) to 2 and the
> > +        * input divider (M1) to 1 as recommended by the manual when using
> > +        * SDM.
> >          */
> >         val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
> > -       val &= ~(GENMASK(21, 16) | BIT(0));
> > -       writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
> > +       val &= ~BIT(1);
> > +       val |= BIT(0);
> > +       writel(val, reg + SUN50I_H616_PLL_AUDIO_REG);
> >
> >         /*
> >          * First clock parent (osc32K) is unusable for CEC. But since there
> Hi Ryan,
> I noticed some white-space issues when cherry-picking this change from
> your repo.
> scripts/checkpatch.pl
> 0001-clk-sunxi-ng-h616-Add-sigma-delta-modulation-setting.patch
> ERROR: trailing whitespace
> #51: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:218:
> +/* $
>
> ERROR: trailing whitespace
> #74: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:240:
> +^I^I.features^I= CCU_FEATURE_FIXED_POSTDIV | $
>
> ERROR: trailing whitespace
> #85: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:698:
> + * The PLL_AUDIO_4X clock defaults to 24.5714 MHz according to the
> manual, with $
>
> ERROR: trailing whitespace
> #86: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:699:
> + * a final divider of 1. The 2X and 1X clocks use 2 and 4
> respectively. The 1x $
>
> ERROR: trailing whitespace
> #87: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:700:
> + * clock is set to either 24576000 or 22579200 for 48Khz and 44.1Khz (and $
>
> ERROR: trailing whitespace
> #112: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:1152:
> +^I * input divider (M1) to 1 as recommended by the manual when using $
>
> ERROR: trailing whitespace
> #113: FILE: drivers/clk/sunxi-ng/ccu-sun50i-h616.c:1153:
> +^I * SDM. $
>
> total: 7 errors, 0 warnings, 80 lines checked
>
> NOTE: For some of the reported defects, checkpatch may be able to
>       mechanically convert to the typical style using --fix or --fix-inplace.
>
> NOTE: Whitespace errors detected.
>       You may wish to use scripts/cleanpatch or scripts/cleanfile

I fixed up all the whitespace errors when applying.

ChenYu

> but that didn't stop it from singing beautifully!,
>
> Tested-by: Marcus Cooper <codekipper@gmail.com>
> BR,
> CK
> > --
> > 2.47.0
> >
> >
diff mbox series

Patch

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
index 6c7623d4c59ea..05727fa1ee46e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
@@ -215,20 +215,30 @@  static struct ccu_nkmp pll_de_clk = {
 	},
 };
 
-/*
- * TODO: Determine SDM settings for the audio PLL. The manual suggests
- * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b
- * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2,
- * pattern=0xe001288c for 22.5792 MHz.
- * This clashes with our fixed PLL_POST_DIV_P.
+/* 
+ * Sigma-delta modulation settings table obtained from the vendor SDK driver.
+ * There are additional M0 and M1 divider bits not modelled here, so forced to
+ * fixed values in the probe routine. Sigma-delta modulation allows providing a
+ * fractional-N divider in the PLL, to help reaching those specific
+ * frequencies with less error.
  */
+static struct ccu_sdm_setting pll_audio_sdm_table[] = {
+	{ .rate = 90316800, .pattern = 0xc001288d, .m = 3, .n = 22 },
+	{ .rate = 98304000, .pattern = 0xc001eb85, .m = 5, .n = 40 },
+};
+
 #define SUN50I_H616_PLL_AUDIO_REG	0x078
 static struct ccu_nm pll_audio_hs_clk = {
 	.enable		= BIT(31),
 	.lock		= BIT(28),
 	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
-	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
+	.m		= _SUNXI_CCU_DIV(16, 6),
+	.sdm		= _SUNXI_CCU_SDM(pll_audio_sdm_table,
+					 BIT(24), 0x178, BIT(31)),
+	.fixed_post_div = 2,
 	.common		= {
+		.features	= CCU_FEATURE_FIXED_POSTDIV | 
+				  CCU_FEATURE_SIGMA_DELTA_MOD,
 		.reg		= 0x078,
 		.hw.init	= CLK_HW_INIT("pll-audio-hs", "osc24M",
 					      &ccu_nm_ops,
@@ -701,18 +711,20 @@  static const struct clk_hw *clk_parent_pll_audio[] = {
 };
 
 /*
- * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
- * rates can be set exactly in conjunction with sigma-delta modulation.
+ * The PLL_AUDIO_4X clock defaults to 24.5714 MHz according to the manual, with 
+ * a final divider of 1. The 2X and 1X clocks use 2 and 4 respectively. The 1x 
+ * clock is set to either 24576000 or 22579200 for 48Khz and 44.1Khz (and 
+ * multiples).
  */
 static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x",
 			    clk_parent_pll_audio,
-			    96, 1, CLK_SET_RATE_PARENT);
+			    4, 1, CLK_SET_RATE_PARENT);
 static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
 			    clk_parent_pll_audio,
-			    48, 1, CLK_SET_RATE_PARENT);
+			    2, 1, CLK_SET_RATE_PARENT);
 static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
 			    clk_parent_pll_audio,
-			    24, 1, CLK_SET_RATE_PARENT);
+			    1, 1, CLK_SET_RATE_PARENT);
 
 static const struct clk_hw *pll_periph0_parents[] = {
 	&pll_periph0_clk.common.hw
@@ -1162,12 +1174,14 @@  static int sun50i_h616_ccu_probe(struct platform_device *pdev)
 	}
 
 	/*
-	 * Force the post-divider of pll-audio to 12 and the output divider
-	 * of it to 2, so 24576000 and 22579200 rates can be set exactly.
+	 * Set the output-divider for the pll-audio clocks (M0) to 2 and the
+	 * input divider (M1) to 1 as recommended by the manual when using 
+	 * SDM. 
 	 */
 	val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
-	val &= ~(GENMASK(21, 16) | BIT(0));
-	writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
+	val &= ~BIT(1);
+	val |= BIT(0);
+	writel(val, reg + SUN50I_H616_PLL_AUDIO_REG);
 
 	/*
 	 * First clock parent (osc32K) is unusable for CEC. But since there