aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.10/950-0602-drm-vc4-hdmi-Add-a-workqueue-to-set-scrambling.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.10/950-0602-drm-vc4-hdmi-Add-a-workqueue-to-set-scrambling.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.10/950-0602-drm-vc4-hdmi-Add-a-workqueue-to-set-scrambling.patch91
1 files changed, 91 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.10/950-0602-drm-vc4-hdmi-Add-a-workqueue-to-set-scrambling.patch b/target/linux/bcm27xx/patches-5.10/950-0602-drm-vc4-hdmi-Add-a-workqueue-to-set-scrambling.patch
new file mode 100644
index 0000000000..ab461f383c
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.10/950-0602-drm-vc4-hdmi-Add-a-workqueue-to-set-scrambling.patch
@@ -0,0 +1,91 @@
+From c20cb28d802aa148cfa90c0682323e9d52dc0466 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Fri, 7 May 2021 15:28:21 +0200
+Subject: [PATCH] drm/vc4: hdmi: Add a workqueue to set scrambling
+
+It looks like some displays (like the LG 27UL850-W) don't enable the
+scrambling when the HDMI driver enables it. However, if we set later the
+scrambler enable bit, the display will work as expected.
+
+Let's create delayed work queue to periodically look at the display
+scrambling status, and if it's not set yet try to enable it again.
+
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/gpu/drm/vc4/vc4_hdmi.c | 25 +++++++++++++++++++++++++
+ drivers/gpu/drm/vc4/vc4_hdmi.h | 2 ++
+ 2 files changed, 27 insertions(+)
+
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -537,6 +537,8 @@ static bool vc4_hdmi_supports_scrambling
+ return true;
+ }
+
++#define SCRAMBLING_POLLING_DELAY_MS 1000
++
+ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
+ {
+ struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+@@ -553,6 +555,9 @@ static void vc4_hdmi_enable_scrambling(s
+
+ HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) |
+ VC5_HDMI_SCRAMBLER_CTL_ENABLE);
++
++ queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work,
++ msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS));
+ }
+
+ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)
+@@ -571,6 +576,9 @@ static void vc4_hdmi_disable_scrambling(
+ if (crtc && !vc4_hdmi_mode_needs_scrambling(&crtc->mode))
+ return;
+
++ if (delayed_work_pending(&vc4_hdmi->scrambling_work))
++ cancel_delayed_work_sync(&vc4_hdmi->scrambling_work);
++
+ HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) &
+ ~VC5_HDMI_SCRAMBLER_CTL_ENABLE);
+
+@@ -578,6 +586,22 @@ static void vc4_hdmi_disable_scrambling(
+ drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false);
+ }
+
++static void vc4_hdmi_scrambling_wq(struct work_struct *work)
++{
++ struct vc4_hdmi *vc4_hdmi = container_of(to_delayed_work(work),
++ struct vc4_hdmi,
++ scrambling_work);
++
++ if (drm_scdc_get_scrambling_status(vc4_hdmi->ddc))
++ return;
++
++ drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true);
++ drm_scdc_set_scrambling(vc4_hdmi->ddc, true);
++
++ queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work,
++ msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS));
++}
++
+ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
+ struct drm_atomic_state *state)
+ {
+@@ -2274,6 +2298,7 @@ static int vc4_hdmi_bind(struct device *
+ vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
+ if (!vc4_hdmi)
+ return -ENOMEM;
++ INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq);
+
+ dev_set_drvdata(dev, vc4_hdmi);
+ encoder = &vc4_hdmi->encoder.base.base;
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
+@@ -131,6 +131,8 @@ struct vc4_hdmi {
+ struct vc4_hdmi_encoder encoder;
+ struct drm_connector connector;
+
++ struct delayed_work scrambling_work;
++
+ struct i2c_adapter *ddc;
+ void __iomem *hdmicore_regs;
+ void __iomem *hd_regs;