2021-08-21 08:54:34 +00:00
|
|
|
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
|
2022-08-28 13:09:23 +00:00
|
|
|
@@ -540,6 +540,8 @@ static bool vc4_hdmi_supports_scrambling
|
2021-08-21 08:54:34 +00:00
|
|
|
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;
|
2022-08-28 13:09:23 +00:00
|
|
|
@@ -556,6 +558,9 @@ static void vc4_hdmi_enable_scrambling(s
|
2021-08-21 08:54:34 +00:00
|
|
|
|
|
|
|
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)
|
2022-08-28 13:09:23 +00:00
|
|
|
@@ -574,6 +579,9 @@ static void vc4_hdmi_disable_scrambling(
|
2021-08-21 08:54:34 +00:00
|
|
|
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);
|
|
|
|
|
2022-08-28 13:09:23 +00:00
|
|
|
@@ -581,6 +589,22 @@ static void vc4_hdmi_disable_scrambling(
|
2021-08-21 08:54:34 +00:00
|
|
|
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)
|
|
|
|
{
|
2022-02-06 16:51:17 +00:00
|
|
|
@@ -2275,6 +2299,7 @@ static int vc4_hdmi_bind(struct device *
|
2021-08-21 08:54:34 +00:00
|
|
|
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;
|