From: Mateusz Kwiatkowski <kfyatek+public...@gmail.com>

The VEC can accept pretty much any relatively reasonable mode, but still
has a bunch of constraints to meet.

Let's create an atomic_check() implementation that will make sure we
don't end up accepting a non-functional mode.

Acked-by: Noralf Trønnes <nor...@tronnes.org>
Signed-off-by: Mateusz Kwiatkowski <kfyatek+public...@gmail.com>
Tested-by: Mateusz Kwiatkowski <kfyatek+public...@gmail.com>
Signed-off-by: Maxime Ripard <max...@cerno.tech>

---

Changes in v6:
- Used htotal instead of vtotal to discriminate PAL against NTSC
---
 drivers/gpu/drm/vc4/vc4_vec.c | 50 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 90e375a8a8f9..bfa8a58dba30 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -453,6 +453,7 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder 
*encoder,
                                        struct drm_crtc_state *crtc_state,
                                        struct drm_connector_state *conn_state)
 {
+       const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
        const struct vc4_vec_tv_mode *vec_mode;
 
        vec_mode = &vc4_vec_tv_modes[conn_state->tv.legacy_mode];
@@ -461,6 +462,55 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder 
*encoder,
            !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
                return -EINVAL;
 
+       if (mode->crtc_hdisplay % 4)
+               return -EINVAL;
+
+       if (!(mode->crtc_hsync_end - mode->crtc_hsync_start))
+               return -EINVAL;
+
+       switch (mode->htotal) {
+       /* NTSC */
+       case 858:
+               if (mode->crtc_vtotal > 262)
+                       return -EINVAL;
+
+               if (mode->crtc_vdisplay < 1 || mode->crtc_vdisplay > 253)
+                       return -EINVAL;
+
+               if (!(mode->crtc_vsync_start - mode->crtc_vdisplay))
+                       return -EINVAL;
+
+               if ((mode->crtc_vsync_end - mode->crtc_vsync_start) != 3)
+                       return -EINVAL;
+
+               if ((mode->crtc_vtotal - mode->crtc_vsync_end) < 4)
+                       return -EINVAL;
+
+               break;
+
+       /* PAL/SECAM */
+       case 864:
+               if (mode->crtc_vtotal > 312)
+                       return -EINVAL;
+
+               if (mode->crtc_vdisplay < 1 || mode->crtc_vdisplay > 305)
+                       return -EINVAL;
+
+               if (!(mode->crtc_vsync_start - mode->crtc_vdisplay))
+                       return -EINVAL;
+
+               if ((mode->crtc_vsync_end - mode->crtc_vsync_start) != 3)
+                       return -EINVAL;
+
+               if ((mode->crtc_vtotal - mode->crtc_vsync_end) < 2)
+                       return -EINVAL;
+
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
        return 0;
 }
 

-- 
b4 0.11.0-dev-99e3a

Reply via email to