2022-05-16 21:40:32 +00:00
|
|
|
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
|
2022-10-26 22:31:12 +00:00
|
|
|
@@ -401,6 +401,7 @@ static void vc4_crtc_config_pv(struct dr
|
2022-05-16 21:40:32 +00:00
|
|
|
CRTC_WRITE(PV_V_CONTROL,
|
|
|
|
PV_VCONTROL_CONTINUOUS |
|
|
|
|
(is_dsi ? PV_VCONTROL_DSI : 0));
|
|
|
|
+ CRTC_WRITE(PV_VSYNCD_EVEN, 0);
|
|
|
|
}
|
|
|
|
|
2022-10-26 22:31:12 +00:00
|
|
|
if (is_dsi)
|
2022-05-16 21:40:32 +00:00
|
|
|
--- 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 = {
|