9b7bc332ef80021a822d04ba5588cde0c30c3376
[openwrt/staging/blocktrron.git] /
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
6
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.
11
12 Signed-off-by: Mateusz Kwiatkowski <kfyatek+publicgit@gmail.com>
13 ---
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(-)
17
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);
25 }
26
27 CRTC_WRITE(PV_VERTA,
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);
33
34 - const struct vc4_vec_tv_mode *vec_mode =
35 - &vc4_vec_tv_modes[new_state->tv.mode];
36 -
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);
41
42 - if (!drm_mode_equal(vec_mode->mode, &crtc_state->mode))
43 - return -EINVAL;
44 -
45 - if (old_state->tv.mode != new_state->tv.mode)
46 - crtc_state->mode_changed = true;
47 + crtc_state->mode_changed = true;
48 }
49
50 return 0;
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);
62
63 @@ -575,8 +571,86 @@ err_put_runtime_pm:
64 err_dev_exit:
65 drm_dev_exit(idx);
66 }
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)
70 +{
71 + const struct drm_display_mode *reference_mode =
72 + vc4_vec_tv_modes[conn_state->tv.mode].mode;
73 +
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)
79 + return -EINVAL;
80 +
81 + switch (reference_mode->vtotal) {
82 + case 525:
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)
92 + return -EINVAL;
93 +
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))
100 + return -EINVAL;
101 +
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)
106 + return -EINVAL;
107 +
108 + break;
109 +
110 + case 625:
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)
120 + return -EINVAL;
121 +
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))
128 + return -EINVAL;
129 +
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)
134 + return -EINVAL;
135 +
136 + break;
137 +
138 + default:
139 + return -EINVAL;
140 + }
141 +
142 + return 0;
143 +}
144
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,
149 };