aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.10/950-0599-drm-vc4-crtc-Lookup-the-encoder-from-the-register-at.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.10/950-0599-drm-vc4-crtc-Lookup-the-encoder-from-the-register-at.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.10/950-0599-drm-vc4-crtc-Lookup-the-encoder-from-the-register-at.patch104
1 files changed, 104 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.10/950-0599-drm-vc4-crtc-Lookup-the-encoder-from-the-register-at.patch b/target/linux/bcm27xx/patches-5.10/950-0599-drm-vc4-crtc-Lookup-the-encoder-from-the-register-at.patch
new file mode 100644
index 0000000000..8009b074a2
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.10/950-0599-drm-vc4-crtc-Lookup-the-encoder-from-the-register-at.patch
@@ -0,0 +1,104 @@
+From bb968f8f963e28d00fff213c62a2449c45ff19f4 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Thu, 6 May 2021 17:15:57 +0200
+Subject: [PATCH] drm/vc4: crtc: Lookup the encoder from the register
+ at boot
+
+At boot, we can't rely on the vc4_get_crtc_encoder since we don't have a
+state yet and thus will not be able to figure out which connector is
+attached to our CRTC.
+
+However, we have a muxing bit in the CRTC register we can use to get the
+encoder currently connected to the pixelvalve. We can thus read that
+register, lookup the associated register through the vc4_pv_data
+structure, and then pass it to vc4_crtc_disable so that we can perform
+the proper operations.
+
+Fixes: 875a4d536842 ("drm/vc4: drv: Disable the CRTC at boot time")
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/gpu/drm/vc4/vc4_crtc.c | 38 ++++++++++++++++++++++++++++++----
+ 1 file changed, 34 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/vc4/vc4_crtc.c
++++ b/drivers/gpu/drm/vc4/vc4_crtc.c
+@@ -431,11 +431,10 @@ static void require_hvs_enabled(struct d
+ }
+
+ static int vc4_crtc_disable(struct drm_crtc *crtc,
++ struct drm_encoder *encoder,
+ struct drm_atomic_state *state,
+ unsigned int channel)
+ {
+- struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, state,
+- drm_atomic_get_old_connector_state);
+ struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+@@ -476,10 +475,29 @@ static int vc4_crtc_disable(struct drm_c
+ return 0;
+ }
+
++static struct drm_encoder *vc4_crtc_get_encoder_by_type(struct drm_crtc *crtc,
++ enum vc4_encoder_type type)
++{
++ struct drm_encoder *encoder;
++
++ drm_for_each_encoder(encoder, crtc->dev) {
++ struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
++
++ if (vc4_encoder->type == type)
++ return encoder;
++ }
++
++ return NULL;
++}
++
+ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
+ {
+ struct drm_device *drm = crtc->dev;
+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
++ enum vc4_encoder_type encoder_type;
++ const struct vc4_pv_data *pv_data;
++ struct drm_encoder *encoder;
++ unsigned encoder_sel;
+ int channel;
+
+ if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
+@@ -498,7 +516,17 @@ int vc4_crtc_disable_at_boot(struct drm_
+ if (channel < 0)
+ return 0;
+
+- return vc4_crtc_disable(crtc, NULL, channel);
++ encoder_sel = VC4_GET_FIELD(CRTC_READ(PV_CONTROL), PV_CONTROL_CLK_SELECT);
++ if (WARN_ON(encoder_sel != 0))
++ return 0;
++
++ pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
++ encoder_type = pv_data->encoder_types[encoder_sel];
++ encoder = vc4_crtc_get_encoder_by_type(crtc, encoder_type);
++ if (WARN_ON(!encoder))
++ return 0;
++
++ return vc4_crtc_disable(crtc, encoder, NULL, channel);
+ }
+
+ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
+@@ -507,6 +535,8 @@ static void vc4_crtc_atomic_disable(stru
+ struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state,
+ crtc);
+ struct vc4_crtc_state *old_vc4_state = to_vc4_crtc_state(old_state);
++ struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, state,
++ drm_atomic_get_old_connector_state);
+ struct drm_device *dev = crtc->dev;
+
+ require_hvs_enabled(dev);
+@@ -514,7 +544,7 @@ static void vc4_crtc_atomic_disable(stru
+ /* Disable vblank irq handling before crtc is disabled. */
+ drm_crtc_vblank_off(crtc);
+
+- vc4_crtc_disable(crtc, state, old_vc4_state->assigned_channel);
++ vc4_crtc_disable(crtc, encoder, state, old_vc4_state->assigned_channel);
+
+ /*
+ * Make sure we issue a vblank event after disabling the CRTC if