* [PATCH v2 0/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts
@ 2026-10-20 15:19 Lucas Tanure
2026-10-20 15:19 ` [PATCH v2 1/3] drm/vc4: Implement vc6_hdmi_phy_disable Lucas Tanure
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Lucas Tanure @ 2026-10-20 15:19 UTC (permalink / raw)
To: Maxime Ripard, Dave Stevenson
Cc: Dom Cobley, Maíra Canal, Raspberry Pi Kernel Maintenance,
Maarten Lankhorst, Thomas Zimmermann, David Airlie,
Simona Vetter, dri-devel, linux-kernel
HDMI 2.0 asks the source to set TMDS_Bit_Clock_Ratio in the sink while
the TMDS clock is stopped and to start the clock at least 1 ms later.
vc4 writes the bit, and enables the scrambler, at the end of the enable
sequence, long after the PHY has started, and clears it before the PHY
stops. A sink that samples the bit when the clock appears never locks
a 4K60 signal from a Raspberry Pi 5, while laptops that follow the
order work on the same sink.
Patch 3 is the fix. Patch 1 is needed on BCM2712, where phy_disable()
was an empty stub upstream, so the clock did not stop on disable; the
Raspberry Pi tree has carried this since 2024. Patch 2 fixes a
pre-existing race in the scrambling work cancel that the fix would
otherwise make easier to hit.
v1 was tested on a Raspberry Pi 5 running the Raspberry Pi 6.18 kernel
with the same change applied, against the sink that showed the
problem: plain enable at 4K60, 1080p60 to 4K60, 4K30 to 4K60, a sink
reset and a sink power cycle all lock with zero character errors. v2 is
compile-checked only so far; the hardware test will be repeated and
reported in this thread. Mainline was not booted on the Pi 5. The
BCM2711 path is unchanged except for the enable order; I have no Pi 4
at hand.
Changes in v2:
- Add Dom Cobley's vc6_hdmi_phy_disable() from the Raspberry Pi tree so
the PHY really stops on BCM2712 before the SCDC bits are cleared.
- Cancel the scrambling work unconditionally with
cancel_delayed_work_sync(); the pending check skipped a running
instance that then re-armed itself.
- Enable the controller scrambler at the same point as the sink bits,
before the PHY starts, instead of leaving it at the end of the enable
sequence with the sink descrambler already on.
- Drop the extra usleep_range(); drm_scdc_set_high_tmds_clock_ratio()
already waits.
- v1: https://lore.kernel.org/lkml/20261020134941.631907-1-lucas.tanure@neat.no/
Dom Cobley (1):
drm/vc4: Implement vc6_hdmi_phy_disable
Lucas Tanure (2):
drm/vc4: hdmi: always cancel the scrambling work synchronously
drm/vc4: hdmi: enable scrambling before the TMDS clock starts
drivers/gpu/drm/vc4/vc4_hdmi.c | 10 +++++-----
drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 5 +++++
2 files changed, 10 insertions(+), 5 deletions(-)
--
2.56.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/3] drm/vc4: Implement vc6_hdmi_phy_disable
2026-10-20 15:19 [PATCH v2 0/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts Lucas Tanure
@ 2026-10-20 15:19 ` Lucas Tanure
2026-10-24 13:13 ` Maíra Canal
2026-10-20 15:19 ` [PATCH v2 2/3] drm/vc4: hdmi: always cancel the scrambling work synchronously Lucas Tanure
2026-10-20 15:19 ` [PATCH v2 3/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts Lucas Tanure
2 siblings, 1 reply; 7+ messages in thread
From: Lucas Tanure @ 2026-10-20 15:19 UTC (permalink / raw)
To: Maxime Ripard, Dave Stevenson
Cc: Dom Cobley, Maíra Canal, Raspberry Pi Kernel Maintenance,
Maarten Lankhorst, Thomas Zimmermann, David Airlie,
Simona Vetter, dri-devel, linux-kernel
From: Dom Cobley <popcornmix@gmail.com>
The body of this function was missing so we don't reset the phy
when disabling it.
Fixes: 0b1dbe82e051 ("drm/vc4: hdmi: Add support for BCM2712 HDMI controllers")
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
Signed-off-by: Lucas Tanure <lucas.tanure@neat.no>
---
drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index 56e6a35da357..5040f014bf7e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -1197,4 +1197,9 @@ void vc6_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
void vc6_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
+ vc6_hdmi_reset_phy(vc4_hdmi);
+ spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
}
--
2.56.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/3] drm/vc4: hdmi: always cancel the scrambling work synchronously
2026-10-20 15:19 [PATCH v2 0/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts Lucas Tanure
2026-10-20 15:19 ` [PATCH v2 1/3] drm/vc4: Implement vc6_hdmi_phy_disable Lucas Tanure
@ 2026-10-20 15:19 ` Lucas Tanure
2026-10-24 13:23 ` Maíra Canal
2026-10-20 15:19 ` [PATCH v2 3/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts Lucas Tanure
2 siblings, 1 reply; 7+ messages in thread
From: Lucas Tanure @ 2026-10-20 15:19 UTC (permalink / raw)
To: Maxime Ripard, Dave Stevenson
Cc: Dom Cobley, Maíra Canal, Raspberry Pi Kernel Maintenance,
Maarten Lankhorst, Thomas Zimmermann, David Airlie,
Simona Vetter, dri-devel, linux-kernel
The scrambling work re-arms itself every second while a scrambled mode
is active. When the output is disabled, the work may be executing at
that moment rather than pending, and delayed_work_pending() is then
false, so the cancel is skipped. The running instance finishes after
the disable, sees the sink report scrambling off, writes the SCDC
scrambling and clock ratio bits back on, and queues itself again. The
sink is left configured for a scrambled 1/40 link that no longer exists
and the work keeps running until the next enable.
cancel_delayed_work_sync() handles both states: it waits for a running
instance and blocks it from queueing itself again.
Fixes: 257d36d493e9 ("drm/vc4: hdmi: Add a workqueue to set scrambling")
Assisted-by: LLM
Signed-off-by: Lucas Tanure <lucas.tanure@neat.no>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 2cc46036f11d..4a386e053d3f 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -843,8 +843,7 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)
vc4_hdmi->scdc_enabled = false;
- if (delayed_work_pending(&vc4_hdmi->scrambling_work))
- cancel_delayed_work_sync(&vc4_hdmi->scrambling_work);
+ cancel_delayed_work_sync(&vc4_hdmi->scrambling_work);
if (!drm_dev_enter(drm, &idx))
return;
--
2.56.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 3/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts
2026-10-20 15:19 [PATCH v2 0/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts Lucas Tanure
2026-10-20 15:19 ` [PATCH v2 1/3] drm/vc4: Implement vc6_hdmi_phy_disable Lucas Tanure
2026-10-20 15:19 ` [PATCH v2 2/3] drm/vc4: hdmi: always cancel the scrambling work synchronously Lucas Tanure
@ 2026-10-20 15:19 ` Lucas Tanure
2026-10-24 13:34 ` Maíra Canal
2 siblings, 1 reply; 7+ messages in thread
From: Lucas Tanure @ 2026-10-20 15:19 UTC (permalink / raw)
To: Maxime Ripard, Dave Stevenson
Cc: Dom Cobley, Maíra Canal, Raspberry Pi Kernel Maintenance,
Maarten Lankhorst, Thomas Zimmermann, David Airlie,
Simona Vetter, dri-devel, linux-kernel
HDMI 2.0 requires a source to suspend the TMDS clock, write the
TMDS_Bit_Clock_Ratio bit in the sink's SCDC registers, wait at least
1 ms and only then resume the clock. vc4 does the opposite: the PHY
starts at the new rate first, and the SCDC bits are written tens of
milliseconds later, at the very end of the enable sequence, together
with the source side scrambler. On disable the bits are cleared while
the clock is still running.
Some sinks sample the bit only when the clock appears. One HDMI 2.0
sink we tested then sets up its receiver for a 1/10 clock and never
recovers: a Raspberry Pi 5 at 3840x2160@60 shows no picture, while
1080p60 and 4K30 work and other sources work at 4K60 on the same sink.
Writing the bit by hand before enabling the output makes the same mode
lock every time.
Enable scrambling, on the sink and in the controller, before the PHY is
started, and disable it only after the PHY has been stopped. The SCDC
helper already waits the required time after writing the ratio bit.
Fixes: c85695a2016e ("drm/vc4: hdmi: Enable the scrambler")
Link: https://github.com/raspberrypi/linux/issues/7693
Assisted-by: LLM
Signed-off-by: Lucas Tanure <lucas.tanure@neat.no>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 4a386e053d3f..e57fc33af6b3 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -918,8 +918,6 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
}
- vc4_hdmi_disable_scrambling(encoder);
-
drm_dev_exit(idx);
out:
@@ -947,6 +945,8 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
if (vc4_hdmi->variant->phy_disable)
vc4_hdmi->variant->phy_disable(vc4_hdmi);
+ vc4_hdmi_disable_scrambling(encoder);
+
clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock);
clk_disable_unprepare(vc4_hdmi->pixel_clock);
@@ -1554,6 +1554,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
goto err_disable_pixel_clock;
}
+ vc4_hdmi_enable_scrambling(encoder);
+
if (vc4_hdmi->variant->phy_init)
vc4_hdmi->variant->phy_init(vc4_hdmi, conn_state);
@@ -1688,7 +1690,6 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
}
vc4_hdmi_recenter_fifo(vc4_hdmi);
- vc4_hdmi_enable_scrambling(encoder);
drm_dev_exit(idx);
--
2.56.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/3] drm/vc4: Implement vc6_hdmi_phy_disable
2026-10-20 15:19 ` [PATCH v2 1/3] drm/vc4: Implement vc6_hdmi_phy_disable Lucas Tanure
@ 2026-10-24 13:13 ` Maíra Canal
0 siblings, 0 replies; 7+ messages in thread
From: Maíra Canal @ 2026-10-24 13:13 UTC (permalink / raw)
To: Lucas Tanure, Maxime Ripard, Dave Stevenson
Cc: Dom Cobley, Raspberry Pi Kernel Maintenance, Maarten Lankhorst,
Thomas Zimmermann, David Airlie, Simona Vetter, dri-devel,
linux-kernel
Hi Lucas,
On 20/10/26 12:19, Lucas Tanure wrote:
> From: Dom Cobley <popcornmix@gmail.com>
>
> The body of this function was missing so we don't reset the phy
> when disabling it.
Please, improve this commit message. At the moment, it's not explaining
what's is fixing, nor how.
Best regards,
- Maíra
>
> Fixes: 0b1dbe82e051 ("drm/vc4: hdmi: Add support for BCM2712 HDMI controllers")
> Signed-off-by: Dom Cobley <popcornmix@gmail.com>
> Signed-off-by: Lucas Tanure <lucas.tanure@neat.no>
> ---
> drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> index 56e6a35da357..5040f014bf7e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -1197,4 +1197,9 @@ void vc6_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
>
> void vc6_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
> {
> + unsigned long flags;
> +
> + spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
> + vc6_hdmi_reset_phy(vc4_hdmi);
> + spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
> }
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/3] drm/vc4: hdmi: always cancel the scrambling work synchronously
2026-10-20 15:19 ` [PATCH v2 2/3] drm/vc4: hdmi: always cancel the scrambling work synchronously Lucas Tanure
@ 2026-10-24 13:23 ` Maíra Canal
0 siblings, 0 replies; 7+ messages in thread
From: Maíra Canal @ 2026-10-24 13:23 UTC (permalink / raw)
To: Lucas Tanure, Maxime Ripard, Dave Stevenson
Cc: Dom Cobley, Raspberry Pi Kernel Maintenance, Maarten Lankhorst,
Thomas Zimmermann, David Airlie, Simona Vetter, dri-devel,
linux-kernel
On 20/10/26 12:19, Lucas Tanure wrote:
> The scrambling work re-arms itself every second while a scrambled mode
> is active. When the output is disabled, the work may be executing at
> that moment rather than pending, and delayed_work_pending() is then
> false, so the cancel is skipped. The running instance finishes after
> the disable, sees the sink report scrambling off, writes the SCDC
> scrambling and clock ratio bits back on, and queues itself again. The
> sink is left configured for a scrambled 1/40 link that no longer exists
> and the work keeps running until the next enable.
>
> cancel_delayed_work_sync() handles both states: it waits for a running
> instance and blocks it from queueing itself again.
>
> Fixes: 257d36d493e9 ("drm/vc4: hdmi: Add a workqueue to set scrambling")
> Assisted-by: LLM
> Signed-off-by: Lucas Tanure <lucas.tanure@neat.no>
Reviewed-by: Maíra Canal <mcanal@igalia.com>
Best regards,
- Maíra
> ---
> drivers/gpu/drm/vc4/vc4_hdmi.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 2cc46036f11d..4a386e053d3f 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -843,8 +843,7 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)
>
> vc4_hdmi->scdc_enabled = false;
>
> - if (delayed_work_pending(&vc4_hdmi->scrambling_work))
> - cancel_delayed_work_sync(&vc4_hdmi->scrambling_work);
> + cancel_delayed_work_sync(&vc4_hdmi->scrambling_work);
>
> if (!drm_dev_enter(drm, &idx))
> return;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 3/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts
2026-10-20 15:19 ` [PATCH v2 3/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts Lucas Tanure
@ 2026-10-24 13:34 ` Maíra Canal
0 siblings, 0 replies; 7+ messages in thread
From: Maíra Canal @ 2026-10-24 13:34 UTC (permalink / raw)
To: Lucas Tanure, Maxime Ripard, Dave Stevenson
Cc: Dom Cobley, Raspberry Pi Kernel Maintenance, Maarten Lankhorst,
Thomas Zimmermann, David Airlie, Simona Vetter, dri-devel,
linux-kernel
On 20/10/26 12:19, Lucas Tanure wrote:
> HDMI 2.0 requires a source to suspend the TMDS clock, write the
> TMDS_Bit_Clock_Ratio bit in the sink's SCDC registers, wait at least
> 1 ms and only then resume the clock. vc4 does the opposite: the PHY
> starts at the new rate first, and the SCDC bits are written tens of
> milliseconds later, at the very end of the enable sequence, together
> with the source side scrambler. On disable the bits are cleared while
> the clock is still running.
>
> Some sinks sample the bit only when the clock appears. One HDMI 2.0
> sink we tested then sets up its receiver for a 1/10 clock and never
> recovers: a Raspberry Pi 5 at 3840x2160@60 shows no picture, while
> 1080p60 and 4K30 work and other sources work at 4K60 on the same sink.
> Writing the bit by hand before enabling the output makes the same mode
> lock every time.
>
> Enable scrambling, on the sink and in the controller, before the PHY is
> started, and disable it only after the PHY has been stopped. The SCDC
> helper already waits the required time after writing the ratio bit.
>
Please add "Cc: stable@vger.kernel.org" to all your patches in the next
version.
> Fixes: c85695a2016e ("drm/vc4: hdmi: Enable the scrambler")
> Link: https://github.com/raspberrypi/linux/issues/7693
> Assisted-by: LLM
> Signed-off-by: Lucas Tanure <lucas.tanure@neat.no>
Reviewed-by: Maíra Canal <mcanal@igalia.com>
Best regards,
- Maíra
> ---
> drivers/gpu/drm/vc4/vc4_hdmi.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 4a386e053d3f..e57fc33af6b3 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -918,8 +918,6 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
> spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
> }
>
> - vc4_hdmi_disable_scrambling(encoder);
> -
> drm_dev_exit(idx);
>
> out:
> @@ -947,6 +945,8 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
> if (vc4_hdmi->variant->phy_disable)
> vc4_hdmi->variant->phy_disable(vc4_hdmi);
>
> + vc4_hdmi_disable_scrambling(encoder);
> +
> clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock);
> clk_disable_unprepare(vc4_hdmi->pixel_clock);
>
> @@ -1554,6 +1554,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
> goto err_disable_pixel_clock;
> }
>
> + vc4_hdmi_enable_scrambling(encoder);
> +
> if (vc4_hdmi->variant->phy_init)
> vc4_hdmi->variant->phy_init(vc4_hdmi, conn_state);
>
> @@ -1688,7 +1690,6 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
> }
>
> vc4_hdmi_recenter_fifo(vc4_hdmi);
> - vc4_hdmi_enable_scrambling(encoder);
>
> drm_dev_exit(idx);
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-24 13:35 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-20 15:19 [PATCH v2 0/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts Lucas Tanure
2026-10-20 15:19 ` [PATCH v2 1/3] drm/vc4: Implement vc6_hdmi_phy_disable Lucas Tanure
2026-10-24 13:13 ` Maíra Canal
2026-10-20 15:19 ` [PATCH v2 2/3] drm/vc4: hdmi: always cancel the scrambling work synchronously Lucas Tanure
2026-10-24 13:23 ` Maíra Canal
2026-10-20 15:19 ` [PATCH v2 3/3] drm/vc4: hdmi: enable scrambling before the TMDS clock starts Lucas Tanure
2026-10-24 13:34 ` Maíra Canal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®