Re: [PATCH v4 1/5] clk: sunxi-ng: common: Support minimum and maximum rate

2024-05-22 Thread Frank Oltmanns
Hi Måns,

21.05.2024 15:43:10 Måns Rullgård :

> Frank Oltmanns  writes:
>
>> The Allwinner SoC's typically have an upper and lower limit for their
>> clocks' rates. Up until now, support for that has been implemented
>> separately for each clock type.
>>
>> Implement that functionality in the sunxi-ng's common part making use of
>> the CCF rate liming capabilities, so that it is available for all clock
>> types.
>>
>> Suggested-by: Maxime Ripard 
>> Signed-off-by: Frank Oltmanns 
>> Cc: sta...@vger.kernel.org
>> ---
>> drivers/clk/sunxi-ng/ccu_common.c | 19 +++
>> drivers/clk/sunxi-ng/ccu_common.h |  3 +++
>> 2 files changed, 22 insertions(+)
>
> This just landed in 6.6 stable, and it broke HDMI output on an A20 based
> device, the clocks ending up all wrong as seen in this diff of
> /sys/kernel/debug/clk/clk_summary:
>
> @@ -70,16 +71,14 @@
>    apb1-i2c0  0   0    0    2400    0 
>  
>   
>  
>     pll-gpu   0   0    0    12  0 
>  
> -   pll-video1    3   3    1    15900   0 
>  
> +   pll-video1    2   2    1    15900   0 
>  
>    hdmi   1   1    0    3975    0 
>  
>   
>  
>    tcon0-ch1-sclk2    1   1    1    3975    0 
>  
>   tcon0-ch1-sclk1 1   1    1    3975    0 
>  
>   
>  
> -  pll-video1-2x  1   1    0    31800   0 
>  
> +  pll-video1-2x  0   0    0    31800   0 
>  
>   
>  
> - hdmi-tmds   2   2    0    3975    0 
>  
> -    hdmi-ddc 1   1    0    1987500 0 
>  
>     pll-periph-base   2   2    0    12  0 
>  
>    mbus   1   1    0    3   0 
>  
>    pll-periph-sata    0   0    0    1   0 
>  
> @@ -199,7 +198,7 @@
>   
>  
>    ace    0   0    0    38400   0 
>  
>    ve 0   0    0    38400   0 
>  
> -   pll-video0    4   4    2    29700   0 
>  
> +   pll-video0    5   5    2    29700   0 
>  
>    hdmi1  0   0    0    29700   0 
>  
>    tcon1-ch1-sclk2    0   0    0    29700   0 
>  
>   tcon1-ch1-sclk1 0   0    0    29700   0 
>  
> @@ -222,8 +221,10 @@
>   
>  
>    de-be0 1   1    1    29700   0 
>  
>   
>  
> -  pll-video0-2x  0   0    0    59400   0 
>  
> +  pll-video0-2x  1   1    0    59400   0 
>  
>   
>  
> + hdmi-tmds   2   2    0    59400   0 
>  
> +    hdmi-ddc 1   1    0    2970    0 
>  
>     pll-audio-base    0   0    0    150 0 
>  
>    pll-audio-8x   0   0    0    300 0 
>  
>   i2s2    0   0    0    300 0 
>  
>
> Reverting this commit makes it work again.

Thank you for your detailed report!

I've had a first look at hdmi-tmds and hdmi-ddc, and neither seems to be 
calling ccu_is_better_rate() in their determine_rate() functions. Their parents 
have the exact same rates in your diff, so, my current working assumption is 
that they can't be the cause either.

I'll have a more detailed look over the weekend. Until then, if anyone has some 
ideas where I should have a look next, please share your thoughts.

Best regards,
  Frank

>
>> diff --git a/drivers/clk/sunxi-ng/ccu_co

Re: [PATCH v4 0/5] Pinephone video out fixes (flipping between two frames)

2024-04-03 Thread Frank Oltmanns
Dear clk and sunxi-ng maintainers,

Patches 1-4 have been reviewed and there are no pending issues. If there
is something else you need me to do to get this applied, please let me
know.

Thanks,
  Frank

On 2024-03-10 at 14:21:10 +0100, Frank Oltmanns  wrote:
> On some pinephones the video output sometimes freezes (flips between two
> frames) [1]. It seems to be that the reason for this behaviour is that
> PLL-MIPI is outside its limits, and the GPU is not running at a fixed
> rate.
>
> In this patch series I propose the following changes:
>   1. sunxi-ng: Adhere to the following constraints given in the
>  Allwinner A64 Manual regarding PLL-MIPI:
>   * M/N <= 3
>   * (PLL_VIDEO0)/M >= 24MHz
>   * 500MHz <= clockrate <= 1400MHz
>
>   2. Remove two operating points from the A64 DTS OPPs, so that the GPU
>  runs at a fixed rate of 432 MHz.
>
> Note, that when pinning the GPU to 432 MHz the issue [1] completely
> disappears for me. I've searched the BSP and could not find any
> indication that supports the idea of having the three OPPs. The only
> frequency I found in the BPSs for A64 is 432 MHz, which has also proven
> stable for me.
>
> I very much appreciate your feedback!
>
> [1] https://gitlab.com/postmarketOS/pmaports/-/issues/805
>
> Signed-off-by: Frank Oltmanns 
> ---
> Changes in v4:
> - sunxi-ng: common: Address review comments.
> - Link to v3: 
> https://lore.kernel.org/r/20240304-pinephone-pll-fixes-v3-0-94ab828f2...@oltmanns.dev
>
> Changes in v3:
> - dts: Pin GPU to 432 MHz.
> - nkm and a64: Move minimum and maximum rate handling to the common part
>   of the sunxi-ng driver.
> - Removed st7703 patch from series.
> - Link to v2: 
> https://lore.kernel.org/r/20240205-pinephone-pll-fixes-v2-0-96a46a2d8...@oltmanns.dev
>
> Changes in v2:
> - dts: Increase minimum GPU frequency to 192 MHz.
> - nkm and a64: Add minimum and maximum rate for PLL-MIPI.
> - nkm: Use the same approach for skipping invalid rates in
>   ccu_nkm_find_best() as in ccu_nkm_find_best_with_parent_adj().
> - nkm: Improve names for ratio struct members and hence get rid of
>   describing comments.
> - nkm and a64: Correct description in the commit messages: M/N <= 3
> - Remove patches for nm as they were not needed.
> - st7703: Rework the commit message to cover more background for the
>   change.
> - Link to v1: 
> https://lore.kernel.org/r/20231218-pinephone-pll-fixes-v1-0-e238b6ed6...@oltmanns.dev
>
> ---
> Frank Oltmanns (5):
>   clk: sunxi-ng: common: Support minimum and maximum rate
>   clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI
>   clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate
>   clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent 
> rate
>   arm64: dts: allwinner: a64: Run GPU at 432 MHz
>
>  arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi |  8 
>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 14 +-
>  drivers/clk/sunxi-ng/ccu_common.c | 19 +++
>  drivers/clk/sunxi-ng/ccu_common.h |  3 +++
>  drivers/clk/sunxi-ng/ccu_nkm.c| 21 +
>  drivers/clk/sunxi-ng/ccu_nkm.h|  2 ++
>  6 files changed, 54 insertions(+), 13 deletions(-)
> ---
> base-commit: dcb6c8ee6acc6c347caec1e73fb900c0f4ff9806
> change-id: 20231218-pinephone-pll-fixes-0ccdfde273e4
>
> Best regards,


Re: [PATCH] drm/sun4i: tcon: Support keeping dclk rate upon ancestor clock changes

2024-03-13 Thread Frank Oltmanns
On 2024-03-13 at 19:11:37 +0100, Jernej Škrabec  
wrote:
Hi Jernej,

Thank you for your having a thorough look at this!

