| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- From ae200c4c1d2d0c9f827e7f73d00f00074e3a7a04 Mon Sep 17 00:00:00 2001
- From: Mateusz Kwiatkowski <[email protected]>
- 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 <[email protected]>
- ---
- 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 = {
|