1 From a4614b6f6c4e3a9ef80c88f272c1503b91f7ef8c Mon Sep 17 00:00:00 2001
2 From: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
3 Date: Thu, 15 Jul 2021 01:08:08 +0200
4 Subject: [PATCH] drm/vc4: Relax VEC modeline requirements and add
5 progressive mode support
7 Make vc4_vec_encoder_atomic_check() accept arbitrary modelines, as long
8 as they result in somewhat sane output from the VEC. The bounds have
9 been determined empirically. Additionally, add support for the
10 progressive 262-line and 312-line modes.
12 Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
14 drivers/gpu/drm/vc4/vc4_crtc.c | 1 +
15 drivers/gpu/drm/vc4/vc4_vec.c | 94 ++++++++++++++++++++++++++++++----
16 2 files changed, 85 insertions(+), 10 deletions(-)
18 --- a/drivers/gpu/drm/vc4/vc4_crtc.c
19 +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
20 @@ -422,6 +422,7 @@ static void vc4_crtc_config_pv(struct dr
21 CRTC_WRITE(PV_V_CONTROL,
22 PV_VCONTROL_CONTINUOUS |
23 (is_dsi ? PV_VCONTROL_DSI : 0));
24 + CRTC_WRITE(PV_VSYNCD_EVEN, 0);
28 --- a/drivers/gpu/drm/vc4/vc4_vec.c
29 +++ b/drivers/gpu/drm/vc4/vc4_vec.c
30 @@ -400,18 +400,11 @@ static int vc4_vec_connector_atomic_chec
31 struct drm_connector_state *new_state =
32 drm_atomic_get_new_connector_state(state, conn);
34 - const struct vc4_vec_tv_mode *vec_mode =
35 - &vc4_vec_tv_modes[new_state->tv.mode];
37 - if (new_state->crtc) {
38 + if (new_state->crtc && old_state->tv.mode != new_state->tv.mode) {
39 struct drm_crtc_state *crtc_state =
40 drm_atomic_get_new_crtc_state(state, new_state->crtc);
42 - if (!drm_mode_equal(vec_mode->mode, &crtc_state->mode))
45 - if (old_state->tv.mode != new_state->tv.mode)
46 - crtc_state->mode_changed = true;
47 + crtc_state->mode_changed = true;
51 @@ -546,7 +539,10 @@ static void vc4_vec_encoder_enable(struc
52 VEC_WRITE(VEC_CLMP0_START, 0xac);
53 VEC_WRITE(VEC_CLMP0_END, 0xec);
54 VEC_WRITE(VEC_CONFIG2,
55 - VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
56 + VEC_CONFIG2_UV_DIG_DIS |
57 + VEC_CONFIG2_RGB_DIG_DIS |
58 + ((encoder->crtc->state->adjusted_mode.flags &
59 + DRM_MODE_FLAG_INTERLACE) ? 0 : VEC_CONFIG2_PROG_SCAN));
60 VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
61 VEC_WRITE(VEC_DAC_CONFIG, vec->variant->dac_config);
63 @@ -575,8 +571,86 @@ err_put_runtime_pm:
67 +static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
68 + struct drm_crtc_state *crtc_state,
69 + struct drm_connector_state *conn_state)
71 + const struct drm_display_mode *reference_mode =
72 + vc4_vec_tv_modes[conn_state->tv.mode].mode;
74 + if (crtc_state->adjusted_mode.crtc_clock != reference_mode->clock ||
75 + crtc_state->adjusted_mode.crtc_htotal != reference_mode->htotal ||
76 + crtc_state->adjusted_mode.crtc_hdisplay % 4 != 0 ||
77 + crtc_state->adjusted_mode.crtc_hsync_end -
78 + crtc_state->adjusted_mode.crtc_hsync_start < 1)
81 + switch (reference_mode->vtotal) {
83 + if (crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
84 + crtc_state->adjusted_mode.crtc_vdisplay > 253 ||
85 + crtc_state->adjusted_mode.crtc_vsync_start -
86 + crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
87 + crtc_state->adjusted_mode.crtc_vsync_end -
88 + crtc_state->adjusted_mode.crtc_vsync_start != 3 ||
89 + crtc_state->adjusted_mode.crtc_vtotal -
90 + crtc_state->adjusted_mode.crtc_vsync_end < 4 ||
91 + crtc_state->adjusted_mode.crtc_vtotal > 262)
94 + if ((crtc_state->adjusted_mode.flags &
95 + DRM_MODE_FLAG_INTERLACE) &&
96 + (crtc_state->adjusted_mode.vdisplay % 2 != 0 ||
97 + crtc_state->adjusted_mode.vsync_start % 2 != 1 ||
98 + crtc_state->adjusted_mode.vsync_end % 2 != 1 ||
99 + crtc_state->adjusted_mode.vtotal % 2 != 1))
102 + /* progressive mode is hard-wired to 262 total lines */
103 + if (!(crtc_state->adjusted_mode.flags &
104 + DRM_MODE_FLAG_INTERLACE) &&
105 + crtc_state->adjusted_mode.crtc_vtotal != 262)
111 + if (crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
112 + crtc_state->adjusted_mode.crtc_vdisplay > 305 ||
113 + crtc_state->adjusted_mode.crtc_vsync_start -
114 + crtc_state->adjusted_mode.crtc_vdisplay < 1 ||
115 + crtc_state->adjusted_mode.crtc_vsync_end -
116 + crtc_state->adjusted_mode.crtc_vsync_start != 3 ||
117 + crtc_state->adjusted_mode.crtc_vtotal -
118 + crtc_state->adjusted_mode.crtc_vsync_end < 2 ||
119 + crtc_state->adjusted_mode.crtc_vtotal > 312)
122 + if ((crtc_state->adjusted_mode.flags &
123 + DRM_MODE_FLAG_INTERLACE) &&
124 + (crtc_state->adjusted_mode.vdisplay % 2 != 0 ||
125 + crtc_state->adjusted_mode.vsync_start % 2 != 0 ||
126 + crtc_state->adjusted_mode.vsync_end % 2 != 0 ||
127 + crtc_state->adjusted_mode.vtotal % 2 != 1))
130 + /* progressive mode is hard-wired to 312 total lines */
131 + if (!(crtc_state->adjusted_mode.flags &
132 + DRM_MODE_FLAG_INTERLACE) &&
133 + crtc_state->adjusted_mode.crtc_vtotal != 312)
145 static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
146 + .atomic_check = vc4_vec_encoder_atomic_check,
147 .atomic_disable = vc4_vec_encoder_disable,
148 .atomic_enable = vc4_vec_encoder_enable,