aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0555-drm-vc4-Relax-VEC-modeline-requirements-and-add-prog.patch
blob: 72c5c2085d0004c3f0bb7983032818d91af9b6ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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 = {