> Hi Frank!
>
> Thanks on tackling this issue.
>
> Dne nedelja, 10. marec 2024 ob 14:32:29 CET je Frank Oltmanns napisal(a):
>> Allow the dclk to reset its rate when a rate change is initiated from an
>> ancestor clock. This makes it possible to no longer to get an exclusive
>> lock. As a consequence, it is now possible to set new rates if
>> necessary, e.g. when an external display is connected.
>>
>> The first user of this functionality is the A64 because PLL-VIDEO0 is an
>> ancestor for both HDMI and TCON0. This allows to select an optimal rate
>> for TCON0 as long as there is no external HDMI connection. Once a change
>> in PLL-VIDEO0 is performed when an HDMI connection is established, TCON0
>> can react gracefully and select an optimal rate based on this the new
>> constraint.
>>
>> Signed-off-by: Frank Oltmanns 
>> ---
>> I would like to make the Allwinner A64's data-clock keep its rate
>> when its ancestor's (pll-video0) rate changes. Keeping data-clock's rate
>> is required, to let the A64 drive both an LCD and HDMI display at the
>> same time, because both have pll-video0 as an ancestor.
>>
>> TCONs that use this flag store the ideal rate for their data-clock and
>> subscribe to be notified when data-clock changes. When rate setting has
>> finished (indicated by a POST_RATE_CHANGE event) the call back function
>> schedules delayed work to set the data-clock's rate to the initial value
>> after 100 ms. Using delayed work maks sure that the clock setting is
>> finished.
>>
>> I've implemented this functionality as a quirk, so that it is possible
>> to use it only for the A64.
>>
>> This patch supersedes [1].
>>
>> This work is inspired by an out-of-tree patchset [2] [3] [4].
>> Unfortunately, the patchset uses clk_set_rate() directly in a notifier
>> callback, which the following comment on clk_notifier_register()
>> forbids: "The callbacks associated with the notifier must not re-enter
>> into the clk framework by calling any top-level clk APIs." [5]
>> Furthermore, that out-of-tree patchset no longer works since 6.6,
>> because setting pll-mipi is now also resetting pll-video0 and therefore
>> causes a race condition.
>>
>> Thank you for considering this contribution,
>>   Frank
>>
>> [1] 
>> https://lore.kernel.org/lkml/20230825-pll-mipi_keep_rate-v1-0-35bc43570...@oltmanns.dev/
>> [2] 
>> https://codeberg.org/megi/linux/commit/a37cda2fff41a67a2bacf82b1594e10335d0bd8a
>> [3] 
>> https://codeberg.org/megi/linux/commit/24dc09128d2c8efc6ddf19249420e9798e967a46
>> [4] 
>> https://codeberg.org/megi/linux/commit/728a93d46f99f0eb231ed6fa8971a45f97c7182c
>> [5] https://elixir.bootlin.com/linux/v6.7.9/source/drivers/clk/clk.c#L4669
>> ---
>>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 70 
>> ++
>>  drivers/gpu/drm/sun4i/sun4i_tcon.h | 12 +++
>>  2 files changed, 76 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
>> b/drivers/gpu/drm/sun4i/sun4i_tcon.c
>> index a1a2c845ade0..b880bd44049a 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
>> @@ -108,9 +108,11 @@ static void sun4i_tcon_channel_set_status(struct 
>> sun4i_tcon *tcon, int channel,
>>
>>  if (enabled) {
>>  clk_prepare_enable(clk);
>> -clk_rate_exclusive_get(clk);
>> +if (!tcon->quirks->restores_rate)
>> +clk_rate_exclusive_get(clk);
>>  } else {
>> -clk_rate_exclusive_put(clk);
>> +if (!tcon->quirks->restores_rate)
>> +clk_rate_exclusive_put(clk);
>>  clk_disable_unprepare(clk);
>>  }
>>  }
>> @@ -343,6 +345,53 @@ static void sun4i_tcon0_mode_set_dithering(struct 
>> sun4i_tcon *tcon,
>>  regmap_write(tcon->regs, SUN4I_TCON_FRM_CTL_REG, val);
>>  }
>>
>> +static void sun4i_rate_reset_notifier_delayed_update(struct work_struct 
>> *work)
>> +{
>> +struct sun4i_rate_reset_nb *rate_reset = container_of(work, struct 
>> sun4i_rate_reset_nb,
>> +
>> reset_rate_work.work);
>> +
>> +clk_set_rate(rate_reset->target_clk, rate_reset->saved_rate);
>> +}
>> +
>> +static int sun4i_rate_reset_notifier_cb(struct notifier_block *nb,

Re: [PATCH] drm/sun4i: tcon: Support keeping dclk rate upon ancestor clock changes

2024-03-11 Thread Frank Oltmanns
Hello Ondřej,

On 2024-03-10 at 23:23:57 +0100, Ondřej Jirman  wrote:
> Hello Frank,
>
> On Sun, Mar 10, 2024 at 02:32:29PM +0100, Frank Oltmanns wrote:
>> +static int sun4i_rate_reset_notifier_cb(struct notifier_block *nb,
>> +  unsigned long event, void *data)
>> +{
>> +struct sun4i_rate_reset_nb *rate_reset = to_sun4i_rate_reset_nb(nb);
>> +
>> +if (event == POST_RATE_CHANGE)
>> +schedule_delayed_work(_reset->reset_rate_work, 
>> msecs_to_jiffies(100));
>
> If you get multiple reset notifier calls within 100ms of the first one,
> the delay from the last one will not be 100ms, so this may violate 
> expectations
> you're describing in the commit message.

Let me start by saying, the implicit expectation is that the new user of
pll-video0 will get an exclusive lock on pll-video0 (otherwise,
data-clock would reset pll-video0 after those 100ms rendering the whole
endeavor of the new user pointless). This constraint makes the chances
that the above event (two consecutive rate changes within 100ms) occurs
very slim.

That being said, I don't see a problem with cancelling the delayed work
on PRE_RATE_CHANGE and restarting it on ABORT_RATE_CHANGE like this:

+static int sun4i_rate_reset_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+   struct sun4i_rate_reset_nb *rate_reset = to_sun4i_rate_reset_nb(nb);
+
+   if (event == PRE_RATE_CHANGE) {
+   rate_reset->is_cancelled = 
cancel_delayed_work(_reset->reset_rate_work);
+   } else if ((event == POST_RATE_CHANGE) ||
+(event == ABORT_RATE_CHANGE) && rate_reset->is_cancelled) {
+   schedule_delayed_work(_reset->reset_rate_work, 
msecs_to_jiffies(100));
+   rate_reset->is_cancelled = false;
+   }
+
+   return NOTIFY_DONE;
+}

The need for this new code is slim (IMHO) but on the other hand it
doesn't add much complexity. I'll add it in V2 including the
is_cancelled member in sun4i_rate_reset_nb if I don't receive any
objections during this week.

Thanks,
  Frank

>
> schedule_delayed_work doesn't re-schedule the work if it's already pending.
>
> Kind regards,
>   o.


[PATCH] drm/sun4i: tcon: Support keeping dclk rate upon ancestor clock changes

2024-03-10 Thread Frank Oltmanns
Allow the dclk to reset its rate when a rate change is initiated from an
ancestor clock. This makes it possible to no longer to get an exclusive
lock. As a consequence, it is now possible to set new rates if
necessary, e.g. when an external display is connected.

The first user of this functionality is the A64 because PLL-VIDEO0 is an
ancestor for both HDMI and TCON0. This allows to select an optimal rate
for TCON0 as long as there is no external HDMI connection. Once a change
in PLL-VIDEO0 is performed when an HDMI connection is established, TCON0
can react gracefully and select an optimal rate based on this the new
constraint.

Signed-off-by: Frank Oltmanns 
---
I would like to make the Allwinner A64's data-clock keep its rate
when its ancestor's (pll-video0) rate changes. Keeping data-clock's rate
is required, to let the A64 drive both an LCD and HDMI display at the
same time, because both have pll-video0 as an ancestor.

TCONs that use this flag store the ideal rate for their data-clock and
subscribe to be notified when data-clock changes. When rate setting has
finished (indicated by a POST_RATE_CHANGE event) the call back function
schedules delayed work to set the data-clock's rate to the initial value
after 100 ms. Using delayed work maks sure that the clock setting is
finished.

I've implemented this functionality as a quirk, so that it is possible
to use it only for the A64.

This patch supersedes [1].

This work is inspired by an out-of-tree patchset [2] [3] [4].
Unfortunately, the patchset uses clk_set_rate() directly in a notifier
callback, which the following comment on clk_notifier_register()
forbids: "The callbacks associated with the notifier must not re-enter
into the clk framework by calling any top-level clk APIs." [5]
Furthermore, that out-of-tree patchset no longer works since 6.6,
because setting pll-mipi is now also resetting pll-video0 and therefore
causes a race condition.

Thank you for considering this contribution,
  Frank

[1] 
https://lore.kernel.org/lkml/20230825-pll-mipi_keep_rate-v1-0-35bc43570...@oltmanns.dev/
[2] 
https://codeberg.org/megi/linux/commit/a37cda2fff41a67a2bacf82b1594e10335d0bd8a
[3] 
https://codeberg.org/megi/linux/commit/24dc09128d2c8efc6ddf19249420e9798e967a46
[4] 
https://codeberg.org/megi/linux/commit/728a93d46f99f0eb231ed6fa8971a45f97c7182c
[5] https://elixir.bootlin.com/linux/v6.7.9/source/drivers/clk/clk.c#L4669
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 70 ++
 drivers/gpu/drm/sun4i/sun4i_tcon.h | 12 +++
 2 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index a1a2c845ade0..b880bd44049a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -108,9 +108,11 @@ static void sun4i_tcon_channel_set_status(struct 
sun4i_tcon *tcon, int channel,
 
if (enabled) {
clk_prepare_enable(clk);
-   clk_rate_exclusive_get(clk);
+   if (!tcon->quirks->restores_rate)
+   clk_rate_exclusive_get(clk);
} else {
-   clk_rate_exclusive_put(clk);
+   if (!tcon->quirks->restores_rate)
+   clk_rate_exclusive_put(clk);
clk_disable_unprepare(clk);
}
 }
@@ -343,6 +345,53 @@ static void sun4i_tcon0_mode_set_dithering(struct 
sun4i_tcon *tcon,
regmap_write(tcon->regs, SUN4I_TCON_FRM_CTL_REG, val);
 }
 
+static void sun4i_rate_reset_notifier_delayed_update(struct work_struct *work)
+{
+   struct sun4i_rate_reset_nb *rate_reset = container_of(work, struct 
sun4i_rate_reset_nb,
+   
reset_rate_work.work);
+
+   clk_set_rate(rate_reset->target_clk, rate_reset->saved_rate);
+}
+
+static int sun4i_rate_reset_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+   struct sun4i_rate_reset_nb *rate_reset = to_sun4i_rate_reset_nb(nb);
+
+   if (event == POST_RATE_CHANGE)
+   schedule_delayed_work(_reset->reset_rate_work, 
msecs_to_jiffies(100));
+
+   return NOTIFY_DONE;
+}
+
+static void sun4i_rate_reset_notifier_register(struct sun4i_rate_reset_nb 
*rate_reset_nb)
+{
+   if (rate_reset_nb->is_registered)
+   return;
+
+   rate_reset_nb->clk_nb.notifier_call = sun4i_rate_reset_notifier_cb;
+
+   INIT_DELAYED_WORK(_reset_nb->reset_rate_work,
+ sun4i_rate_reset_notifier_delayed_update);
+
+   if (!clk_notifier_register(rate_reset_nb->target_clk,
+  _reset_nb->clk_nb))
+   rate_reset_nb->is_registered = true;
+}
+
+static struct sun4i_rate_reset_nb tcon_rate_reset_tcon0_nb;
+
+static void sun4i_tcon0_set_dclk_rate(struct sun4i_tcon *tcon, unsigned long 
rate)
+{
+   clk_set_rate(tcon->

[PATCH v4 5/5] arm64: dts: allwinner: a64: Run GPU at 432 MHz

2024-03-10 Thread Frank Oltmanns
The Allwinner A64's GPU has currently three operating points. However,
the BSP runs the GPU fixed at 432 MHz. In addition, at least one of the
devices using that SoC - the pinephone - shows unstabilities (see link)
that can be circumvented by running the GPU at a fixed rate.

Therefore, remove the other two operating points from the GPU OPP table,
so that the GPU runs at a fixed rate of 432 MHz.

Link: https://gitlab.com/postmarketOS/pmaports/-/issues/805
Acked-by: Erico Nunes 
Signed-off-by: Frank Oltmanns 
---
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 8 
 1 file changed, 8 deletions(-)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 57ac18738c99..c810380aab6d 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -107,14 +107,6 @@ de: display-engine {
gpu_opp_table: opp-table-gpu {
compatible = "operating-points-v2";
 
-   opp-12000 {
-   opp-hz = /bits/ 64 <12000>;
-   };
-
-   opp-31200 {
-   opp-hz = /bits/ 64 <31200>;
-   };
-
opp-43200 {
opp-hz = /bits/ 64 <43200>;
};

-- 
2.44.0



[PATCH v4 4/5] clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent rate

2024-03-10 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N <= 3
 - (PLL_VIDEO0)/M >= 24MHz

Use these constraints.

Reviewed-by: Jernej Skrabec 
Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 6a4b2b9ef30a..07796c79a23e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -171,11 +171,13 @@ static struct ccu_nkm pll_mipi_clk = {
 * user manual, and by experiments the PLL doesn't work without
 * these bits toggled.
 */
-   .enable = BIT(31) | BIT(23) | BIT(22),
-   .lock   = BIT(28),
-   .n  = _SUNXI_CCU_MULT(8, 4),
-   .k  = _SUNXI_CCU_MULT_MIN(4, 2, 2),
-   .m  = _SUNXI_CCU_DIV(0, 4),
+   .enable = BIT(31) | BIT(23) | BIT(22),
+   .lock   = BIT(28),
+   .n  = _SUNXI_CCU_MULT(8, 4),
+   .k  = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+   .m  = _SUNXI_CCU_DIV(0, 4),
+   .max_m_n_ratio  = 3,
+   .min_parent_m_ratio = 2400,
.common = {
.reg= 0x040,
.hw.init= CLK_HW_INIT("pll-mipi", "pll-video0",

-- 
2.44.0



[PATCH v4 2/5] clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI

2024-03-10 Thread Frank Oltmanns
When the Allwinner A64's TCON0 searches the ideal rate for the connected
panel, it may happen that it requests a rate from its parent PLL-MIPI
which PLL-MIPI does not support.

This happens for example on the Olimex TERES-I laptop where TCON0
requests PLL-MIPI to change to a rate of several GHz which causes the
panel to stay blank. It also happens on the pinephone where a rate of
less than 500 MHz is requested which causes instabilities on some
phones.

Set the minimum and maximum rate of Allwinner A64's PLL-MIPI according
to the Allwinner User Manual.

Fixes: ca1170b69968 ("clk: sunxi-ng: a64: force select PLL_MIPI in TCON0 mux")
Reported-by: Diego Roversi 
Closes: https://groups.google.com/g/linux-sunxi/c/Rh-Uqqa66bw
Tested-by: Diego Roversi 
Cc: sta...@vger.kernel.org
Reviewed-by: Maxime Ripard 
Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 8951ffc14ff5..6a4b2b9ef30a 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = {
  _nkm_ops,
  CLK_SET_RATE_UNGATE | 
CLK_SET_RATE_PARENT),
.features   = CCU_FEATURE_CLOSEST_RATE,
+   .min_rate   = 5,
+   .max_rate   = 14,
},
 };
 

-- 
2.44.0



[PATCH v4 3/5] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate

2024-03-10 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N <= 3
 - (PLL_VIDEO0)/M >= 24MHz

The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for
these constraints.

Reviewed-by: Jernej Skrabec 
Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu_nkm.c | 21 +
 drivers/clk/sunxi-ng/ccu_nkm.h |  2 ++
 2 files changed, 23 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 853f84398e2b..1168d894d636 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -16,6 +16,20 @@ struct _ccu_nkm {
unsigned long   m, min_m, max_m;
 };
 
+static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long 
parent,
+ unsigned long n, unsigned long m)
+{
+   struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common);
+
+   if (nkm->max_m_n_ratio && (m > nkm->max_m_n_ratio * n))
+   return false;
+
+   if (nkm->min_parent_m_ratio && (parent < nkm->min_parent_m_ratio * m))
+   return false;
+
+   return true;
+}
+
 static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common 
*common,
   struct clk_hw *parent_hw,
   unsigned long *parent, 
unsigned long rate,
@@ -31,6 +45,10 @@ static unsigned long 
ccu_nkm_find_best_with_parent_adj(struct ccu_common *common
unsigned long tmp_rate, tmp_parent;
 
tmp_parent = clk_hw_round_rate(parent_hw, rate 
* _m / (_n * _k));
+
+   if (!ccu_nkm_is_valid_rate(common, tmp_parent, 
_n, _m))
+   continue;
+
tmp_rate = tmp_parent * _n * _k / _m;
 
if (ccu_is_better_rate(common, rate, tmp_rate, 
best_rate) ||
@@ -64,6 +82,9 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, 
unsigned long rate,
for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
+   if (!ccu_nkm_is_valid_rate(common, parent, _n, 
_m))
+   continue;
+
unsigned long tmp_rate;
 
tmp_rate = parent * _n * _k / _m;
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
index 6601defb3f38..c409212ee40e 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.h
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -27,6 +27,8 @@ struct ccu_nkm {
struct ccu_mux_internal mux;
 
unsigned intfixed_post_div;
+   unsigned long   max_m_n_ratio;
+   unsigned long   min_parent_m_ratio;
 
struct ccu_common   common;
 };

-- 
2.44.0



[PATCH v4 1/5] clk: sunxi-ng: common: Support minimum and maximum rate

2024-03-10 Thread Frank Oltmanns
The Allwinner SoC's typically have an upper and lower limit for their
clocks' rates. Up until now, support for that has been implemented
separately for each clock type.

Implement that functionality in the sunxi-ng's common part making use of
the CCF rate liming capabilities, so that it is available for all clock
types.

Suggested-by: Maxime Ripard 
Signed-off-by: Frank Oltmanns 
Cc: sta...@vger.kernel.org
---
 drivers/clk/sunxi-ng/ccu_common.c | 19 +++
 drivers/clk/sunxi-ng/ccu_common.h |  3 +++
 2 files changed, 22 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_common.c 
b/drivers/clk/sunxi-ng/ccu_common.c
index 8babce55302f..ac0091b4ce24 100644
--- a/drivers/clk/sunxi-ng/ccu_common.c
+++ b/drivers/clk/sunxi-ng/ccu_common.c
@@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common,
unsigned long current_rate,
unsigned long best_rate)
 {
+   unsigned long min_rate, max_rate;
+
+   clk_hw_get_rate_range(>hw, _rate, _rate);
+
+   if (current_rate > max_rate)
+   return false;
+
+   if (current_rate < min_rate)
+   return false;
+
if (common->features & CCU_FEATURE_CLOSEST_RATE)
return abs(current_rate - target_rate) < abs(best_rate - 
target_rate);
 
@@ -122,6 +132,7 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct 
device *dev,
 
for (i = 0; i < desc->hw_clks->num ; i++) {
struct clk_hw *hw = desc->hw_clks->hws[i];
+   struct ccu_common *common = hw_to_ccu_common(hw);
const char *name;
 
if (!hw)
@@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct 
device *dev,
pr_err("Couldn't register clock %d - %s\n", i, name);
goto err_clk_unreg;
}
+
+   if (common->max_rate)
+   clk_hw_set_rate_range(hw, common->min_rate,
+ common->max_rate);
+   else
+   WARN(common->min_rate,
+"No max_rate, ignoring min_rate of clock %d - 
%s\n",
+i, name);
}
 
ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
diff --git a/drivers/clk/sunxi-ng/ccu_common.h 
b/drivers/clk/sunxi-ng/ccu_common.h
index 942a72c09437..329734f8cf42 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -31,6 +31,9 @@ struct ccu_common {
u16 lock_reg;
u32 prediv;
 
+   unsigned long   min_rate;
+   unsigned long   max_rate;
+
unsigned long   features;
spinlock_t  *lock;
struct clk_hw   hw;

-- 
2.44.0



[PATCH v4 0/5] Pinephone video out fixes (flipping between two frames)

2024-03-10 Thread Frank Oltmanns
On some pinephones the video output sometimes freezes (flips between two
frames) [1]. It seems to be that the reason for this behaviour is that
PLL-MIPI is outside its limits, and the GPU is not running at a fixed
rate.

In this patch series I propose the following changes:
  1. sunxi-ng: Adhere to the following constraints given in the
 Allwinner A64 Manual regarding PLL-MIPI:
  * M/N <= 3
  * (PLL_VIDEO0)/M >= 24MHz
  * 500MHz <= clockrate <= 1400MHz

  2. Remove two operating points from the A64 DTS OPPs, so that the GPU
 runs at a fixed rate of 432 MHz.

Note, that when pinning the GPU to 432 MHz the issue [1] completely
disappears for me. I've searched the BSP and could not find any
indication that supports the idea of having the three OPPs. The only
frequency I found in the BPSs for A64 is 432 MHz, which has also proven
stable for me.

I very much appreciate your feedback!

[1] https://gitlab.com/postmarketOS/pmaports/-/issues/805

Signed-off-by: Frank Oltmanns 
---
Changes in v4:
- sunxi-ng: common: Address review comments.
- Link to v3: 
https://lore.kernel.org/r/20240304-pinephone-pll-fixes-v3-0-94ab828f2...@oltmanns.dev

Changes in v3:
- dts: Pin GPU to 432 MHz.
- nkm and a64: Move minimum and maximum rate handling to the common part
  of the sunxi-ng driver.
- Removed st7703 patch from series.
- Link to v2: 
https://lore.kernel.org/r/20240205-pinephone-pll-fixes-v2-0-96a46a2d8...@oltmanns.dev

Changes in v2:
- dts: Increase minimum GPU frequency to 192 MHz.
- nkm and a64: Add minimum and maximum rate for PLL-MIPI.
- nkm: Use the same approach for skipping invalid rates in
  ccu_nkm_find_best() as in ccu_nkm_find_best_with_parent_adj().
- nkm: Improve names for ratio struct members and hence get rid of
  describing comments.
- nkm and a64: Correct description in the commit messages: M/N <= 3
- Remove patches for nm as they were not needed.
- st7703: Rework the commit message to cover more background for the
  change.
- Link to v1: 
https://lore.kernel.org/r/20231218-pinephone-pll-fixes-v1-0-e238b6ed6...@oltmanns.dev

---
Frank Oltmanns (5):
  clk: sunxi-ng: common: Support minimum and maximum rate
  clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI
  clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate
  clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent 
rate
  arm64: dts: allwinner: a64: Run GPU at 432 MHz

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi |  8 
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 14 +-
 drivers/clk/sunxi-ng/ccu_common.c | 19 +++
 drivers/clk/sunxi-ng/ccu_common.h |  3 +++
 drivers/clk/sunxi-ng/ccu_nkm.c| 21 +
 drivers/clk/sunxi-ng/ccu_nkm.h|  2 ++
 6 files changed, 54 insertions(+), 13 deletions(-)
---
base-commit: dcb6c8ee6acc6c347caec1e73fb900c0f4ff9806
change-id: 20231218-pinephone-pll-fixes-0ccdfde273e4

Best regards,
-- 
Frank Oltmanns 



[PATCH v3 5/5] arm64: dts: allwinner: a64: Run GPU at 432 MHz

2024-03-03 Thread Frank Oltmanns
The Allwinner A64's GPU has currently three operating points. However,
the BSP runs the GPU fixed at 432 MHz. In addition, at least one of the
devices using that SoC - the pinephone - shows unstabilities (see link)
that can be circumvented by running the GPU at a fixed rate.

Therefore, remove the other two operating points from the GPU OPP table,
so that the GPU runs at a fixed rate of 432 MHz.

Link: https://gitlab.com/postmarketOS/pmaports/-/issues/805
Signed-off-by: Frank Oltmanns 
---
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 8 
 1 file changed, 8 deletions(-)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 57ac18738c99..c810380aab6d 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -107,14 +107,6 @@ de: display-engine {
gpu_opp_table: opp-table-gpu {
compatible = "operating-points-v2";
 
-   opp-12000 {
-   opp-hz = /bits/ 64 <12000>;
-   };
-
-   opp-31200 {
-   opp-hz = /bits/ 64 <31200>;
-   };
-
opp-43200 {
opp-hz = /bits/ 64 <43200>;
};

-- 
2.44.0



[PATCH v3 4/5] clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent rate

2024-03-03 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N <= 3
 - (PLL_VIDEO0)/M >= 24MHz

Use these constraints.

Reviewed-by: Jernej Skrabec 
Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 6a4b2b9ef30a..07796c79a23e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -171,11 +171,13 @@ static struct ccu_nkm pll_mipi_clk = {
 * user manual, and by experiments the PLL doesn't work without
 * these bits toggled.
 */
-   .enable = BIT(31) | BIT(23) | BIT(22),
-   .lock   = BIT(28),
-   .n  = _SUNXI_CCU_MULT(8, 4),
-   .k  = _SUNXI_CCU_MULT_MIN(4, 2, 2),
-   .m  = _SUNXI_CCU_DIV(0, 4),
+   .enable = BIT(31) | BIT(23) | BIT(22),
+   .lock   = BIT(28),
+   .n  = _SUNXI_CCU_MULT(8, 4),
+   .k  = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+   .m  = _SUNXI_CCU_DIV(0, 4),
+   .max_m_n_ratio  = 3,
+   .min_parent_m_ratio = 2400,
.common = {
.reg= 0x040,
.hw.init= CLK_HW_INIT("pll-mipi", "pll-video0",

-- 
2.44.0



[PATCH v3 3/5] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate

2024-03-03 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N <= 3
 - (PLL_VIDEO0)/M >= 24MHz

The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for
these constraints.

Reviewed-by: Jernej Skrabec 
Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu_nkm.c | 21 +
 drivers/clk/sunxi-ng/ccu_nkm.h |  2 ++
 2 files changed, 23 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 853f84398e2b..1168d894d636 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -16,6 +16,20 @@ struct _ccu_nkm {
unsigned long   m, min_m, max_m;
 };
 
+static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long 
parent,
+ unsigned long n, unsigned long m)
+{
+   struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common);
+
+   if (nkm->max_m_n_ratio && (m > nkm->max_m_n_ratio * n))
+   return false;
+
+   if (nkm->min_parent_m_ratio && (parent < nkm->min_parent_m_ratio * m))
+   return false;
+
+   return true;
+}
+
 static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common 
*common,
   struct clk_hw *parent_hw,
   unsigned long *parent, 
unsigned long rate,
@@ -31,6 +45,10 @@ static unsigned long 
ccu_nkm_find_best_with_parent_adj(struct ccu_common *common
unsigned long tmp_rate, tmp_parent;
 
tmp_parent = clk_hw_round_rate(parent_hw, rate 
* _m / (_n * _k));
+
+   if (!ccu_nkm_is_valid_rate(common, tmp_parent, 
_n, _m))
+   continue;
+
tmp_rate = tmp_parent * _n * _k / _m;
 
if (ccu_is_better_rate(common, rate, tmp_rate, 
best_rate) ||
@@ -64,6 +82,9 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, 
unsigned long rate,
for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
+   if (!ccu_nkm_is_valid_rate(common, parent, _n, 
_m))
+   continue;
+
unsigned long tmp_rate;
 
tmp_rate = parent * _n * _k / _m;
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
index 6601defb3f38..c409212ee40e 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.h
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -27,6 +27,8 @@ struct ccu_nkm {
struct ccu_mux_internal mux;
 
unsigned intfixed_post_div;
+   unsigned long   max_m_n_ratio;
+   unsigned long   min_parent_m_ratio;
 
struct ccu_common   common;
 };

-- 
2.44.0



[PATCH v3 2/5] clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI

2024-03-03 Thread Frank Oltmanns
When the Allwinner A64's TCON0 searches the ideal rate for the connected
panel, it may happen that it requests a rate from its parent PLL-MIPI
which PLL-MIPI does not support.

This happens for example on the Olimex TERES-I laptop where TCON0
requests PLL-MIPI to change to a rate of several GHz which causes the
panel to stay blank. It also happens on the pinephone where a rate of
less than 500 MHz is requested which causes instabilities on some
phones.

Set the minimum and maximum rate of Allwinner A64's PLL-MIPI according
to the Allwinner User Manual.

Fixes: ca1170b69968 ("clk: sunxi-ng: a64: force select PLL_MIPI in TCON0 mux")
Reported-by: Diego Roversi 
Closes: https://groups.google.com/g/linux-sunxi/c/Rh-Uqqa66bw
Signed-off-by: Frank Oltmanns 
Tested-by: Diego Roversi 
Cc: sta...@vger.kernel.org
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 8951ffc14ff5..6a4b2b9ef30a 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = {
  _nkm_ops,
  CLK_SET_RATE_UNGATE | 
CLK_SET_RATE_PARENT),
.features   = CCU_FEATURE_CLOSEST_RATE,
+   .min_rate   = 5,
+   .max_rate   = 14,
},
 };
 

-- 
2.44.0



[PATCH v3 1/5] clk: sunxi-ng: common: Support minimum and maximum rate

2024-03-03 Thread Frank Oltmanns
The Allwinner SoC's typically have an upper and lower limit for their
clocks' rates. Up until now, support for that has been implemented
separately for each clock type.

Implement that functionality in the sunxi-ng's common part making use of
the CCF rate liming capabilities, so that it is available for all clock
types.

Suggested-by: Maxime Ripard 
Signed-off-by: Frank Oltmanns 
Cc: sta...@vger.kernel.org
---
 drivers/clk/sunxi-ng/ccu_common.c | 15 +++
 drivers/clk/sunxi-ng/ccu_common.h |  3 +++
 2 files changed, 18 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_common.c 
b/drivers/clk/sunxi-ng/ccu_common.c
index 8babce55302f..2152063eee16 100644
--- a/drivers/clk/sunxi-ng/ccu_common.c
+++ b/drivers/clk/sunxi-ng/ccu_common.c
@@ -44,6 +44,12 @@ bool ccu_is_better_rate(struct ccu_common *common,
unsigned long current_rate,
unsigned long best_rate)
 {
+   if (common->max_rate && current_rate > common->max_rate)
+   return false;
+
+   if (common->min_rate && current_rate < common->min_rate)
+   return false;
+
if (common->features & CCU_FEATURE_CLOSEST_RATE)
return abs(current_rate - target_rate) < abs(best_rate - 
target_rate);
 
@@ -122,7 +128,10 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct 
device *dev,
 
for (i = 0; i < desc->hw_clks->num ; i++) {
struct clk_hw *hw = desc->hw_clks->hws[i];
+   struct ccu_common *common = hw_to_ccu_common(hw);
const char *name;
+   unsigned long min_rate = 0;
+   unsigned long max_rate = ULONG_MAX;
 
if (!hw)
continue;
@@ -136,6 +145,12 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct 
device *dev,
pr_err("Couldn't register clock %d - %s\n", i, name);
goto err_clk_unreg;
}
+
+   if (common->min_rate)
+   min_rate = common->min_rate;
+   if (common->max_rate)
+   max_rate = common->max_rate;
+   clk_hw_set_rate_range(hw, min_rate, max_rate);
}
 
ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
diff --git a/drivers/clk/sunxi-ng/ccu_common.h 
b/drivers/clk/sunxi-ng/ccu_common.h
index 942a72c09437..329734f8cf42 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -31,6 +31,9 @@ struct ccu_common {
u16 lock_reg;
u32 prediv;
 
+   unsigned long   min_rate;
+   unsigned long   max_rate;
+
unsigned long   features;
spinlock_t  *lock;
struct clk_hw   hw;

-- 
2.44.0



[PATCH v3 0/5] Pinephone video out fixes (flipping between two frames)

2024-03-03 Thread Frank Oltmanns
On some pinephones the video output sometimes freezes (flips between two
frames) [1]. It seems to be that the reason for this behaviour is that
PLL-MIPI is outside its limits, and the GPU is not running at a fixed
rate.

In this patch series I propose the following changes:
  1. sunxi-ng: Adhere to the following constraints given in the
 Allwinner A64 Manual regarding PLL-MIPI:
  * M/N <= 3
  * (PLL_VIDEO0)/M >= 24MHz
  * 500MHz <= clockrate <= 1400MHz

  2. Remove two operating points from the A64 DTS OPPs, so that the GPU
 runs at a fixed rate of 432 MHz.

Note, that when pinning the GPU to 432 MHz the issue [1] completely
disappears for me. I've searched the BSP and could not find any
indication that supports the idea of having the three OPPs. The only
frequency I found in the BPSs for A64 is 432 MHz, which has also proven
stable for me.

Another bigger change compared to the previous version is that I've
removed the patch to adapt the XBD599 panel's timings to Allwinner A64's
PLL-MIPI new constraints from this series. Mainly, because I'm currently
evaluationg other options that may or may not work. (It may work at
least until HDMI support is upstreamed.) I'll probably resend the patch
at a later point in time.

I very much appreciate your feedback!

[1] https://gitlab.com/postmarketOS/pmaports/-/issues/805

Signed-off-by: Frank Oltmanns 
---
Changes in v3:
- dts: Pin GPU to 432 MHz.
- nkm and a64: Move minimum and maximum rate handling to the common part
  of the sunxi-ng driver.
- Removed st7703 patch from series.
- Link to v2: 
https://lore.kernel.org/r/20240205-pinephone-pll-fixes-v2-0-96a46a2d8...@oltmanns.dev

Changes in v2:
- dts: Increase minimum GPU frequency to 192 MHz.
- nkm and a64: Add minimum and maximum rate for PLL-MIPI.
- nkm: Use the same approach for skipping invalid rates in
  ccu_nkm_find_best() as in ccu_nkm_find_best_with_parent_adj().
- nkm: Improve names for ratio struct members and hence get rid of
  describing comments.
- nkm and a64: Correct description in the commit messages: M/N <= 3
- Remove patches for nm as they were not needed.
- st7703: Rework the commit message to cover more background for the
  change.
- Link to v1: 
https://lore.kernel.org/r/20231218-pinephone-pll-fixes-v1-0-e238b6ed6...@oltmanns.dev

---
Frank Oltmanns (5):
  clk: sunxi-ng: common: Support minimum and maximum rate
  clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI
  clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate
  clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent 
rate
  arm64: dts: allwinner: a64: Run GPU at 432 MHz

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi |  8 
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 14 +-
 drivers/clk/sunxi-ng/ccu_common.c | 15 +++
 drivers/clk/sunxi-ng/ccu_common.h |  3 +++
 drivers/clk/sunxi-ng/ccu_nkm.c| 21 +
 drivers/clk/sunxi-ng/ccu_nkm.h|  2 ++
 6 files changed, 50 insertions(+), 13 deletions(-)
---
base-commit: 216c1282dde38ca87ebdf1ccacee5a0682901574
change-id: 20231218-pinephone-pll-fixes-0ccdfde273e4

Best regards,
-- 
Frank Oltmanns 



Re: [PATCH v2 0/6] Pinephone video out fixes (flipping between two frames)

2024-02-25 Thread Frank Oltmanns
Hi Jernej,
hi Maxime,
hi Ondřej,

On 2024-02-19 at 10:41:19 +0100, Frank Oltmanns  wrote:
> Hi Ondřej,
>
> On 2024-02-11 at 20:25:29 +0100, Ondřej Jirman  wrote:
>> Hi Frank,
>>
>> On Sun, Feb 11, 2024 at 04:09:16PM +0100, Frank Oltmanns wrote:
>>> Hi Ondřej,
>>>
>>> On 2024-02-05 at 17:02:00 +0100, Ondřej Jirman  wrote:
>>> > On Mon, Feb 05, 2024 at 04:54:07PM +0100, Ondřej Jirman wrote:
>>> >> On Mon, Feb 05, 2024 at 04:22:23PM +0100, Frank Oltmanns wrote:
>>> >>
>>> >> [...]
>>> >>
>>> >> Also sunxi-ng clk driver does apply NM factors at once to PLL_GPU clock,
>>> >> which can cause sudden frequency increase beyond intended output 
>>> >> frequency,
>>> >> because division is applied immediately while multiplication is reflected
>>> >> slowly.
>>> >>
>>> >> Eg. if you're changing divider from 7 to 1, you can get a sudden 7x 
>>> >> output
>>> >> frequency spike, before PLL VCO manages to lower the frequency through N 
>>> >> clk
>>> >> divider feedback loop and lock on again. This can mess up whatever's 
>>> >> connected
>>> >> to the output quite badly.
>>> >>
>>> >> You'd have to put logging on kernel writes to PLL_GPU register to see 
>>> >> what
>>> >> is written in there and if divider is lowered significantly on some GPU
>>> >> devfreq frequency transitions.
>>>
>>> By looking at the clocks in clk_summary in debugfs, the rate of PLL-GPU
>>> always matches the rate of the GPU (at least at 120, 312, and 432 MHz).
>>> This is further underlined by the fact, that none of the rates can be
>>> achieved by integer dividing one of the other rates. sunxi-ng would
>>> only favor a different rate for pll-gpu than the one that is requested
>>> for the gpu, if pll-gpu is already running at a rate such that there
>>> exists an M ∈ {1, 2, 3, 4, 5, 6, 7, 8}, where
>>>   rate of pll-gpu / M = requested gpu rate
>>> or if the requested rate could not be reached directly by pll-gpu. Both
>>> is not the case for the rates in question (120, 192, 312, and 432 MHz).
>>>
>>> This means that the following divisor/multipliers are used by sunxi-ng's
>>> ccu_nm:
>>> N =  5, M = 1 for 120 MHz (min value without PATCH 6)
>>> N =  8, M = 1 for 192 MHz (min value after applying PATCH 6)
>>> N = 13, M = 1 for 312 MHz
>>> N = 18, M = 1 for 432 MHz
>>>
>>> So, with or without PATCH 6, the divider stays constant and it's only
>>> the multiplier that changes. This means, there should be no unexpected
>>> frequency spikes, right?
>>
>> Maybe. Thanks for giving it a try. There may still be other kinds of glitches
>> even if the divisor stays the same. It all depends how the register update is
>> implemented in the PLL block. It's hard to say. I guess, unless Allwinner
>> guarantees glitchless output from a given PLL when changing its parameters,
>> you can't rely on the output being clean during changes.
>>
>>> >> It's also unclear what happens when FRAC_CLK_OUT or PLL_MODE_SEL changes.
>>>
>>> Those are not changed once the clock is initialized. The bug however
>>> occurs hours or days after booting. IMO, this makes it unlikely that this
>>> could be the culprit.
>>>
>>> >> Maybe not much because M is supposed to be set to 1, but you still need 
>>> >> to
>>> >> care when enabling fractional mode, and setting M to 1 because that's 
>>> >> exactly
>>> >> the bad scenario if M was previously higher than 1.
>>> >>
>>> >> It's tricky.
>>> >>
>>> >> Having GPU module clock gated during PLL config changes may help! You can
>>> >> do that without locking yourself out, unlike with the CPU PLL.
>>> >>
>>> >> There's a gate enable bit for it at GPU_CLK_REG.SCLK_GATING. (page 122)
>>>
>>> The GPU should already be properly gated:
>>> https://elixir.bootlin.com/linux/v6.7.4/source/drivers/clk/sunxi-ng/ccu-sun50i-a64.c#L599
>>
>> How so? That's just clock declaration. How does it guarantee the clock to the
>> module is gated during parent PLL configuration changes?
>>
>
> You're of course right.
>
> I now tried using a similar approach like the one for changes for on
> PLL-CPU. It's using a notifier to connect the CPU to t

Re: [PATCH v2 5/6] drm/panel: st7703: Drive XBD599 panel at higher clock rate

2024-02-25 Thread Frank Oltmanns
Hi Maxime,

On 2024-02-22 at 11:29:51 +0100, Maxime Ripard  wrote:
> [[PGP Signed Part:Undecided]]
> On Sun, Feb 11, 2024 at 04:42:43PM +0100, Frank Oltmanns wrote:
>>
>> On 2024-02-08 at 20:05:08 +0100, Maxime Ripard  wrote:
>> > [[PGP Signed Part:Undecided]]
>> > Hi Frank,
>> >
>> > On Mon, Feb 05, 2024 at 04:22:28PM +0100, Frank Oltmanns wrote:
>> >> This panel is used in the pinephone that runs on a Allwinner A64 SOC.
>> >> The SOC requires pll-mipi to run at more than 500 MHz.
>> >>
>> >> This is the relevant clock tree:
>> >>  pll-mipi
>> >> tcon0
>> >>tcon-data-clock
>> >>
>> >> tcon-data-clock has to run at 1/4 the DSI per-lane bit rate. The XBD599
>> >> has 24 bpp and 4 lanes. Therefore, the resulting requested
>> >> tcon-data-clock rate is:
>> >> crtc_clock * 1000 * (24 / 4) / 4
>> >>
>> >> tcon-data-clock runs at tcon0 / 4 (fixed divisor), so it requests a
>> >> parent rate of
>> >> 4 * (crtc_clock * 1000 * (24 / 4) / 4)
>> >>
>> >> Since tcon0 is a ccu_mux, the rate of tcon0 equals the rate of pll-mipi.
>> >>
>> >> pll-mipi's constraint to run at 500MHz or higher forces us to have a
>> >> crtc_clock >= 8 kHz if we want a 60 Hz vertical refresh rate.
>> >>
>> >> Change [hv]sync_(start|end) so that we reach a clock rate of 83502 kHz
>> >> so that it is high enough to align with pll-pipi limits.
>> >>
>> >> Signed-off-by: Frank Oltmanns 
>> >
>> > That commit log is great, but it's kind of off-topic. It's a panel
>> > driver, it can be used on any MIPI-DSI controller, the only relevant
>> > information there should be the panel timings required in the datasheet.
>> >
>> > The PLL setup is something for the MIPI-DSI driver to adjust, not for
>> > the panel to care for.
>> >
>>
>> I absolutely agree. It even was the reason for my submission of a
>> sunxi-ng patch series last year that was accepted, to make pll-mipi more
>> flexible. :)
>>
>> The only remaining option I currently see for adjusting the sunxi-ng
>> driver to further accomodate the panel, is trying to use a higher
>> divisor than 4 for calculating tcon-data-clock from tcon0. I remember
>> reading a discussion about this, but as far as I remember that proposal
>> was rejected (by you, IIRC).
>>
>> While I appreciate other suggestion as well, I'll look into options for
>> using a different divisor than 4.
>
> Like I said, I'm not against the patch at all, it looks great to me on
> principle. I just think you should completely rephrase the commit log
> using the datasheet as the only reliable source of the display timings.
> Whether sun4i can work around the panel requirements is something
> completely orthogonal to the discussion, and thus the commit log.
>

I was trying to follow the guidelines [1] for describing the reason
behind my changes to the panel. My original commit message was a lot
shorter, which, understandably, resulted in follow up questions [2].
With the current commit log, I'm trying to address those questions.
According to the device tree, the panel is only used in the pinephone.
The only reason for the change is that the SoC used by the only user of
this panel can not provide the rate the panel requests with the current
values. I think this information is relevant.

Unfortunately, as described in [2], I cannot back these values with any
datasheets because I couldn't find any. I could only find hints that
they are not publicly available. Icenowy (added to CC) submitted the
original values.

Best regards,
  Frank

[1]: 
https://www.kernel.org/doc/html/v6.7/process/submitting-patches.html#describe-your-changes
[2]: https://lore.kernel.org/lkml/87wmsvo0fh@oltmanns.dev/

>
> Maxime
>
> [[End of PGP Signed Part]]


Re: [PATCH v2 3/6] clk: sunxi-ng: nkm: Support minimum and maximum rate

2024-02-21 Thread Frank Oltmanns
Hi Jernej,
hi Maxime,

On 2024-02-05 at 16:22:26 +0100, Frank Oltmanns  wrote:
> According to the Allwinner User Manual, the Allwinner A64 requires
> PLL-MIPI to run at 500MHz-1.4GHz. Add support for that to ccu_nkm.

I should point out that limiting PLL-MIPI also fixes a regression
that was introduced in 6.5, specifically
ca1170b69968233b34d26432245eddf7d265186b "clk: sunxi-ng: a64: force
select PLL_MIPI in TCON0 mux". This has been bisected and reported by
Diego [1].

I don't know the procedure (yet), but probably the fix (if and when
accepted) should be backported at least to 6.6 (first broken LTS), 6.7
(stable), and 6.8 (next stable).

My suggestion:
 - In V3 of this series, I will reorder the patches, so that what is now
   PATCH 3 and 4 becomes 1 and 2 respectively, so that they can be
   applied to 6.6 more easily.
 - Maxime, IIUC you requested some refactoring for handling the rate
   limits [2]. I propose, we use my current proposal as-is, and I will
   do a follow-up series for the refactoring.

Please let me know how you would like me to proceed.

Thanks,
  Frank

[1]: https://groups.google.com/g/linux-sunxi/c/Rh-Uqqa66bw
[2]: 
https://lore.kernel.org/all/exb2lvjcozak5fayrgyenrd3ntii4jfxgvqork4klyz5pky2aq@dj2zyw5su6pv/

>
> Signed-off-by: Frank Oltmanns 
> ---
>  drivers/clk/sunxi-ng/ccu_nkm.c | 13 +
>  drivers/clk/sunxi-ng/ccu_nkm.h |  2 ++
>  2 files changed, 15 insertions(+)
>
> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
> index 1168d894d636..7d135908d6e0 100644
> --- a/drivers/clk/sunxi-ng/ccu_nkm.c
> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
> @@ -181,6 +181,12 @@ static unsigned long ccu_nkm_round_rate(struct 
> ccu_mux_internal *mux,
>   if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
>   rate *= nkm->fixed_post_div;
>
> + if (nkm->min_rate && rate < nkm->min_rate)
> + rate = nkm->min_rate;
> +
> + if (nkm->max_rate && rate > nkm->max_rate)
> + rate = nkm->max_rate;
> +
>   if (!clk_hw_can_set_rate_parent(>common.hw))
>   rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, 
> >common);
>   else
> @@ -220,6 +226,13 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned 
> long rate,
>   _nkm.min_m = 1;
>   _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
>
> +
> + if (nkm->min_rate && rate < nkm->min_rate)
> + rate = nkm->min_rate;
> +
> + if (nkm->max_rate && rate > nkm->max_rate)
> + rate = nkm->max_rate;
> +
>   ccu_nkm_find_best(parent_rate, rate, &_nkm, >common);
>
>   spin_lock_irqsave(nkm->common.lock, flags);
> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
> index c409212ee40e..358a9df6b6a0 100644
> --- a/drivers/clk/sunxi-ng/ccu_nkm.h
> +++ b/drivers/clk/sunxi-ng/ccu_nkm.h
> @@ -27,6 +27,8 @@ struct ccu_nkm {
>   struct ccu_mux_internal mux;
>
>   unsigned intfixed_post_div;
> + unsigned long   min_rate;
> + unsigned long   max_rate;
>   unsigned long   max_m_n_ratio;
>   unsigned long   min_parent_m_ratio;


Re: [PATCH v2 0/6] Pinephone video out fixes (flipping between two frames)

2024-02-19 Thread Frank Oltmanns
Hi Ondřej,

On 2024-02-11 at 20:25:29 +0100, Ondřej Jirman  wrote:
> Hi Frank,
>
> On Sun, Feb 11, 2024 at 04:09:16PM +0100, Frank Oltmanns wrote:
>> Hi Ondřej,
>>
>> On 2024-02-05 at 17:02:00 +0100, Ondřej Jirman  wrote:
>> > On Mon, Feb 05, 2024 at 04:54:07PM +0100, Ondřej Jirman wrote:
>> >> On Mon, Feb 05, 2024 at 04:22:23PM +0100, Frank Oltmanns wrote:
>> >>
>> >> [...]
>> >>
>> >> Also sunxi-ng clk driver does apply NM factors at once to PLL_GPU clock,
>> >> which can cause sudden frequency increase beyond intended output 
>> >> frequency,
>> >> because division is applied immediately while multiplication is reflected
>> >> slowly.
>> >>
>> >> Eg. if you're changing divider from 7 to 1, you can get a sudden 7x output
>> >> frequency spike, before PLL VCO manages to lower the frequency through N 
>> >> clk
>> >> divider feedback loop and lock on again. This can mess up whatever's 
>> >> connected
>> >> to the output quite badly.
>> >>
>> >> You'd have to put logging on kernel writes to PLL_GPU register to see what
>> >> is written in there and if divider is lowered significantly on some GPU
>> >> devfreq frequency transitions.
>>
>> By looking at the clocks in clk_summary in debugfs, the rate of PLL-GPU
>> always matches the rate of the GPU (at least at 120, 312, and 432 MHz).
>> This is further underlined by the fact, that none of the rates can be
>> achieved by integer dividing one of the other rates. sunxi-ng would
>> only favor a different rate for pll-gpu than the one that is requested
>> for the gpu, if pll-gpu is already running at a rate such that there
>> exists an M ∈ {1, 2, 3, 4, 5, 6, 7, 8}, where
>>   rate of pll-gpu / M = requested gpu rate
>> or if the requested rate could not be reached directly by pll-gpu. Both
>> is not the case for the rates in question (120, 192, 312, and 432 MHz).
>>
>> This means that the following divisor/multipliers are used by sunxi-ng's
>> ccu_nm:
>> N =  5, M = 1 for 120 MHz (min value without PATCH 6)
>> N =  8, M = 1 for 192 MHz (min value after applying PATCH 6)
>> N = 13, M = 1 for 312 MHz
>> N = 18, M = 1 for 432 MHz
>>
>> So, with or without PATCH 6, the divider stays constant and it's only
>> the multiplier that changes. This means, there should be no unexpected
>> frequency spikes, right?
>
> Maybe. Thanks for giving it a try. There may still be other kinds of glitches
> even if the divisor stays the same. It all depends how the register update is
> implemented in the PLL block. It's hard to say. I guess, unless Allwinner
> guarantees glitchless output from a given PLL when changing its parameters,
> you can't rely on the output being clean during changes.
>
>> >> It's also unclear what happens when FRAC_CLK_OUT or PLL_MODE_SEL changes.
>>
>> Those are not changed once the clock is initialized. The bug however
>> occurs hours or days after booting. IMO, this makes it unlikely that this
>> could be the culprit.
>>
>> >> Maybe not much because M is supposed to be set to 1, but you still need to
>> >> care when enabling fractional mode, and setting M to 1 because that's 
>> >> exactly
>> >> the bad scenario if M was previously higher than 1.
>> >>
>> >> It's tricky.
>> >>
>> >> Having GPU module clock gated during PLL config changes may help! You can
>> >> do that without locking yourself out, unlike with the CPU PLL.
>> >>
>> >> There's a gate enable bit for it at GPU_CLK_REG.SCLK_GATING. (page 122)
>>
>> The GPU should already be properly gated:
>> https://elixir.bootlin.com/linux/v6.7.4/source/drivers/clk/sunxi-ng/ccu-sun50i-a64.c#L599
>
> How so? That's just clock declaration. How does it guarantee the clock to the
> module is gated during parent PLL configuration changes?
>

You're of course right.

I now tried using a similar approach like the one for changes for on
PLL-CPU. It's using a notifier to connect the CPU to the 24 MHz
oscillator and, after PLL-CPU is at its new rate, connecting it back to
PLL-CPU.

For the GPU my approach was to disable the GPU prior to changing
PLL-GPU's rate and then re-enabling it, once the rate change is
complete. I think, that's what you were proposing, right?

Unfortunately, this results in a frozen phone even more quickly.

Below is my code. Again, it doesn't solve the problem, but maybe
somebody can spot what I'm doing wrong.

Best regards,
  Frank

diff --git a/drivers/clk/

Re: [PATCH v2 3/6] clk: sunxi-ng: nkm: Support minimum and maximum rate

2024-02-18 Thread Frank Oltmanns
Hi Maxime,

On 2024-02-08 at 13:16:27 +0100, Maxime Ripard  wrote:
> [[PGP Signed Part:Undecided]]
> On Mon, Feb 05, 2024 at 04:22:26PM +0100, Frank Oltmanns wrote:
>> According to the Allwinner User Manual, the Allwinner A64 requires
>> PLL-MIPI to run at 500MHz-1.4GHz. Add support for that to ccu_nkm.
>>
>> Signed-off-by: Frank Oltmanns 
>> ---
>>  drivers/clk/sunxi-ng/ccu_nkm.c | 13 +
>>  drivers/clk/sunxi-ng/ccu_nkm.h |  2 ++
>>  2 files changed, 15 insertions(+)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
>> index 1168d894d636..7d135908d6e0 100644
>> --- a/drivers/clk/sunxi-ng/ccu_nkm.c
>> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
>> @@ -181,6 +181,12 @@ static unsigned long ccu_nkm_round_rate(struct 
>> ccu_mux_internal *mux,
>>  if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
>>  rate *= nkm->fixed_post_div;
>>
>> +if (nkm->min_rate && rate < nkm->min_rate)
>> +rate = nkm->min_rate;
>> +
>> +if (nkm->max_rate && rate > nkm->max_rate)
>> +rate = nkm->max_rate;
>> +
>
> This is provided by the clock range already. If you call
> clk_hw_set_rate_range, it should work just fine.

I have to admit, that I don't know that much about sunxi-ng or the CCF
and therefore humbly request some guidance.

I've looked at other examples of clk_hw_set_rate_range() usage and it
seems there is not a lot of adoption for this functionality even though
it was already introduced mid-2015. This makes me wonder, why that is.

Anyhow, it seems in all examples I found, clk_hw_set_rate_range() is
called immediately after registering the clk_hw. So, in the case of
sunxi-ng, we'd need to do that in sunxi_ccu_probe, which is a common
function for all sunxi-ng clock types. Correct?

If so, surely, you don't want me to introduce clock type specific code
to a common function, so I assume you want min_rate and max_rate to
become members of struct ccu_common. Correct?

If so, since there already are some clock types in sunxi-ng that support
having a minimum and maximum rate, these clocks should be refactored
eventually. Correct?

Finally, in sunxi-ng there is a feature of having a fixed_post_div (see,
e.g., the first to lines of the diff above). It seems to me that CCF
cannot know about these post_divs, so we'd also need to transfer the
fixed_post_div to ccu_common and use that when calling
clk_hw_set_rate_range. Correct?

The fact that you casually dropped the two sentences above and me
deducing you want a somewhat large refactoring of the functionality for
sunxi-ng, makes me wonder if I completely misunderstood your request.

Best regards,
  Frank

>
> Maxime
>
> [[End of PGP Signed Part]]


Re: [PATCH v2 5/6] drm/panel: st7703: Drive XBD599 panel at higher clock rate

2024-02-12 Thread Frank Oltmanns


On 2024-02-11 at 16:42:43 +0100, Frank Oltmanns  wrote:
> On 2024-02-08 at 20:05:08 +0100, Maxime Ripard  wrote:
>> [[PGP Signed Part:Undecided]]
>> Hi Frank,
>>
>> On Mon, Feb 05, 2024 at 04:22:28PM +0100, Frank Oltmanns wrote:
>>> This panel is used in the pinephone that runs on a Allwinner A64 SOC.
>>> The SOC requires pll-mipi to run at more than 500 MHz.
>>>
>>> This is the relevant clock tree:
>>>  pll-mipi
>>> tcon0
>>>tcon-data-clock
>>>
>>> tcon-data-clock has to run at 1/4 the DSI per-lane bit rate. The XBD599
>>> has 24 bpp and 4 lanes. Therefore, the resulting requested
>>> tcon-data-clock rate is:
>>> crtc_clock * 1000 * (24 / 4) / 4
>>>
>>> tcon-data-clock runs at tcon0 / 4 (fixed divisor), so it requests a
>>> parent rate of
>>> 4 * (crtc_clock * 1000 * (24 / 4) / 4)
>>>
>>> Since tcon0 is a ccu_mux, the rate of tcon0 equals the rate of pll-mipi.
>>>
>>> pll-mipi's constraint to run at 500MHz or higher forces us to have a
>>> crtc_clock >= 83333 kHz if we want a 60 Hz vertical refresh rate.
>>>
>>> Change [hv]sync_(start|end) so that we reach a clock rate of 83502 kHz
>>> so that it is high enough to align with pll-pipi limits.
>>>
>>> Signed-off-by: Frank Oltmanns 
>>
>> That commit log is great, but it's kind of off-topic. It's a panel
>> driver, it can be used on any MIPI-DSI controller, the only relevant
>> information there should be the panel timings required in the datasheet.
>>
>> The PLL setup is something for the MIPI-DSI driver to adjust, not for
>> the panel to care for.
>>
>
> I absolutely agree. It even was the reason for my submission of a
> sunxi-ng patch series last year that was accepted, to make pll-mipi more
> flexible. :)
>
> The only remaining option I currently see for adjusting the sunxi-ng
> driver to further accomodate the panel, is trying to use a higher
> divisor than 4 for calculating tcon-data-clock from tcon0. I remember
> reading a discussion about this, but as far as I remember that proposal
> was rejected (by you, IIRC).
>
> While I appreciate other suggestion as well, I'll look into options for
> using a different divisor than 4.

I tried the following:
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -391,7 +391,7 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon 
*tcon,
 * dclk is required to run at 1/4 the DSI per-lane bit rate.
 */
tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
-   tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
+   tcon->dclk_max_div = 127;
clk_set_rate(tcon->dclk, mode->crtc_clock * 1000 * (bpp / lanes)
  / SUN6I_DSI_TCON_DIV);

On the pinephone, this selects a divisor of 6 resulting in a 25% frame
drop. I.e., unless I'm missing something using a divisor other than 4 is
not an option. This also matches your report from 2019: "Well, it's also
breaking another panel." [1]

I can currently see the following options:

a. Drive PLL-MIPI outside spec and panel within spec (current situation,
   but missing a small patch [2] that fixes the crtc_clock and nothing
   else) and live with the fact that some pinephones will run
   unreliably.

b. Drive PLL-MIPI and panel within spec and shove data into the panel at
   a too high rate (i.e., apply the rest of this series but not this
   specific patch). This seems to mostly work, but hasn't seen any long
   term testing. Short term testing showed that this approach results in
   a slight but noticable unsmooth scrolling behavior.

c. Drive PLL-MIPI within spec and panel outside spec (i.e., apply a
   future version of the whole series). This has been tested for over a
   month on three devices that I know of. There are no reports of panels
   not working with the suggested parameters.

All options require additional work on the GPU rate which is currently
being discussed in a parallel thread of this series. Unless somebody
comes up with a better idea, I will pause working on fixing PLL-MIPI and
focus on the GPU instead. While I doubt it, maybe fixing the GPU is
sufficient and continuing to drive PLL-MIPI outside spec proves to be
ok.

[1]: https://lore.kernel.org/all/20190828130341.s5z76wejulwdgxlc@flea/
[2]: https://lore.kernel.org/all/20230219114553.288057-2-fr...@oltmanns.dev/

Best regards,
  Frank

>
> Best regards,
>   Frank
>
>>
>> Maxime
>>
>> [[End of PGP Signed Part]]


Re: [PATCH v2 5/6] drm/panel: st7703: Drive XBD599 panel at higher clock rate

2024-02-11 Thread Frank Oltmanns


On 2024-02-08 at 20:05:08 +0100, Maxime Ripard  wrote:
> [[PGP Signed Part:Undecided]]
> Hi Frank,
>
> On Mon, Feb 05, 2024 at 04:22:28PM +0100, Frank Oltmanns wrote:
>> This panel is used in the pinephone that runs on a Allwinner A64 SOC.
>> The SOC requires pll-mipi to run at more than 500 MHz.
>>
>> This is the relevant clock tree:
>>  pll-mipi
>> tcon0
>>tcon-data-clock
>>
>> tcon-data-clock has to run at 1/4 the DSI per-lane bit rate. The XBD599
>> has 24 bpp and 4 lanes. Therefore, the resulting requested
>> tcon-data-clock rate is:
>> crtc_clock * 1000 * (24 / 4) / 4
>>
>> tcon-data-clock runs at tcon0 / 4 (fixed divisor), so it requests a
>> parent rate of
>> 4 * (crtc_clock * 1000 * (24 / 4) / 4)
>>
>> Since tcon0 is a ccu_mux, the rate of tcon0 equals the rate of pll-mipi.
>>
>> pll-mipi's constraint to run at 500MHz or higher forces us to have a
>> crtc_clock >= 8 kHz if we want a 60 Hz vertical refresh rate.
>>
>> Change [hv]sync_(start|end) so that we reach a clock rate of 83502 kHz
>> so that it is high enough to align with pll-pipi limits.
>>
>> Signed-off-by: Frank Oltmanns 
>
> That commit log is great, but it's kind of off-topic. It's a panel
> driver, it can be used on any MIPI-DSI controller, the only relevant
> information there should be the panel timings required in the datasheet.
>
> The PLL setup is something for the MIPI-DSI driver to adjust, not for
> the panel to care for.
>

I absolutely agree. It even was the reason for my submission of a
sunxi-ng patch series last year that was accepted, to make pll-mipi more
flexible. :)

The only remaining option I currently see for adjusting the sunxi-ng
driver to further accomodate the panel, is trying to use a higher
divisor than 4 for calculating tcon-data-clock from tcon0. I remember
reading a discussion about this, but as far as I remember that proposal
was rejected (by you, IIRC).

While I appreciate other suggestion as well, I'll look into options for
using a different divisor than 4.

Best regards,
  Frank

>
> Maxime
>
> [[End of PGP Signed Part]]


Re: [PATCH v2 0/6] Pinephone video out fixes (flipping between two frames)

2024-02-11 Thread Frank Oltmanns
Hi Ondřej,

On 2024-02-05 at 17:02:00 +0100, Ondřej Jirman  wrote:
> On Mon, Feb 05, 2024 at 04:54:07PM +0100, Ondřej Jirman wrote:
>> On Mon, Feb 05, 2024 at 04:22:23PM +0100, Frank Oltmanns wrote:
>> > On some pinephones the video output sometimes freezes (flips between two
>> > frames) [1]. It seems to be that the reason for this behaviour is that
>> > PLL-MIPI, PLL-GPU and GPU are operating outside their limits.
>> >
>> > In this patch series I propose the followin changes:
>> >   1. sunxi-ng: Adhere to the following constraints given in the
>> >  Allwinner A64 Manual regarding PLL-MIPI:
>> >   * M/N <= 3
>> >   * (PLL_VIDEO0)/M >= 24MHz
>> >   * 500MHz <= clockrate <= 1400MHz
>> >
>> >   2. Choose a higher clock rate for the ST7703 based XDB599 panel, so
>> >  that the panel function well with the Allwinner A64 SOC. PLL-MIPI
>> >  must run between 500 MHz and 1.4 GHz. As PLL-MIPI runs at 6 times
>> >  the panel's clock rate, we need the panel's clock to be at least
>> >  83.333 MHz.
>> >
>> >   3. Increase the minimum frequency in the A64 DTS OPPs from 120 MHz to
>> >  192 MHz. This further reduces the issue.
>> >
>> > Unfortunately, with these patches the issue [1] is not completely gone,
>> > but becomes less likely.
>> >
>> > Note, that when pinning the GPU to 432 MHz the issue completely
>> > disappears for me. I've searched the BSP and could not find any
>> > indication that supports the idea of having the three OPPs. The only
>> > frequency I found in the BPSs for A64 is 432 MHz, that has also proven
>> > stable for me. So, while increasing the minimum frequency to 192 MHz
>> > reduces the issue, should we maybe instead set the GPU to a fixed 432
>> > MHz instead?
>>
>> Per A64 User Manual 1.1 page 81:
>>
>> (9). Clock output of PLL_GPU can be used for GPU;and dynamic frequency 
>> scaling is not supported;
>
> You may be able to elegantly work around this by pinning PLL_GPU to a certain
> frequency (assing it in DT and then don't decalre gpu clock as
> CLK_SET_RATE_PARENT). Say 432 MHz for PLL and then do the scaling via 
> GPU_CLK_REG
> N divider between 432MHz and 216MHz and maybe 108MHz if that brings any gains.
>

I really like this idea. Unfortunately, it seems that the divisor of the
GPU_CLK_REG must always be set to 1. I tried to convey this info in the
commit message for PATCH 6. If using a different divisor than 1 the bug
I'm trying to fix here occurs within minutes. Nevertheless, I gave your
proposal a quick try - it seems so elegant. Unfortunately, but not
unexpectedly, the bug occured almost immediately.

> Then you can perhaps sidestep all these potential issues with PLL_GPU and
> lack of DVFS support decalred in the manual.
>
> regards,
>   o.
>
>> Also sunxi-ng clk driver does apply NM factors at once to PLL_GPU clock,
>> which can cause sudden frequency increase beyond intended output frequency,
>> because division is applied immediately while multiplication is reflected
>> slowly.
>>
>> Eg. if you're changing divider from 7 to 1, you can get a sudden 7x output
>> frequency spike, before PLL VCO manages to lower the frequency through N clk
>> divider feedback loop and lock on again. This can mess up whatever's 
>> connected
>> to the output quite badly.
>>
>> You'd have to put logging on kernel writes to PLL_GPU register to see what
>> is written in there and if divider is lowered significantly on some GPU
>> devfreq frequency transitions.

By looking at the clocks in clk_summary in debugfs, the rate of PLL-GPU
always matches the rate of the GPU (at least at 120, 312, and 432 MHz).
This is further underlined by the fact, that none of the rates can be
achieved by integer dividing one of the other rates. sunxi-ng would
only favor a different rate for pll-gpu than the one that is requested
for the gpu, if pll-gpu is already running at a rate such that there
exists an M ∈ {1, 2, 3, 4, 5, 6, 7, 8}, where
  rate of pll-gpu / M = requested gpu rate
or if the requested rate could not be reached directly by pll-gpu. Both
is not the case for the rates in question (120, 192, 312, and 432 MHz).

This means that the following divisor/multipliers are used by sunxi-ng's
ccu_nm:
N =  5, M = 1 for 120 MHz (min value without PATCH 6)
N =  8, M = 1 for 192 MHz (min value after applying PATCH 6)
N = 13, M = 1 for 312 MHz
N = 18, M = 1 for 432 MHz

So, with or without PATCH 6, the divider stays constant and it's only
the multiplier that changes. This means, there should be no unexpected
frequency spikes, right?

>> I

Re: [PATCH v2 3/6] clk: sunxi-ng: nkm: Support minimum and maximum rate

2024-02-05 Thread Frank Oltmanns


On 2024-02-05 at 18:56:09 +0100, Jernej Škrabec  
wrote:
> Dne ponedeljek, 05. februar 2024 ob 16:22:26 CET je Frank Oltmanns napisal(a):
>> According to the Allwinner User Manual, the Allwinner A64 requires
>> PLL-MIPI to run at 500MHz-1.4GHz. Add support for that to ccu_nkm.
>>
>> Signed-off-by: Frank Oltmanns 
>> ---
>>  drivers/clk/sunxi-ng/ccu_nkm.c | 13 +
>>  drivers/clk/sunxi-ng/ccu_nkm.h |  2 ++
>>  2 files changed, 15 insertions(+)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
>> index 1168d894d636..7d135908d6e0 100644
>> --- a/drivers/clk/sunxi-ng/ccu_nkm.c
>> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
>> @@ -181,6 +181,12 @@ static unsigned long ccu_nkm_round_rate(struct 
>> ccu_mux_internal *mux,
>>  if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
>>  rate *= nkm->fixed_post_div;
>>
>> +if (nkm->min_rate && rate < nkm->min_rate)
>> +rate = nkm->min_rate;
>> +
>> +if (nkm->max_rate && rate > nkm->max_rate)
>> +rate = nkm->max_rate;
>
> Please take a look at ccu_nm_round_rate() code. You need to consider postdiv
> and you can return immediately.

There is a difference here insofar that ccu_nm is always connected to a
fixed rate parent (at least that's my understanding). Therefore, in
ccu_nm_round_rate() we can be sure that the min or max rate can really
be set. In ccu_nkm we don't have that luxury, we actually have to find a
rate that is approximately equal to the min and max rate, based on the
parent rate. Therefore, we can't return immediately.

Also, I'm not sure what you mean about me needing to consider postdiv.
That's what I did. The check is after multiplying with the postdiv. It's
the same as in ccu_nm_round_rate() (just minus the immediate return).

>
>> +
>>  if (!clk_hw_can_set_rate_parent(>common.hw))
>>  rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, 
>> >common);
>>  else
>> @@ -220,6 +226,13 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned 
>> long rate,
>>  _nkm.min_m = 1;
>>  _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
>>
>> +
>> +if (nkm->min_rate && rate < nkm->min_rate)
>> +rate = nkm->min_rate;
>> +
>> +if (nkm->max_rate && rate > nkm->max_rate)
>> +rate = nkm->max_rate;
>> +
>
> No need for this, clk subsystem calls round rate before setting actual clock
> rate.

I'll remove the checks in V3.

Best regards,
  Frank

>
> Best regards,
> Jernej
>
>>  ccu_nkm_find_best(parent_rate, rate, &_nkm, >common);
>>
>>  spin_lock_irqsave(nkm->common.lock, flags);
>> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
>> index c409212ee40e..358a9df6b6a0 100644
>> --- a/drivers/clk/sunxi-ng/ccu_nkm.h
>> +++ b/drivers/clk/sunxi-ng/ccu_nkm.h
>> @@ -27,6 +27,8 @@ struct ccu_nkm {
>>  struct ccu_mux_internal mux;
>>
>>  unsigned intfixed_post_div;
>> +unsigned long   min_rate;
>> +unsigned long   max_rate;
>>  unsigned long   max_m_n_ratio;
>>  unsigned long   min_parent_m_ratio;
>>
>>
>>


Re: [PATCH v2 1/6] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate

2024-02-05 Thread Frank Oltmanns
Hi Jernej,

On 2024-02-05 at 18:45:27 +0100, Jernej Škrabec  
wrote:
> Dne ponedeljek, 05. februar 2024 ob 16:22:24 CET je Frank Oltmanns napisal(a):
>> The Allwinner A64 manual lists the following constraints for the
>> PLL-MIPI clock:
>>  - M/N <= 3
>>  - (PLL_VIDEO0)/M >= 24MHz
>>
>> The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for
>> these constraints.
>>
>> Signed-off-by: Frank Oltmanns 
>
> Haven't we discussed that this patch is unnecessary because same effect can
> be reached by limiting minimum frequency?

The patch for ccu_nm was unnecessary:
https://lore.kernel.org/all/87jzoug2jz@oltmanns.dev/

Unfortunately, we still need this one.

Best regards,
  Frank

>
> Best regards,
> Jernej
>
>> ---
>>  drivers/clk/sunxi-ng/ccu_nkm.c | 21 +
>>  drivers/clk/sunxi-ng/ccu_nkm.h |  2 ++
>>  2 files changed, 23 insertions(+)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
>> index 853f84398e2b..1168d894d636 100644
>> --- a/drivers/clk/sunxi-ng/ccu_nkm.c
>> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
>> @@ -16,6 +16,20 @@ struct _ccu_nkm {
>>  unsigned long   m, min_m, max_m;
>>  };
>>
>> +static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long 
>> parent,
>> +  unsigned long n, unsigned long m)
>> +{
>> +struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common);
>> +
>> +if (nkm->max_m_n_ratio && (m > nkm->max_m_n_ratio * n))
>> +return false;
>> +
>> +if (nkm->min_parent_m_ratio && (parent < nkm->min_parent_m_ratio * m))
>> +return false;
>> +
>> +return true;
>> +}
>> +
>>  static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common 
>> *common,
>> struct clk_hw *parent_hw,
>> unsigned long *parent, 
>> unsigned long rate,
>> @@ -31,6 +45,10 @@ static unsigned long 
>> ccu_nkm_find_best_with_parent_adj(struct ccu_common *common
>>  unsigned long tmp_rate, tmp_parent;
>>
>>  tmp_parent = clk_hw_round_rate(parent_hw, rate 
>> * _m / (_n * _k));
>> +
>> +if (!ccu_nkm_is_valid_rate(common, tmp_parent, 
>> _n, _m))
>> +continue;
>> +
>>  tmp_rate = tmp_parent * _n * _k / _m;
>>
>>  if (ccu_is_better_rate(common, rate, tmp_rate, 
>> best_rate) ||
>> @@ -64,6 +82,9 @@ static unsigned long ccu_nkm_find_best(unsigned long 
>> parent, unsigned long rate,
>>  for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
>>  for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
>>  for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
>> +if (!ccu_nkm_is_valid_rate(common, parent, _n, 
>> _m))
>> +continue;
>> +
>>  unsigned long tmp_rate;
>>
>>  tmp_rate = parent * _n * _k / _m;
>> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
>> index 6601defb3f38..c409212ee40e 100644
>> --- a/drivers/clk/sunxi-ng/ccu_nkm.h
>> +++ b/drivers/clk/sunxi-ng/ccu_nkm.h
>> @@ -27,6 +27,8 @@ struct ccu_nkm {
>>  struct ccu_mux_internal mux;
>>
>>  unsigned intfixed_post_div;
>> +unsigned long   max_m_n_ratio;
>> +unsigned long   min_parent_m_ratio;
>>
>>  struct ccu_common   common;
>>  };
>>
>>


[PATCH v2 4/6] clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI

2024-02-05 Thread Frank Oltmanns
Set the minimum and maximum rate of Allwinner A64's PLL-MIPI according
to the Allwinner User Manual.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index df679dada792..99c2ce11da74 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -178,6 +178,8 @@ static struct ccu_nkm pll_mipi_clk = {
.m  = _SUNXI_CCU_DIV(0, 4),
.max_m_n_ratio  = 3,
.min_parent_m_ratio = 2400,
+   .min_rate   = 5,
+   .max_rate   = 14,
.common = {
.reg= 0x040,
.hw.init= CLK_HW_INIT("pll-mipi", "pll-video0",

-- 
2.43.0



[PATCH v2 6/6] arm64: dts: allwinner: a64: Fix minimum GPU OPP rate

2024-02-05 Thread Frank Oltmanns
The PLL-GPU has a minimum rate of 192 MHz according to the A64 manual.

If run at less than 192 MHz the pinephone (based on the A64) sometimes
replays the last few frames that were displayed over and over (see first
link below).

Note, that running PLL-GPU at 240 MHz and using a divisor of 2 *should*
circumvent this problem as well. But unfortunately, the GPU shows the
erratic behaviour even more often, even though its parent is driven at a
supported range. This might be due to a similar issue to the one
observed on the Allwinner H6 (see second link).

Running both the GPU and PLL-GPU at more then 192 MHz reduces the
occurrenc of the issue.

Therefore, increase the minimum rate in the GPU OPP table to 192 MHz.

Link: https://gitlab.com/postmarketOS/pmaports/-/issues/805
Link: https://lore.kernel.org/linux-arm-kernel/2562485.k3LOHGUjKi@kista/T/
Signed-off-by: Frank Oltmanns 
---
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 57ac18738c99..448d7fbdd1a9 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -107,8 +107,8 @@ de: display-engine {
gpu_opp_table: opp-table-gpu {
compatible = "operating-points-v2";
 
-   opp-12000 {
-   opp-hz = /bits/ 64 <12000>;
+   opp-19200 {
+   opp-hz = /bits/ 64 <19200>;
};
 
opp-31200 {

-- 
2.43.0



[PATCH v2 3/6] clk: sunxi-ng: nkm: Support minimum and maximum rate

2024-02-05 Thread Frank Oltmanns
According to the Allwinner User Manual, the Allwinner A64 requires
PLL-MIPI to run at 500MHz-1.4GHz. Add support for that to ccu_nkm.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu_nkm.c | 13 +
 drivers/clk/sunxi-ng/ccu_nkm.h |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 1168d894d636..7d135908d6e0 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -181,6 +181,12 @@ static unsigned long ccu_nkm_round_rate(struct 
ccu_mux_internal *mux,
if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate *= nkm->fixed_post_div;
 
+   if (nkm->min_rate && rate < nkm->min_rate)
+   rate = nkm->min_rate;
+
+   if (nkm->max_rate && rate > nkm->max_rate)
+   rate = nkm->max_rate;
+
if (!clk_hw_can_set_rate_parent(>common.hw))
rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, 
>common);
else
@@ -220,6 +226,13 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned 
long rate,
_nkm.min_m = 1;
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
 
+
+   if (nkm->min_rate && rate < nkm->min_rate)
+   rate = nkm->min_rate;
+
+   if (nkm->max_rate && rate > nkm->max_rate)
+   rate = nkm->max_rate;
+
ccu_nkm_find_best(parent_rate, rate, &_nkm, >common);
 
spin_lock_irqsave(nkm->common.lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
index c409212ee40e..358a9df6b6a0 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.h
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -27,6 +27,8 @@ struct ccu_nkm {
struct ccu_mux_internal mux;
 
unsigned intfixed_post_div;
+   unsigned long   min_rate;
+   unsigned long   max_rate;
unsigned long   max_m_n_ratio;
unsigned long   min_parent_m_ratio;
 

-- 
2.43.0



[PATCH v2 5/6] drm/panel: st7703: Drive XBD599 panel at higher clock rate

2024-02-05 Thread Frank Oltmanns
This panel is used in the pinephone that runs on a Allwinner A64 SOC.
The SOC requires pll-mipi to run at more than 500 MHz.

This is the relevant clock tree:
 pll-mipi
tcon0
   tcon-data-clock

tcon-data-clock has to run at 1/4 the DSI per-lane bit rate. The XBD599
has 24 bpp and 4 lanes. Therefore, the resulting requested
tcon-data-clock rate is:
crtc_clock * 1000 * (24 / 4) / 4

tcon-data-clock runs at tcon0 / 4 (fixed divisor), so it requests a
parent rate of
4 * (crtc_clock * 1000 * (24 / 4) / 4)

Since tcon0 is a ccu_mux, the rate of tcon0 equals the rate of pll-mipi.

pll-mipi's constraint to run at 500MHz or higher forces us to have a
crtc_clock >= 8 kHz if we want a 60 Hz vertical refresh rate.

Change [hv]sync_(start|end) so that we reach a clock rate of 83502 kHz
so that it is high enough to align with pll-pipi limits.

Signed-off-by: Frank Oltmanns 
---
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index b55bafd1a8be..6886fd7f765e 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -320,14 +320,14 @@ static int xbd599_init_sequence(struct st7703 *ctx)
 
 static const struct drm_display_mode xbd599_mode = {
.hdisplay= 720,
-   .hsync_start = 720 + 40,
-   .hsync_end   = 720 + 40 + 40,
-   .htotal  = 720 + 40 + 40 + 40,
+   .hsync_start = 720 + 65,
+   .hsync_end   = 720 + 65 + 65,
+   .htotal  = 720 + 65 + 65 + 65,
.vdisplay= 1440,
-   .vsync_start = 1440 + 18,
-   .vsync_end   = 1440 + 18 + 10,
-   .vtotal  = 1440 + 18 + 10 + 17,
-   .clock   = 69000,
+   .vsync_start = 1440 + 30,
+   .vsync_end   = 1440 + 30 + 22,
+   .vtotal  = 1440 + 30 + 22 + 29,
+   .clock   = (720 + 65 + 65 + 65) * (1440 + 30 + 22 + 29) * 60 / 1000,
.flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
.width_mm= 68,
.height_mm   = 136,

-- 
2.43.0



[PATCH v2 1/6] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate

2024-02-05 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N <= 3
 - (PLL_VIDEO0)/M >= 24MHz

The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for
these constraints.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu_nkm.c | 21 +
 drivers/clk/sunxi-ng/ccu_nkm.h |  2 ++
 2 files changed, 23 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 853f84398e2b..1168d894d636 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -16,6 +16,20 @@ struct _ccu_nkm {
unsigned long   m, min_m, max_m;
 };
 
+static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long 
parent,
+ unsigned long n, unsigned long m)
+{
+   struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common);
+
+   if (nkm->max_m_n_ratio && (m > nkm->max_m_n_ratio * n))
+   return false;
+
+   if (nkm->min_parent_m_ratio && (parent < nkm->min_parent_m_ratio * m))
+   return false;
+
+   return true;
+}
+
 static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common 
*common,
   struct clk_hw *parent_hw,
   unsigned long *parent, 
unsigned long rate,
@@ -31,6 +45,10 @@ static unsigned long 
ccu_nkm_find_best_with_parent_adj(struct ccu_common *common
unsigned long tmp_rate, tmp_parent;
 
tmp_parent = clk_hw_round_rate(parent_hw, rate 
* _m / (_n * _k));
+
+   if (!ccu_nkm_is_valid_rate(common, tmp_parent, 
_n, _m))
+   continue;
+
tmp_rate = tmp_parent * _n * _k / _m;
 
if (ccu_is_better_rate(common, rate, tmp_rate, 
best_rate) ||
@@ -64,6 +82,9 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, 
unsigned long rate,
for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
+   if (!ccu_nkm_is_valid_rate(common, parent, _n, 
_m))
+   continue;
+
unsigned long tmp_rate;
 
tmp_rate = parent * _n * _k / _m;
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
index 6601defb3f38..c409212ee40e 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.h
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -27,6 +27,8 @@ struct ccu_nkm {
struct ccu_mux_internal mux;
 
unsigned intfixed_post_div;
+   unsigned long   max_m_n_ratio;
+   unsigned long   min_parent_m_ratio;
 
struct ccu_common   common;
 };

-- 
2.43.0



[PATCH v2 0/6] Pinephone video out fixes (flipping between two frames)

2024-02-05 Thread Frank Oltmanns
On some pinephones the video output sometimes freezes (flips between two
frames) [1]. It seems to be that the reason for this behaviour is that
PLL-MIPI, PLL-GPU and GPU are operating outside their limits.

In this patch series I propose the followin changes:
  1. sunxi-ng: Adhere to the following constraints given in the
 Allwinner A64 Manual regarding PLL-MIPI:
  * M/N <= 3
  * (PLL_VIDEO0)/M >= 24MHz
  * 500MHz <= clockrate <= 1400MHz

  2. Choose a higher clock rate for the ST7703 based XDB599 panel, so
 that the panel function well with the Allwinner A64 SOC. PLL-MIPI
 must run between 500 MHz and 1.4 GHz. As PLL-MIPI runs at 6 times
 the panel's clock rate, we need the panel's clock to be at least
 83.333 MHz.

  3. Increase the minimum frequency in the A64 DTS OPPs from 120 MHz to
 192 MHz. This further reduces the issue.

Unfortunately, with these patches the issue [1] is not completely gone,
but becomes less likely.

Note, that when pinning the GPU to 432 MHz the issue completely
disappears for me. I've searched the BSP and could not find any
indication that supports the idea of having the three OPPs. The only
frequency I found in the BPSs for A64 is 432 MHz, that has also proven
stable for me. So, while increasing the minimum frequency to 192 MHz
reduces the issue, should we maybe instead set the GPU to a fixed 432
MHz instead?

I very much appreciate your feedback!

[1] https://gitlab.com/postmarketOS/pmaports/-/issues/805

Signed-off-by: Frank Oltmanns 
---
Changes in v2:
- dts: Increase minimum GPU frequency to 192 MHz.
- nkm and a64: Add minimum and maximum rate for PLL-MIPI.
- nkm: Use the same approach for skipping invalid rates in
  ccu_nkm_find_best() as in ccu_nkm_find_best_with_parent_adj().
- nkm: Improve names for ratio struct members and hence get rid of
  describing comments.
- nkm and a64: Correct description in the commit messages: M/N <= 3
- Remove patches for nm as they were not needed.
- st7703: Rework the commit message to cover more background for the
  change.
- Link to v1: 
https://lore.kernel.org/r/20231218-pinephone-pll-fixes-v1-0-e238b6ed6...@oltmanns.dev

---
Frank Oltmanns (6):
  clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate
  clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent 
rate
  clk: sunxi-ng: nkm: Support minimum and maximum rate
  clk: sunxi-ng: a64: Set minimum and maximum rate for PLL-MIPI
  drm/panel: st7703: Drive XBD599 panel at higher clock rate
  arm64: dts: allwinner: a64: Fix minimum GPU OPP rate

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi |  4 ++--
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 14 +++
 drivers/clk/sunxi-ng/ccu_nkm.c| 34 +++
 drivers/clk/sunxi-ng/ccu_nkm.h|  4 
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 14 +--
 5 files changed, 56 insertions(+), 14 deletions(-)
---
base-commit: 059c53e877ca6e723e10490c27c1487a63e66efe
change-id: 20231218-pinephone-pll-fixes-0ccdfde273e4

Best regards,
-- 
Frank Oltmanns 



[PATCH v2 2/6] clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent rate

2024-02-05 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N <= 3
 - (PLL_VIDEO0)/M >= 24MHz

Use these constraints.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 8951ffc14ff5..df679dada792 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -171,11 +171,13 @@ static struct ccu_nkm pll_mipi_clk = {
 * user manual, and by experiments the PLL doesn't work without
 * these bits toggled.
 */
-   .enable = BIT(31) | BIT(23) | BIT(22),
-   .lock   = BIT(28),
-   .n  = _SUNXI_CCU_MULT(8, 4),
-   .k  = _SUNXI_CCU_MULT_MIN(4, 2, 2),
-   .m  = _SUNXI_CCU_DIV(0, 4),
+   .enable = BIT(31) | BIT(23) | BIT(22),
+   .lock   = BIT(28),
+   .n  = _SUNXI_CCU_MULT(8, 4),
+   .k  = _SUNXI_CCU_MULT_MIN(4, 2, 2),
+   .m  = _SUNXI_CCU_DIV(0, 4),
+   .max_m_n_ratio  = 3,
+   .min_parent_m_ratio = 2400,
.common = {
.reg= 0x040,
.hw.init= CLK_HW_INIT("pll-mipi", "pll-video0",

-- 
2.43.0



Re: [PATCH 4/5] clk: sunxi-ng: a64: Add constraints on PLL-VIDEO0's n/m ratio

2023-12-31 Thread Frank Oltmanns


On 2023-12-19 at 17:54:19 +0100, Jernej Škrabec  
wrote:
> Dne ponedeljek, 18. december 2023 ob 14:35:22 CET je Frank Oltmanns 
> napisal(a):
>> The Allwinner A64 manual lists the following constraint for the
>> PLL-VIDEO0 clock: 8 <= N/M <= 25
>>
>> Use this constraint.
>>
>> Signed-off-by: Frank Oltmanns 
>> ---
>>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 8 ++--
>>  1 file changed, 6 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
>> b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> index c034ac027d1c..75d839da446c 100644
>> --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> @@ -68,7 +68,8 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, 
>> "pll-audio-base",
>> BIT(28), /* lock */
>> CLK_SET_RATE_UNGATE);
>>
>> -static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, 
>> "pll-video0",
>> +static 
>> SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT_NM_RATIO(pll_video0_clk,
>> +"pll-video0",
>>  "osc24M", 0x010,
>>  19200,  /* Minimum rate 
>> */
>>  100800, /* Maximum rate 
>> */

I just realized that adding the whole ratio limits for ccu_nm is
superfluous as you could just as well express them in for of a minimum
and maximum range:
Since 8 <= N/M <= 25 and parent_rate = 24 MHz, therefore
  192 MHz <= rate <= 600 MHz.

These absolute limits are also listed in Allwinner's A64 manual.

BUT, here the upper limit was raised to 1008 MHz:
5de39acaf34604bd04834f092479cf4dcc946dd "clk: sunxi-ng: a64: Add max.
rate constraint to video PLL"

With this upper limit the ratio limitation is effectively:
8 <= N/M <= 42

Icenowy Zheng (added to CC) had the reasonable explanation that this was
used in the BSP kernel, so we should probably stick to that and ditch
the two PLL-VIDEO0 related patches. What are your thoughts on that?

>> @@ -80,7 +81,10 @@ static 
>> SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, "pll-vid
>>  29700,  /* frac rate 1 
>> */
>>  BIT(31),/* gate */
>>  BIT(28),/* lock */
>> -CLK_SET_RATE_UNGATE);
>> +CLK_SET_RATE_UNGATE,
>> +CCU_FEATURE_FRACTIONAL |
>> +CCU_FEATURE_CLOSEST_RATE,
>
> Above flags are unrelated change, put them in new patch if needed.
>
> Best regards,
> Jernej
>
>> +8, 25); /* min/max nm 
>> ratio */
>>
>>  static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
>>  "osc24M", 0x018,
>>
>>


Re: [PATCH 5/5] drm/panel: st7703: Drive XBD599 panel at higher clock rate

2023-12-30 Thread Frank Oltmanns


On 2023-12-20 at 16:18:49 +0100, Jernej Škrabec  
wrote:
> Dne sreda, 20. december 2023 ob 08:14:27 CET je Frank Oltmanns napisal(a):
>>
>> On 2023-12-19 at 18:04:29 +0100, Jernej Škrabec  
>> wrote:
>> > Dne ponedeljek, 18. december 2023 ob 14:35:23 CET je Frank Oltmanns 
>> > napisal(a):
>> >> This panel is used in the pinephone that runs on a Allwinner A64 SOC.
>> >> Acoording to it's datasheet, the SOC requires PLL-MIPI to run at more
>> >> than 500 MHz.
>> >>
>> >> Therefore, change [hv]sync_(start|end) so that we reach a clock rate
>> >> that is high enough to drive PLL-MIPI within its limits.
>> >>
>> >> Signed-off-by: Frank Oltmanns 
>> >
>> > I'm not too sure about this patch. I see that PLL_MIPI doesn't have set
>> > minimum frequency limit in clock driver. If you add it, clock framework
>> > should find rate that is high enough and divisible with target rate.
>>
>> This one is really a tough nut. Unfortunately, the PLL_MIPI clock for
>> this panel has to run exactly at 6 * panel clock. Let me start by
>> showing the relevant part of the clock tree (this is on the pinephone
>> after applying the patches):
>> pll-video0 39360
>>pll-mipi500945454
>>   tcon0500945454
>>  tcon-data-clock   125236363
>>
>> To elaborate, tcon-data-clock has to run at 1/4 the DSI per-lane bit
>> rate [1]. It's a fixed divisor
>>
>> The panel I'm proposing to change is defined as this:
>>
>> static const struct st7703_panel_desc xbd599_desc = {
>>  .mode = _mode,
>>  .lanes = 4,
>>  .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
>>  .format = MIPI_DSI_FMT_RGB888,
>>  .init_sequence = xbd599_init_sequence,
>> };
>>
>> So, we have 24 bpp and 4 lanes. Therefore, the resulting requested
>> tcon-data-clock rate is
>> crtc_clock * 1000 * (24 / 4) / 4
>>
>> tcon-data-clock therefore requests a parent rate of
>> 4 * (crtc_clock * 1000 * (24 / 4) / 4)
>>
>> The initial 4 is the fixed divisor between tcon0 and tcon-data-clock.
>> Since tcon0 is a ccu_mux, the rate of tcon0 equals the rate of pll-mipi.
>>
>> Since PLL-MIPI has to run at at least at 500MHz this forces us to have a
>> crtc_clock >= 83.333 MHz. The mode I'm prorposing results in a rate of
>> 83.502 MHz.
>
> This is much better explanation why this change is needed. Still, I think
> adding min and max rate to PLL_MIPI would make sense, so proper rates
> are guaranteed.

Okay, I'll include min and max rate in V2, because you're right that
it's the sane thing to do and actually it wasn't too much work. I (and
others) do experience crashes if pll-mipi is driven below the 500 MHz
mark, so let's fix this once and for all.

> Anyway, do you know where are all those old values come from?

I've done some digging on lore and the values were originally submitted
by Icenowy Zheng as part of a series to support the pinephone's LCD [1].
There has been some refactoring after this initial submission and Ondrej
Jirman took over. But the values are still the ones submitted by
Icenowy, so I've added her to CC. I couldn't find any documentation for
this specific panel.

> And how did
> you come up with new ones?

Trial and no error. :)

No, really, it was just a lucky guess. I know nothing about LCD panels,
so I only looked at the original values:
.htotal =  720 + 40 + 40 + 40,
.vtotal = 1440 + 18 + 10 + 17,

I thought, what if every time I increase a horizontal value by 2, I
increase a vertical value by 1 (very roughly).

So I ended up with:
.htotal =  720 + 65 + 65 + 65,
.vtotal = 1440 + 30 + 22 + 29,

So, in conclusion, I've increased each of the horizontal values by 25
and each of the vertical values by 12. Then I just tried out these new
values, and the world didn't end. :)

If this is stupid, please somebody let me know.

I (and at least one postmarket OS tester) have been daily driving the
panel with these values for about a week now.

I've checked the panel's refresh rate with the following test setup:
 - I created a 60 fps video that shows the current frame number in each
   frame. The video is 10 seconds (600 frames) long. [2]
 - I played that video on my pinephone using vlc. [3]
 - I recorded the playback with a Google Pixel 5 phone at 1/8 slow
   motion (240 fps).
 - I converted the video into individual pictures [4], resized
   the pictures to 10% [5], and finally - after deleting some superfluous
   pictures at the beginning and end - I created one big collage out of
   these [6].

I've uploaded the video[7], resulting co

Re: [PATCH 5/5] drm/panel: st7703: Drive XBD599 panel at higher clock rate

2023-12-22 Thread Frank Oltmanns


On 2023-12-20 at 19:57:06 +0100, Frank Oltmanns  wrote:
> Ok, I've done more detailed testing, and it seems this patch results in
> lots of dropped frames. I'm sorry for not being more thorough earlier.
> I'll do some more testing without this patch and might have to either
> remove it from V2 of this series.
>
> I need to see if the same stability can be achieved when running
> PLL-MIPI outside its specied range.

I've done some more (load) testing and observing the panel for dropped
frames.

The conclusion I draw from those results is that this patch isn't
necessary for the pinephone. It would be enough to use the correct clock
rate based on the existing values [*]:
-   .clock   = 69000,
+   .clock   = (720 + 40 + 40 + 40) * (1440 + 18 + 10 + 17) * 60 / 1000,

I've asked in the postmarketOS community for a bit more testing. They
already have a merge request that contains these changes [2].

This means that we would continue to drive PLL-MIPI outside it's
specified range. I have, so far, not experienced any downside of doing
so. It seems enough to fix the ratios that are part of the first four
patches in this series without introducing a min and max rate.

In conclusion, I'll soon (after some more feedback from the fine folks
at postmarketOS) submit a V2 that addresses the fixes requested in the
first four patches of this series. I'll drop the existing PATCH 5 and
replace it with the one I sent in February [1] instead.

After that, just for fun, I'll probably look into min_rate and max_rate
for nkm clocks and which consequences it has on the pinephone. I might
or might not send a follow up series for that. However, if the pinephone
runs stable without it, it's not a high priority for me.

Best regards,
  Frank

[*] I've already submitted a patch in February '23 [1]. It was of little
use back then because the A64's PLL-MIPI clock was not able to run
close to that rate. But since kernel 6.6 PLL-MIPI is able to set
it's parent rate, so that it can come quite close to the required
rate:
 + Panel requires 74.844 MHz with the current timings.
 +-> tcon-data-clock rate should be 112.266 MHz (panel*24/4/4).
  +-> PLL-MIPI rate should be 449.064 MHz (TCON0 * 4)

The 6.6 kernel the following rates are possible:
 + PLL-MIPI: ~448.984615 MHz
 +-> tcon-data-clock: ~112.246153
  +-> panel: ~74.830768 MHz

Which leaves us with a vertical refresh rate of ~59.989 Hz,
deviating less then 0.2% from the ideal 60Hz. That's probably closer
than the accumulated accuracy of all involved components can
reliably achieve. I'd say, let's leave it at that.

[1]: https://lore.kernel.org/lkml/20230219114553.288057-2-fr...@oltmanns.dev/
[2]: https://gitlab.com/postmarketOS/pmaports/-/merge_requests/4645
>
> Best regards,
>   Frank
>
> On 2023-12-20 at 16:18:49 +0100, Jernej Škrabec  
> wrote:
>> Dne sreda, 20. december 2023 ob 08:14:27 CET je Frank Oltmanns napisal(a):
>>>
>>> On 2023-12-19 at 18:04:29 +0100, Jernej Škrabec  
>>> wrote:
>>> > Dne ponedeljek, 18. december 2023 ob 14:35:23 CET je Frank Oltmanns 
>>> > napisal(a):
>>> >> This panel is used in the pinephone that runs on a Allwinner A64 SOC.
>>> >> Acoording to it's datasheet, the SOC requires PLL-MIPI to run at more
>>> >> than 500 MHz.
>>> >>
>>> >> Therefore, change [hv]sync_(start|end) so that we reach a clock rate
>>> >> that is high enough to drive PLL-MIPI within its limits.
>>> >>
>>> >> Signed-off-by: Frank Oltmanns 
>>> >
>>> > I'm not too sure about this patch. I see that PLL_MIPI doesn't have set
>>> > minimum frequency limit in clock driver. If you add it, clock framework
>>> > should find rate that is high enough and divisible with target rate.
>>>
>>> This one is really a tough nut. Unfortunately, the PLL_MIPI clock for
>>> this panel has to run exactly at 6 * panel clock. Let me start by
>>> showing the relevant part of the clock tree (this is on the pinephone
>>> after applying the patches):
>>> pll-video0 39360
>>>pll-mipi500945454
>>>   tcon0500945454
>>>  tcon-data-clock   125236363
>>>
>>> To elaborate, tcon-data-clock has to run at 1/4 the DSI per-lane bit
>>> rate [1]. It's a fixed divisor
>>>
>>> The panel I'm proposing to change is defined as this:
>>>
>>> static const struct st7703_panel_desc xbd599_desc = {
>>> .mode = _mode,
>>> .lanes = 4,
>>> .mode_flags = MIPI_DSI_MODE_VIDEO | 
>>> MIPI_DSI_MODE_VI

Re: [PATCH 4/5] clk: sunxi-ng: a64: Add constraints on PLL-VIDEO0's n/m ratio

2023-12-21 Thread Frank Oltmanns


On 2023-12-20 at 16:12:42 +0100, Jernej Škrabec  
wrote:
> Dne sreda, 20. december 2023 ob 08:09:28 CET je Frank Oltmanns napisal(a):
>>
>> On 2023-12-19 at 17:54:19 +0100, Jernej Škrabec  
>> wrote:
>> > Dne ponedeljek, 18. december 2023 ob 14:35:22 CET je Frank Oltmanns 
>> > napisal(a):
>> >> The Allwinner A64 manual lists the following constraint for the
>> >> PLL-VIDEO0 clock: 8 <= N/M <= 25
>> >>
>> >> Use this constraint.
>> >>
>> >> Signed-off-by: Frank Oltmanns 
>> >> ---
>> >>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 8 ++--
>> >>  1 file changed, 6 insertions(+), 2 deletions(-)
>> >>
>> >> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
>> >> b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> >> index c034ac027d1c..75d839da446c 100644
>> >> --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> >> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> >> @@ -68,7 +68,8 @@ static 
>> >> SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
>> >>  BIT(28), /* lock */
>> >>  CLK_SET_RATE_UNGATE);
>> >>
>> >> -static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, 
>> >> "pll-video0",
>> >> +static 
>> >> SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT_NM_RATIO(pll_video0_clk,
>> >> + "pll-video0",
>> >>   "osc24M", 0x010,
>> >>   19200,  /* Minimum rate 
>> >> */
>> >>   100800, /* Maximum rate 
>> >> */
>> >> @@ -80,7 +81,10 @@ static 
>> >> SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, "pll-vid
>> >>   29700,  /* frac rate 1 
>> >> */
>> >>   BIT(31),/* gate */
>> >>   BIT(28),/* lock */
>> >> - CLK_SET_RATE_UNGATE);
>> >> + CLK_SET_RATE_UNGATE,
>> >> + CCU_FEATURE_FRACTIONAL |
>> >> + CCU_FEATURE_CLOSEST_RATE,
>> >
>> > Above flags are unrelated change, put them in new patch if needed.
>>
>> You might notice that I am using a new macro for initializing the
>> pll_video0_clk struct:
>> New: SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT_NM_RATIO
>> Old: SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST
>>
>> Setting the two CCU_FEATURE flags is part of the old initialization
>> macro.
>>
>> I'll add SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_NM_RATIO_CLOSEST which
>> hopefully resolves the confusion.
>
> I'm in doubt if we need so many macros. How many users of these macro we'll 
> have?
> I see that R40 SoC would also need same ratio limits, but other that that, 
> none?

Ok, IIUC no additional macro and we keep this part of the patch as is.

Best regards,
  Frank

>
> Best regards,
> Jernej
>
>>
>> Thanks,
>>   Frank
>>
>> >
>> > Best regards,
>> > Jernej
>> >
>> >> + 8, 25); /* min/max nm 
>> >> ratio */
>> >>
>> >>  static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
>> >>   "osc24M", 0x018,
>> >>
>> >>
>>


Re: [PATCH 5/5] drm/panel: st7703: Drive XBD599 panel at higher clock rate

2023-12-20 Thread Frank Oltmanns


Ok, I've done more detailed testing, and it seems this patch results in
lots of dropped frames. I'm sorry for not being more thorough earlier.
I'll do some more testing without this patch and might have to either
remove it from V2 of this series.

I need to see if the same stability can be achieved when running
PLL-MIPI outside its specied range.

Best regards,
  Frank

On 2023-12-20 at 16:18:49 +0100, Jernej Škrabec  
wrote:
> Dne sreda, 20. december 2023 ob 08:14:27 CET je Frank Oltmanns napisal(a):
>>
>> On 2023-12-19 at 18:04:29 +0100, Jernej Škrabec  
>> wrote:
>> > Dne ponedeljek, 18. december 2023 ob 14:35:23 CET je Frank Oltmanns 
>> > napisal(a):
>> >> This panel is used in the pinephone that runs on a Allwinner A64 SOC.
>> >> Acoording to it's datasheet, the SOC requires PLL-MIPI to run at more
>> >> than 500 MHz.
>> >>
>> >> Therefore, change [hv]sync_(start|end) so that we reach a clock rate
>> >> that is high enough to drive PLL-MIPI within its limits.
>> >>
>> >> Signed-off-by: Frank Oltmanns 
>> >
>> > I'm not too sure about this patch. I see that PLL_MIPI doesn't have set
>> > minimum frequency limit in clock driver. If you add it, clock framework
>> > should find rate that is high enough and divisible with target rate.
>>
>> This one is really a tough nut. Unfortunately, the PLL_MIPI clock for
>> this panel has to run exactly at 6 * panel clock. Let me start by
>> showing the relevant part of the clock tree (this is on the pinephone
>> after applying the patches):
>> pll-video0 39360
>>pll-mipi500945454
>>   tcon0500945454
>>  tcon-data-clock   125236363
>>
>> To elaborate, tcon-data-clock has to run at 1/4 the DSI per-lane bit
>> rate [1]. It's a fixed divisor
>>
>> The panel I'm proposing to change is defined as this:
>>
>> static const struct st7703_panel_desc xbd599_desc = {
>>  .mode = _mode,
>>  .lanes = 4,
>>  .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
>>  .format = MIPI_DSI_FMT_RGB888,
>>  .init_sequence = xbd599_init_sequence,
>> };
>>
>> So, we have 24 bpp and 4 lanes. Therefore, the resulting requested
>> tcon-data-clock rate is
>> crtc_clock * 1000 * (24 / 4) / 4
>>
>> tcon-data-clock therefore requests a parent rate of
>> 4 * (crtc_clock * 1000 * (24 / 4) / 4)
>>
>> The initial 4 is the fixed divisor between tcon0 and tcon-data-clock.
>> Since tcon0 is a ccu_mux, the rate of tcon0 equals the rate of pll-mipi.
>>
>> Since PLL-MIPI has to run at at least at 500MHz this forces us to have a
>> crtc_clock >= 83.333 MHz. The mode I'm prorposing results in a rate of
>> 83.502 MHz.
>
> This is much better explanation why this change is needed. Still, I think
> adding min and max rate to PLL_MIPI would make sense, so proper rates
> are guaranteed.
>
> Anyway, do you know where are all those old values come from? And how did
> you come up with new ones? I guess you can't just simply change timings,
> there are probably some HW limitations? Do you know if BSP kernel support
> this panel and how this situation is solved there?
>
>>
>> If we only changed the constraints on the PLL_MIPI without changing the
>> panel mode, we end up with a mismatch. This, in turn, would result in
>> dropped frames, right?
>
> From what I read, I think frame rate would be higher than 60 fps. What
> exactly would happen depends on the panel.
>
> Best regards,
> Jernej
>
>>
>> Best regards,
>>   Frank
>>
>> [1] Source:
>> https://elixir.bootlin.com/linux/v6.6.7/source/drivers/gpu/drm/sun4i/sun4i_tcon.c#L346
>>
>> >
>> > Best regards,
>> > Jernej
>> >
>> >> ---
>> >>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 14 +++---
>> >>  1 file changed, 7 insertions(+), 7 deletions(-)
>> >>
>> >> diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
>> >> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> >> index b55bafd1a8be..6886fd7f765e 100644
>> >> --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> >> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> >> @@ -320,14 +320,14 @@ static int xbd599_init_sequence(struct st7703 *ctx)
>> >>
>> >>  static const struct drm_display_mode xbd599_mode = {
>> >>   .hdisplay= 720,
>> >> - .hsync_start = 720 + 40,
>> >> - .hsync_end   = 720 + 40 + 40,
>> >> - .htotal  = 720 + 40 + 40 + 40,
>> >> + .hsync_start = 720 + 65,
>> >> + .hsync_end   = 720 + 65 + 65,
>> >> + .htotal  = 720 + 65 + 65 + 65,
>> >>   .vdisplay= 1440,
>> >> - .vsync_start = 1440 + 18,
>> >> - .vsync_end   = 1440 + 18 + 10,
>> >> - .vtotal  = 1440 + 18 + 10 + 17,
>> >> - .clock   = 69000,
>> >> + .vsync_start = 1440 + 30,
>> >> + .vsync_end   = 1440 + 30 + 22,
>> >> + .vtotal  = 1440 + 30 + 22 + 29,
>> >> + .clock   = (720 + 65 + 65 + 65) * (1440 + 30 + 22 + 29) * 60 / 1000,
>> >>   .flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
>> >>   .width_mm= 68,
>> >>   .height_mm   = 136,
>> >>
>> >>
>>


Re: [PATCH 5/5] drm/panel: st7703: Drive XBD599 panel at higher clock rate

2023-12-20 Thread Frank Oltmanns


On 2023-12-19 at 18:04:29 +0100, Jernej Škrabec  
wrote:
> Dne ponedeljek, 18. december 2023 ob 14:35:23 CET je Frank Oltmanns 
> napisal(a):
>> This panel is used in the pinephone that runs on a Allwinner A64 SOC.
>> Acoording to it's datasheet, the SOC requires PLL-MIPI to run at more
>> than 500 MHz.
>>
>> Therefore, change [hv]sync_(start|end) so that we reach a clock rate
>> that is high enough to drive PLL-MIPI within its limits.
>>
>> Signed-off-by: Frank Oltmanns 
>
> I'm not too sure about this patch. I see that PLL_MIPI doesn't have set
> minimum frequency limit in clock driver. If you add it, clock framework
> should find rate that is high enough and divisible with target rate.

This one is really a tough nut. Unfortunately, the PLL_MIPI clock for
this panel has to run exactly at 6 * panel clock. Let me start by
showing the relevant part of the clock tree (this is on the pinephone
after applying the patches):
pll-video0 39360
   pll-mipi500945454
  tcon0500945454
 tcon-data-clock   125236363

To elaborate, tcon-data-clock has to run at 1/4 the DSI per-lane bit
rate [1]. It's a fixed divisor

The panel I'm proposing to change is defined as this:

static const struct st7703_panel_desc xbd599_desc = {
.mode = _mode,
.lanes = 4,
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
.format = MIPI_DSI_FMT_RGB888,
.init_sequence = xbd599_init_sequence,
};

So, we have 24 bpp and 4 lanes. Therefore, the resulting requested
tcon-data-clock rate is
crtc_clock * 1000 * (24 / 4) / 4

tcon-data-clock therefore requests a parent rate of
4 * (crtc_clock * 1000 * (24 / 4) / 4)

The initial 4 is the fixed divisor between tcon0 and tcon-data-clock.
Since tcon0 is a ccu_mux, the rate of tcon0 equals the rate of pll-mipi.

Since PLL-MIPI has to run at at least at 500MHz this forces us to have a
crtc_clock >= 83.333 MHz. The mode I'm prorposing results in a rate of
83.502 MHz.

If we only changed the constraints on the PLL_MIPI without changing the
panel mode, we end up with a mismatch. This, in turn, would result in
dropped frames, right?

Best regards,
  Frank

[1] Source:
https://elixir.bootlin.com/linux/v6.6.7/source/drivers/gpu/drm/sun4i/sun4i_tcon.c#L346

>
> Best regards,
> Jernej
>
>> ---
>>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 14 +++---
>>  1 file changed, 7 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
>> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> index b55bafd1a8be..6886fd7f765e 100644
>> --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> @@ -320,14 +320,14 @@ static int xbd599_init_sequence(struct st7703 *ctx)
>>
>>  static const struct drm_display_mode xbd599_mode = {
>>  .hdisplay= 720,
>> -.hsync_start = 720 + 40,
>> -.hsync_end   = 720 + 40 + 40,
>> -.htotal  = 720 + 40 + 40 + 40,
>> +.hsync_start = 720 + 65,
>> +.hsync_end   = 720 + 65 + 65,
>> +.htotal  = 720 + 65 + 65 + 65,
>>  .vdisplay= 1440,
>> -.vsync_start = 1440 + 18,
>> -.vsync_end   = 1440 + 18 + 10,
>> -.vtotal  = 1440 + 18 + 10 + 17,
>> -.clock   = 69000,
>> +.vsync_start = 1440 + 30,
>> +.vsync_end   = 1440 + 30 + 22,
>> +.vtotal  = 1440 + 30 + 22 + 29,
>> +.clock   = (720 + 65 + 65 + 65) * (1440 + 30 + 22 + 29) * 60 / 1000,
>>  .flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
>>  .width_mm= 68,
>>  .height_mm   = 136,
>>
>>


Re: [PATCH 4/5] clk: sunxi-ng: a64: Add constraints on PLL-VIDEO0's n/m ratio

2023-12-19 Thread Frank Oltmanns


On 2023-12-19 at 17:54:19 +0100, Jernej Škrabec  
wrote:
> Dne ponedeljek, 18. december 2023 ob 14:35:22 CET je Frank Oltmanns 
> napisal(a):
>> The Allwinner A64 manual lists the following constraint for the
>> PLL-VIDEO0 clock: 8 <= N/M <= 25
>>
>> Use this constraint.
>>
>> Signed-off-by: Frank Oltmanns 
>> ---
>>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 8 ++--
>>  1 file changed, 6 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
>> b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> index c034ac027d1c..75d839da446c 100644
>> --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> @@ -68,7 +68,8 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, 
>> "pll-audio-base",
>> BIT(28), /* lock */
>> CLK_SET_RATE_UNGATE);
>>
>> -static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, 
>> "pll-video0",
>> +static 
>> SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT_NM_RATIO(pll_video0_clk,
>> +"pll-video0",
>>  "osc24M", 0x010,
>>  19200,  /* Minimum rate 
>> */
>>  100800, /* Maximum rate 
>> */
>> @@ -80,7 +81,10 @@ static 
>> SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, "pll-vid
>>  29700,  /* frac rate 1 
>> */
>>  BIT(31),/* gate */
>>  BIT(28),/* lock */
>> -CLK_SET_RATE_UNGATE);
>> +CLK_SET_RATE_UNGATE,
>> +CCU_FEATURE_FRACTIONAL |
>> +CCU_FEATURE_CLOSEST_RATE,
>
> Above flags are unrelated change, put them in new patch if needed.

You might notice that I am using a new macro for initializing the
pll_video0_clk struct:
New: SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT_NM_RATIO
Old: SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST

Setting the two CCU_FEATURE flags is part of the old initialization
macro.

I'll add SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_NM_RATIO_CLOSEST which
hopefully resolves the confusion.

Thanks,
  Frank

>
> Best regards,
> Jernej
>
>> +8, 25); /* min/max nm 
>> ratio */
>>
>>  static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
>>  "osc24M", 0x018,
>>
>>


Re: [PATCH 1/5] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate

2023-12-19 Thread Frank Oltmanns
Hi Jernej!

On 2023-12-19 at 17:46:08 +0100, Jernej Škrabec  
wrote:
> Hi Frank!
>
> Dne ponedeljek, 18. december 2023 ob 14:35:19 CET je Frank Oltmanns 
> napisal(a):
>> The Allwinner A64 manual lists the following constraints for the
>> PLL-MIPI clock:
>>  - M/N >= 3
>
> This should be "<="

Yes, good catch! I will fix it in V2.

>
>>  - (PLL_VIDEO0)/M >= 24MHz
>>
>> The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for
>> these constraints.
>>
>> Signed-off-by: Frank Oltmanns 
>> ---
>>  drivers/clk/sunxi-ng/ccu_nkm.c | 23 +++
>>  drivers/clk/sunxi-ng/ccu_nkm.h |  8 
>>  2 files changed, 31 insertions(+)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
>> index eed64547ad42..2af5c1ebd527 100644
>> --- a/drivers/clk/sunxi-ng/ccu_nkm.c
>> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
>> @@ -16,6 +16,20 @@ struct _ccu_nkm {
>>  unsigned long   m, min_m, max_m;
>>  };
>>
>> +static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long 
>> parent,
>> +  unsigned long n, unsigned long m)
>> +{
>> +struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common);
>> +
>> +if (nkm->max_mn_ratio && (m > nkm->max_mn_ratio * n))
>> +return false;
>> +
>> +if (nkm->parent_wo_nk && (parent < nkm->parent_wo_nk * m))
>> +return false;
>> +
>> +return true;
>> +}
>> +
>>  static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common 
>> *common,
>> struct clk_hw *parent_hw,
>> unsigned long *parent, 
>> unsigned long rate,
>> @@ -32,6 +46,9 @@ static unsigned long 
>> ccu_nkm_find_best_with_parent_adj(struct ccu_common *common
>>
>>  tmp_parent = clk_hw_round_rate(parent_hw, rate 
>> * _m / (_n * _k));
>>
>> +if (!ccu_nkm_is_valid_rate(common, tmp_parent, 
>> _n, _m))
>> +continue;
>> +
>>  tmp_rate = tmp_parent * _n * _k / _m;
>>
>>  if (ccu_is_better_rate(common, rate, tmp_rate, 
>> best_rate) ||
>> @@ -65,6 +82,12 @@ static unsigned long ccu_nkm_find_best(unsigned long 
>> parent, unsigned long rate,
>>  for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
>>  for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
>>  for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
>> +if ((common->reg == 0x040) && (_m > 3 * _n))
>> +break;
>> +
>> +if ((common->reg == 0x040) && (parent < 
>> 2400 * _m))
>> +continue;
>> +
>
> You already figured this part.
>
>>  unsigned long tmp_rate;
>>
>>  tmp_rate = parent * _n * _k / _m;
>> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
>> index 6601defb3f38..d3d3eaf55faf 100644
>> --- a/drivers/clk/sunxi-ng/ccu_nkm.h
>> +++ b/drivers/clk/sunxi-ng/ccu_nkm.h
>> @@ -16,6 +16,12 @@
>>   * struct ccu_nkm - Definition of an N-K-M clock
>>   *
>>   * Clocks based on the formula parent * N * K / M
>> + *
>> + * @max_mn_ratio:   Maximum value for M / N.
>> + * @parent_wo_nk:   The minimum rate the parent must provide after applying 
>> the divisor,
>> + *  but without applying the multipliers, i.e. the 
>> contstraint
>> + * (parent rate)/M >= parent_wo_nk
>> + *  must be fulfilled.
>>   */
>>  struct ccu_nkm {
>>  u32 enable;
>> @@ -27,6 +33,8 @@ struct ccu_nkm {
>>  struct ccu_mux_internal mux;
>>
>>  unsigned intfixed_post_div;
>> +unsigned long   max_mn_ratio;
>> +unsigned long   parent_wo_nk;
>
> What about max_m_n_ratio and max_parent_m_ratio, to be consistent? This
> should also allow to simplify description.

Jernej, thank you so much! This is brilliant! I was racking my brain for
a good name but failed. Now, that I see your proposal, I don't know why
I hadn't come up with it. It's the obvious choice.

I'd say with the new names we should be able to get rid of the comments
describing the new struct members (also in ccu_nm.h). What are your
thoughts on that?

Best regards,
  Frank

>
> Best regards,
> Jernej
>
>>
>>  struct ccu_common   common;
>>  };
>>
>>


[PATCH 0/5] Pinephone video out fixes (flipping between two frames)

2023-12-18 Thread Frank Oltmanns
On some pinephones the video output sometimes freezes (flips between two
frames) [1]. It seems to be that the reason for this behaviour is that
PLL-MIPI and PLL-VIDEO0 are operating outside there specified limits.

The changes I propose in this patch series consists of two major parts:
  1. sunxi-ng: Adhere to the following constraints given in the
 Allwinner A64 Manual:
  a. PLL-MIPI:
  * M/N >= 3
  * (PLL_VIDEO0)/M >= 24MHz
  b. PLL-VIDEO0:
  * 8 <= N/M <= 25

  2. Choose a higher clock rate for the ST7703 based XDB599 panel, so
 that the panel functions with the Allwinner A64 SOC. PLL-MIPI
 must run between 500 MHz and 1.4 GHz. As PLL-MIPI runs at 6 times
 the panel's clock rate, we need its clock to be at least 83.333
 MHz.

So far, I've tested the patches only on my pinephone. Before the patches
it would freeze at least every other day. With the patches it has not
shown this behavior in over a week.

I very much appreciate your feedback!

[1] https://gitlab.com/postmarketOS/pmaports/-/issues/805

Signed-off-by: Frank Oltmanns 
---
Frank Oltmanns (5):
  clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate
  clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent 
rate
  clk: sunxi-ng: nm: Support constraints on n/m ratio and parent rate
  clk: sunxi-ng: a64: Add constraints on PLL-VIDEO0's n/m ratio
  drm/panel: st7703: Drive XBD599 panel at higher clock rate

 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 10 ++--
 drivers/clk/sunxi-ng/ccu_nkm.c| 23 ++
 drivers/clk/sunxi-ng/ccu_nkm.h|  8 +++
 drivers/clk/sunxi-ng/ccu_nm.c | 21 +++--
 drivers/clk/sunxi-ng/ccu_nm.h | 34 +--
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 14 +--
 6 files changed, 97 insertions(+), 13 deletions(-)
---
base-commit: d0ac5722dae5f4302bb4ef6df10d0afa718df80b
change-id: 20231218-pinephone-pll-fixes-0ccdfde273e4

Best regards,
-- 
Frank Oltmanns 



[PATCH 4/5] clk: sunxi-ng: a64: Add constraints on PLL-VIDEO0's n/m ratio

2023-12-18 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraint for the
PLL-VIDEO0 clock: 8 <= N/M <= 25

Use this constraint.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index c034ac027d1c..75d839da446c 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -68,7 +68,8 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, 
"pll-audio-base",
   BIT(28), /* lock */
   CLK_SET_RATE_UNGATE);
 
-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, 
"pll-video0",
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT_NM_RATIO(pll_video0_clk,
+   "pll-video0",
"osc24M", 0x010,
19200,  /* Minimum rate 
*/
100800, /* Maximum rate 
*/
@@ -80,7 +81,10 @@ static 
SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, "pll-vid
29700,  /* frac rate 1 
*/
BIT(31),/* gate */
BIT(28),/* lock */
-   CLK_SET_RATE_UNGATE);
+   CLK_SET_RATE_UNGATE,
+   CCU_FEATURE_FRACTIONAL |
+   CCU_FEATURE_CLOSEST_RATE,
+   8, 25); /* min/max nm 
ratio */
 
 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
"osc24M", 0x018,

-- 
2.43.0



[PATCH 5/5] drm/panel: st7703: Drive XBD599 panel at higher clock rate

2023-12-18 Thread Frank Oltmanns
This panel is used in the pinephone that runs on a Allwinner A64 SOC.
Acoording to it's datasheet, the SOC requires PLL-MIPI to run at more
than 500 MHz.

Therefore, change [hv]sync_(start|end) so that we reach a clock rate
that is high enough to drive PLL-MIPI within its limits.

Signed-off-by: Frank Oltmanns 
---
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index b55bafd1a8be..6886fd7f765e 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -320,14 +320,14 @@ static int xbd599_init_sequence(struct st7703 *ctx)
 
 static const struct drm_display_mode xbd599_mode = {
.hdisplay= 720,
-   .hsync_start = 720 + 40,
-   .hsync_end   = 720 + 40 + 40,
-   .htotal  = 720 + 40 + 40 + 40,
+   .hsync_start = 720 + 65,
+   .hsync_end   = 720 + 65 + 65,
+   .htotal  = 720 + 65 + 65 + 65,
.vdisplay= 1440,
-   .vsync_start = 1440 + 18,
-   .vsync_end   = 1440 + 18 + 10,
-   .vtotal  = 1440 + 18 + 10 + 17,
-   .clock   = 69000,
+   .vsync_start = 1440 + 30,
+   .vsync_end   = 1440 + 30 + 22,
+   .vtotal  = 1440 + 30 + 22 + 29,
+   .clock   = (720 + 65 + 65 + 65) * (1440 + 30 + 22 + 29) * 60 / 1000,
.flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
.width_mm= 68,
.height_mm   = 136,

-- 
2.43.0



[PATCH 3/5] clk: sunxi-ng: nm: Support constraints on n/m ratio and parent rate

2023-12-18 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraint for the
PLL-VIDEO0 clock: 8 <= N/M <= 25

The PLL-MIPI clock is implemented as ccu_nm. Therefore, add support for
this constraint.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu_nm.c | 21 +++--
 drivers/clk/sunxi-ng/ccu_nm.h | 34 --
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index ffac3deb89d6..cfc6981e398b 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -27,6 +27,19 @@ static unsigned long ccu_nm_calc_rate(unsigned long parent,
return rate;
 }
 
+static bool ccu_nm_is_valid_rate(struct ccu_common *common, unsigned long n, 
unsigned long m)
+{
+   struct ccu_nm *nm = container_of(common, struct ccu_nm, common);
+
+   if (nm->max_nm_ratio && (n > nm->max_nm_ratio * m))
+   return false;
+
+   if (nm->min_nm_ratio && (n < nm->min_nm_ratio * m))
+   return false;
+
+   return true;
+}
+
 static unsigned long ccu_nm_find_best(struct ccu_common *common, unsigned long 
parent,
  unsigned long rate, struct _ccu_nm *nm)
 {
@@ -36,8 +49,12 @@ static unsigned long ccu_nm_find_best(struct ccu_common 
*common, unsigned long p
 
for (_n = nm->min_n; _n <= nm->max_n; _n++) {
for (_m = nm->min_m; _m <= nm->max_m; _m++) {
-   unsigned long tmp_rate = ccu_nm_calc_rate(parent,
- _n, _m);
+   unsigned long tmp_rate;
+
+   if (!ccu_nm_is_valid_rate(common, _n, _m))
+   continue;
+
+   tmp_rate = ccu_nm_calc_rate(parent, _n, _m);
 
if (ccu_is_better_rate(common, rate, tmp_rate, 
best_rate)) {
best_rate = tmp_rate;
diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h
index 93c11693574f..0075df6d9697 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.h
+++ b/drivers/clk/sunxi-ng/ccu_nm.h
@@ -31,6 +31,8 @@ struct ccu_nm {
unsigned intfixed_post_div;
unsigned intmin_rate;
unsigned intmax_rate;
+   unsigned long   min_nm_ratio; /* minimum value for m/n */
+   unsigned long   max_nm_ratio; /* maximum value for m/n */
 
struct ccu_common   common;
 };
@@ -108,7 +110,8 @@ struct ccu_nm {
},  \
}
 
-#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT(_struct, _name,  \
+#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT_NM_RATIO(
\
+_struct, _name,\
 _parent, _reg, \
 _min_rate, _max_rate,  \
 _nshift, _nwidth,  \
@@ -117,7 +120,9 @@ struct ccu_nm {
 _frac_rate_0,  \
 _frac_rate_1,  \
 _gate, _lock, _flags,  \
-_features) \
+_features, \
+_min_nm_ratio, \
+_max_nm_ratio) \
struct ccu_nm _struct = {   \
.enable = _gate,\
.lock   = _lock,\
@@ -128,6 +133,8 @@ struct ccu_nm {
  _frac_rate_1),\
.min_rate   = _min_rate,\
.max_rate   = _max_rate,\
+   .min_nm_ratio   = _min_nm_ratio,\
+   .max_nm_ratio   = _max_nm_ratio,\
.common = { \
.reg= _reg, \
.features   = _features,\
@@ -138,6 +145,29 @@ struct ccu_nm {
},  \
}
 
+#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT(_struct, _name,  \
+_parent, _reg, \
+_min_rate, _max_rate,  \
+_nshift, _nwidth,  

[PATCH 2/5] clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent rate

2023-12-18 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N >= 3
 - (PLL_VIDEO0)/M >= 24MHz

Use these constraints.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 8951ffc14ff5..c034ac027d1c 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -176,6 +176,8 @@ static struct ccu_nkm pll_mipi_clk = {
.n  = _SUNXI_CCU_MULT(8, 4),
.k  = _SUNXI_CCU_MULT_MIN(4, 2, 2),
.m  = _SUNXI_CCU_DIV(0, 4),
+   .max_mn_ratio   = 3,
+   .parent_wo_nk   = 2400,
.common = {
.reg= 0x040,
.hw.init= CLK_HW_INIT("pll-mipi", "pll-video0",

-- 
2.43.0



[PATCH 1/5] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate

2023-12-18 Thread Frank Oltmanns
The Allwinner A64 manual lists the following constraints for the
PLL-MIPI clock:
 - M/N >= 3
 - (PLL_VIDEO0)/M >= 24MHz

The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for
these constraints.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu_nkm.c | 23 +++
 drivers/clk/sunxi-ng/ccu_nkm.h |  8 
 2 files changed, 31 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index eed64547ad42..2af5c1ebd527 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -16,6 +16,20 @@ struct _ccu_nkm {
unsigned long   m, min_m, max_m;
 };
 
+static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long 
parent,
+ unsigned long n, unsigned long m)
+{
+   struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common);
+
+   if (nkm->max_mn_ratio && (m > nkm->max_mn_ratio * n))
+   return false;
+
+   if (nkm->parent_wo_nk && (parent < nkm->parent_wo_nk * m))
+   return false;
+
+   return true;
+}
+
 static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common 
*common,
   struct clk_hw *parent_hw,
   unsigned long *parent, 
unsigned long rate,
@@ -32,6 +46,9 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(struct 
ccu_common *common
 
tmp_parent = clk_hw_round_rate(parent_hw, rate 
* _m / (_n * _k));
 
+   if (!ccu_nkm_is_valid_rate(common, tmp_parent, 
_n, _m))
+   continue;
+
tmp_rate = tmp_parent * _n * _k / _m;
 
if (ccu_is_better_rate(common, rate, tmp_rate, 
best_rate) ||
@@ -65,6 +82,12 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, 
unsigned long rate,
for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
+   if ((common->reg == 0x040) && (_m > 3 * _n))
+   break;
+
+   if ((common->reg == 0x040) && (parent < 
2400 * _m))
+   continue;
+
unsigned long tmp_rate;
 
tmp_rate = parent * _n * _k / _m;
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
index 6601defb3f38..d3d3eaf55faf 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.h
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -16,6 +16,12 @@
  * struct ccu_nkm - Definition of an N-K-M clock
  *
  * Clocks based on the formula parent * N * K / M
+ *
+ * @max_mn_ratio:  Maximum value for M / N.
+ * @parent_wo_nk:  The minimum rate the parent must provide after applying 
the divisor,
+ * but without applying the multipliers, i.e. the 
contstraint
+ *(parent rate)/M >= parent_wo_nk
+ * must be fulfilled.
  */
 struct ccu_nkm {
u32 enable;
@@ -27,6 +33,8 @@ struct ccu_nkm {
struct ccu_mux_internal mux;
 
unsigned intfixed_post_div;
+   unsigned long   max_mn_ratio;
+   unsigned long   parent_wo_nk;
 
struct ccu_common   common;
 };

-- 
2.43.0



Re: [PATCH 1/5] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate

2023-12-18 Thread Frank Oltmanns


On 2023-12-18 at 14:35:19 +0100, Frank Oltmanns  wrote:
> The Allwinner A64 manual lists the following constraints for the
> PLL-MIPI clock:
>  - M/N >= 3
>  - (PLL_VIDEO0)/M >= 24MHz
>
> The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for
> these constraints.
>
> Signed-off-by: Frank Oltmanns 
> ---
>  drivers/clk/sunxi-ng/ccu_nkm.c | 23 +++
>  drivers/clk/sunxi-ng/ccu_nkm.h |  8 
>  2 files changed, 31 insertions(+)
>
> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
> index eed64547ad42..2af5c1ebd527 100644
> --- a/drivers/clk/sunxi-ng/ccu_nkm.c
> +++ b/drivers/clk/sunxi-ng/ccu_nkm.c
> @@ -16,6 +16,20 @@ struct _ccu_nkm {
>   unsigned long   m, min_m, max_m;
>  };
>
> +static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long 
> parent,
> +   unsigned long n, unsigned long m)
> +{
> + struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common);
> +
> + if (nkm->max_mn_ratio && (m > nkm->max_mn_ratio * n))
> + return false;
> +
> + if (nkm->parent_wo_nk && (parent < nkm->parent_wo_nk * m))
> + return false;
> +
> + return true;
> +}
> +
>  static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common 
> *common,
>  struct clk_hw *parent_hw,
>  unsigned long *parent, 
> unsigned long rate,
> @@ -32,6 +46,9 @@ static unsigned long 
> ccu_nkm_find_best_with_parent_adj(struct ccu_common *common
>
>   tmp_parent = clk_hw_round_rate(parent_hw, rate 
> * _m / (_n * _k));
>
> + if (!ccu_nkm_is_valid_rate(common, tmp_parent, 
> _n, _m))
> + continue;
> +
>   tmp_rate = tmp_parent * _n * _k / _m;
>
>   if (ccu_is_better_rate(common, rate, tmp_rate, 
> best_rate) ||
> @@ -65,6 +82,12 @@ static unsigned long ccu_nkm_find_best(unsigned long 
> parent, unsigned long rate,
>   for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
>   for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
>   for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
> + if ((common->reg == 0x040) && (_m > 3 * _n))
> + break;
> +
> + if ((common->reg == 0x040) && (parent < 
> 2400 * _m))
> + continue;
> +

This, of course, is rubbish and should be this instead:
+   if (!ccu_nkm_is_valid_rate(common, parent, _n, 
_m))
+   continue;
+

I'll submit a V2 after receiving some feedback.

>   unsigned long tmp_rate;
>
>   tmp_rate = parent * _n * _k / _m;
> diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
> index 6601defb3f38..d3d3eaf55faf 100644
> --- a/drivers/clk/sunxi-ng/ccu_nkm.h
> +++ b/drivers/clk/sunxi-ng/ccu_nkm.h
> @@ -16,6 +16,12 @@
>   * struct ccu_nkm - Definition of an N-K-M clock
>   *
>   * Clocks based on the formula parent * N * K / M
> + *
> + * @max_mn_ratio:Maximum value for M / N.
> + * @parent_wo_nk:The minimum rate the parent must provide after applying 
> the divisor,
> + *   but without applying the multipliers, i.e. the 
> contstraint
> + *  (parent rate)/M >= parent_wo_nk
> + *   must be fulfilled.
>   */
>  struct ccu_nkm {
>   u32 enable;
> @@ -27,6 +33,8 @@ struct ccu_nkm {
>   struct ccu_mux_internal mux;
>
>   unsigned intfixed_post_div;
> + unsigned long   max_mn_ratio;
> + unsigned long   parent_wo_nk;
>
>   struct ccu_common   common;
>  };


Re: [PATCH 0/3] Make Allwinner A64's pll-mipi keep its rate when parent rate changes

2023-08-28 Thread Frank Oltmanns


On 2023-08-28 at 10:04:51 +0200, Maxime Ripard  wrote:
> On Fri, Aug 25, 2023 at 05:07:58PM +0200, Frank Oltmanns wrote:
>> Thank you for your feedback, Maxime!
>>
>> On 2023-08-25 at 10:13:53 +0200, Maxime Ripard  wrote:
>> > [[PGP Signed Part:Undecided]]
>> > Hi,
>> >
>> > On Fri, Aug 25, 2023 at 07:36:36AM +0200, Frank Oltmanns wrote:
>> >> I would like to make the Allwinner A64's pll-mipi to keep its rate when
>> >> its parent's (pll-video0) rate changes. Keeping pll-mipi's rate is
>> >> required, to let the A64 drive both an LCD and HDMI display at the same
>> >> time, because both have pll-video0 as an ancestor.
>> >>
>> >> PATCH 1 adds this functionality as a feature into the clk framework (new
>> >> flag: CLK_KEEP_RATE).
>> >>
>> >> Cores that use this flag, store a rate as req_rate when it or one of its
>> >> descendants requests a new rate.
>> >>
>> >> That rate is then restored in the clk_change_rate recursion, which walks
>> >> through the tree. It will reach the flagged core (e.g. pll-mipi) after
>> >> the parent's rate (e.g. pll-video0) has already been set to the new
>> >> rate. It will then call determine_rate (which requests the parent's
>> >> current, i.e. new, rate) to determine a rate that is close to the
>> >> flagged core's previous rate. Afterward it will re-calculate the rates
>> >> for the flagged core's subtree.
>> >
>> > I don't think it's the right way forward. It makes the core logic more
>> > complicated, for something that is redundant with the notifiers
>> > mechanism that has been the go-to for that kind of things so far.
>>
>> Yeah, that was my initial idea as well. But I couldn't get it to work.
>> See details below.
>>
>> Do you have an example of a clock that restores its previous rate after
>> the parent rate has changed? I've looked left and right, but to me it
>> seems that notifiers are mainly used for setting clocks into some kind
>> of "safe mode" prior to the rate change. Examples:
>>
>> sunxi-ng:
>> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_mux.c#L273
>> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_common.c#L60
>>
>> but also others:
>> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/at91/clk-master.c#L248
>> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/meson/meson8b.c#L3755
>> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/qcom/clk-cpu-8996.c#L546
>
> There's examples for phases and parents, but not for rates afaics. We
> shouldn't behave any differently though.
>
>> > It's not really obvious to me why the notifiers don't work there.
>> >
>> >> This work is inspired by an out-of-tree patchset [1] [2] [3].
>> >> Unfortunately, the patchset uses clk_set_rate() in a notifier callback,
>> >> which the following comment on clk_notifier_register() forbids: "The
>> >> callbacks associated with the notifier must not re-enter into the clk
>> >> framework by calling any top-level clk APIs." [4] Furthermore, that
>> >> out-of-tree patchset no longer works with the current linux-next,
>> >> because setting pll-mipi is now also resetting pll-video0 [5].
>> >
>> > Is it because of the "The callbacks associated with the notifier must
>> > not re-enter into the clk framework by calling any top-level clk APIs."
>> > comment?
>>
>> I don't think that's the reason.
>
> I'm not sure I follow you there. How can we find a solution to a problem
> you don't know about or can't know for sure?

I was hoping that the discussion here would give me some clues (and it
does). You have already explained, that the issue is the locks. I'm
still confused why Icenowy's patches work. They use clk_set_rate() in a
notifier callback and despite that they work (up until kernel 6.5). The
only thing that has changed here (that I'm aware of), is that pll-mipi
now sets the parent rate in clk-next.

>> I'm fairly certain that the problem is, that pll-mipi tries to set the
>> parent rate. Maybe it should check if the parent is locked, before
>> determining a rate that requires the parent rate to change. 樂
>
> Why would the clock framework documentation mention an issue that only
> arises with a single clock on a single SoC?

No, sorry, that's not what I said or meant. I was wondering if
ccu_nkm_determine_rate should check if the parent rate has no exclusive
lock, before assuming 

Re: [PATCH 0/3] Make Allwinner A64's pll-mipi keep its rate when parent rate changes

2023-08-28 Thread Frank Oltmanns


On 2023-08-28 at 10:25:01 +0200, Maxime Ripard  wrote:
> On Sat, Aug 26, 2023 at 11:12:16AM +0200, Frank Oltmanns wrote:
>>
>> On 2023-08-25 at 17:07:58 +0200, Frank Oltmanns  wrote:
>> > Thank you for your feedback, Maxime!
>> >
>> > On 2023-08-25 at 10:13:53 +0200, Maxime Ripard  wrote:
>> >> [[PGP Signed Part:Undecided]]
>> >> Hi,
>> >>
>> >> On Fri, Aug 25, 2023 at 07:36:36AM +0200, Frank Oltmanns wrote:
>> >>> I would like to make the Allwinner A64's pll-mipi to keep its rate when
>> >>> its parent's (pll-video0) rate changes. Keeping pll-mipi's rate is
>> >>> required, to let the A64 drive both an LCD and HDMI display at the same
>> >>> time, because both have pll-video0 as an ancestor.
>> >>>
>> >>> PATCH 1 adds this functionality as a feature into the clk framework (new
>> >>> flag: CLK_KEEP_RATE).
>> >>>
>> >>> Cores that use this flag, store a rate as req_rate when it or one of its
>> >>> descendants requests a new rate.
>> >>>
>> >>> That rate is then restored in the clk_change_rate recursion, which walks
>> >>> through the tree. It will reach the flagged core (e.g. pll-mipi) after
>> >>> the parent's rate (e.g. pll-video0) has already been set to the new
>> >>> rate. It will then call determine_rate (which requests the parent's
>> >>> current, i.e. new, rate) to determine a rate that is close to the
>> >>> flagged core's previous rate. Afterward it will re-calculate the rates
>> >>> for the flagged core's subtree.
>> >>
>> >> I don't think it's the right way forward. It makes the core logic more
>> >> complicated, for something that is redundant with the notifiers
>> >> mechanism that has been the go-to for that kind of things so far.
>> >
>> > Yeah, that was my initial idea as well. But I couldn't get it to work.
>> > See details below.
>> >
>> > Do you have an example of a clock that restores its previous rate after
>> > the parent rate has changed? I've looked left and right, but to me it
>> > seems that notifiers are mainly used for setting clocks into some kind
>> > of "safe mode" prior to the rate change. Examples:
>> >
>> > sunxi-ng:
>> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_mux.c#L273
>> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_common.c#L60
>> >
>> > but also others:
>> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/at91/clk-master.c#L248
>> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/meson/meson8b.c#L3755
>> > https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/qcom/clk-cpu-8996.c#L546
>> >
>> >> It's not really obvious to me why the notifiers don't work there.
>> >>
>> >>> This work is inspired by an out-of-tree patchset [1] [2] [3].
>> >>> Unfortunately, the patchset uses clk_set_rate() in a notifier callback,
>> >>> which the following comment on clk_notifier_register() forbids: "The
>> >>> callbacks associated with the notifier must not re-enter into the clk
>> >>> framework by calling any top-level clk APIs." [4] Furthermore, that
>> >>> out-of-tree patchset no longer works with the current linux-next,
>> >>> because setting pll-mipi is now also resetting pll-video0 [5].
>> >>
>> >> Is it because of the "The callbacks associated with the notifier must
>> >> not re-enter into the clk framework by calling any top-level clk APIs."
>> >> comment?
>> >
>> > I don't think that's the reason. I'm fairly certain that the problem is,
>> > that pll-mipi tries to set the parent rate. Maybe it should check if the
>> > parent is locked, before determining a rate that requires the parent
>> > rate to change. 樂 Currently, it only calls clk_hw_can_set_rate_parent()
>> > which only checks the flag, but does not check if it is really possible
>> > to change the parent's rate.
>> >
>> > Regardless, please don't prematurely dismiss my proposal. It has the
>> > advantage that it is not specific for sunxi-ng, but could be used for
>> > other drivers as well. Maybe there other instances of exclusive locks
>> > today where the CLK_KEEP_RATE flag might work equally well. 路
>> >
>> >> If so, I think the 

Re: [PATCH 0/3] Make Allwinner A64's pll-mipi keep its rate when parent rate changes

2023-08-26 Thread Frank Oltmanns


On 2023-08-25 at 17:07:58 +0200, Frank Oltmanns  wrote:
> Thank you for your feedback, Maxime!
>
> On 2023-08-25 at 10:13:53 +0200, Maxime Ripard  wrote:
>> [[PGP Signed Part:Undecided]]
>> Hi,
>>
>> On Fri, Aug 25, 2023 at 07:36:36AM +0200, Frank Oltmanns wrote:
>>> I would like to make the Allwinner A64's pll-mipi to keep its rate when
>>> its parent's (pll-video0) rate changes. Keeping pll-mipi's rate is
>>> required, to let the A64 drive both an LCD and HDMI display at the same
>>> time, because both have pll-video0 as an ancestor.
>>>
>>> PATCH 1 adds this functionality as a feature into the clk framework (new
>>> flag: CLK_KEEP_RATE).
>>>
>>> Cores that use this flag, store a rate as req_rate when it or one of its
>>> descendants requests a new rate.
>>>
>>> That rate is then restored in the clk_change_rate recursion, which walks
>>> through the tree. It will reach the flagged core (e.g. pll-mipi) after
>>> the parent's rate (e.g. pll-video0) has already been set to the new
>>> rate. It will then call determine_rate (which requests the parent's
>>> current, i.e. new, rate) to determine a rate that is close to the
>>> flagged core's previous rate. Afterward it will re-calculate the rates
>>> for the flagged core's subtree.
>>
>> I don't think it's the right way forward. It makes the core logic more
>> complicated, for something that is redundant with the notifiers
>> mechanism that has been the go-to for that kind of things so far.
>
> Yeah, that was my initial idea as well. But I couldn't get it to work.
> See details below.
>
> Do you have an example of a clock that restores its previous rate after
> the parent rate has changed? I've looked left and right, but to me it
> seems that notifiers are mainly used for setting clocks into some kind
> of "safe mode" prior to the rate change. Examples:
>
> sunxi-ng:
> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_mux.c#L273
> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_common.c#L60
>
> but also others:
> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/at91/clk-master.c#L248
> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/meson/meson8b.c#L3755
> https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/qcom/clk-cpu-8996.c#L546
>
>> It's not really obvious to me why the notifiers don't work there.
>>
>>> This work is inspired by an out-of-tree patchset [1] [2] [3].
>>> Unfortunately, the patchset uses clk_set_rate() in a notifier callback,
>>> which the following comment on clk_notifier_register() forbids: "The
>>> callbacks associated with the notifier must not re-enter into the clk
>>> framework by calling any top-level clk APIs." [4] Furthermore, that
>>> out-of-tree patchset no longer works with the current linux-next,
>>> because setting pll-mipi is now also resetting pll-video0 [5].
>>
>> Is it because of the "The callbacks associated with the notifier must
>> not re-enter into the clk framework by calling any top-level clk APIs."
>> comment?
>
> I don't think that's the reason. I'm fairly certain that the problem is,
> that pll-mipi tries to set the parent rate. Maybe it should check if the
> parent is locked, before determining a rate that requires the parent
> rate to change. 樂 Currently, it only calls clk_hw_can_set_rate_parent()
> which only checks the flag, but does not check if it is really possible
> to change the parent's rate.
>
> Regardless, please don't prematurely dismiss my proposal. It has the
> advantage that it is not specific for sunxi-ng, but could be used for
> other drivers as well. Maybe there other instances of exclusive locks
> today where the CLK_KEEP_RATE flag might work equally well. 路
>
>> If so, I think the thing we should emphasize is that it's about *any
>> top-level clk API*, as in clk_set_rate() or clk_set_parent().
>>
>> The issue is that any consumer-facing API is taking the clk_prepare lock
>> and thus we would have reentrancy. But we're a provider there, and none
>> of the clk_hw_* functions are taking that lock. Neither do our own function.
>>
>> So we could call in that notifier our set_rate callback directly, or we
>> could create a clk_hw_set_rate() function.
>>
>> The first one will create cache issue between the actual rate that the
>> common clock framework is running and the one we actually enforced, but
>> we could create a function to flush the CCF cache.
>>
>> The second one is probably simpler.

Re: [PATCH 0/3] Make Allwinner A64's pll-mipi keep its rate when parent rate changes

2023-08-25 Thread Frank Oltmanns
Thank you for your feedback, Maxime!

On 2023-08-25 at 10:13:53 +0200, Maxime Ripard  wrote:
> [[PGP Signed Part:Undecided]]
> Hi,
>
> On Fri, Aug 25, 2023 at 07:36:36AM +0200, Frank Oltmanns wrote:
>> I would like to make the Allwinner A64's pll-mipi to keep its rate when
>> its parent's (pll-video0) rate changes. Keeping pll-mipi's rate is
>> required, to let the A64 drive both an LCD and HDMI display at the same
>> time, because both have pll-video0 as an ancestor.
>>
>> PATCH 1 adds this functionality as a feature into the clk framework (new
>> flag: CLK_KEEP_RATE).
>>
>> Cores that use this flag, store a rate as req_rate when it or one of its
>> descendants requests a new rate.
>>
>> That rate is then restored in the clk_change_rate recursion, which walks
>> through the tree. It will reach the flagged core (e.g. pll-mipi) after
>> the parent's rate (e.g. pll-video0) has already been set to the new
>> rate. It will then call determine_rate (which requests the parent's
>> current, i.e. new, rate) to determine a rate that is close to the
>> flagged core's previous rate. Afterward it will re-calculate the rates
>> for the flagged core's subtree.
>
> I don't think it's the right way forward. It makes the core logic more
> complicated, for something that is redundant with the notifiers
> mechanism that has been the go-to for that kind of things so far.

Yeah, that was my initial idea as well. But I couldn't get it to work.
See details below.

Do you have an example of a clock that restores its previous rate after
the parent rate has changed? I've looked left and right, but to me it
seems that notifiers are mainly used for setting clocks into some kind
of "safe mode" prior to the rate change. Examples:

sunxi-ng:
https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_mux.c#L273
https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/sunxi-ng/ccu_common.c#L60

but also others:
https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/at91/clk-master.c#L248
https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/meson/meson8b.c#L3755
https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/qcom/clk-cpu-8996.c#L546

> It's not really obvious to me why the notifiers don't work there.
>
>> This work is inspired by an out-of-tree patchset [1] [2] [3].
>> Unfortunately, the patchset uses clk_set_rate() in a notifier callback,
>> which the following comment on clk_notifier_register() forbids: "The
>> callbacks associated with the notifier must not re-enter into the clk
>> framework by calling any top-level clk APIs." [4] Furthermore, that
>> out-of-tree patchset no longer works with the current linux-next,
>> because setting pll-mipi is now also resetting pll-video0 [5].
>
> Is it because of the "The callbacks associated with the notifier must
> not re-enter into the clk framework by calling any top-level clk APIs."
> comment?

I don't think that's the reason. I'm fairly certain that the problem is,
that pll-mipi tries to set the parent rate. Maybe it should check if the
parent is locked, before determining a rate that requires the parent
rate to change. 樂 Currently, it only calls clk_hw_can_set_rate_parent()
which only checks the flag, but does not check if it is really possible
to change the parent's rate.

Regardless, please don't prematurely dismiss my proposal. It has the
advantage that it is not specific for sunxi-ng, but could be used for
other drivers as well. Maybe there other instances of exclusive locks
today where the CLK_KEEP_RATE flag might work equally well. 路

> If so, I think the thing we should emphasize is that it's about *any
> top-level clk API*, as in clk_set_rate() or clk_set_parent().
>
> The issue is that any consumer-facing API is taking the clk_prepare lock
> and thus we would have reentrancy. But we're a provider there, and none
> of the clk_hw_* functions are taking that lock. Neither do our own function.
>
> So we could call in that notifier our set_rate callback directly, or we
> could create a clk_hw_set_rate() function.
>
> The first one will create cache issue between the actual rate that the
> common clock framework is running and the one we actually enforced, but
> we could create a function to flush the CCF cache.
>
> The second one is probably simpler.

I'm probably missing something, because I don't think this would work.
For reference, this is our tree:

pll-video0
   hdmi-phy-clk
   hdmi
   tcon1
   pll-mipi
  tcon0
 tcon-data-clock

When pll-video0's rate is changed (e.g. because a HDMI monitor is
plugged in), the rates of the complete subtree for pll-video0 are
recalculated, including tcon0 and tcon-data-clock. The rate of tcon0 is
ba

[PATCH 1/3] clk: keep clock rate when parent rate changes

2023-08-24 Thread Frank Oltmanns
Allow clocks to keep their rate when parent (or grandparent) rate
changes.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/clk.c| 48 +++-
 include/linux/clk-provider.h |  2 ++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c249f9791ae8..a382876c18da 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2245,6 +2245,9 @@ static struct clk_core *clk_calc_new_rates(struct 
clk_core *core,
best_parent_rate != parent->rate)
top = clk_calc_new_rates(parent, best_parent_rate);
 
+   if ((core->flags & CLK_KEEP_RATE))
+   core->req_rate = new_rate;
+
 out:
clk_calc_subtree(core, new_rate, parent, p_index);
 
@@ -2343,9 +2346,51 @@ static void clk_change_rate(struct clk_core *core)
clk_core_prepare_enable(parent);
 
trace_clk_set_rate(core, core->new_rate);
+   if (!skip_set_rate && core->ops->set_rate) {
+   if (core->flags & CLK_KEEP_RATE && clk_core_can_round(core)) {
+   struct clk_rate_request req;
+   unsigned long flags;
+   int ret;
+
+   clk_core_init_rate_req(core, , core->req_rate);
 
-   if (!skip_set_rate && core->ops->set_rate)
+   /*
+* Re-determine the new rate for the clock based on the 
requested rate.
+*
+* In this stage, the clock must not set a new parent 
rate or try a
+* different parent, so temporarily prevent that from 
happening.
+*/
+   flags = core->flags;
+   core->flags &= ~(CLK_SET_RATE_PARENT);
+   core->flags |= CLK_SET_RATE_NO_REPARENT;
+   ret = clk_core_determine_round_nolock(core, );
+   core->flags = flags;
+
+   /*
+* If necessary, store the new rate and propagate to 
the subtree.
+*
+* The previously calculated rates (new_rate) of this 
core's subtree are no
+* longer correct, because this clock will be set to a 
rate that differs
+* from the rate that was used to calculate the subtree.
+*
+* FIXME: This means that the rate also differs from 
the new_rate that was
+*announced in the PRE_RATE_CHANGE 
notification. Be careful when
+*applying this flag, that the subtree does not 
depend on the
+*correct new rate being propagated.
+*/
+   if (ret >= 0 && req.rate != core->new_rate) {
+   core->new_rate = req.rate;
+   pr_debug("%s: clk %s: keeping rate %lu as 
%lu\n",
+  __func__, core->name, core->req_rate, 
core->new_rate);
+
+   hlist_for_each_entry(child, >children, 
child_node) {
+   child->new_rate = clk_recalc(child, 
core->new_rate);
+   clk_calc_subtree(child, 
child->new_rate, NULL, 0);
+   }
+   }
+   }
core->ops->set_rate(core->hw, core->new_rate, best_parent_rate);
+   }
 
trace_clk_set_rate_complete(core, core->new_rate);
 
@@ -3388,6 +3433,7 @@ static const struct {
ENTRY(CLK_IS_CRITICAL),
ENTRY(CLK_OPS_PARENT_ENABLE),
ENTRY(CLK_DUTY_CYCLE_PARENT),
+   ENTRY(CLK_KEEP_RATE),
 #undef ENTRY
 };
 
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index ec32ec58c59f..fba78a99ac56 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -32,6 +32,8 @@
 #define CLK_OPS_PARENT_ENABLE  BIT(12)
 /* duty cycle call may be forwarded to the parent clock */
 #define CLK_DUTY_CYCLE_PARENT  BIT(13)
+/* try to keep rate, if parent rate changes */
+#define CLK_KEEP_RATE  BIT(14)
 
 struct clk;
 struct clk_hw;

-- 
2.41.0



[PATCH 3/3] drm/sun4i: tcon: parent keeps TCON0 clock stable on A64

2023-08-24 Thread Frank Oltmanns
From: Icenowy Zheng 

As the clk framework keeps A64's TCON0 clock stable when HDMI changes
its parent's clock, do not protect TCON0 clock on A64 in the TCON driver
to allow PLL-Video0 to get changed by HDMI.

Signed-off-by: Icenowy Zheng 
Signed-off-by: Frank Oltmanns 
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 15 +--
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  1 +
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 6a52fb12cbfb..4439e62b7a34 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -108,9 +108,11 @@ static void sun4i_tcon_channel_set_status(struct 
sun4i_tcon *tcon, int channel,
 
if (enabled) {
clk_prepare_enable(clk);
-   clk_rate_exclusive_get(clk);
+   if (!tcon->quirks->rate_kept_by_parent)
+   clk_rate_exclusive_get(clk);
} else {
-   clk_rate_exclusive_put(clk);
+   if (!tcon->quirks->rate_kept_by_parent)
+   clk_rate_exclusive_put(clk);
clk_disable_unprepare(clk);
}
 }
@@ -1505,6 +1507,14 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = 
{
.supports_lvds  = true,
 };
 
+static const struct sun4i_tcon_quirks sun50i_a64_lcd_quirks = {
+   .supports_lvds  = true,
+   .has_channel_0  = true,
+   .rate_kept_by_parent= true,
+   .dclk_min_div   = 1,
+   .setup_lvds_phy = sun6i_tcon_setup_lvds_phy,
+};
+
 static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
.supports_lvds  = true,
.has_channel_0  = true,
@@ -1563,6 +1573,7 @@ const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun9i-a80-tcon-tv", .data = 
_a80_tcon_tv_quirks },
{ .compatible = "allwinner,sun20i-d1-tcon-lcd", .data = 
_d1_lcd_quirks },
{ .compatible = "allwinner,sun20i-d1-tcon-tv", .data = 
_r40_tv_quirks },
+   { .compatible = "allwinner,sun50i-a64-tcon-lcd", .data = 
_a64_lcd_quirks },
{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h 
b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index fa23aa23fe4a..c4ce7c29192e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -243,6 +243,7 @@ struct sun4i_tcon_quirks {
boolneeds_edp_reset; /* a80 edp reset needed for tcon0 access */
boolsupports_lvds;   /* Does the TCON support an LVDS output? */
boolpolarity_in_ch0; /* some tcon1 channels have polarity bits in 
tcon0 pol register */
+   boolrate_kept_by_parent; /* Does parent keep TCON0 clock stable? */
u8  dclk_min_div;   /* minimum divider for TCON0 DCLK */
 
/* callback to handle tcon muxing options */

-- 
2.41.0



[PATCH 2/3] clk: sunxi-ng: a64: keep rate of pll-mipi stable across parent rate changes

2023-08-24 Thread Frank Oltmanns
Keep the clock rate of Allwinner A64's pll-mipi even when the parent
(pll-video0) changes its rate. This is required, to drive both an LCD
and HDMI display, because both have pll-video0 as an ancestor.

Signed-off-by: Frank Oltmanns 
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 8951ffc14ff5..d22094ce1d66 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -180,7 +180,8 @@ static struct ccu_nkm pll_mipi_clk = {
.reg= 0x040,
.hw.init= CLK_HW_INIT("pll-mipi", "pll-video0",
  _nkm_ops,
- CLK_SET_RATE_UNGATE | 
CLK_SET_RATE_PARENT),
+ CLK_SET_RATE_UNGATE | 
CLK_SET_RATE_PARENT |
+ CLK_KEEP_RATE),
.features   = CCU_FEATURE_CLOSEST_RATE,
},
 };

-- 
2.41.0



[PATCH 0/3] Make Allwinner A64's pll-mipi keep its rate when parent rate changes

2023-08-24 Thread Frank Oltmanns
I would like to make the Allwinner A64's pll-mipi to keep its rate when
its parent's (pll-video0) rate changes. Keeping pll-mipi's rate is
required, to let the A64 drive both an LCD and HDMI display at the same
time, because both have pll-video0 as an ancestor.

PATCH 1 adds this functionality as a feature into the clk framework (new
flag: CLK_KEEP_RATE).

Cores that use this flag, store a rate as req_rate when it or one of its
descendants requests a new rate.

That rate is then restored in the clk_change_rate recursion, which walks
through the tree. It will reach the flagged core (e.g. pll-mipi) after
the parent's rate (e.g. pll-video0) has already been set to the new
rate. It will then call determine_rate (which requests the parent's
current, i.e. new, rate) to determine a rate that is close to the
flagged core's previous rate. Afterward it will re-calculate the rates
for the flagged core's subtree.

PATCH 2 & 3 demonstrate how the new flag can be used for A64's pll-mipi.
By setting this flag, it is no longer required to get an exclusive lock
when setting tcon0's rate, because the rate will be restored when its
parent's (pll-mipi) rate is restored.

This work is inspired by an out-of-tree patchset [1] [2] [3].
Unfortunately, the patchset uses clk_set_rate() in a notifier callback,
which the following comment on clk_notifier_register() forbids: "The
callbacks associated with the notifier must not re-enter into the clk
framework by calling any top-level clk APIs." [4] Furthermore, that
out-of-tree patchset no longer works with the current linux-next,
because setting pll-mipi is now also resetting pll-video0 [5].

Thank you for considering this contribution,
  Frank

[1] 
https://github.com/megous/linux/commit/4124e115de82797f604808aaa5caad4512a9a1ed
[2] 
https://github.com/megous/linux/commit/edc93fd70ee759fd989664fcb85996cb48a006e6
[3] 
https://github.com/megous/linux/commit/40f5fc5b08b21142931662147d039ec217c9ba2f
[4] https://elixir.bootlin.com/linux/v6.4.11/source/drivers/clk/clk.c#L4578
[5] 
https://lore.kernel.org/linux-kernel/20230807-pll-mipi_set_rate_parent-v6-0-f173239a4...@oltmanns.dev/

Signed-off-by: Frank Oltmanns 
---
Frank Oltmanns (2):
  clk: keep clock rate when parent rate changes
  clk: sunxi-ng: a64: keep rate of pll-mipi stable across parent rate 
changes

Icenowy Zheng (1):
  drm/sun4i: tcon: parent keeps TCON0 clock stable on A64

 drivers/clk/clk.c | 48 ++-
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c |  3 ++-
 drivers/gpu/drm/sun4i/sun4i_tcon.c| 15 +--
 drivers/gpu/drm/sun4i/sun4i_tcon.h|  1 +
 include/linux/clk-provider.h  |  2 ++
 5 files changed, 65 insertions(+), 4 deletions(-)
---
base-commit: c539c5c0a7ccafe7169c02564cceeb50317b540b
change-id: 20230824-pll-mipi_keep_rate-0a3a0d3574cf

Best regards,
-- 
Frank Oltmanns 



Re: [PATCH 2/3] clk: sunxi-ng: a64: keep tcon0 clock rate when pll-video0's rate changes

2023-08-12 Thread Frank Oltmanns


On 2023-08-07 at 18:22:26 +0800, Icenowy Zheng  wrote:
> 在 2023-08-07星期一的 11:48 +0200,Frank Oltmanns写道:
>>
>> On 2023-08-07 at 17:43:52 +0800, Icenowy Zheng 
>> wrote:
>> > 在 2023-08-07星期一的 11:36 +0200,Frank Oltmanns写道:
>> > > From: Icenowy Zheng 
>> > >
>> > > Notify TCON0 clock (and in consequence PLL-MIPI by
>> > > CLK_SET_RATE_PARENT)
>> > > to reset when PLL-Video0 changes (because of HDMI PHY clk which
>> > > is a
>> > > child of PLL-Video0 and has CLK_SET_RATE_PARENT set). In this way
>> > > we
>> > > can
>> > > get clock tree to satisfy both pipelines.
>> >
>> > Well for fixing one's patch that contains SoB, use the following
>> > format:
>> >
>> > Signed-off-by: A 
>> > [B: fixed something]
>> > Signed-off-by: B 
>>
>> Ah, okay. Will do. But I keep A in the "From: " line, correct?
>
> Yes.
>

One more thing: You seem to be using a new mail address. Do you want me
to replace the "From" and SoB's with the new address?

Thanks,
  Frank

>
>>
>> Thanks,
>>   Frank
>>
>> > > ---
>> > >  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 15 +++
>> > >  1 file changed, 15 insertions(+)
>> > >
>> > > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> > > b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> > > index ef567775fc95..93beedb0428e 100644
>> > > --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> > > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> > > @@ -943,6 +943,17 @@ static struct ccu_mux_nb sun50i_a64_cpu_nb =
>> > > {
>> > > .bypass_index   = 1, /* index of 24 MHz oscillator */
>> > >  };
>> > >  
>> > > +/*
>> > > + * Since PLL-Video0 is an ancestor of both tcon0 and HDMI PYH,
>> > > tcon0
>> > > clock will
>> > > + * conflict with HDMI PHY clock which is on another display
>> > > pipeline.
>> > > + *
>> > > + * Therefore, a notifier is required to restore the rate of
>> > > TCON0
>> > > when the rate
>> > > + * of PLL-Video0 changed.
>> > > + */
>> > > +static struct ccu_rate_reset_nb
>> > > sun50i_a64_pll_video0_reset_tcon0_nb
>> > > = {
>> > > +   .common = _video0_clk.common,
>> > > +};
>> > > +
>> > >  static int sun50i_a64_ccu_probe(struct platform_device *pdev)
>> > >  {
>> > > void __iomem *reg;
>> > > @@ -978,6 +989,10 @@ static int sun50i_a64_ccu_probe(struct
>> > > platform_device *pdev)
>> > > ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
>> > >   _a64_cpu_nb);
>> > >  
>> > > +   /* Reset the rate of TCON0 clock when PLL-VIDEO0 is
>> > > changed
>> > > */
>> > > +   sun50i_a64_pll_video0_reset_tcon0_nb.target_clk =
>> > > tcon0_clk.common.hw.clk;
>> > > +   ccu_rate_reset_notifier_register(_a64_pll_video0_r
>> > > eset
>> > > _tcon0_nb);
>> > > +
>> > > return 0;
>> > >  }
>> > >  
>> > >


Re: [PATCH 0/3] pll-video0 notifier for v6.5+

2023-08-12 Thread Frank Oltmanns


On 2023-08-10 at 21:18:12 +0800, Chen-Yu Tsai  wrote:
> On Mon, Aug 7, 2023 at 5:36 PM Frank Oltmanns  wrote:
>>
>> Hi Icenowy,
>>
>> it is my understanding that you are the original author of the following
>> patches are in Ondřej's 6.4 branch [1] [2] [3] but not in his 6.5
>> branch. I assume it is because of merge conflicts as the part about
>> setting the parent has already been fixed in the 6.5 release candidates.
>>
>> Therefore I've removed those parts and adopted the commit message of
>> PATCH 2. I've removed your SoB, because I think you'd need to sign of
>> the revised version. Especially patch 2 has become a bit simpler and I'm
>> wondering if it makes sense to try to upstream the three patches now.
>> What do you think?
>>
>> Thank you for your amazing work!
>>
>> Best regards,
>>   Frank
>
> Please send to all maintainers and relevant mailing lists (as given
> by get_maintainers.pl).
>

Thank you for pointing this out. This was actually intended as an RFC
specifically for Icenowy, but I forgot to mark it as such.

Furthermore, I decided to cc the two lists because I had trouble
receiving Icenowy's mails in the past and I wanted to make sure I could
at least browse the archives for responses.

I'll take more care next time.

Thanks,
  Frank

>
>
>> [1]: 
>> https://github.com/megous/linux/commit/2cd3d57adf83e2d091baed77e1aafc01d545d123
>> [2]: 
>> https://github.com/megous/linux/commit/c9c7bfe22f0fefdfc1dc2ce84b452964112399d7
>> [3]: 
>> https://github.com/megous/linux/commit/e19ccee10a8492535b6cda1ba972074d6e65
>>
>> Signed-off-by: Frank Oltmanns 
>> ---
>> Icenowy Zheng (3):
>>   clk: sunxi-ng: add support for rate resetting notifier
>>   clk: sunxi-ng: a64: keep tcon0 clock rate when pll-video0's rate 
>> changes
>>   drm/sun4i: tcon: hand over the duty to keep TCON0 clock to CCU on A64
>>
>>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 15 +++
>>  drivers/clk/sunxi-ng/ccu_common.c | 22 ++
>>  drivers/clk/sunxi-ng/ccu_common.h | 12 
>>  drivers/gpu/drm/sun4i/sun4i_tcon.c| 15 +--
>>  drivers/gpu/drm/sun4i/sun4i_tcon.h|  1 +
>>  5 files changed, 63 insertions(+), 2 deletions(-)
>> ---
>> base-commit: 1cf5c37ee3c2334a964c65e52b4e0c59b4332d7c
>> change-id: 20230807-a64_pll_video0_notifier-164cbc78b341
>>
>> Best regards,
>> --
>> Frank Oltmanns 
>>
>>


Re: [PATCH 1/3] clk: sunxi-ng: add support for rate resetting notifier

2023-08-07 Thread Frank Oltmanns


On 2023-08-07 at 17:42:22 +0800, Icenowy Zheng  wrote:
> 在 2023-08-07星期一的 11:36 +0200,Frank Oltmanns写道:
>> From: Icenowy Zheng 
>>
>> In some situaitons, we will want a clock rate be kept while its
>> parent
>> can change, for example, to make dual-head work on A64, TCON0 clock
>> needs to be kept for LCD display and its parent (or grandparent)
>> PLL-Video0 need to be changed for HDMI display. (There's a quirk on
>> A64
>> that HDMI PHY can only use PLL-Video0, not PLL-Video1).
>>
>> Add a notifier helper to create such kind of rate keeping notifier by
>> reset the rate after the parent changed.
>>
>> Signed-off-by: Icenowy Zheng 
>> ---
>>  drivers/clk/sunxi-ng/ccu_common.c | 22 ++
>>  drivers/clk/sunxi-ng/ccu_common.h | 12 
>>  2 files changed, 34 insertions(+)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-
>> ng/ccu_common.c
>> index 8d28a7a079d0..434fa46ad460 100644
>> --- a/drivers/clk/sunxi-ng/ccu_common.c
>> +++ b/drivers/clk/sunxi-ng/ccu_common.c
>> @@ -87,6 +87,28 @@ int ccu_pll_notifier_register(struct ccu_pll_nb
>> *pll_nb)
>>  }
>>  EXPORT_SYMBOL_NS_GPL(ccu_pll_notifier_register, SUNXI_CCU);
>>  
>> +static int ccu_rate_reset_notifier_cb(struct notifier_block *nb,
>> + unsigned long event, void
>> *data)
>> +{
>> +   struct ccu_rate_reset_nb *rate_reset =
>> to_ccu_rate_reset_nb(nb);
>> +
>> +   if (event == PRE_RATE_CHANGE) {
>> +   rate_reset->saved_rate = clk_get_rate(rate_reset-
>> >target_clk);
>
> In fact I think we should have a better way to save the intended clock
> rate ;-)
>

Are you referring to struct clk_core's clk_req member [1]? Maxime Ripard
also mentioned it to me [2]? Or do you have something else in mind?

Note that I have a patchset on the way [3], that will improve rate
selection for pll-video0 and its descendants. I'll double-check if that
improves the situation in a way so that the clk_get_rate() might be good
enough.

Thanks,
  Frank

[1]: https://elixir.bootlin.com/linux/latest/source/drivers/clk/clk.c#L68
[2]: 
https://lore.kernel.org/linux-clk/xcgmqvdoip53yao4sfoznnppauhmsmdablwoewh43zjv3bhidp@d7pxqohxydve/
[3]: 
https://lore.kernel.org/linux-clk/20230806-pll-mipi_set_rate_parent-v5-0-db4f5ca33...@oltmanns.dev/

>
>> +   } else if (event == POST_RATE_CHANGE) {
>> +   clk_set_rate(rate_reset->target_clk, rate_reset-
>> >saved_rate);
>> +   }
>> +
>> +   return NOTIFY_DONE;
>> +}
>> +
>> +int ccu_rate_reset_notifier_register(struct ccu_rate_reset_nb
>> *rate_reset_nb)
>> +{
>> +   rate_reset_nb->clk_nb.notifier_call =
>> ccu_rate_reset_notifier_cb;
>> +
>> +   return clk_notifier_register(rate_reset_nb->common->hw.clk,
>> +    _reset_nb->clk_nb);
>> +}
>> +
>>  static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device
>> *dev,
>>    struct device_node *node, void __iomem
>> *reg,
>>    const struct sunxi_ccu_desc *desc)
>> diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-
>> ng/ccu_common.h
>> index fbf16c6b896d..6b0b05fae123 100644
>> --- a/drivers/clk/sunxi-ng/ccu_common.h
>> +++ b/drivers/clk/sunxi-ng/ccu_common.h
>> @@ -69,4 +69,16 @@ int devm_sunxi_ccu_probe(struct device *dev, void
>> __iomem *reg,
>>  void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
>> const struct sunxi_ccu_desc *desc);
>>  
>> +struct ccu_rate_reset_nb {
>> +   struct notifier_block   clk_nb;
>> +   struct ccu_common   *common;
>> +
>> +   struct clk  *target_clk;
>> +   unsigned long   saved_rate;
>> +};
>> +
>> +#define to_ccu_rate_reset_nb(_nb) container_of(_nb, struct
>> ccu_rate_reset_nb, clk_nb)
>> +
>> +int ccu_rate_reset_notifier_register(struct ccu_rate_reset_nb
>> *rate_reset_nb);
>> +
>>  #endif /* _COMMON_H_ */
>>


Re: [PATCH 2/3] clk: sunxi-ng: a64: keep tcon0 clock rate when pll-video0's rate changes

2023-08-07 Thread Frank Oltmanns


On 2023-08-07 at 17:43:52 +0800, Icenowy Zheng  wrote:
> 在 2023-08-07星期一的 11:36 +0200,Frank Oltmanns写道:
>> From: Icenowy Zheng 
>>
>> Notify TCON0 clock (and in consequence PLL-MIPI by
>> CLK_SET_RATE_PARENT)
>> to reset when PLL-Video0 changes (because of HDMI PHY clk which is a
>> child of PLL-Video0 and has CLK_SET_RATE_PARENT set). In this way we
>> can
>> get clock tree to satisfy both pipelines.
>
> Well for fixing one's patch that contains SoB, use the following
> format:
>
> Signed-off-by: A 
> [B: fixed something]
> Signed-off-by: B 

Ah, okay. Will do. But I keep A in the "From: " line, correct?

Thanks,
  Frank

>> ---
>>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 15 +++
>>  1 file changed, 15 insertions(+)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> index ef567775fc95..93beedb0428e 100644
>> --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
>> @@ -943,6 +943,17 @@ static struct ccu_mux_nb sun50i_a64_cpu_nb = {
>> .bypass_index   = 1, /* index of 24 MHz oscillator */
>>  };
>>  
>> +/*
>> + * Since PLL-Video0 is an ancestor of both tcon0 and HDMI PYH, tcon0
>> clock will
>> + * conflict with HDMI PHY clock which is on another display
>> pipeline.
>> + *
>> + * Therefore, a notifier is required to restore the rate of TCON0
>> when the rate
>> + * of PLL-Video0 changed.
>> + */
>> +static struct ccu_rate_reset_nb sun50i_a64_pll_video0_reset_tcon0_nb
>> = {
>> +   .common = _video0_clk.common,
>> +};
>> +
>>  static int sun50i_a64_ccu_probe(struct platform_device *pdev)
>>  {
>> void __iomem *reg;
>> @@ -978,6 +989,10 @@ static int sun50i_a64_ccu_probe(struct
>> platform_device *pdev)
>> ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
>>   _a64_cpu_nb);
>>  
>> +   /* Reset the rate of TCON0 clock when PLL-VIDEO0 is changed
>> */
>> +   sun50i_a64_pll_video0_reset_tcon0_nb.target_clk =
>> tcon0_clk.common.hw.clk;
>> +   ccu_rate_reset_notifier_register(_a64_pll_video0_reset
>> _tcon0_nb);
>> +
>> return 0;
>>  }
>>  
>>


[PATCH 3/3] drm/sun4i: tcon: hand over the duty to keep TCON0 clock to CCU on A64

2023-08-07 Thread Frank Oltmanns
From: Icenowy Zheng 

As the A64 CCU driver has already the ability to keep TCON0 clock stable
when HDMI changes its parent's clock, do not protect TCON0 clock on A64
in the TCON driver to allow PLL-Video0 gets changed by HDMI (the CCU
will then restore the TCON0 clock rate).

Signed-off-by: Icenowy Zheng 
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 15 +--
 drivers/gpu/drm/sun4i/sun4i_tcon.h |  1 +
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index c44d5f3350d1..6f2d544c5f29 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -110,9 +110,11 @@ static void sun4i_tcon_channel_set_status(struct 
sun4i_tcon *tcon, int channel,
 
if (enabled) {
clk_prepare_enable(clk);
-   clk_rate_exclusive_get(clk);
+   if (!tcon->quirks->clk_kept_by_ccu)
+   clk_rate_exclusive_get(clk);
} else {
-   clk_rate_exclusive_put(clk);
+   if (!tcon->quirks->clk_kept_by_ccu)
+   clk_rate_exclusive_put(clk);
clk_disable_unprepare(clk);
}
 }
@@ -1562,6 +1564,14 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = 
{
.supports_lvds  = true,
 };
 
+static const struct sun4i_tcon_quirks sun50i_a64_lcd_quirks = {
+   .supports_lvds  = true,
+   .has_channel_0  = true,
+   .clk_kept_by_ccu= true,
+   .dclk_min_div   = 1,
+   .setup_lvds_phy = sun6i_tcon_setup_lvds_phy,
+};
+
 static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
.supports_lvds  = true,
.has_channel_0  = true,
@@ -1620,6 +1630,7 @@ const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun9i-a80-tcon-tv", .data = 
_a80_tcon_tv_quirks },
{ .compatible = "allwinner,sun20i-d1-tcon-lcd", .data = 
_d1_lcd_quirks },
{ .compatible = "allwinner,sun20i-d1-tcon-tv", .data = 
_r40_tv_quirks },
+   { .compatible = "allwinner,sun50i-a64-tcon-lcd", .data = 
_a64_lcd_quirks },
{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h 
b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 864d70b9d242..7ba3df9e27df 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -250,6 +250,7 @@ struct sun4i_tcon_quirks {
boolneeds_edp_reset; /* a80 edp reset needed for tcon0 access */
boolsupports_lvds;   /* Does the TCON support an LVDS output? */
boolpolarity_in_ch0; /* some tcon1 channels have polarity bits in 
tcon0 pol register */
+   boolclk_kept_by_ccu; /* On A64 we rely on CCU to keep TCON0 clock 
stable */
u8  dclk_min_div;   /* minimum divider for TCON0 DCLK */
 
/* callback to handle tcon muxing options */

-- 
2.41.0



[PATCH 2/3] clk: sunxi-ng: a64: keep tcon0 clock rate when pll-video0's rate changes

2023-08-07 Thread Frank Oltmanns
From: Icenowy Zheng 

Notify TCON0 clock (and in consequence PLL-MIPI by CLK_SET_RATE_PARENT)
to reset when PLL-Video0 changes (because of HDMI PHY clk which is a
child of PLL-Video0 and has CLK_SET_RATE_PARENT set). In this way we can
get clock tree to satisfy both pipelines.
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c 
b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index ef567775fc95..93beedb0428e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -943,6 +943,17 @@ static struct ccu_mux_nb sun50i_a64_cpu_nb = {
.bypass_index   = 1, /* index of 24 MHz oscillator */
 };
 
+/*
+ * Since PLL-Video0 is an ancestor of both tcon0 and HDMI PYH, tcon0 clock will
+ * conflict with HDMI PHY clock which is on another display pipeline.
+ *
+ * Therefore, a notifier is required to restore the rate of TCON0 when the rate
+ * of PLL-Video0 changed.
+ */
+static struct ccu_rate_reset_nb sun50i_a64_pll_video0_reset_tcon0_nb = {
+   .common = _video0_clk.common,
+};
+
 static int sun50i_a64_ccu_probe(struct platform_device *pdev)
 {
void __iomem *reg;
@@ -978,6 +989,10 @@ static int sun50i_a64_ccu_probe(struct platform_device 
*pdev)
ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
  _a64_cpu_nb);
 
+   /* Reset the rate of TCON0 clock when PLL-VIDEO0 is changed */
+   sun50i_a64_pll_video0_reset_tcon0_nb.target_clk = 
tcon0_clk.common.hw.clk;
+   ccu_rate_reset_notifier_register(_a64_pll_video0_reset_tcon0_nb);
+
return 0;
 }
 

-- 
2.41.0



[PATCH 1/3] clk: sunxi-ng: add support for rate resetting notifier

2023-08-07 Thread Frank Oltmanns
From: Icenowy Zheng 

In some situaitons, we will want a clock rate be kept while its parent
can change, for example, to make dual-head work on A64, TCON0 clock
needs to be kept for LCD display and its parent (or grandparent)
PLL-Video0 need to be changed for HDMI display. (There's a quirk on A64
that HDMI PHY can only use PLL-Video0, not PLL-Video1).

Add a notifier helper to create such kind of rate keeping notifier by
reset the rate after the parent changed.

Signed-off-by: Icenowy Zheng 
---
 drivers/clk/sunxi-ng/ccu_common.c | 22 ++
 drivers/clk/sunxi-ng/ccu_common.h | 12 
 2 files changed, 34 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_common.c 
b/drivers/clk/sunxi-ng/ccu_common.c
index 8d28a7a079d0..434fa46ad460 100644
--- a/drivers/clk/sunxi-ng/ccu_common.c
+++ b/drivers/clk/sunxi-ng/ccu_common.c
@@ -87,6 +87,28 @@ int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb)
 }
 EXPORT_SYMBOL_NS_GPL(ccu_pll_notifier_register, SUNXI_CCU);
 
+static int ccu_rate_reset_notifier_cb(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+   struct ccu_rate_reset_nb *rate_reset = to_ccu_rate_reset_nb(nb);
+
+   if (event == PRE_RATE_CHANGE) {
+   rate_reset->saved_rate = clk_get_rate(rate_reset->target_clk);
+   } else if (event == POST_RATE_CHANGE) {
+   clk_set_rate(rate_reset->target_clk, rate_reset->saved_rate);
+   }
+
+   return NOTIFY_DONE;
+}
+
+int ccu_rate_reset_notifier_register(struct ccu_rate_reset_nb *rate_reset_nb)
+{
+   rate_reset_nb->clk_nb.notifier_call = ccu_rate_reset_notifier_cb;
+
+   return clk_notifier_register(rate_reset_nb->common->hw.clk,
+_reset_nb->clk_nb);
+}
+
 static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
   struct device_node *node, void __iomem *reg,
   const struct sunxi_ccu_desc *desc)
diff --git a/drivers/clk/sunxi-ng/ccu_common.h 
b/drivers/clk/sunxi-ng/ccu_common.h
index fbf16c6b896d..6b0b05fae123 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -69,4 +69,16 @@ int devm_sunxi_ccu_probe(struct device *dev, void __iomem 
*reg,
 void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
const struct sunxi_ccu_desc *desc);
 
+struct ccu_rate_reset_nb {
+   struct notifier_block   clk_nb;
+   struct ccu_common   *common;
+
+   struct clk  *target_clk;
+   unsigned long   saved_rate;
+};
+
+#define to_ccu_rate_reset_nb(_nb) container_of(_nb, struct ccu_rate_reset_nb, 
clk_nb)
+
+int ccu_rate_reset_notifier_register(struct ccu_rate_reset_nb *rate_reset_nb);
+
 #endif /* _COMMON_H_ */

-- 
2.41.0



[PATCH 0/3] pll-video0 notifier for v6.5+

2023-08-07 Thread Frank Oltmanns
Hi Icenowy,

it is my understanding that you are the original author of the following
patches are in Ondřej's 6.4 branch [1] [2] [3] but not in his 6.5
branch. I assume it is because of merge conflicts as the part about
setting the parent has already been fixed in the 6.5 release candidates.

Therefore I've removed those parts and adopted the commit message of
PATCH 2. I've removed your SoB, because I think you'd need to sign of
the revised version. Especially patch 2 has become a bit simpler and I'm
wondering if it makes sense to try to upstream the three patches now.
What do you think?

Thank you for your amazing work!

Best regards,
  Frank

[1]: 
https://github.com/megous/linux/commit/2cd3d57adf83e2d091baed77e1aafc01d545d123
[2]: 
https://github.com/megous/linux/commit/c9c7bfe22f0fefdfc1dc2ce84b452964112399d7
[3]: 
https://github.com/megous/linux/commit/e19ccee10a8492535b6cda1ba972074d6e65

Signed-off-by: Frank Oltmanns 
---
Icenowy Zheng (3):
  clk: sunxi-ng: add support for rate resetting notifier
  clk: sunxi-ng: a64: keep tcon0 clock rate when pll-video0's rate changes
  drm/sun4i: tcon: hand over the duty to keep TCON0 clock to CCU on A64

 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 15 +++
 drivers/clk/sunxi-ng/ccu_common.c | 22 ++
 drivers/clk/sunxi-ng/ccu_common.h | 12 
 drivers/gpu/drm/sun4i/sun4i_tcon.c| 15 +--
 drivers/gpu/drm/sun4i/sun4i_tcon.h|  1 +
 5 files changed, 63 insertions(+), 2 deletions(-)
---
base-commit: 1cf5c37ee3c2334a964c65e52b4e0c59b4332d7c
change-id: 20230807-a64_pll_video0_notifier-164cbc78b341

Best regards,
-- 
Frank Oltmanns 



Re: [PATCH V3 1/3] dt-bindings: panel: Add Anbernic RG353V-V2 panel compatible

2023-08-06 Thread Frank Oltmanns
Hi Chris,
hi Guido,

On 2023-06-06 at 08:12:36 +0200, Frank Oltmanns  wrote:
> Hi Chris,
> hi Guido,
>
> On 2023-04-26 at 16:54:46 +0200, Guido Günther  wrote:
>> Hi Chris,
>> could you check if these two modifications by Frank of the init sequence
>>
>>
>> https://lore.kernel.org/dri-devel/20230211171748.36692-2-fr...@oltmanns.dev/
>>
>> https://lore.kernel.org/dri-devel/20230213123238.76889-2-fr...@oltmanns.dev/
>>
>> work for your panel too?
>
> I saw that Chris' patchset got accepted into drm-next, and I'm glad that
> more panels will therefore work out of the box. But: Did anyone check if
> the modifications I submitted in February and that Guido referenced
> above work with the new panel?

Chris, could you please check that the new rg353v-panel-v2 works with
the changes I proposed.

Guido, could you please check that the jh057n00900 panel works with the
changes I proposed.

Without these patches the XBD599 panel does not work reliably, so in the
long run it's desirable to include them in mainline. Currently, the only
user of the XBD599 panel that I'm aware of is the pinephone. Therefore,
all distributions supporting the pinephone rely on out-of-tree patches
to support the XDB599 panel.

I'd appreciate if we could rectify this situation.

Thank you both for your support,
  Frank

> Thanks,
>   Frank
>
>> Cheers,
>>  -- Guido
>>
>> On Wed, Apr 26, 2023 at 09:32:11AM -0500, Chris Morgan wrote:
>>> From: Chris Morgan 
>>>
>>> The Anbernic RG353V-V2 panel is a 3.5 inch 640x480 MIPI-DSI LCD panel.
>>> It's based on the ST7703 LCD controller just like rocktech,jh057n00900.
>>> It's used in a 2nd revision of the Anbernic RG353V handheld gaming
>>> device. Like the first revision of the RG353V the control chip is known
>>> but the panel itself is unknown, so name it for the device.
>>>
>>> Signed-off-by: Chris Morgan 
>>> Acked-by: Krzysztof Kozlowski 
>>> Acked-by: Guido Günther 
>>> ---
>>>  .../devicetree/bindings/display/panel/rocktech,jh057n00900.yaml | 2 ++
>>>  1 file changed, 2 insertions(+)
>>>
>>> diff --git 
>>> a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml 
>>> b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
>>> index 09b5eb7542f8..150e81090af2 100644
>>> --- 
>>> a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
>>> +++ 
>>> b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
>>> @@ -20,6 +20,8 @@ allOf:
>>>  properties:
>>>compatible:
>>>  enum:
>>> +  # Anberic RG353V-V2 5.0" 640x480 TFT LCD panel
>>> +  - anbernic,rg353v-panel-v2
>>># Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel
>>>- rocktech,jh057n00900
>>># Xingbangda XBD599 5.99" 720x1440 TFT LCD panel
>>> --
>>> 2.34.1
>>>
>>
>> On Wed, Apr 26, 2023 at 09:32:12AM -0500, Chris Morgan wrote:
>>> From: Chris Morgan 
>>>
>>> A later revision of the datasheet for the ST7703 refers to this command
>>> as "SETECO".
>>>
>>> Signed-off-by: Chris Morgan 
>>> Reviewed-by: Guido Günther 
>>> ---
>>>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 5 ++---
>>>  1 file changed, 2 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
>>> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>>> index 6747ca237ced..fc55b5fbb67f 100644
>>> --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>>> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>>> @@ -41,8 +41,8 @@
>>>  #define ST7703_CMD_UNKNOWN_BF   0xBF
>>>  #define ST7703_CMD_SETSCR   0xC0
>>>  #define ST7703_CMD_SETPOWER 0xC1
>>> +#define ST7703_CMD_SETECO   0xC6
>>>  #define ST7703_CMD_SETPANEL 0xCC
>>> -#define ST7703_CMD_UNKNOWN_C6   0xC6
>>>  #define ST7703_CMD_SETGAMMA 0xE0
>>>  #define ST7703_CMD_SETEQ0xE3
>>>  #define ST7703_CMD_SETGIP1  0xE9
>>> @@ -249,8 +249,7 @@ static int xbd599_init_sequence(struct st7703 *ctx)
>>>   * ESD_DET_TIME_SEL = 0 frames
>>>   */);
>>>
>>> -   /* Undocumented command. */
>>> -   mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 
>>> 0xFF, 0x00);
>>> +   mipi_dsi_dcs_write_seq(dsi, ST7703_CMD

Re: [PATCH V3 1/3] dt-bindings: panel: Add Anbernic RG353V-V2 panel compatible

2023-06-06 Thread Frank Oltmanns
Hi Chris,
hi Guido,

On 2023-04-26 at 16:54:46 +0200, Guido Günther  wrote:
> Hi Chris,
> could you check if these two modifications by Frank of the init sequence
>
>
> https://lore.kernel.org/dri-devel/20230211171748.36692-2-fr...@oltmanns.dev/
>
> https://lore.kernel.org/dri-devel/20230213123238.76889-2-fr...@oltmanns.dev/
>
> work for your panel too?

I saw that Chris' patchset got accepted into drm-next, and I'm glad that
more panels will therefore work out of the box. But: Did anyone check if
the modifications I submitted in February and that Guido referenced
above work with the new panel?

Thanks,
  Frank

> Cheers,
>  -- Guido
>
> On Wed, Apr 26, 2023 at 09:32:11AM -0500, Chris Morgan wrote:
>> From: Chris Morgan 
>>
>> The Anbernic RG353V-V2 panel is a 3.5 inch 640x480 MIPI-DSI LCD panel.
>> It's based on the ST7703 LCD controller just like rocktech,jh057n00900.
>> It's used in a 2nd revision of the Anbernic RG353V handheld gaming
>> device. Like the first revision of the RG353V the control chip is known
>> but the panel itself is unknown, so name it for the device.
>>
>> Signed-off-by: Chris Morgan 
>> Acked-by: Krzysztof Kozlowski 
>> Acked-by: Guido Günther 
>> ---
>>  .../devicetree/bindings/display/panel/rocktech,jh057n00900.yaml | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git 
>> a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml 
>> b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
>> index 09b5eb7542f8..150e81090af2 100644
>> --- 
>> a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
>> +++ 
>> b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml
>> @@ -20,6 +20,8 @@ allOf:
>>  properties:
>>compatible:
>>  enum:
>> +  # Anberic RG353V-V2 5.0" 640x480 TFT LCD panel
>> +  - anbernic,rg353v-panel-v2
>># Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel
>>- rocktech,jh057n00900
>># Xingbangda XBD599 5.99" 720x1440 TFT LCD panel
>> --
>> 2.34.1
>>
>
> On Wed, Apr 26, 2023 at 09:32:12AM -0500, Chris Morgan wrote:
>> From: Chris Morgan 
>>
>> A later revision of the datasheet for the ST7703 refers to this command
>> as "SETECO".
>>
>> Signed-off-by: Chris Morgan 
>> Reviewed-by: Guido Günther 
>> ---
>>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 5 ++---
>>  1 file changed, 2 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
>> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> index 6747ca237ced..fc55b5fbb67f 100644
>> --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> @@ -41,8 +41,8 @@
>>  #define ST7703_CMD_UNKNOWN_BF0xBF
>>  #define ST7703_CMD_SETSCR0xC0
>>  #define ST7703_CMD_SETPOWER  0xC1
>> +#define ST7703_CMD_SETECO0xC6
>>  #define ST7703_CMD_SETPANEL  0xCC
>> -#define ST7703_CMD_UNKNOWN_C60xC6
>>  #define ST7703_CMD_SETGAMMA  0xE0
>>  #define ST7703_CMD_SETEQ 0xE3
>>  #define ST7703_CMD_SETGIP1   0xE9
>> @@ -249,8 +249,7 @@ static int xbd599_init_sequence(struct st7703 *ctx)
>>* ESD_DET_TIME_SEL = 0 frames
>>*/);
>>
>> -/* Undocumented command. */
>> -mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_UNKNOWN_C6, 0x01, 0x00, 0xFF, 
>> 0xFF, 0x00);
>> +mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETECO, 0x01, 0x00, 0xFF, 0xFF, 
>> 0x00);
>>
>>  mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETPOWER,
>> 0x74, /* VBTHS, VBTLS: VGH = 17V, VBL = -11V */
>> --
>> 2.34.1
>>
>
> On Wed, Apr 26, 2023 at 09:32:13AM -0500, Chris Morgan wrote:
>> From: Chris Morgan 
>>
>> The Anbernic RG353V-V2 is a 5 inch panel used in a new revision of the
>> Anbernic RG353V handheld gaming device. Add support for it.
>>
>> Unfortunately it appears this controller is not able to support 120hz
>> or 100hz mode like the first revision panel.
>>
>> Signed-off-by: Chris Morgan 
>> Reviewed-by: Guido Günther 
>> ---
>>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 97 +++
>>  1 file changed, 97 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
>> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> index fc55b5fbb67f..3aa31f3d6157 100644
>> --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> @@ -28,6 +28,7 @@
>>  /* Manufacturer specific Commands send via DSI */
>>  #define ST7703_CMD_ALL_PIXEL_OFF 0x22
>>  #define ST7703_CMD_ALL_PIXEL_ON  0x23
>> +#define ST7703_CMD_SETAPID   0xB1
>>  #define ST7703_CMD_SETDISP   0xB2
>>  #define ST7703_CMD_SETRGBIF  0xB3
>>  #define ST7703_CMD_SETCYC0xB4
>> @@ -42,11 +43,14 @@
>>  #define ST7703_CMD_SETSCR0xC0
>>  #define ST7703_CMD_SETPOWER  0xC1
>>  #define ST7703_CMD_SETECO0xC6
>> +#define ST7703_CMD_SETIO 0xC7
>> +#define ST7703_CMD_SETCABC   0xC8
>>  #define 

Re: [PATCH v4 0/4] drm: sun4i: set proper TCON0 DCLK rate in DSI mode

2023-05-09 Thread Frank Oltmanns
Hello Roman,

On 2023-05-09 at 13:04:50 +0200, "Roman Beranek"  wrote:
> On Mon May 8, 2023 at 10:47 AM CEST, Frank Oltmanns wrote:
>> I played back a 60 fps video (10 seconds) and recorded the panel's
>> output with a 240 fps camera. I noticed only 2 dropped frames, that I
>> account to the imperfect data rate of 107.8MHz instead of 108 MHz due
>> to pll-video0's rate being 294MHz instead of the 297 MHz for reasons
>> I described in the thread on your v2 of this patch [4]).
>
> Yes. That's what should happen, right? Or do you report this as a
> defect?

Sorry, I didn't communicate more clearly. Without your patch, I'm losing
a number of frames in the realm of three digits. With your patch I only
lost 2 frames which is expetcted. Your patches are a big improvement.

This is the opposite of a defect report. :-)

Thanks,
  Frank

>
> Roman


Re: [PATCH v2 0/7] drm: sun4i: set proper TCON0 DCLK rate in DSI mode

2023-05-08 Thread Frank Oltmanns
Hello again,

On 2023-05-08 at 08:54:28 +0200, Frank Oltmanns  wrote:
> Hello Roman,
>
> On 2023-05-03 at 16:22:32 +0200, "Roman Beranek"  wrote:
>> Hello everyone,
>>
>> I apologize for my absence from the discussion during past week, I got
>> hit with tonsillitis.
>
> I hope you feel better!
>
>> On Mon May 1, 2023 at 3:40 PM CEST, Frank Oltmanns wrote:
>>> Looking at ccu_nkm_determine_rate(), we've found our culprit because it
>>> does not try parent clock rates other than the current one. The same
>>> applies to all other ccu_nkm_* functions.
>>
>> Yes, that's why I dropped CLK_SET_RATE_PARENT from pll-mipi in v3.
>>
>>>  b. Add functionality to ccu_nkm_* to also update the parent clock rate.
>>>
>>> I'm actually interested in tackling b, but I can't make any promises as
>>> to if and when I'll be able to solve it. I'm not certain about any side
>>> effects this might have.
>>
>> It sounds like an interesting exercise. But what if HDMI is then added
>> to the mix?
>
> Thanks for interest in this discussion! I really appreciate it!
>
> First of all, let me admit that I'm no expert on this. But nobody else
> has replied so far, and I want to keep this conversation going, so let
> me share my view.
>
> My understanding is that pll-mipi being able to set pll-video0's rate
> should not have an impact on HDMI, neither positive nor negative. If I'm
> not mistaken those two things are orthogonal.
>
> The relevant part of the clk_summary with your v4 [1] patch on top of
> drm-next looks like this:
>
>  enable  protect  hardware
>clock  countcountrateenable
> --
> pll-video011   29400 Y
>hdmi   00   29400 N
>tcon1  00   29400 N
>pll-mipi   11   43120 Y
>   tcon0   21   43120 Y
>  tcon-data-clock  11   10780 Y
>pll-video0-2x  00   58800 Y
>
> Note, that pll-video0 is protected.
>
> I don't own any boards that support HDMI in mainline. For the pinephone
> this support is added e.g. in megi's kernel, where connecting an HDMI
> output results in pll-video0's rate being set to 297MHz, even though it
> is 294MHz after boot.
>
> So, for reference, this is the same part of the clk_summary with megi's
> 6.3.0 kernel, USB-C dock unplugged:
>
>  enable  protect  hardware
>clock  countcountrateenable
> --
> pll-video030   29400 Y
>hdmi-phy-clk   107350 Y
>hdmi   10   29400 Y
>tcon1  00   29400 N
>pll-mipi   10   43120 Y
>   tcon0   20   43120 Y
>  tcon-pixel-clock 10   10780 Y
>pll-video0-2x  00   58800 Y
>
> pll-video0 is not protected. When plugging in the USB-C dock with an HDMI
> monitor connected, the situation looks like this:

Just for reference, the protection count is disabled by this commit [1]
in megi's kernel.

In the commit message Icenowy Zheng refers to "the ability to keep TCON0
clock stable when HDMI changes its parent's clock." She implemented this
in these two previous commits [2] [3]. None of this is in mainline.

Best regards,
  Frank

[1]: 
https://github.com/megous/linux/commit/039f7ee3f44adfbe4c6b7c2f1798b9a70c9fb9ee
[2]: 
https://github.com/megous/linux/commit/a927843932f16e5a7f5ff57fbfd2d5f11c712b67
[3]: 
https://github.com/megous/linux/commit/0e305371eaa49128856acce9830e6af079442ad6

>
>  enable  protect  hardware
>clock  countcountrateenable
> --
> pll-video041   29700 Y
>hdmi-phy-clk   10   14850 Y
>hdmi   10   14850 Y
>tcon1  

Re: [PATCH v4 0/4] drm: sun4i: set proper TCON0 DCLK rate in DSI mode

2023-05-08 Thread Frank Oltmanns
Hi Roman,

On 2023-05-05 at 07:21:06 +0200, Roman Beranek  wrote:
> According to Allwinner's BSP code, in DSI mode, TCON0 clock needs to be
> running at what's effectively the per-lane datarate of the DSI link.
> Given that the TCON DCLK divider is fixed to 4 (SUN6I_DSI_TCON_DIV),
> DCLK can't be set equal to the dotclock. Therefore labeling TCON DCLK
> as sun4i_dotclock or tcon-pixel-clock shall be avoided.
>
> With bpp bits per pixel transmitted over n DSI lanes, the target DCLK
> rate for a given pixel clock is obtained as follows:
>
> DCLK rate = 1/4 * bpp / n * pixel clock
>
> Effect of this change can be observed through the rate of Vblank IRQs
> which should now match refresh rate implied by set display mode. It
> was verified to do so on a A64 board with a 2-lane and a 4-lane panel.
>
> v2:
> 1. prevent reparent of tcon0 to pll-video0-2x
> 2. include pll-video0 in setting TCON0 DCLK rate
> 3. tested the whole thing also on a PinePhone
>
> v3:
> 1. accept that pll-video0 can't be included in setting TCON0 DCLK rate
> 2. reset pll-video0 to its default rate in case u-boot changed it
>
> v4:
> 1. keep pll-video0 as is
> 2. assign parent to TCON0 mux in sun50i_a64_ccu_probe (not in DT)
>
> Roman Beranek (4):
>   clk: sunxi-ng: a64: force select PLL_MIPI in TCON0 mux
>   ARM: dts: sunxi: rename tcon's clock output
>   drm: sun4i: rename sun4i_dotclock to sun4i_tcon_dclk
>   drm: sun4i: calculate proper DCLK rate for DSI
>
>  arch/arm/boot/dts/sun5i.dtsi  |  2 +-
>  arch/arm/boot/dts/sun8i-a23-a33.dtsi  |  2 +-
>  arch/arm/boot/dts/sun8i-a83t.dtsi |  2 +-
>  arch/arm/boot/dts/sun8i-v3s.dtsi  |  2 +-
>  arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi |  2 +-
>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 14 +-
>  drivers/gpu/drm/sun4i/Makefile|  2 +-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c| 46 +++
>  .../{sun4i_dotclock.c => sun4i_tcon_dclk.c}   |  2 +-
>  .../{sun4i_dotclock.h => sun4i_tcon_dclk.h}   |  0
>  10 files changed, 46 insertions(+), 28 deletions(-)
>  rename drivers/gpu/drm/sun4i/{sun4i_dotclock.c => sun4i_tcon_dclk.c} (99%)
>  rename drivers/gpu/drm/sun4i/{sun4i_dotclock.h => sun4i_tcon_dclk.h} (100%)
>
>
> base-commit: 8a91b29f1f50ce7742cdbe5cf11d17f128511f3f

I tested this on my pinephone on drm-next, using additional patches for
the pinephone's panel. [1] [2] [3]

I played back a 60 fps video (10 seconds) and recorded the panel's
output with a 240 fps camera. I noticed only 2 dropped frames, that I
account to the imperfect data rate of 107.8MHz instead of 108 MHz due to
pll-video0's rate being 294MHz instead of the 297 MHz for reasons I
described in the thread on your v2 of this patch [4]).

Tested-by: Frank Oltmanns 

Thanks,
  Frank

[1]: https://lore.kernel.org/all/20230213123238.76889-2-fr...@oltmanns.dev/
[2]: https://lore.kernel.org/all/20230211171748.36692-2-fr...@oltmanns.dev/
[3]: 
https://github.com/megous/linux/commit/e83ffbfe930562257abef1eed4abb8e2251b795a
[4]: https://lore.kernel.org/all/87cz3uzpx1@oltmanns.dev/


Re: [PATCH v2 0/7] drm: sun4i: set proper TCON0 DCLK rate in DSI mode

2023-05-08 Thread Frank Oltmanns
Hello Roman,

On 2023-05-03 at 16:22:32 +0200, "Roman Beranek"  wrote:
> Hello everyone,
>
> I apologize for my absence from the discussion during past week, I got
> hit with tonsillitis.

I hope you feel better!

> On Mon May 1, 2023 at 3:40 PM CEST, Frank Oltmanns wrote:
>> Looking at ccu_nkm_determine_rate(), we've found our culprit because it
>> does not try parent clock rates other than the current one. The same
>> applies to all other ccu_nkm_* functions.
>
> Yes, that's why I dropped CLK_SET_RATE_PARENT from pll-mipi in v3.
>
>>  b. Add functionality to ccu_nkm_* to also update the parent clock rate.
>>
>> I'm actually interested in tackling b, but I can't make any promises as
>> to if and when I'll be able to solve it. I'm not certain about any side
>> effects this might have.
>
> It sounds like an interesting exercise. But what if HDMI is then added
> to the mix?

Thanks for interest in this discussion! I really appreciate it!

First of all, let me admit that I'm no expert on this. But nobody else
has replied so far, and I want to keep this conversation going, so let
me share my view.

My understanding is that pll-mipi being able to set pll-video0's rate
should not have an impact on HDMI, neither positive nor negative. If I'm
not mistaken those two things are orthogonal.

The relevant part of the clk_summary with your v4 [1] patch on top of
drm-next looks like this:

 enable  protect  hardware
   clock  countcountrateenable
--
pll-video011   29400 Y
   hdmi   00   29400 N
   tcon1  00   29400 N
   pll-mipi   11   43120 Y
  tcon0   21   43120 Y
 tcon-data-clock  11   10780 Y
   pll-video0-2x  00   58800 Y

Note, that pll-video0 is protected.

I don't own any boards that support HDMI in mainline. For the pinephone
this support is added e.g. in megi's kernel, where connecting an HDMI
output results in pll-video0's rate being set to 297MHz, even though it
is 294MHz after boot.

So, for reference, this is the same part of the clk_summary with megi's
6.3.0 kernel, USB-C dock unplugged:

 enable  protect  hardware
   clock  countcountrateenable
--
pll-video030   29400 Y
   hdmi-phy-clk   107350 Y
   hdmi   10   29400 Y
   tcon1  00   29400 N
   pll-mipi   10   43120 Y
  tcon0   20   43120 Y
 tcon-pixel-clock 10   10780 Y
   pll-video0-2x  00   58800 Y

pll-video0 is not protected. When plugging in the USB-C dock with an HDMI
monitor connected, the situation looks like this:

 enable  protect  hardware
   clock  countcountrateenable
--
pll-video041   29700 Y
   hdmi-phy-clk   10   14850 Y
   hdmi   10   14850 Y
   tcon1  11   14850 Y
   pll-mipi   10   424285714 Y
  tcon0   20   424285714 Y
 tcon-pixel-clock 10   106071428 Y
   pll-video0-2x  00   59400 Y

As you can see, pll-video0 is updated to 297 MHz. My understanding is
(again: not an expert here) this is only possible due to the missing
protection.

What I'm trying to say is that I don't see a connection between HDMI and
having the functionality in ccu_nkm_* to update the parent clock rate.

But I do think it would be preferable to have pll-video0 at 297 MHz
after boot on the pinephone. We could achieve this with my two previous
proposals:

 a) Set pll-video0 to 297 MHz on boot
 b) Add functionality to ccu_nkm_* to also update the parent clock rate.

If solution b is viable, the goal for the pinephone (and any other
boards supporting HDMI) would then be to select a pixel-data-clock so
that the rate for p

Re: [PATCH v2 0/7] drm: sun4i: set proper TCON0 DCLK rate in DSI mode

2023-05-01 Thread Frank Oltmanns
Maxime, Jernej, I was trying to understand why pll-video0 is not updated
and I tracked down the culprit to ccu_nkm.c.

On 2023-04-23 at 15:24:33 +0200, Frank Oltmanns  wrote:
> On 2023-04-18 at 09:40:01 +0200, Roman Beranek  wrote:
>> According to Allwinner's BSP code, in DSI mode, TCON0 clock needs to be
>> running at what's effectively the per-lane datarate of the DSI link.
>> Given that the TCON DCLK divider is fixed to 4 (SUN6I_DSI_TCON_DIV),
>> DCLK can't be set equal to the dotclock. Therefore labeling TCON DCLK
>> as sun4i_dotclock or tcon-pixel-clock shall be avoided.
>>
>> With bpp bits per pixel transmitted over n DSI lanes, the target DCLK
>> rate for a given pixel clock is obtained as follows:
>>
>> DCLK rate = 1/4 * bpp / n * pixel clock
>>
>> Effect of this change can be observed through the rate of Vblank IRQs
>> which should now match refresh rate implied by set display mode. It
>> was verified to do so on a A64 board with a 2-lane and a 4-lane panel.
[...]
> I've tried your patches on my pinephone. I also set the panel's clock to
> 72 MHz, so at 24 bpp and 4 lanes that should result in a data clock of
> 108 MHz. This should be possible when pll-video0 is at 297 MHz.
>
> Unfortunately, pll-video0 is not set and therefore the relevant part of
> the clk_summary looks like this:
>
>   enable  prepare  protect  hardware
> clock  countcountcountrateenable
> 
>  pll-video0111   29400 Y
> hdmi   000   29400 N
> tcon1  000   29400 N
> pll-mipi   111   43120 Y
>tcon0   221   43120 Y
>   tcon-data-clock  111   10780 Y
> pll-video0-2x  000   58800 Y
>
> Note, I've cut the columns accuracy, phase, and duty cycle, because they
> show the same values for all clocks (0, 0, 5).
>
> My understanding was that with this patchset setting the parent clock
> should be possible. Do you have any idea why it doesn't work on the
> pinephone? Or maybe it does work on yours and I'm making some kind of
> mistake?

To better understand what's going on I've extended the clk_rate_request
class to also output the requested rate. The relevant output is this
(leading line numbers by me for referencing the lines below):
line  1: kworker/u8:2-49  [002] . 1.850141: 
clk_rate_request_start: tcon-data-clock rate 10800 min 0 max 
18446744073709551615, parent tcon0 (58800)
line  2: kworker/u8:2-49  [002] . 1.850149: 
clk_rate_request_start: tcon0 rate 43200 min 0 max 18446744073709551615, 
parent pll-mipi (58800)
line  3: kworker/u8:2-49  [002] . 1.850154: 
clk_rate_request_start: pll-mipi rate 43200 min 0 max 18446744073709551615, 
parent pll-video0 (29400)
line  4: kworker/u8:2-49  [002] . 1.850168: 
clk_rate_request_done: pll-mipi rate 43120 min 0 max 18446744073709551615, 
parent pll-video0 (29400)
line  5: kworker/u8:2-49  [002] . 1.850169: 
clk_rate_request_done: tcon0 rate 43120 min 0 max 18446744073709551615, 
parent pll-mipi (43120)
line  6: kworker/u8:2-49  [002] . 1.850171: 
clk_rate_request_done: tcon-data-clock rate 10780 min 0 max 
18446744073709551615, parent tcon0 (43120)
line  7: kworker/u8:2-49  [002] . 1.850172: 
clk_rate_request_start: tcon-data-clock rate 10800 min 0 max 
18446744073709551615, parent tcon0 (58800)
line  8: kworker/u8:2-49  [002] . 1.850174: 
clk_rate_request_start: tcon0 rate 43200 min 0 max 18446744073709551615, 
parent pll-mipi (58800)
line  9: kworker/u8:2-49  [002] . 1.850179: 
clk_rate_request_start: pll-mipi rate 43200 min 0 max 18446744073709551615, 
parent pll-video0 (29400)
line 10: kworker/u8:2-49  [002] . 1.850190: 
clk_rate_request_done: pll-mipi rate 43120 min 0 max 18446744073709551615, 
parent pll-video0 (29400)
line 11: kworker/u8:2-49  [002] . 1.850191: 
clk_rate_request_done: tcon0 rate 43120 min 0 max 18446744073709551615, 
parent pll-mipi (43120)
line 12: kworker/u8:2-49  [002] . 1.850192: 
clk_rate_request_done: tcon-data-clock rate 10780 min 0 max 
18446744073709551615, parent tcon0 (43120)
line 13: kworker/u8:2-49  [002] . 1.850193: 
clk_rate_request_start: tcon0 rate 43120 min 0 max 18446744073709551615, 
parent pll-mipi (5880

Re: [PATCH v3 4/7] arm64: dts: allwinner: a64: reset pll-video0 rate

2023-04-29 Thread Frank Oltmanns
Hi Jernej,

On 2023-04-28 at 08:43:29 +0200, Jernej Škrabec  
wrote:
> Dne četrtek, 27. april 2023 ob 11:16:08 CEST je Roman Beranek napisal(a):
>> With pll-mipi as its source clock, the exact rate to which TCON0's data
>> clock can be set to is constrained by the current rate of pll-video0.
>> Unless changed on a request of another consumer, the rate of pll-video0
>> is left as inherited from the bootloader.
>>
>> The default rate on reset is 297 MHz, a value preferable to what it is
>> later set to in u-boot (294 MHz). This happens unintentionally though,
>> as u-boot, for the sake of simplicity, rounds the rate requested by DE2
>> driver (297 MHz) to 6 MHz steps.
>>
>> Reset the PLL to its default rate of 297 MHz.
>
> Why would that be preferable? You actually dropped "clk: sunxi-ng: a64:
> propagate rate change from pll-mipi" patch which would take care for adjusting
> parent rate to correct value.

For me, on the pinephone, it somehow doesn't. Please see here:
https://lore.kernel.org/all/87cz3uzpx1@oltmanns.dev/

I haven't figured out yet why that is. But hopefully, I'll find time in
the coming days / weeks to look into that.

Best regards,
  Frank

> Best regards,
> Jernej
>
>>
>> Signed-off-by: Roman Beranek 
>> ---
>>  arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
>> b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index
>> e6a194db420d..cfc60dce80b0 100644
>> --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
>> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
>> @@ -667,6 +667,9 @@ ccu: clock@1c2 {
>>  clock-names = "hosc", "losc";
>>  #clock-cells = <1>;
>>  #reset-cells = <1>;
>> +
>> +assigned-clocks = < CLK_PLL_VIDEO0>;
>> +assigned-clock-rates = <29700>;
>>  };
>>
>>  pio: pinctrl@1c20800 {


Re: [PATCH v2 0/7] drm: sun4i: set proper TCON0 DCLK rate in DSI mode

2023-04-23 Thread Frank Oltmanns
Hi Roman,

On 2023-04-18 at 09:40:01 +0200, Roman Beranek  wrote:
> According to Allwinner's BSP code, in DSI mode, TCON0 clock needs to be
> running at what's effectively the per-lane datarate of the DSI link.
> Given that the TCON DCLK divider is fixed to 4 (SUN6I_DSI_TCON_DIV),
> DCLK can't be set equal to the dotclock. Therefore labeling TCON DCLK
> as sun4i_dotclock or tcon-pixel-clock shall be avoided.
>
> With bpp bits per pixel transmitted over n DSI lanes, the target DCLK
> rate for a given pixel clock is obtained as follows:
>
> DCLK rate = 1/4 * bpp / n * pixel clock
>
> Effect of this change can be observed through the rate of Vblank IRQs
> which should now match refresh rate implied by set display mode. It
> was verified to do so on a A64 board with a 2-lane and a 4-lane panel.
>
> v2:
> 1. prevent reparent of tcon0 to pll-video0-2x
> 2. include pll-video0 in setting TCON0 DCLK rate
> 3. tested the whole thing also on a PinePhone
>
> Roman Beranek (7):
>   clk: sunxi-ng: a64: propagate rate change from pll-mipi
>   clk: sunxi-ng: a64: export PLL_MIPI
>   clk: sunxi-ng: a64: prevent CLK_TCON0 being reparented
>   arm64: dts: allwinner: a64: assign PLL_MIPI to CLK_TCON0
>   ARM: dts: sunxi: rename tcon's clock output
>   drm: sun4i: rename sun4i_dotclock to sun4i_tcon_dclk
>   drm: sun4i: calculate proper DCLK rate for DSI
>
>  arch/arm/boot/dts/sun5i.dtsi  |  2 +-
>  arch/arm/boot/dts/sun8i-a23-a33.dtsi  |  2 +-
>  arch/arm/boot/dts/sun8i-a83t.dtsi |  2 +-
>  arch/arm/boot/dts/sun8i-v3s.dtsi  |  2 +-
>  arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi |  4 +-
>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c |  6 ++-
>  drivers/clk/sunxi-ng/ccu-sun50i-a64.h |  4 +-
>  drivers/gpu/drm/sun4i/Makefile|  2 +-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c| 46 +++
>  .../{sun4i_dotclock.c => sun4i_tcon_dclk.c}   |  2 +-
>  .../{sun4i_dotclock.h => sun4i_tcon_dclk.h}   |  0
>  include/dt-bindings/clock/sun50i-a64-ccu.h|  1 +
>  12 files changed, 43 insertions(+), 30 deletions(-)
>  rename drivers/gpu/drm/sun4i/{sun4i_dotclock.c => sun4i_tcon_dclk.c} (99%)
>  rename drivers/gpu/drm/sun4i/{sun4i_dotclock.h => sun4i_tcon_dclk.h} (100%)
>
>
> base-commit: 4aa35a0130d6b8afbefc9ef530a521fb0fb9b8e1


I've tried your patches on my pinephone. I also set the panel's clock to
72 MHz, so at 24 bpp and 4 lanes that should result in a data clock of
108 MHz. This should be possible when pll-video0 is at 297 MHz.

Unfortunately, pll-video0 is not set and therefore the relevant part of
the clk_summary looks like this:

  enable  prepare  protect  hardware
clock  countcountcountrateenable

 pll-video0111   29400 Y
hdmi   000   29400 N
tcon1  000   29400 N
pll-mipi   111   43120 Y
   tcon0   221   43120 Y
  tcon-data-clock  111   10780 Y
pll-video0-2x  000   58800 Y

Note, I've cut the columns accuracy, phase, and duty cycle, because they
show the same values for all clocks (0, 0, 5).

My understanding was that with this patchset setting the parent clock
should be possible. Do you have any idea why it doesn't work on the
pinephone? Or maybe it does work on yours and I'm making some kind of
mistake?

On a brighter note, when I initialize pll-video0 to 297 MHz in
sunxi-ng/ccu-sun50i-a64.c:sun50i_a64_ccu_probe() I get an even 108 Mhz
for the data clock. The patch is:

writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);

+   /*
+* Initialize PLL VIDEO0 to default values (297 MHz)
+* to clean up any changes made by bootloader
+*/
+   writel(0x03006207, reg + 0x10);
+
ret = devm_sunxi_ccu_probe(>dev, reg, _a64_ccu_desc);
if (ret)
return ret;

Best,
  Frank


Re: [PATCH 3/3] drm: sun4i: calculate proper DCLK rate for DSI

2023-04-03 Thread Frank Oltmanns


On 2023-04-03 at 15:52:36 +0200, "Roman Beranek"  wrote:
> On Sun Apr 2, 2023 at 12:49 PM CEST, Frank Oltmanns wrote:
>>
>> When apply this to drm-next my panel stays dark. I haven't figured out
>> yet why, though. The other two patches in this series work fine, i.e.
>> they have no effect as they are just a refactoring.
>>
>> I'm testing this on my pinephone. It's the same with the patch I
>> submitted. For whatever reason, it no longer works on drm-next.
>
> I've reproduced the issue on my PinePhone and noticed that tcon0 had set
> pll-video0-2x as its parent instead of pll-mipi. Having tried a whole
> range of pll-video0 rates, I'm now convinced that DSI only works when
> tcon0 has pll-mipi as its parent.
>
> As little a change as setting .clock in the default mode of PP's panel
> to 73500 can fix it. Better yet, dropping pll-video0-2x from the set
> of acceptable parents for tcon0 fixes it universally. And that's what
> megi's kernel does, though the measure was introduced with a different
> rationale:
> <https://github.com/megous/linux/commit/7374d5756aa0cc3f11e494e3cbc54f6c7c01e1a8>

For sake of completeness, the patch you referenced builds on this patch:
https://github.com/megous/linux/commit/45e0aa8d9e34

Are you saying that your other boards and panels work without these
patches?

Best regards,
  Frank

>
> Roman


Re: [PATCH 3/3] drm: sun4i: calculate proper DCLK rate for DSI

2023-04-02 Thread Frank Oltmanns
Hi Roman,

On 2023-03-31 at 13:02:45 +0200, Roman Beranek  wrote:
> In DSI mode, TCON0's data clock is required to run at 1/4 the per-lane
> bit rate.
>
> Signed-off-by: Roman Beranek 
> ---
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 36 +-
>  1 file changed, 21 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
> b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index eec26b1faa4b..b263de7a8237 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -291,18 +291,6 @@ static int sun4i_tcon_get_clk_delay(const struct 
> drm_display_mode *mode,
>   return delay;
>  }
>
> -static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> - const struct drm_display_mode *mode)
> -{
> - /* Configure the dot clock */
> - clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> -
> - /* Set the resolution */
> - regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> -  SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
> -  SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
> -}
> -
>  static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
>  const struct drm_connector 
> *connector)
>  {
> @@ -367,10 +355,18 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon 
> *tcon,
>   u32 block_space, start_delay;
>   u32 tcon_div;
>
> + /*
> +  * dclk is required to run at 1/4 the DSI per-lane bit rate.
> +  */
>   tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
>   tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> + clk_set_rate(tcon->dclk, mode->crtc_clock * 1000 * (bpp / lanes)
> +   / SUN6I_DSI_TCON_DIV);

When apply this to drm-next my panel stays dark. I haven't figured out
yet why, though. The other two patches in this series work fine, i.e.
they have no effect as they are just a refactoring.

I'm testing this on my pinephone. It's the same with the patch I
submitted. For whatever reason, it no longer works on drm-next.

At the time I'm writing this, drm-next is at 82bbec189ab3 "Merge
v6.3-rc4 into drm-next".

Does it work for you? And if so, on which commit are you basing this
series?

Thanks,
  Frank


>
> - sun4i_tcon0_mode_set_common(tcon, mode);
> + /* Set the resolution */
> + regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> +  SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
> +  SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>
>   /* Set dithering if needed */
>   sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> @@ -438,7 +434,12 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon 
> *tcon,
>
>   tcon->dclk_min_div = 7;
>   tcon->dclk_max_div = 7;
> - sun4i_tcon0_mode_set_common(tcon, mode);
> + clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> +
> + /* Set the resolution */
> + regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> +  SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
> +  SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>
>   /* Set dithering if needed */
>   sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
> @@ -515,7 +516,12 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon 
> *tcon,
>
>   tcon->dclk_min_div = tcon->quirks->dclk_min_div;
>   tcon->dclk_max_div = 127;
> - sun4i_tcon0_mode_set_common(tcon, mode);
> + clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
> +
> + /* Set the resolution */
> + regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
> +  SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
> +  SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
>
>   /* Set dithering if needed */
>   sun4i_tcon0_mode_set_dithering(tcon, connector);


--
--
Frank Oltmanns


Re: [PATCH] drm/sun4i: uncouple DSI dotclock divider from TCON0_DCLK_REG

2023-03-29 Thread Frank Oltmanns
Hi Roman,

On 2023-03-29 at 21:58:02 +0200, Maxime Ripard  wrote:
> On Tue, Mar 28, 2023 at 01:48:33AM +0200, Roman Beranek wrote:
>> On Mon Mar 27, 2023 at 10:20 PM CEST, Maxime Ripard wrote:
>> >
>> > On Sat, Mar 25, 2023 at 12:40:04PM +0100, Frank Oltmanns wrote:
>> > > Claiming to set the divider to a different value (bpp / lanes) than what 
>> > > we’re actually using in
>> > > the end (SUN6I_DSIO_TCON_DIV) is somehow bugging me. I feel like the 
>> > > proposal that I submitted is
>> > > more direct: 
>> > > <https://lore.kernel.org/all/20230319160704.9858-2-fr...@oltmanns.dev/>
>> >
>> > Yeah, this patch looks better to me too: it's simpler, more 
>> > straightforward. If Roman can confirm it
>> > works with his testing, I'll be happy to merge it.
>> >
>>
>> So I've just found out that my understanding of what sun4i_dotclock is
>> was wrong the whole time. I treated it as a virtual clock representing
>> the true CRTC pixel clock and only coincidentally also matching what
>> A64 Reference Manual labels as TCON0 data clock (a coincidence to which
>> DSI is an exception).
>>
>> Now that I finally see dotclock as 'what could dclk be an abbreviation
>> to', I to agree that it's not only straightforward but also correct to
>> keep the divider at 4 and adjust the rate as is done it the patch Frank
>> submitted.
>>
>> In order to preserve semantic correctness however, I propose to preface
>> the change with a patch that renames sun4i_dotclock and tcon-pixel-clock
>> such that dot/pixel is replaced with d/data. What do you think?
>
> I don't think it's exposed to the userspace in any way so it makes sense to me

Roman, will you please submit a V2 of the patch I submitted then? Or do
you want me to do it?

Thanks,
  Frank

>
> Maxime
>


--


Re: [PATCH] drm/sun4i: uncouple DSI dotclock divider from TCON0_DCLK_REG

2023-03-29 Thread Frank Oltmanns


Hi,

On 2023-03-29 at 21:56:39 +0200, Maxime Ripard  wrote:
> Hi,
>
> On Tue, Mar 28, 2023 at 09:28:19PM +0200, Frank Oltmanns wrote:
>> --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
>> +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
>> @@ -819,6 +819,34 @@ static void sun6i_dsi_encoder_disable(struct 
>> drm_encoder *encoder)
>>  regulator_disable(dsi->regulator);
>>  }
>>
>> +static bool sun6i_dsi_encoder_mode_fixup(
>> +   struct drm_encoder *encoder,
>> +   const struct drm_display_mode *mode,
>> +   struct drm_display_mode *adjusted_mode)
>
> So, mode_fixup is kind of deprecated in favour of atomic_check

I see. Thanks for pointing that out.

>> +{
>> +if (encoder->encoder_type == DRM_MODE_ENCODER_DSI) {
>> +/*
>> + * For DSI the PLL rate has to respect the bits per pixel and
>> + * number of lanes.
>> + *
>> + * According to the BSP code:
>> + * PLL rate = DOTCLOCK * bpp / lanes
>> + *
>> + * Therefore, the clock has to be adjusted in order to set the
>> + * correct PLL rate when actually setting the clock.
>> + */
>> +struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
>> +struct mipi_dsi_device *device = dsi->device;
>> +u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
>> +u8 lanes = device->lanes;
>> +
>> +adjusted_mode->crtc_clock = mode->crtc_clock
>> + * bpp / (lanes * SUN6I_DSI_TCON_DIV);
>
> And that's visible to the userspace, so it's not where we should store
> that value. I guess the best way to do something similar would be to
> store it into crtc_state, and then reuse it there. But it starts to make
> a lot of rather complicated code compared to your previous patch.

Ah, interesting. But I agree, let's stick to the simpler aproach.

Thanks,
  Frank

>
> Maxime
>
> [[End of PGP Signed Part]]

--


Re: [PATCH] drm/sun4i: uncouple DSI dotclock divider from TCON0_DCLK_REG

2023-03-28 Thread Frank Oltmanns


Hi,

On 2023-03-27 at 22:20:45 +0200, Maxime Ripard  wrote:
> Hi,
>
> On Sat, Mar 25, 2023 at 12:40:04PM +0100, Frank Oltmanns wrote:
[...]
>> Actually, I had the following third patch prepared that adjusted the 
>> dotclock rate so that the
>> required PLL rate is set. But again, this seems very indirect, so that’s why 
>> I refrained from
>> submitting it and I submitted the linked patch above instead.
>>
>> Anyway, here is the third proposal:
>>
>> — a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
>> +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
>> @@ -819,6 +819,34 @@ static void sun6i_dsi_encoder_disable(struct 
>> drm_encoder *encoder)
>>  regulator_disable(dsi->regulator);
>>  }
>>
>> +static bool sun6i_dsi_encoder_mode_fixup(
>> ⁃ struct drm_encoder *encoder,
>> ⁃ const struct drm_display_mode *mode,
>> ⁃ struct drm_display_mode *adjusted_mode)
>> +{
>> ⁃ if (encoder->encoder_type == DRM_MODE_ENCODER_DSI) {
>> ⁃ /*
>> ⁃ * For DSI the PLL rate has to respect the bits per pixel and
>> ⁃ * number of lanes.
>> ⁃ *
>> ⁃ * According to the BSP code:
>> ⁃ * PLL rate = DOTCLOCK * bpp / lanes
>> ⁃ *
>> ⁃ * Therefore, the clock has to be adjusted in order to set the
>> ⁃ * correct PLL rate when actually setting the clock.
>> ⁃ */
>> ⁃ struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
>> ⁃ struct mipi_dsi_device *device = dsi->device;
>> ⁃ u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
>> ⁃ u8 lanes = device->lanes;
>> ⁃
>>
>> ⁃ adjusted_mode->crtc_clock = mode->crtc_clock
>> ⁃ * bpp / (lanes * SUN6I_DSI_TCON_DIV);
>> ⁃ }
>> ⁃
>>
>> ⁃ return true;
>> +}
>> ⁃ static int sun6i_dsi_get_modes(struct drm_connector *connector)
>>   {
>>   struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector);
>> @@ -851,6 +879,7 @@ static const struct drm_connector_funcs 
>> sun6i_dsi_connector_funcs = {
>>  static const struct drm_encoder_helper_funcs sun6i_dsi_enc_helper_funcs = {
>>  .disable= sun6i_dsi_encoder_disable,
>>  .enable = sun6i_dsi_encoder_enable,
>> ⁃ .mode_fixup = sun6i_dsi_encoder_mode_fixup,
>>   };
>
> It's not clear to me what this patch is supposed to be doing, there's no 
> mode_fixup implementation
> upstream?
>

Sorry, my mail client tried some fancy formatting. :(

This is the patch again.

--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -819,6 +819,34 @@ static void sun6i_dsi_encoder_disable(struct drm_encoder 
*encoder)
regulator_disable(dsi->regulator);
 }

+static bool sun6i_dsi_encoder_mode_fixup(
+  struct drm_encoder *encoder,
+  const struct drm_display_mode *mode,
+  struct drm_display_mode *adjusted_mode)
+{
+   if (encoder->encoder_type == DRM_MODE_ENCODER_DSI) {
+   /*
+* For DSI the PLL rate has to respect the bits per pixel and
+* number of lanes.
+*
+* According to the BSP code:
+* PLL rate = DOTCLOCK * bpp / lanes
+*
+* Therefore, the clock has to be adjusted in order to set the
+* correct PLL rate when actually setting the clock.
+*/
+   struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
+   struct mipi_dsi_device *device = dsi->device;
+   u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
+   u8 lanes = device->lanes;
+
+   adjusted_mode->crtc_clock = mode->crtc_clock
+* bpp / (lanes * SUN6I_DSI_TCON_DIV);
+   }
+
+   return true;
+}
+
 static int sun6i_dsi_get_modes(struct drm_connector *connector)
 {
struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector);
@@ -851,6 +879,7 @@ static const struct drm_connector_funcs 
sun6i_dsi_connector_funcs = {
 static const struct drm_encoder_helper_funcs sun6i_dsi_enc_helper_funcs = {
.disable= sun6i_dsi_encoder_disable,
.enable = sun6i_dsi_encoder_enable,
+   .mode_fixup = sun6i_dsi_encoder_mode_fixup,
 };

 static u32 sun6i_dsi_dcs_build_pkt_hdr(struct sun6i_dsi *dsi,


I still like the original patch better, but I'd be happy to submit this
as a proper patch, if this is more to your liking.

Thanks,
  Frank


> Maxime
>
--


Re: [PATCH] drm/sun4i: uncouple DSI dotclock divider from TCON0_DCLK_REG

2023-03-25 Thread Frank Oltmanns
Hi,

On 2023-03-20 at 17:16:36 +0100, Roman Beranek  wrote:
> In the case of DSI output, the value of SUN4I_TCON0_DCLK_DIV (4) does
> not represent the actual dotclock divider, PLL_MIPI instead runs at
> (bpp / lanes )-multiple [1] of the dotclock. [2] Setting 4 as dotclock
> divder thus leads to reduced frame rate, specifically by 1/3 on 4-lane
> panels, and by 2/3 on 2-lane panels respectively.
>
> As sun4i_dotclock driver stores its calculated divider directly in
> the register, conditional handling of the DSI output scenario is needed.
> Instead of reading the divider from SUN4I_TCON0_DCLK_REG, retrieve
> the value from tcon->dclk_min_div.
>
> [1] bits per pixel / number of DSI lanes
> [2] 
> 
>
> Signed-off-by: Roman Beranek 
> —
>  drivers/gpu/drm/sun4i/sun4i_dotclock.c | 6 +-
>  drivers/gpu/drm/sun4i/sun4i_tcon.c | 5 +++–
>  drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
>  3 files changed, 9 insertions(+), 3 deletions(-)
>
> diff –git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c 
> b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> index 417ade3d2565..26fa99aff590 100644
> — a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
> @@ -11,6 +11,7 @@
>
>  #include “sun4i_tcon.h”
>  #include “sun4i_dotclock.h”
> +#include “sun6i_mipi_dsi.h”
>
>  struct sun4i_dclk {
>   struct clk_hw  hw;
> @@ -56,6 +57,9 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw 
> *hw,
>   struct sun4i_dclk *dclk = hw_to_dclk(hw);
>   u32 val;
>
> + if (dclk->tcon->is_dsi)
> + return parent_rate / dclk->tcon->dclk_min_div;
> +
>   regmap_read(dclk->regmap, SUN4I_TCON0_DCLK_REG, );
>
>   val >>= SUN4I_TCON0_DCLK_DIV_SHIFT;
> @@ -116,7 +120,7 @@ static int sun4i_dclk_set_rate(struct clk_hw *hw, 
> unsigned long rate,
>  unsigned long parent_rate)
>  {
>   struct sun4i_dclk *dclk = hw_to_dclk(hw);
> - u8 div = parent_rate / rate;
> + u8 div = dclk->tcon->is_dsi ? SUN6I_DSI_TCON_DIV : parent_rate / rate;
>
>   return regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG,
> GENMASK(6, 0), div);
> diff –git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
> b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> index 523a6d787921..7f5d3c135058 100644
> — a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> @@ -367,8 +367,9 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon 
> *tcon,
>   u32 block_space, start_delay;
>   u32 tcon_div;
>
> - tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
> - tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
> + tcon->is_dsi = true;
> + tcon->dclk_min_div = bpp / lanes;
> + tcon->dclk_max_div = bpp / lanes;

Claiming to set the divider to a different value (bpp / lanes) than what we’re 
actually using in the end (SUN6I_DSIO_TCON_DIV) is somehow bugging me. I feel 
like the proposal that I submitted is more direct:


Actually, I had the following third patch prepared that adjusted the dotclock 
rate so that the required PLL rate is set. But again, this seems very indirect, 
so that’s why I refrained from submitting it and I submitted the linked patch 
above instead.

Anyway, here is the third proposal:

— a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -819,6 +819,34 @@ static void sun6i_dsi_encoder_disable(struct drm_encoder 
*encoder)
regulator_disable(dsi->regulator);
 }

+static bool sun6i_dsi_encoder_mode_fixup(
⁃ struct drm_encoder *encoder,
⁃ const struct drm_display_mode *mode,
⁃ struct drm_display_mode *adjusted_mode)
+{
⁃ if (encoder->encoder_type == DRM_MODE_ENCODER_DSI) {
⁃ /*
⁃ * For DSI the PLL rate has to respect the bits per pixel and
⁃ * number of lanes.
⁃ *
⁃ * According to the BSP code:
⁃ * PLL rate = DOTCLOCK * bpp / lanes
⁃ *
⁃ * Therefore, the clock has to be adjusted in order to set the
⁃ * correct PLL rate when actually setting the clock.
⁃ */
⁃ struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
⁃ struct mipi_dsi_device *device = dsi->device;
⁃ u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
⁃ u8 lanes = device->lanes;
⁃ 

⁃ adjusted_mode->crtc_clock = mode->crtc_clock
⁃ * bpp / (lanes * SUN6I_DSI_TCON_DIV);
⁃ }
⁃ 

⁃ return true;
+}
⁃ static int sun6i_dsi_get_modes(struct drm_connector *connector)
  {
  struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector);
@@ -851,6 +879,7 @@ static const struct drm_connector_funcs 
sun6i_dsi_connector_funcs = {
 static const struct drm_encoder_helper_funcs sun6i_dsi_enc_helper_funcs = {
.disable= sun6i_dsi_encoder_disable,
.enable = sun6i_dsi_encoder_enable,
⁃ .mode_fixup = sun6i_dsi_encoder_mode_fixup,
  };

  static u32 

Re: [PATCH 1/1] drm/sun4i: tcon: Fix setting PLL rate when using DSI

2023-03-21 Thread Frank Oltmanns
Hi Maxime,

On 2023-03-21 at 15:57:39 +0100, Maxime Ripard  wrote:
> Hi,
>
> On Sun, Mar 19, 2023 at 05:07:04PM +0100, Frank Oltmanns wrote:
>> Set the required PLL rate by adjusting the dotclock rate when calling
>> clk_set_rate() when using DSI.
>>
>> According to the Allwinners A64’s BSP code, a TCON divider of 4 has to
>> be used and the PLL rate needs to be set to the following frequency when
>> using DSI:
>> PLL rate = DCLK * bpp / lanes
>>
>> After this change the common mode set function would only contain
>> setting the resolution. Therefore, dissolve the function and transfer
>> the functionality to the individual mode set functions.
>>
>> Signed-off-by: Frank Oltmanns 
>
> This is similar to:
> <https://lore.kernel.org/all/20230320161636.24411-1-romanbera...@icloud.com/>
>
> What’s the story there?

Sorry, as Roman wrote in the other thread, I submitted the patch after not 
hearing back from him for a week. My apologies, I wasn’t patient enough. So now 
there are two submissions to consider. FWIW, I think this patch is a bit more 
straightforward than the other one.

Best regards,
  Frank

> Maxime
>


[PATCH 1/1] drm/sun4i: tcon: Fix setting PLL rate when using DSI

2023-03-19 Thread Frank Oltmanns
Set the required PLL rate by adjusting the dotclock rate when calling
clk_set_rate() when using DSI.

According to the Allwinners A64's BSP code, a TCON divider of 4 has to
be used and the PLL rate needs to be set to the following frequency when
using DSI:
PLL rate = DCLK * bpp / lanes

After this change the common mode set function would only contain
setting the resolution. Therefore, dissolve the function and transfer
the functionality to the individual mode set functions.

Signed-off-by: Frank Oltmanns 
---
 drivers/gpu/drm/sun4i/sun4i_tcon.c | 46 --
 1 file changed, 31 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c 
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 62b3538bd81f..02d52be42f06 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -323,18 +323,6 @@ static int sun4i_tcon_get_clk_delay(const struct 
drm_display_mode *mode,
return delay;
 }
 
-static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
-   const struct drm_display_mode *mode)
-{
-   /* Configure the dot clock */
-   clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
-
-   /* Set the resolution */
-   regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
-SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
-SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
-}
-
 static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
   const struct drm_connector 
*connector)
 {
@@ -399,10 +387,24 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon 
*tcon,
u32 block_space, start_delay;
u32 tcon_div;
 
+   /*
+* Configure the dot clock:
+* For DSI the PLL rate has to respect the bits per pixel and
+* number of lanes.
+*
+* According to the BSP code:
+* TCON divider = 4
+* PLL rate = DCLK * bpp / lanes
+*/
tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
+   clk_set_rate(tcon->dclk, mode->crtc_clock * 1000
+* bpp / (lanes * SUN6I_DSI_TCON_DIV));
 
-   sun4i_tcon0_mode_set_common(tcon, mode);
+   /* Set the resolution */
+   regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
 
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -470,7 +472,14 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon 
*tcon,
 
tcon->dclk_min_div = 7;
tcon->dclk_max_div = 7;
-   sun4i_tcon0_mode_set_common(tcon, mode);
+
+   /* Configure the dot clock */
+   clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+   /* Set the resolution */
+   regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
 
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -549,7 +558,14 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon 
*tcon,
 
tcon->dclk_min_div = tcon->quirks->dclk_min_div;
tcon->dclk_max_div = 127;
-   sun4i_tcon0_mode_set_common(tcon, mode);
+
+   /* Configure the dot clock */
+   clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+   /* Set the resolution */
+   regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
 
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, connector);
-- 
2.39.2



[PATCH 0/1] Fixing the DSI dot clock on Allwinner

2023-03-19 Thread Frank Oltmanns
According to the Allwinner A64's BSP code, the PLL rate needs to be set to the 
following frequency when using DSI:
PLL rate = DCLK * bpp / lanes

Source: [1]
The relevant lines for DSI (ommisions and comments mine):
dclk_rate = lcdp->panel_info.lcd_dclk_freq * 100;
lcd_rate = dclk_rate * clk_info.dsi_div; // dsi_div = bpp/lane
pll_rate = lcd_rate * clk_info.lcd_div;  // lcd_div = 1 --> pll_rate = lcd_rate
dsi_rate = pll_rate / clk_info.dsi_div   // --> dsi_rate = dclk_rate
clk_set_rate(lcdp->clk_parent, pll_rate);

This was already discussed by Maxime, Jagan and Michael in the past in the 
thread following this message: [2]. Unfortunately, there never was a conclusion 
in the form of code.

The attached patch is a slight variation of a patch that is part of megi's 
kernel branch that many PinePhone distributions (e.g. postmarketOS) use [3]. It 
calculates the TCON clock rate by using the formula above and dividing it by 
SUN6I_DSI_TCON_DIV, in order to force the parent clock to be set to the correct 
rate.

If I read the thread following this message [2] correctly, this was also what 
Maxime had in mind.

Please also note that, unfortunately, I only have a single board and panel 
(namely the PinePhone) to test this on.

Thanks,
  Frank

[1] 
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L781
[2] 
https://lore.kernel.org/lkml/camty3zash2iz+jeqte3d58axfguhmsg9yoo56zhhoee4c4y...@mail.gmail.com/
[3] 
https://github.com/megous/linux/commit/eb5f28fb58727f4a6546f211486aad0d19cdea3f

Frank Oltmanns (1):
  drm/sun4i: tcon: Fix setting PLL rate when using DSI

 drivers/gpu/drm/sun4i/sun4i_tcon.c | 46 --
 1 file changed, 31 insertions(+), 15 deletions(-)

-- 
2.39.2



Re: [PATCH 1/1] drm/panel: st7703: Fix vertical refresh rate of XBD599

2023-02-26 Thread Frank Oltmanns
Hi Ondřej,
hi Guido,

On 2023-02-19 at 13:35:42 +0100, Ondřej Jirman  wrote:

> On Sun, Feb 19, 2023 at 12:45:53PM +0100, Frank Oltmanns wrote:
>> Fix the XBD599 panel’s slight visual stutter by correcting the pixel
>> clock speed so that the panel’s 60Hz vertical refresh rate is met.
>>
>> Set the clock speed using the underlying formula instead of a magic
>> number. To have a consistent procedure for both panels, set the JH057N
>> panel’s clock also as a formula.
>>
>> —
>>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 4 ++–
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff –git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
>> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> index 6747ca237ced..cd7d631f7573 100644
>> — a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> @@ -139,7 +139,7 @@ static const struct drm_display_mode jh057n00900_mode = {
>>  .vsync_start = 1440 + 20,
>>  .vsync_end   = 1440 + 20 + 4,
>>  .vtotal  = 1440 + 20 + 4 + 12,
>> -.clock   = 75276,
>> +.clock   = (720 + 90 + 20 + 20) * (1440 + 20 + 4 + 12) * 60 / 1000,
>>  .flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
>>  .width_mm= 65,
>>  .height_mm   = 130,
>> @@ -324,7 +324,7 @@ static const struct drm_display_mode xbd599_mode = {
>>  .vsync_start = 1440 + 18,
>>  .vsync_end   = 1440 + 18 + 10,
>>  .vtotal  = 1440 + 18 + 10 + 17,
>> -.clock   = 69000,
>> +.clock   = (720 + 40 + 40 + 40) * (1440 + 18 + 10 + 17) * 60 / 1000,
>
> As for pinephone, A64 can’t produce 74.844 MHz precisely, so this will not 
> work.
>
> Better fix is to alter the mode so that clock can be something the only SoC 
> this
> panel is used with can actually produce.
>
> See eg. 
> <https://github.com/megous/linux/commit/dd070679d717e7f34af7558563698240a43981a6>
> which is tested to actually produce 60Hz by measuring the vsync events against
> the CPU timer.

I did some testing using a 60fps video I produced using the following command:
ffmpeg -f lavfi -i testsrc=duration=10:size=80x50:rate=60 -vf 
“drawtext=text=%{n}:fontsize=36:r=60:x=(w-tw)/2: 
y=h-(1*lh):fontcolor=white:box=1:boxcolor=0x0099” test_80x50.mp4

This 10-second video shows an increasing number on every frame, which makes it 
easy to spot dropped frames by recording the playback with a camera that can 
record more than 60fps (I used a 240fps camera).

When playing back that video with your current drm-6.2 branch I get a steady 
60fps. But applying either your or my patch to mainline, only helps very 
little. Frames are being skipped more often than not in both cases.

Therefore, I need to investigate more and retract the patch for now.

The other two patches I sent earlier, however, are far more important for 
making the pinephone usable on mainline.

Best regards,
  Frank

>
> Your patch will not produce the intended effect.
>
> kind regards,
>   o.
>
>>  .flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
>>  .width_mm= 68,
>>  .height_mm   = 136,
>> –
>> 2.39.1
>>


Re: [PATCH 1/1] drm/panel: st7703: Fix vertical refresh rate of XBD599

2023-02-20 Thread Frank Oltmanns
Hi Ondřej,
hi all,

Ondřej Jirman  writes:
> On Sun, Feb 19, 2023 at 12:45:53PM +0100, Frank Oltmanns wrote:
>> Fix the XBD599 panel’s slight visual stutter by correcting the pixel
>> clock speed so that the panel’s 60Hz vertical refresh rate is met.
>>
>> Set the clock speed using the underlying formula instead of a magic
>> number. To have a consistent procedure for both panels, set the JH057N
>> panel’s clock also as a formula.
>>
>> —
>>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 4 ++–
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff –git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
>> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> index 6747ca237ced..cd7d631f7573 100644
>> — a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> @@ -139,7 +139,7 @@ static const struct drm_display_mode jh057n00900_mode = {
>>  .vsync_start = 1440 + 20,
>>  .vsync_end   = 1440 + 20 + 4,
>>  .vtotal  = 1440 + 20 + 4 + 12,
>> -.clock   = 75276,
>> +.clock   = (720 + 90 + 20 + 20) * (1440 + 20 + 4 + 12) * 60 / 1000,
>>  .flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
>>  .width_mm= 65,
>>  .height_mm   = 130,
>> @@ -324,7 +324,7 @@ static const struct drm_display_mode xbd599_mode = {
>>  .vsync_start = 1440 + 18,
>>  .vsync_end   = 1440 + 18 + 10,
>>  .vtotal  = 1440 + 18 + 10 + 17,
>> -.clock   = 69000,
>> +.clock   = (720 + 40 + 40 + 40) * (1440 + 18 + 10 + 17) * 60 / 1000,
>
> As for pinephone, A64 can’t produce 74.844 MHz precisely, so this will not 
> work.
>
> Better fix is to alter the mode so that clock can be something the only SoC 
> this
> panel is used with can actually produce.
>
> See eg. 
> <https://github.com/megous/linux/commit/dd070679d717e7f34af7558563698240a43981a6>
> which is tested to actually produce 60Hz by measuring the vsync events against
> the CPU timer.
>
> Your patch will not produce the intended effect.
>
> kind regards,
>   o.
>

The TL;DR of my upcoming musings are: Thank you very much for your feedback! Any
recommendations for an informative read about the topic that you or anybody else
has, is greatly appreciated.

How did you measure the vsync events? Were you using vblank interrupts [1]?

I have to admit that I tested only visually and couldn’t spot a difference
between your patch and mine. I’ll need to put more thinking into this, and maybe
you or anyone reading this can help me with that.

My interpretation of the `struct drm_display_mode` documentation [2] was, that
these are logical dimensions/clocks that somewhere down the stack are converted
to their physical/hardware representation.

But now I’ve read the description of the struct’s “crtc_clock” member more
carefully. It says:
“Actual pixel or dot clock in the hardware. This differs from the
logical @clock when e.g. using interlacing, double-clocking, stereo
modes or other fancy stuff that changes the timings and signals
actually sent over the wire.”

So, can I say that if we don’t use “interlacing, double-clocking, stereo modes
or other fancy stuff” that `crtc_clock` will be equal to `clock` and therefore
we have to choose `clock` according to the SoC’s capabilities?

Also, I haven’t found a source about which values to use for the front and back
porch part of the panel and why can you just “arbitrarily” change those. My
assumption is, that those are just extra pixels we can add to make the
dimensions match the ratio of clock and vertical refresh rate. At least that
seems to be, what you did in your patch. But again, no source to back my
assumption about the range the porches can have.

I’ve put the following docs on my “to read and understand” list:
• Allwinner A64 User Manual (to learn more about the SoC’s TCON0 and what
  clock’s the SoC can produce)
• drm-internals.rst
• “Rendering PinePhone’s display” [3], to learn why it produces 69 MHz.
• Your commit message for the PinePhone Pro panel [4] (found on your blog:
  <https://xnux.eu/log/>)

Is there anything else I should add?

Thank you again and best regards,
  Frank

[1] 
<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_vblank.c>
[2] 
<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/drm/drm_modes.h#n198>
[3] <https://lupyuen.github.io/articles/de>
[4] 
<https://github.com/megous/linux/commit/a173b114c9323c718530280b3a918d0925edaa6a>

>>  .flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
>>  .width_mm= 68,
>>  .height_mm   = 136,
>> –
>> 2.39.1
>>


[PATCH 1/1] drm/panel: st7703: Fix vertical refresh rate of XBD599

2023-02-19 Thread Frank Oltmanns
Fix the XBD599 panel's slight visual stutter by correcting the pixel
clock speed so that the panel's 60Hz vertical refresh rate is met.

Set the clock speed using the underlying formula instead of a magic
number. To have a consistent procedure for both panels, set the JH057N
panel's clock also as a formula.
---
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 6747ca237ced..cd7d631f7573 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -139,7 +139,7 @@ static const struct drm_display_mode jh057n00900_mode = {
.vsync_start = 1440 + 20,
.vsync_end   = 1440 + 20 + 4,
.vtotal  = 1440 + 20 + 4 + 12,
-   .clock   = 75276,
+   .clock   = (720 + 90 + 20 + 20) * (1440 + 20 + 4 + 12) * 60 / 1000,
.flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
.width_mm= 65,
.height_mm   = 130,
@@ -324,7 +324,7 @@ static const struct drm_display_mode xbd599_mode = {
.vsync_start = 1440 + 18,
.vsync_end   = 1440 + 18 + 10,
.vtotal  = 1440 + 18 + 10 + 17,
-   .clock   = 69000,
+   .clock   = (720 + 40 + 40 + 40) * (1440 + 18 + 10 + 17) * 60 / 1000,
.flags   = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
.width_mm= 68,
.height_mm   = 136,
-- 
2.39.1



[PATCH 0/1] drm/panel: st7703: Fix vertical refresh rate of XBD599

2023-02-19 Thread Frank Oltmanns
Currently, the XBD599 panel has a pixel clock rate that results in a
vertical refresh rate of ~55.3 Hz. This causes a slight visual
stuttering, for example on the PinePhone.

To address this, I adjusted the pixel clock rate to 74844 kHz. Instead
of using this hard coded value, I inserted the formula. This approach is
already in use by:
panel-jdi-fhd-r63452.c
panel-samsung-s6e88a0-ams452ef01.c
panel-asus-z00t-tm5p5-n35596.c
panel-ebbg-ft8719.c
panel-visionox-vtdr6130.c
panel-sony-tulip-truly-nt35521.c
panel-sharp-ls060t1sx01.c
panel-samsung-sofef00.c

To have a consistent procedure within panel-sitronix-st7703.c, I also
used the formula for the JH057N panel's clock. The value for JH057N was
already correct, so this change is purely cosmetic.

I do realize that I submitted three separate patches for the ST7703
within just a few days ([1], [2]). Should I re-submit all three patches
as a single patch set? These are my first contributions to the Linux
kernel, therefore, I kindly ask for forgiveness regarding any breach of
etiquette.

Thanks,
  Frank

[1] https://lore.kernel.org/all/20230211171748.36692-1-fr...@oltmanns.dev/
[2] https://lore.kernel.org/all/20230213123238.76889-1-fr...@oltmanns.dev/

Frank Oltmanns (1):
  drm/panel: st7703: Fix vertical refresh rate of XBD599

 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

-- 
2.39.1



[PATCH v2 1/1] drm/panel: st7703: Fix timings when entering/exiting sleep

2023-02-13 Thread Frank Oltmanns
Fix flickering of the pinephone's XDB599 panel that happens after
resume.

Extend the delay after issuing the command to exit sleep mode from 60 to
120 msec as per the controller's specification.

Introduce a 120 msec delay after issuing the command to enter sleep
mode. This is needed in order for the controller to reliably finalize
the sleep in sequence before switching of power supply.

In contrast to the JH057N panel, the XBD599 panel does not require a 20
msec delay after initialization and exiting sleep mode. Therefore, move
the delay into the already existing device specific initialization
function.

The XDB599 does not require a 20 msec delay between the SETBGP and
SETVCOM commands. Therefore, remove the delay from the device specific
initialization function.

Signed-off-by: Frank Oltmanns 
Cc: Ondrej Jirman 
Reported-by: Samuel Holland 
---
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 6747ca237ced..c49f4ef883fc 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -126,6 +126,7 @@ static int jh057n_init_sequence(struct st7703 *ctx)
   0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 
0x41,
   0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 
0x10,
   0x11, 0x18);
+   msleep(20);
 
return 0;
 }
@@ -273,7 +274,6 @@ static int xbd599_init_sequence(struct st7703 *ctx)
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
   0x07, /* VREF_SEL = 4.2V */
   0x07  /* NVREF_SEL = 4.2V */);
-   msleep(20);
 
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
   0x2C, /* VCOMDC_F = -0.67V */
@@ -350,16 +350,14 @@ static int st7703_enable(struct drm_panel *panel)
return ret;
}
 
-   msleep(20);
-
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret < 0) {
dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
return ret;
}
 
-   /* Panel is operational 120 msec after reset */
-   msleep(60);
+   /* It takes the controller 120 msec to wake up after sleep. */
+   msleep(120);
 
ret = mipi_dsi_dcs_set_display_on(dsi);
if (ret)
@@ -384,6 +382,9 @@ static int st7703_disable(struct drm_panel *panel)
if (ret < 0)
dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
 
+   /* It takes the controller 120 msec to enter sleep mode. */
+   msleep(120);
+
return 0;
 }
 
-- 
2.39.1



[PATCH v2 0/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-13 Thread Frank Oltmanns
This is V2 of a patch that fixes flickering after resume from sleep on
panel xingbangda,xbd599 (e.g. used in PinePhone).

Please see here for the discussion around V1:
https://lore.kernel.org/all/20230212120830.46880-1-fr...@oltmanns.dev/T/

V1 introduced panel specific functions for the JH057N and XBD599 panels.
Ondřej Dirman deemed this unneccesary and finally convinced me.

Therefore, V2 is a much simpler patch.

The patch is just a refactoring of Ondřej's original patch, that is
already used today by PinePhone distributions like PostmarketOS.

This patch has not been tested with the JH057N panel used in the Librem
5 devkit. I hereby kindly ask for Librem (i.e. Guido) to test this.

The patch is based on drm-next.

Ondřej, since this is just a very minor refactoring of your work, I
would gladly put you as the author, if you wish so.

Thanks,
  Frank

Frank Oltmanns (1):
  drm/panel: st7703: Fix timings when entering/exiting sleep

 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

-- 
2.39.1



Re: [PATCH 1/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-13 Thread Frank Oltmanns
Hi Ondřej,

ok, now I get it. Thank you very much for your thorough explanation. It really 
appreciate it!

Ondřej Jirman  writes:
> On Sun, Feb 12, 2023 at 06:52:05PM +0100, Frank Oltmanns wrote:
>> Ondřej Jirman  writes:
>>
>> > On Sun, Feb 12, 2023 at 01:08:29PM +0100, Frank Oltmanns wrote:
>> Please let me point you to the discussion you and Guido had ~2.5 years ago:
>> <https://lore.kernel.org/all/20200729154809.ga435...@bogon.m.sigxcpu.org/>
>
> Guido references some unspecified datasheet. We only have a st7703 datasheet
> to go by, and that requires 120ms and is relevant for both panels.
>
> Also the patch that Guido tested removed a few 20ms delays from the init
> sequence for the librem panel. Maybe that broke the init for librem panel and
> not the extra few ms after sleep out that the patch added.

Ok, I see. You removed the 20 msec delay after the panel specific
initialization sequence and before issuing SLPOUT in your original
patch.

>> I read that screenshot, that we need a 120 msec wait after sleep OUT before 
>> we
>> can send another sleep in (see the “Restriction” row). I can’t seem to find
>> the reference to the 120 msec delay after the sleep IN command. I read the
>> flow chart at the bottom as informational about the duration of the whole
>> procedure that happens after issuing the sleep in command. The only
>> restriction is that we can’t issue any command for 5 msec after sleep in was
>> issued.
>
> It’s at the bottom, sleep in takes 120ms to execute. Part of the execution is
> draining the charge from the panel. You can’t shutdown power supplies before
> sleep in completes, so you need the delay after sleep in and before regulator
> powerdown, otherwise the flow chart will not have the time to execute 
> properly,
> and the panel will be left in a bad state.

Ok, that makes sense.

>> > So there needs to be 120ms delay after sleep in and after sleep out,
>> > regardless of which panel is driven by this controller, to ensure the panel
>> > stays operational even when the user is quickly switching it on/off 
>> > repeatedly.
>> >
>> > So I don’t think you should be doing panel specific quirks here.
>>
>> Maybe. I can only say that without the timings in this patch (i.e. the ones
>> from your kernel branch) the display on my pinephone is flickering after the
>> first (and every subsequent) time the display is turned off. With your new
>> timing everything works great on the pinephone. Guido states that the timings
>> in your original patch (i.e. the XDB599 specific timings in this patch) the
>> Librem 5 devkit panel doesn’t work.
>
> Adding extra delays after sleep in/before sleep out should not break Librem
> panel. Previous patches also changed the powerup sequence to hold the reset
> before powerup of the power supplies, and rearranged other delays.
>
> They were made before the problem with the panel discharge was properly
> understood.
>
> I suggest just going a bit more conservatively than what I did with my 
> original
> patch series, and just make sure there are 120ms delays after sleep out and
> before sleep in + extra delay after regulator powerup and don’t do anything 
> that
> may decrease delays for librem devkit panel. Just adding delays should not 
> break
> anything, sine the only timings that have maximums specified in the datasheet
> are for power rail voltage rampup times.

I agree, that the one 20 msec delay that you removed, is probably what
broke the JH057N panel and not the extra delays. Unfortunately, there is
no way for me to verify that statement, because I don’t have access to
Librem’s devkit.

So, I can only offer to prepare a V2 and kindly ask Guido to test it. V2
will be much simpler:
• Increase the delay after issuing sleep out from 60 to 120 msec for all
  panels.
• Add a delay of 120 msec after issuing sleep in for all panels.
• Move the 20 msec delay between initialization and sleep out into the
  initialization function for the JH057N panel (like in this version of
  the patch).
• Remove a 20 msec delay from the initialization function of the XBD599
  panel (like in this version of the patch).

> (Also some timings during powerup/down may appear to have different needs on
> Librem devkit simply because panel driver is not really affecting the
> regulators, because they are already powered up due to being referenced by 
> other
> drivers/devices, because they are shared. This is a bit tricky to test
> properly. It’s necessary to test both power sequence cases, where the 
> regulators
> are known to be off, and when they are already referenced by other drivers.
> On librem devkit, one of them seems to be shared by audio codec and 
> touchscree

Re: [PATCH 1/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Frank Oltmanns
Hi Ondřej,
hi Guido,

Ondřej, thank you very much for your feedback!

I have a couple of questions.

Ondřej Jirman  writes:

> On Sun, Feb 12, 2023 at 01:08:29PM +0100, Frank Oltmanns wrote:
>> In contrast to the JH057N panel, the XBD599 panel does not require a 20
>> msec delay after initialization and exiting sleep mode. Therefore, move
>> the delay into the already existing device specific initialization
>> function.
>>
>> Also, the timing contraints after entering and exiting sleep mode differ
>> between the two panels:
>>  - The JH057N requires a shorter delay than the XDB599 after waking up
>>from sleep mode and before enabling the display.
>>  - The XDB599 requires a delay in order to drain the display of charge,
>>which is not required on the JH057N.
>
> There’s no difference between the panels here. It’s a controller specified
> requirement.
>
> <https://megous.com/dl/tmp/1ef533ed8a7ce841.png>
>
> 60ms used in the driver between sleep out and display on is just
> incorrect from the datasheet perspective.

Please let me point you to the discussion you and Guido had ~2.5 years ago:
<https://lore.kernel.org/all/20200729154809.ga435...@bogon.m.sigxcpu.org/>

What resonates most with me is the following statement from Guido:
> > > > Given the amount of ST7703 look alikes i don’t think you can go by the
> > > > datasheet and hope not to break other panels. The current sleeps cater
> > > > for the rocktech panel (which suffered from similar issues you describe
> > > > when we took other parameters) so you need to make those panel specific.

My takeaway is, that neither panel needed the actual 120 msec wait time. But 
Guido was reluctant to change the timing for the Librem 5 devkit panel. That’s 
why I went for the panel specific implementation.

Of course, we can revisit that decision. Since I don’t have the Librem 5 
devkit, I have to kindly ask Guido for advise.

> You also have to wait 120ms after sleep in (or HW reset) and before shutting
> down the panel. If you don’t, after a bunch of cycles of this incorrect
> power up/down sequence the panel will start blinking weirdly, and the 
> incorrect
> power up/down sequence without delays will not be able to recover it. You’ll
> have to let the panel sit for 5-10 minutes powered off before it starts to
> behave itself again.
>
> The documentation for sleep in specifies what’s happening during sleep in,
> and why this delay is necessary after sleep in:
>
> <https://megous.com/dl/tmp/2284b9d0f506b9b8.png>

I read that screenshot, that we need a 120 msec wait after sleep OUT before we 
can send another sleep in (see the “Restriction” row). I can’t seem to find the 
reference to the 120 msec delay after the sleep IN command. I read the flow 
chart at the bottom as informational about the duration of the whole procedure 
that happens after issuing the sleep in command. The only restriction is that 
we can’t issue any command for 5 msec after sleep in was issued.

> So there needs to be 120ms delay after sleep in and after sleep out,
> regardless of which panel is driven by this controller, to ensure the panel
> stays operational even when the user is quickly switching it on/off 
> repeatedly.
>
> So I don’t think you should be doing panel specific quirks here.

Maybe. I can only say that without the timings in this patch (i.e. the ones 
from your kernel branch) the display on my pinephone is flickering after the 
first (and every subsequent) time the display is turned off. With your new 
timing everything works great on the pinephone. Guido states that the timings 
in your original patch (i.e. the XDB599 specific timings in this patch) the 
Librem 5 devkit panel doesn’t work.

Do you have a proposal how to proceed without implementing panel specific 
timings?

Thanks,
  Frank

>
> regards,
>   o.
>
>> Therefore, introduce panel specific functions for the delays.
>>
>> The XDB599 does not require a 20 msec delay between the SETBGP and
>> SETVCOM commands. Therefore, remove the delay from the device specific
>> initialization function.
>>
>> Signed-off-by: Frank Oltmanns 
>> Cc: Ondrej Jirman 
>> Reported-by: Samuel Holland 
>> —
>>  drivers/gpu/drm/panel/panel-sitronix-st7703.c | 40 —
>>  1 file changed, 35 insertions(+), 5 deletions(-)
>>
>> diff –git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
>> b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> index 6747ca237ced..a149341c4a8b 100644
>> — a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
>> @@ -66,6 +66,8 @@ struct st7703_panel_desc {
>>  unsigned long

Re: [PATCH 0/1] drm/panel: st7703: Fix initialization failures on Xingbangda XBD599

2023-02-12 Thread Frank Oltmanns


[PATCH 0/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Frank Oltmanns
This patch fixes flickering after resume from sleep on panel
xingbangda,xbd599 (e.g. used in PinePhone).

It was originally submitted by Ondrej Jirman in July 2020:
https://lore.kernel.org/all/20200716123753.3552425-1-meg...@megous.com/

The original patchset contained two patches. This submission fixes the
patch that broke handling of the JH057N panel of the Purism Librem 5.

In essence, it does not change any behavior towards the JH057N panel,
but only affects the XDB599.

The patch is just a refactoring of Ondřej's original patch, that is
already used today by PinePhone distributions like PostmarketOS.

I was torn between using function pointers and just calling msleep()
with device specific delays. I decided to go with function pointers,
because my understanding is that calling msleep(0), which would be
required for waiting for the JH057N display to discharge, still results
in a delay. The empty function I used has no side effect on that panel.

The patch is based on drm-next.

Ondřej, since this is just a refactoring, I would gladly add your SoB,
if you wish so.

Thanks,
  Frank

Frank Oltmanns (1):
  drm/panel: st7703: Fix resume of XBD599 panel

 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 40 ---
 1 file changed, 35 insertions(+), 5 deletions(-)

-- 
2.39.1



[PATCH 0/1] drm/panel: st7703: Fix initialization failures on Xingbangda XBD599

2023-02-12 Thread Frank Oltmanns
This patch fixes intermittent panel initialization failures and screen
corruption during resume from sleep on panel xingbangda,xbd599 (e.g.
used in PinePhone).

It was originally submitted by Ondrej Jirman in July 2020:
https://lore.kernel.org/all/20200716123753.3552425-1-meg...@megous.com/

The original patchset contained two patches. One of them broke the panel
on the Purism Librem 5.

This is the concluding message from Guido Günther in that thread:
https://lore.kernel.org/all/20200801110409.ga6...@bogon.m.sigxcpu.org/#t

Guido wanted changes to the commit message. I updated it to adress his
requests.

I send this patch in Ondřej's name with his consent.

The patch is based on drm-next.

Please let me know what you think.

Thanks,
  Frank

Ondrej Jirman (1):
  drm/panel: st7703: Pick different reset sequence

 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 25 ++-
 1 file changed, 13 insertions(+), 12 deletions(-)

-- 
2.39.1



[PATCH 1/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Frank Oltmanns
In contrast to the JH057N panel, the XBD599 panel does not require a 20
msec delay after initialization and exiting sleep mode. Therefore, move
the delay into the already existing device specific initialization
function.

Also, the timing contraints after entering and exiting sleep mode differ
between the two panels:
 - The JH057N requires a shorter delay than the XDB599 after waking up
   from sleep mode and before enabling the display.
 - The XDB599 requires a delay in order to drain the display of charge,
   which is not required on the JH057N.

Therefore, introduce panel specific functions for the delays.

The XDB599 does not require a 20 msec delay between the SETBGP and
SETVCOM commands. Therefore, remove the delay from the device specific
initialization function.

Signed-off-by: Frank Oltmanns 
Cc: Ondrej Jirman 
Reported-by: Samuel Holland 
---
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 40 ---
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 6747ca237ced..a149341c4a8b 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -66,6 +66,8 @@ struct st7703_panel_desc {
unsigned long mode_flags;
enum mipi_dsi_pixel_format format;
int (*init_sequence)(struct st7703 *ctx);
+   void (*wait_after_sleep_out)(void);
+   void (*drain_charge)(void);
 };
 
 static inline struct st7703 *panel_to_st7703(struct drm_panel *panel)
@@ -126,10 +128,24 @@ static int jh057n_init_sequence(struct st7703 *ctx)
   0x18, 0x00, 0x09, 0x0E, 0x29, 0x2D, 0x3C, 
0x41,
   0x37, 0x07, 0x0B, 0x0D, 0x10, 0x11, 0x0F, 
0x10,
   0x11, 0x18);
+   msleep(20);
 
return 0;
 }
 
+static void jh057n_wait_after_sleep_out(void)
+{
+   /*
+* Panel is operational 120 msec after reset, i.e. 60 msec after
+* sleep out.
+*/
+   msleep(60);
+}
+
+static void jh057n_drain_charge(void)
+{
+}
+
 static const struct drm_display_mode jh057n00900_mode = {
.hdisplay= 720,
.hsync_start = 720 + 90,
@@ -152,6 +168,8 @@ static const struct st7703_panel_desc 
jh057n00900_panel_desc = {
MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
.format = MIPI_DSI_FMT_RGB888,
.init_sequence = jh057n_init_sequence,
+   .wait_after_sleep_out = jh057n_wait_after_sleep_out,
+   .drain_charge = jh057n_drain_charge,
 };
 
 static int xbd599_init_sequence(struct st7703 *ctx)
@@ -273,7 +291,6 @@ static int xbd599_init_sequence(struct st7703 *ctx)
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETBGP,
   0x07, /* VREF_SEL = 4.2V */
   0x07  /* NVREF_SEL = 4.2V */);
-   msleep(20);
 
mipi_dsi_dcs_write_seq(dsi, ST7703_CMD_SETVCOM,
   0x2C, /* VCOMDC_F = -0.67V */
@@ -315,6 +332,18 @@ static int xbd599_init_sequence(struct st7703 *ctx)
return 0;
 }
 
+static void xbd599_wait_after_sleep_out(void)
+{
+   msleep(120);
+}
+
+static void xbd599_drain_charge(void)
+{
+   /* Drain diplay of charge, to work correctly on next power on. */
+   msleep(120);
+}
+
+
 static const struct drm_display_mode xbd599_mode = {
.hdisplay= 720,
.hsync_start = 720 + 40,
@@ -336,6 +365,8 @@ static const struct st7703_panel_desc xbd599_desc = {
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
.format = MIPI_DSI_FMT_RGB888,
.init_sequence = xbd599_init_sequence,
+   .wait_after_sleep_out = xbd599_wait_after_sleep_out,
+   .drain_charge = xbd599_drain_charge,
 };
 
 static int st7703_enable(struct drm_panel *panel)
@@ -350,16 +381,13 @@ static int st7703_enable(struct drm_panel *panel)
return ret;
}
 
-   msleep(20);
-
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
if (ret < 0) {
dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
return ret;
}
 
-   /* Panel is operational 120 msec after reset */
-   msleep(60);
+   ctx->desc->wait_after_sleep_out();
 
ret = mipi_dsi_dcs_set_display_on(dsi);
if (ret)
@@ -384,6 +412,8 @@ static int st7703_disable(struct drm_panel *panel)
if (ret < 0)
dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
 
+   ctx->desc->drain_charge();
+
return 0;
 }
 
-- 
2.39.1



[PATCH 1/1] drm/panel: st7703: Pick different reset sequence

2023-02-12 Thread Frank Oltmanns
From: Ondrej Jirman 

Switching to a different reset sequence, enabling IOVCC before enabling
VCC.

There also needs to be a delay after enabling the supplies and before
deasserting the reset. The datasheet specifies 1ms after the supplies
reach the required voltage. Use 10-20ms to also give the power supplies
some time to reach the required voltage, too.

This fixes intermittent panel initialization failures and screen
corruption during resume from sleep on panel xingbangda,xbd599 (e.g.
used in PinePhone).

Signed-off-by: Ondrej Jirman 
Signed-off-by: Frank Oltmanns 
Reported-by: Samuel Holland 
---
 drivers/gpu/drm/panel/panel-sitronix-st7703.c | 25 ++-
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c 
b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
index 6747ca237ced..45695aa51f62 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c
@@ -411,29 +411,30 @@ static int st7703_prepare(struct drm_panel *panel)
return 0;
 
dev_dbg(ctx->dev, "Resetting the panel\n");
-   ret = regulator_enable(ctx->vcc);
+   gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
+   ret = regulator_enable(ctx->iovcc);
if (ret < 0) {
-   dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
+   dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
return ret;
}
-   ret = regulator_enable(ctx->iovcc);
+
+   ret = regulator_enable(ctx->vcc);
if (ret < 0) {
-   dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
-   goto disable_vcc;
+   dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
+   regulator_disable(ctx->iovcc);
+   return ret;
}
 
-   gpiod_set_value_cansleep(ctx->reset_gpio, 1);
-   usleep_range(20, 40);
+   /* Give power supplies time to stabilize before deasserting reset. */
+   usleep_range(1, 2);
+
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
-   msleep(20);
+   usleep_range(15000, 2);
 
ctx->prepared = true;
 
return 0;
-
-disable_vcc:
-   regulator_disable(ctx->vcc);
-   return ret;
 }
 
 static const u32 mantix_bus_formats[] = {
-- 
2.39.1



Re: [PATCH 1/1] drm/panel: st7703: Fix resume of XBD599 panel

2023-02-12 Thread Frank Oltmanns