openwrt/target/linux/bcm27xx/patches-5.15/950-0555-drm-vc4-Relax-VEC-...

157 lines
5.5 KiB
Diff

From ae200c4c1d2d0c9f827e7f73d00f00074e3a7a04 Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
Date: Thu, 15 Jul 2021 01:08:08 +0200
Subject: [PATCH] drm/vc4: Relax VEC modeline requirements and add
progressive mode support
Make vc4_vec_encoder_atomic_check() accept arbitrary modelines, as long
as they result in somewhat sane output from the VEC. The bounds have
been determined empirically. Additionally, add support for the
progressive 262-line and 312-line modes.
Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 1 +
drivers/gpu/drm/vc4/vc4_vec.c | 97 ++++++++++++++++++++++++++++------
2 files changed, 83 insertions(+), 15 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -401,6 +401,7 @@ static void vc4_crtc_config_pv(struct dr
CRTC_WRITE(PV_V_CONTROL,
PV_VCONTROL_CONTINUOUS |
(is_dsi ? PV_VCONTROL_DSI : 0));
+ CRTC_WRITE(PV_VSYNCD_EVEN, 0);
}
if (is_dsi)
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -423,18 +423,11 @@ static int vc4_vec_connector_atomic_chec
struct drm_connector_state *new_state =
drm_atomic_get_new_connector_state(state, conn);
- const struct vc4_vec_tv_mode *vec_mode =
- &vc4_vec_tv_modes[new_state->tv.mode];
-
- if (new_state->crtc) {
+ if (new_state->crtc && old_state->tv.mode != new_state->tv.mode) {
struct drm_crtc_state *crtc_state =
drm_atomic_get_new_crtc_state(state, new_state->crtc);
- if (!drm_mode_equal(vec_mode->mode, &crtc_state->mode))
- return -EINVAL;
-
- if (old_state->tv.mode != new_state->tv.mode)
- crtc_state->mode_changed = true;
+ crtc_state->mode_changed = true;
}
return 0;
@@ -559,7 +552,10 @@ static void vc4_vec_encoder_enable(struc
VEC_WRITE(VEC_CLMP0_START, 0xac);
VEC_WRITE(VEC_CLMP0_END, 0xec);
VEC_WRITE(VEC_CONFIG2,
- VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
+ VEC_CONFIG2_UV_DIG_DIS |
+ VEC_CONFIG2_RGB_DIG_DIS |
+ ((encoder->crtc->state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) ? 0 : VEC_CONFIG2_PROG_SCAN));
VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
VEC_WRITE(VEC_DAC_CONFIG, vec->variant->dac_config);
@@ -582,17 +578,88 @@ static void vc4_vec_encoder_enable(struc
}
-static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
- return true;
+ const struct drm_display_mode *reference_mode =
+ vc4_vec_tv_modes[conn_state->tv.mode].mode;
+
+ if (crtc_state->adjusted_mode.crtc_clock != reference_mode->clock ||
+ crtc_state->adjusted_mode.crtc_htotal != reference_mode->htotal ||
+ crtc_state->adjusted_mode.crtc_hdisplay % 4 != 0 ||
+ crtc_state->adjusted_mode.crtc_hsync_end -
+ crtc_state->adjusted_mode.crtc_hsync_start < 1)
+ return -EINVAL;
+
+ switch (reference_mode->vtotal) {
+ case 525:
+ if (crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
+ crtc_state->adjusted_mode.crtc_vdisplay > 253 ||
+ crtc_state->adjusted_mode.crtc_vsync_start -
+ crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
+ crtc_state->adjusted_mode.crtc_vsync_end -
+ crtc_state->adjusted_mode.crtc_vsync_start != 3 ||
+ crtc_state->adjusted_mode.crtc_vtotal -
+ crtc_state->adjusted_mode.crtc_vsync_end < 4 ||
+ crtc_state->adjusted_mode.crtc_vtotal > 262)
+ return -EINVAL;
+
+ if ((crtc_state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) &&
+ (crtc_state->adjusted_mode.vdisplay % 2 != 0 ||
+ crtc_state->adjusted_mode.vsync_start % 2 != 1 ||
+ crtc_state->adjusted_mode.vsync_end % 2 != 1 ||
+ crtc_state->adjusted_mode.vtotal % 2 != 1))
+ return -EINVAL;
+
+ /* progressive mode is hard-wired to 262 total lines */
+ if (!(crtc_state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) &&
+ crtc_state->adjusted_mode.crtc_vtotal != 262)
+ return -EINVAL;
+
+ break;
+
+ case 625:
+ if (crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
+ crtc_state->adjusted_mode.crtc_vdisplay > 305 ||
+ crtc_state->adjusted_mode.crtc_vsync_start -
+ crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
+ crtc_state->adjusted_mode.crtc_vsync_end -
+ crtc_state->adjusted_mode.crtc_vsync_start != 3 ||
+ crtc_state->adjusted_mode.crtc_vtotal -
+ crtc_state->adjusted_mode.crtc_vsync_end < 2 ||
+ crtc_state->adjusted_mode.crtc_vtotal > 312)
+ return -EINVAL;
+
+ if ((crtc_state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) &&
+ (crtc_state->adjusted_mode.vdisplay % 2 != 0 ||
+ crtc_state->adjusted_mode.vsync_start % 2 != 0 ||
+ crtc_state->adjusted_mode.vsync_end % 2 != 0 ||
+ crtc_state->adjusted_mode.vtotal % 2 != 1))
+ return -EINVAL;
+
+ /* progressive mode is hard-wired to 312 total lines */
+ if (!(crtc_state->adjusted_mode.flags &
+ DRM_MODE_FLAG_INTERLACE) &&
+ crtc_state->adjusted_mode.crtc_vtotal != 312)
+ return -EINVAL;
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
}
static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
.disable = vc4_vec_encoder_disable,
.enable = vc4_vec_encoder_enable,
- .mode_fixup = vc4_vec_encoder_mode_fixup,
+ .atomic_check = vc4_vec_encoder_atomic_check,
};
static const struct vc4_vec_variant bcm2835_vec_variant = {