kernel: bump 5.10 to 5.10.98
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.10 / 950-0602-drm-vc4-hdmi-Add-a-workqueue-to-set-scrambling.patch
1 From c20cb28d802aa148cfa90c0682323e9d52dc0466 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Fri, 7 May 2021 15:28:21 +0200
4 Subject: [PATCH] drm/vc4: hdmi: Add a workqueue to set scrambling
5
6 It looks like some displays (like the LG 27UL850-W) don't enable the
7 scrambling when the HDMI driver enables it. However, if we set later the
8 scrambler enable bit, the display will work as expected.
9
10 Let's create delayed work queue to periodically look at the display
11 scrambling status, and if it's not set yet try to enable it again.
12
13 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
14 ---
15 drivers/gpu/drm/vc4/vc4_hdmi.c | 25 +++++++++++++++++++++++++
16 drivers/gpu/drm/vc4/vc4_hdmi.h | 2 ++
17 2 files changed, 27 insertions(+)
18
19 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
20 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
21 @@ -538,6 +538,8 @@ static bool vc4_hdmi_supports_scrambling
22 return true;
23 }
24
25 +#define SCRAMBLING_POLLING_DELAY_MS 1000
26 +
27 static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
28 {
29 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
30 @@ -554,6 +556,9 @@ static void vc4_hdmi_enable_scrambling(s
31
32 HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) |
33 VC5_HDMI_SCRAMBLER_CTL_ENABLE);
34 +
35 + queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work,
36 + msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS));
37 }
38
39 static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)
40 @@ -572,6 +577,9 @@ static void vc4_hdmi_disable_scrambling(
41 if (crtc && !vc4_hdmi_mode_needs_scrambling(&crtc->mode))
42 return;
43
44 + if (delayed_work_pending(&vc4_hdmi->scrambling_work))
45 + cancel_delayed_work_sync(&vc4_hdmi->scrambling_work);
46 +
47 HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) &
48 ~VC5_HDMI_SCRAMBLER_CTL_ENABLE);
49
50 @@ -579,6 +587,22 @@ static void vc4_hdmi_disable_scrambling(
51 drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false);
52 }
53
54 +static void vc4_hdmi_scrambling_wq(struct work_struct *work)
55 +{
56 + struct vc4_hdmi *vc4_hdmi = container_of(to_delayed_work(work),
57 + struct vc4_hdmi,
58 + scrambling_work);
59 +
60 + if (drm_scdc_get_scrambling_status(vc4_hdmi->ddc))
61 + return;
62 +
63 + drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true);
64 + drm_scdc_set_scrambling(vc4_hdmi->ddc, true);
65 +
66 + queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work,
67 + msecs_to_jiffies(SCRAMBLING_POLLING_DELAY_MS));
68 +}
69 +
70 static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
71 struct drm_atomic_state *state)
72 {
73 @@ -2275,6 +2299,7 @@ static int vc4_hdmi_bind(struct device *
74 vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
75 if (!vc4_hdmi)
76 return -ENOMEM;
77 + INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq);
78
79 dev_set_drvdata(dev, vc4_hdmi);
80 encoder = &vc4_hdmi->encoder.base.base;
81 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
82 +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
83 @@ -131,6 +131,8 @@ struct vc4_hdmi {
84 struct vc4_hdmi_encoder encoder;
85 struct drm_connector connector;
86
87 + struct delayed_work scrambling_work;
88 +
89 struct i2c_adapter *ddc;
90 void __iomem *hdmicore_regs;
91 void __iomem *hd_regs;