1 | // SPDX-License-Identifier: GPL-2.0 |
2 | |
3 | #include <drm/drm_atomic.h> |
4 | #include <drm/drm_atomic_helper.h> |
5 | #include <drm/drm_atomic_state_helper.h> |
6 | #include <drm/drm_atomic_uapi.h> |
7 | #include <drm/drm_crtc.h> |
8 | #include <drm/drm_drv.h> |
9 | #include <drm/drm_fourcc.h> |
10 | #include <drm/drm_kunit_helpers.h> |
11 | #include <drm/drm_mode.h> |
12 | #include <drm/drm_modeset_helper_vtables.h> |
13 | #include <drm/drm_plane.h> |
14 | |
15 | #include <kunit/test.h> |
16 | |
17 | #include "../vc4_drv.h" |
18 | |
19 | #include "vc4_mock.h" |
20 | |
21 | struct pv_muxing_priv { |
22 | struct vc4_dev *vc4; |
23 | struct drm_atomic_state *state; |
24 | }; |
25 | |
26 | static bool check_fifo_conflict(struct kunit *test, |
27 | const struct drm_atomic_state *state) |
28 | { |
29 | struct vc4_hvs_state *hvs_state; |
30 | unsigned int used_fifos = 0; |
31 | unsigned int i; |
32 | |
33 | hvs_state = vc4_hvs_get_new_global_state(state); |
34 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hvs_state); |
35 | |
36 | for (i = 0; i < HVS_NUM_CHANNELS; i++) { |
37 | if (!hvs_state->fifo_state[i].in_use) |
38 | continue; |
39 | |
40 | KUNIT_EXPECT_FALSE(test, used_fifos & BIT(i)); |
41 | used_fifos |= BIT(i); |
42 | } |
43 | |
44 | return true; |
45 | } |
46 | |
47 | struct encoder_constraint { |
48 | enum vc4_encoder_type type; |
49 | unsigned int *channels; |
50 | size_t nchannels; |
51 | }; |
52 | |
53 | #define ENCODER_CONSTRAINT(_type, ...) \ |
54 | { \ |
55 | .type = _type, \ |
56 | .channels = (unsigned int[]) { __VA_ARGS__ }, \ |
57 | .nchannels = sizeof((unsigned int[]) { __VA_ARGS__ }) / \ |
58 | sizeof(unsigned int), \ |
59 | } |
60 | |
61 | static bool __check_encoder_constraints(const struct encoder_constraint *constraints, |
62 | size_t nconstraints, |
63 | enum vc4_encoder_type type, |
64 | unsigned int channel) |
65 | { |
66 | unsigned int i; |
67 | |
68 | for (i = 0; i < nconstraints; i++) { |
69 | const struct encoder_constraint *constraint = &constraints[i]; |
70 | unsigned int j; |
71 | |
72 | if (constraint->type != type) |
73 | continue; |
74 | |
75 | for (j = 0; j < constraint->nchannels; j++) { |
76 | unsigned int _channel = constraint->channels[j]; |
77 | |
78 | if (channel != _channel) |
79 | continue; |
80 | |
81 | return true; |
82 | } |
83 | } |
84 | |
85 | return false; |
86 | } |
87 | |
88 | static const struct encoder_constraint vc4_encoder_constraints[] = { |
89 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0), |
90 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0), |
91 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 1), |
92 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1), |
93 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 2), |
94 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 2), |
95 | }; |
96 | |
97 | static const struct encoder_constraint vc5_encoder_constraints[] = { |
98 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0), |
99 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0), |
100 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1), |
101 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 0, 2), |
102 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 0, 1, 2), |
103 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 0, 1, 2), |
104 | ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 0, 1, 2), |
105 | }; |
106 | |
107 | static bool check_vc4_encoder_constraints(enum vc4_encoder_type type, unsigned int channel) |
108 | { |
109 | return __check_encoder_constraints(constraints: vc4_encoder_constraints, |
110 | ARRAY_SIZE(vc4_encoder_constraints), |
111 | type, channel); |
112 | } |
113 | |
114 | static bool check_vc5_encoder_constraints(enum vc4_encoder_type type, unsigned int channel) |
115 | { |
116 | return __check_encoder_constraints(constraints: vc5_encoder_constraints, |
117 | ARRAY_SIZE(vc5_encoder_constraints), |
118 | type, channel); |
119 | } |
120 | |
121 | static struct vc4_crtc_state * |
122 | get_vc4_crtc_state_for_encoder(struct kunit *test, |
123 | const struct drm_atomic_state *state, |
124 | enum vc4_encoder_type type) |
125 | { |
126 | struct drm_device *drm = state->dev; |
127 | struct drm_crtc_state *new_crtc_state; |
128 | struct drm_encoder *encoder; |
129 | struct drm_crtc *crtc; |
130 | |
131 | encoder = vc4_find_encoder_by_type(drm, type); |
132 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder); |
133 | |
134 | crtc = vc4_find_crtc_for_encoder(test, drm, encoder); |
135 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc); |
136 | |
137 | new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); |
138 | if (!new_crtc_state) |
139 | return NULL; |
140 | |
141 | return to_vc4_crtc_state(new_crtc_state); |
142 | } |
143 | |
144 | static bool check_channel_for_encoder(struct kunit *test, |
145 | const struct drm_atomic_state *state, |
146 | enum vc4_encoder_type type, |
147 | bool (*check_fn)(enum vc4_encoder_type type, unsigned int channel)) |
148 | { |
149 | struct vc4_crtc_state *new_vc4_crtc_state; |
150 | struct vc4_hvs_state *new_hvs_state; |
151 | unsigned int channel; |
152 | |
153 | new_hvs_state = vc4_hvs_get_new_global_state(state); |
154 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state); |
155 | |
156 | new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, type); |
157 | KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state); |
158 | |
159 | channel = new_vc4_crtc_state->assigned_channel; |
160 | KUNIT_EXPECT_NE(test, channel, VC4_HVS_CHANNEL_DISABLED); |
161 | |
162 | KUNIT_EXPECT_TRUE(test, new_hvs_state->fifo_state[channel].in_use); |
163 | |
164 | KUNIT_EXPECT_TRUE(test, check_fn(type, channel)); |
165 | |
166 | return true; |
167 | } |
168 | |
169 | struct pv_muxing_param { |
170 | const char *name; |
171 | struct vc4_dev *(*mock_fn)(struct kunit *test); |
172 | bool (*check_fn)(enum vc4_encoder_type type, unsigned int channel); |
173 | enum vc4_encoder_type *encoders; |
174 | size_t nencoders; |
175 | }; |
176 | |
177 | static void vc4_test_pv_muxing_desc(const struct pv_muxing_param *t, char *desc) |
178 | { |
179 | strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); |
180 | } |
181 | |
182 | #define PV_MUXING_TEST(_name, _mock_fn, _check_fn, ...) \ |
183 | { \ |
184 | .name = _name, \ |
185 | .mock_fn = &_mock_fn, \ |
186 | .check_fn = &_check_fn, \ |
187 | .encoders = (enum vc4_encoder_type[]) { __VA_ARGS__ }, \ |
188 | .nencoders = sizeof((enum vc4_encoder_type[]) { __VA_ARGS__ }) / \ |
189 | sizeof(enum vc4_encoder_type), \ |
190 | } |
191 | |
192 | #define VC4_PV_MUXING_TEST(_name, ...) \ |
193 | PV_MUXING_TEST(_name, vc4_mock_device, check_vc4_encoder_constraints, __VA_ARGS__) |
194 | |
195 | #define VC5_PV_MUXING_TEST(_name, ...) \ |
196 | PV_MUXING_TEST(_name, vc5_mock_device, check_vc5_encoder_constraints, __VA_ARGS__) |
197 | |
198 | static const struct pv_muxing_param vc4_test_pv_muxing_params[] = { |
199 | VC4_PV_MUXING_TEST("1 output: DSI0" , |
200 | VC4_ENCODER_TYPE_DSI0), |
201 | VC4_PV_MUXING_TEST("1 output: DPI" , |
202 | VC4_ENCODER_TYPE_DPI), |
203 | VC4_PV_MUXING_TEST("1 output: HDMI0" , |
204 | VC4_ENCODER_TYPE_HDMI0), |
205 | VC4_PV_MUXING_TEST("1 output: VEC" , |
206 | VC4_ENCODER_TYPE_VEC), |
207 | VC4_PV_MUXING_TEST("1 output: DSI1" , |
208 | VC4_ENCODER_TYPE_DSI1), |
209 | VC4_PV_MUXING_TEST("1 output: TXP" , |
210 | VC4_ENCODER_TYPE_TXP), |
211 | VC4_PV_MUXING_TEST("2 outputs: DSI0, HDMI0" , |
212 | VC4_ENCODER_TYPE_DSI0, |
213 | VC4_ENCODER_TYPE_HDMI0), |
214 | VC4_PV_MUXING_TEST("2 outputs: DSI0, VEC" , |
215 | VC4_ENCODER_TYPE_DSI0, |
216 | VC4_ENCODER_TYPE_VEC), |
217 | VC4_PV_MUXING_TEST("2 outputs: DSI0, DSI1" , |
218 | VC4_ENCODER_TYPE_DSI0, |
219 | VC4_ENCODER_TYPE_DSI1), |
220 | VC4_PV_MUXING_TEST("2 outputs: DSI0, TXP" , |
221 | VC4_ENCODER_TYPE_DSI0, |
222 | VC4_ENCODER_TYPE_TXP), |
223 | VC4_PV_MUXING_TEST("2 outputs: DPI, HDMI0" , |
224 | VC4_ENCODER_TYPE_DPI, |
225 | VC4_ENCODER_TYPE_HDMI0), |
226 | VC4_PV_MUXING_TEST("2 outputs: DPI, VEC" , |
227 | VC4_ENCODER_TYPE_DPI, |
228 | VC4_ENCODER_TYPE_VEC), |
229 | VC4_PV_MUXING_TEST("2 outputs: DPI, DSI1" , |
230 | VC4_ENCODER_TYPE_DPI, |
231 | VC4_ENCODER_TYPE_DSI1), |
232 | VC4_PV_MUXING_TEST("2 outputs: DPI, TXP" , |
233 | VC4_ENCODER_TYPE_DPI, |
234 | VC4_ENCODER_TYPE_TXP), |
235 | VC4_PV_MUXING_TEST("2 outputs: HDMI0, DSI1" , |
236 | VC4_ENCODER_TYPE_HDMI0, |
237 | VC4_ENCODER_TYPE_DSI1), |
238 | VC4_PV_MUXING_TEST("2 outputs: HDMI0, TXP" , |
239 | VC4_ENCODER_TYPE_HDMI0, |
240 | VC4_ENCODER_TYPE_TXP), |
241 | VC4_PV_MUXING_TEST("2 outputs: VEC, DSI1" , |
242 | VC4_ENCODER_TYPE_VEC, |
243 | VC4_ENCODER_TYPE_DSI1), |
244 | VC4_PV_MUXING_TEST("2 outputs: VEC, TXP" , |
245 | VC4_ENCODER_TYPE_VEC, |
246 | VC4_ENCODER_TYPE_TXP), |
247 | VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, DSI1" , |
248 | VC4_ENCODER_TYPE_DSI0, |
249 | VC4_ENCODER_TYPE_HDMI0, |
250 | VC4_ENCODER_TYPE_DSI1), |
251 | VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, TXP" , |
252 | VC4_ENCODER_TYPE_DSI0, |
253 | VC4_ENCODER_TYPE_HDMI0, |
254 | VC4_ENCODER_TYPE_TXP), |
255 | VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1" , |
256 | VC4_ENCODER_TYPE_DSI0, |
257 | VC4_ENCODER_TYPE_VEC, |
258 | VC4_ENCODER_TYPE_DSI1), |
259 | VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP" , |
260 | VC4_ENCODER_TYPE_DSI0, |
261 | VC4_ENCODER_TYPE_VEC, |
262 | VC4_ENCODER_TYPE_TXP), |
263 | VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, DSI1" , |
264 | VC4_ENCODER_TYPE_DPI, |
265 | VC4_ENCODER_TYPE_HDMI0, |
266 | VC4_ENCODER_TYPE_DSI1), |
267 | VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, TXP" , |
268 | VC4_ENCODER_TYPE_DPI, |
269 | VC4_ENCODER_TYPE_HDMI0, |
270 | VC4_ENCODER_TYPE_TXP), |
271 | VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1" , |
272 | VC4_ENCODER_TYPE_DPI, |
273 | VC4_ENCODER_TYPE_VEC, |
274 | VC4_ENCODER_TYPE_DSI1), |
275 | VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP" , |
276 | VC4_ENCODER_TYPE_DPI, |
277 | VC4_ENCODER_TYPE_VEC, |
278 | VC4_ENCODER_TYPE_TXP), |
279 | }; |
280 | |
281 | KUNIT_ARRAY_PARAM(vc4_test_pv_muxing, |
282 | vc4_test_pv_muxing_params, |
283 | vc4_test_pv_muxing_desc); |
284 | |
285 | static const struct pv_muxing_param vc4_test_pv_muxing_invalid_params[] = { |
286 | VC4_PV_MUXING_TEST("DPI/DSI0 Conflict" , |
287 | VC4_ENCODER_TYPE_DPI, |
288 | VC4_ENCODER_TYPE_DSI0), |
289 | VC4_PV_MUXING_TEST("TXP/DSI1 Conflict" , |
290 | VC4_ENCODER_TYPE_TXP, |
291 | VC4_ENCODER_TYPE_DSI1), |
292 | VC4_PV_MUXING_TEST("HDMI0/VEC Conflict" , |
293 | VC4_ENCODER_TYPE_HDMI0, |
294 | VC4_ENCODER_TYPE_VEC), |
295 | VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, HDMI0, DSI1, TXP" , |
296 | VC4_ENCODER_TYPE_DSI0, |
297 | VC4_ENCODER_TYPE_HDMI0, |
298 | VC4_ENCODER_TYPE_DSI1, |
299 | VC4_ENCODER_TYPE_TXP), |
300 | VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, TXP" , |
301 | VC4_ENCODER_TYPE_DSI0, |
302 | VC4_ENCODER_TYPE_VEC, |
303 | VC4_ENCODER_TYPE_DSI1, |
304 | VC4_ENCODER_TYPE_TXP), |
305 | VC4_PV_MUXING_TEST("More than 3 outputs: DPI, HDMI0, DSI1, TXP" , |
306 | VC4_ENCODER_TYPE_DPI, |
307 | VC4_ENCODER_TYPE_HDMI0, |
308 | VC4_ENCODER_TYPE_DSI1, |
309 | VC4_ENCODER_TYPE_TXP), |
310 | VC4_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, TXP" , |
311 | VC4_ENCODER_TYPE_DPI, |
312 | VC4_ENCODER_TYPE_VEC, |
313 | VC4_ENCODER_TYPE_DSI1, |
314 | VC4_ENCODER_TYPE_TXP), |
315 | }; |
316 | |
317 | KUNIT_ARRAY_PARAM(vc4_test_pv_muxing_invalid, |
318 | vc4_test_pv_muxing_invalid_params, |
319 | vc4_test_pv_muxing_desc); |
320 | |
321 | static const struct pv_muxing_param vc5_test_pv_muxing_params[] = { |
322 | VC5_PV_MUXING_TEST("1 output: DPI" , |
323 | VC4_ENCODER_TYPE_DPI), |
324 | VC5_PV_MUXING_TEST("1 output: DSI0" , |
325 | VC4_ENCODER_TYPE_DSI0), |
326 | VC5_PV_MUXING_TEST("1 output: DSI1" , |
327 | VC4_ENCODER_TYPE_DSI1), |
328 | VC5_PV_MUXING_TEST("1 output: HDMI0" , |
329 | VC4_ENCODER_TYPE_HDMI0), |
330 | VC5_PV_MUXING_TEST("1 output: HDMI1" , |
331 | VC4_ENCODER_TYPE_HDMI1), |
332 | VC5_PV_MUXING_TEST("1 output: VEC" , |
333 | VC4_ENCODER_TYPE_VEC), |
334 | VC5_PV_MUXING_TEST("2 outputs: DPI, DSI1" , |
335 | VC4_ENCODER_TYPE_DPI, |
336 | VC4_ENCODER_TYPE_DSI1), |
337 | VC5_PV_MUXING_TEST("2 outputs: DPI, HDMI0" , |
338 | VC4_ENCODER_TYPE_DPI, |
339 | VC4_ENCODER_TYPE_HDMI0), |
340 | VC5_PV_MUXING_TEST("2 outputs: DPI, HDMI1" , |
341 | VC4_ENCODER_TYPE_DPI, |
342 | VC4_ENCODER_TYPE_HDMI1), |
343 | VC5_PV_MUXING_TEST("2 outputs: DPI, TXP" , |
344 | VC4_ENCODER_TYPE_DPI, |
345 | VC4_ENCODER_TYPE_TXP), |
346 | VC5_PV_MUXING_TEST("2 outputs: DPI, VEC" , |
347 | VC4_ENCODER_TYPE_DPI, |
348 | VC4_ENCODER_TYPE_VEC), |
349 | VC5_PV_MUXING_TEST("2 outputs: DPI, DSI1" , |
350 | VC4_ENCODER_TYPE_DPI, |
351 | VC4_ENCODER_TYPE_DSI1), |
352 | VC5_PV_MUXING_TEST("2 outputs: DSI0, DSI1" , |
353 | VC4_ENCODER_TYPE_DSI0, |
354 | VC4_ENCODER_TYPE_DSI1), |
355 | VC5_PV_MUXING_TEST("2 outputs: DSI0, HDMI0" , |
356 | VC4_ENCODER_TYPE_DSI0, |
357 | VC4_ENCODER_TYPE_HDMI0), |
358 | VC5_PV_MUXING_TEST("2 outputs: DSI0, HDMI1" , |
359 | VC4_ENCODER_TYPE_DSI0, |
360 | VC4_ENCODER_TYPE_HDMI1), |
361 | VC5_PV_MUXING_TEST("2 outputs: DSI0, TXP" , |
362 | VC4_ENCODER_TYPE_DSI0, |
363 | VC4_ENCODER_TYPE_TXP), |
364 | VC5_PV_MUXING_TEST("2 outputs: DSI0, VEC" , |
365 | VC4_ENCODER_TYPE_DSI0, |
366 | VC4_ENCODER_TYPE_VEC), |
367 | VC5_PV_MUXING_TEST("2 outputs: DSI0, DSI1" , |
368 | VC4_ENCODER_TYPE_DSI0, |
369 | VC4_ENCODER_TYPE_DSI1), |
370 | VC5_PV_MUXING_TEST("2 outputs: DSI1, VEC" , |
371 | VC4_ENCODER_TYPE_DSI1, |
372 | VC4_ENCODER_TYPE_VEC), |
373 | VC5_PV_MUXING_TEST("2 outputs: DSI1, TXP" , |
374 | VC4_ENCODER_TYPE_DSI1, |
375 | VC4_ENCODER_TYPE_TXP), |
376 | VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI0" , |
377 | VC4_ENCODER_TYPE_DSI1, |
378 | VC4_ENCODER_TYPE_HDMI0), |
379 | VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI1" , |
380 | VC4_ENCODER_TYPE_DSI1, |
381 | VC4_ENCODER_TYPE_HDMI1), |
382 | VC5_PV_MUXING_TEST("2 outputs: HDMI0, VEC" , |
383 | VC4_ENCODER_TYPE_HDMI0, |
384 | VC4_ENCODER_TYPE_VEC), |
385 | VC5_PV_MUXING_TEST("2 outputs: HDMI0, TXP" , |
386 | VC4_ENCODER_TYPE_HDMI0, |
387 | VC4_ENCODER_TYPE_TXP), |
388 | VC5_PV_MUXING_TEST("2 outputs: HDMI0, HDMI1" , |
389 | VC4_ENCODER_TYPE_HDMI0, |
390 | VC4_ENCODER_TYPE_HDMI1), |
391 | VC5_PV_MUXING_TEST("2 outputs: HDMI1, VEC" , |
392 | VC4_ENCODER_TYPE_HDMI1, |
393 | VC4_ENCODER_TYPE_VEC), |
394 | VC5_PV_MUXING_TEST("2 outputs: HDMI1, TXP" , |
395 | VC4_ENCODER_TYPE_HDMI1, |
396 | VC4_ENCODER_TYPE_TXP), |
397 | VC5_PV_MUXING_TEST("2 outputs: TXP, VEC" , |
398 | VC4_ENCODER_TYPE_TXP, |
399 | VC4_ENCODER_TYPE_VEC), |
400 | VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP" , |
401 | VC4_ENCODER_TYPE_DPI, |
402 | VC4_ENCODER_TYPE_VEC, |
403 | VC4_ENCODER_TYPE_TXP), |
404 | VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1" , |
405 | VC4_ENCODER_TYPE_DPI, |
406 | VC4_ENCODER_TYPE_VEC, |
407 | VC4_ENCODER_TYPE_DSI1), |
408 | VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, HDMI0" , |
409 | VC4_ENCODER_TYPE_DPI, |
410 | VC4_ENCODER_TYPE_VEC, |
411 | VC4_ENCODER_TYPE_HDMI0), |
412 | VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, HDMI1" , |
413 | VC4_ENCODER_TYPE_DPI, |
414 | VC4_ENCODER_TYPE_VEC, |
415 | VC4_ENCODER_TYPE_HDMI1), |
416 | VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, DSI1" , |
417 | VC4_ENCODER_TYPE_DPI, |
418 | VC4_ENCODER_TYPE_TXP, |
419 | VC4_ENCODER_TYPE_DSI1), |
420 | VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI0" , |
421 | VC4_ENCODER_TYPE_DPI, |
422 | VC4_ENCODER_TYPE_TXP, |
423 | VC4_ENCODER_TYPE_HDMI0), |
424 | VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI1" , |
425 | VC4_ENCODER_TYPE_DPI, |
426 | VC4_ENCODER_TYPE_TXP, |
427 | VC4_ENCODER_TYPE_HDMI1), |
428 | VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI0" , |
429 | VC4_ENCODER_TYPE_DPI, |
430 | VC4_ENCODER_TYPE_DSI1, |
431 | VC4_ENCODER_TYPE_HDMI0), |
432 | VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI1" , |
433 | VC4_ENCODER_TYPE_DPI, |
434 | VC4_ENCODER_TYPE_DSI1, |
435 | VC4_ENCODER_TYPE_HDMI1), |
436 | VC5_PV_MUXING_TEST("3 outputs: DPI, HDMI0, HDMI1" , |
437 | VC4_ENCODER_TYPE_DPI, |
438 | VC4_ENCODER_TYPE_HDMI0, |
439 | VC4_ENCODER_TYPE_HDMI1), |
440 | VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP" , |
441 | VC4_ENCODER_TYPE_DSI0, |
442 | VC4_ENCODER_TYPE_VEC, |
443 | VC4_ENCODER_TYPE_TXP), |
444 | VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1" , |
445 | VC4_ENCODER_TYPE_DSI0, |
446 | VC4_ENCODER_TYPE_VEC, |
447 | VC4_ENCODER_TYPE_DSI1), |
448 | VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, HDMI0" , |
449 | VC4_ENCODER_TYPE_DSI0, |
450 | VC4_ENCODER_TYPE_VEC, |
451 | VC4_ENCODER_TYPE_HDMI0), |
452 | VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, HDMI1" , |
453 | VC4_ENCODER_TYPE_DSI0, |
454 | VC4_ENCODER_TYPE_VEC, |
455 | VC4_ENCODER_TYPE_HDMI1), |
456 | VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, DSI1" , |
457 | VC4_ENCODER_TYPE_DSI0, |
458 | VC4_ENCODER_TYPE_TXP, |
459 | VC4_ENCODER_TYPE_DSI1), |
460 | VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI0" , |
461 | VC4_ENCODER_TYPE_DSI0, |
462 | VC4_ENCODER_TYPE_TXP, |
463 | VC4_ENCODER_TYPE_HDMI0), |
464 | VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI1" , |
465 | VC4_ENCODER_TYPE_DSI0, |
466 | VC4_ENCODER_TYPE_TXP, |
467 | VC4_ENCODER_TYPE_HDMI1), |
468 | VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI0" , |
469 | VC4_ENCODER_TYPE_DSI0, |
470 | VC4_ENCODER_TYPE_DSI1, |
471 | VC4_ENCODER_TYPE_HDMI0), |
472 | VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI1" , |
473 | VC4_ENCODER_TYPE_DSI0, |
474 | VC4_ENCODER_TYPE_DSI1, |
475 | VC4_ENCODER_TYPE_HDMI1), |
476 | VC5_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, HDMI1" , |
477 | VC4_ENCODER_TYPE_DSI0, |
478 | VC4_ENCODER_TYPE_HDMI0, |
479 | VC4_ENCODER_TYPE_HDMI1), |
480 | }; |
481 | |
482 | KUNIT_ARRAY_PARAM(vc5_test_pv_muxing, |
483 | vc5_test_pv_muxing_params, |
484 | vc4_test_pv_muxing_desc); |
485 | |
486 | static const struct pv_muxing_param vc5_test_pv_muxing_invalid_params[] = { |
487 | VC5_PV_MUXING_TEST("DPI/DSI0 Conflict" , |
488 | VC4_ENCODER_TYPE_DPI, |
489 | VC4_ENCODER_TYPE_DSI0), |
490 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1" , |
491 | VC4_ENCODER_TYPE_DPI, |
492 | VC4_ENCODER_TYPE_VEC, |
493 | VC4_ENCODER_TYPE_TXP, |
494 | VC4_ENCODER_TYPE_DSI1), |
495 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0" , |
496 | VC4_ENCODER_TYPE_DPI, |
497 | VC4_ENCODER_TYPE_VEC, |
498 | VC4_ENCODER_TYPE_TXP, |
499 | VC4_ENCODER_TYPE_HDMI0), |
500 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI1" , |
501 | VC4_ENCODER_TYPE_DPI, |
502 | VC4_ENCODER_TYPE_VEC, |
503 | VC4_ENCODER_TYPE_TXP, |
504 | VC4_ENCODER_TYPE_HDMI1), |
505 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0" , |
506 | VC4_ENCODER_TYPE_DPI, |
507 | VC4_ENCODER_TYPE_VEC, |
508 | VC4_ENCODER_TYPE_DSI1, |
509 | VC4_ENCODER_TYPE_HDMI0), |
510 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI1" , |
511 | VC4_ENCODER_TYPE_DPI, |
512 | VC4_ENCODER_TYPE_VEC, |
513 | VC4_ENCODER_TYPE_DSI1, |
514 | VC4_ENCODER_TYPE_HDMI1), |
515 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, HDMI0, HDMI1" , |
516 | VC4_ENCODER_TYPE_DPI, |
517 | VC4_ENCODER_TYPE_VEC, |
518 | VC4_ENCODER_TYPE_HDMI0, |
519 | VC4_ENCODER_TYPE_HDMI1), |
520 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0" , |
521 | VC4_ENCODER_TYPE_DPI, |
522 | VC4_ENCODER_TYPE_TXP, |
523 | VC4_ENCODER_TYPE_DSI1, |
524 | VC4_ENCODER_TYPE_HDMI0), |
525 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI1" , |
526 | VC4_ENCODER_TYPE_DPI, |
527 | VC4_ENCODER_TYPE_TXP, |
528 | VC4_ENCODER_TYPE_DSI1, |
529 | VC4_ENCODER_TYPE_HDMI1), |
530 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, HDMI0, HDMI1" , |
531 | VC4_ENCODER_TYPE_DPI, |
532 | VC4_ENCODER_TYPE_TXP, |
533 | VC4_ENCODER_TYPE_HDMI0, |
534 | VC4_ENCODER_TYPE_HDMI1), |
535 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, DSI1, HDMI0, HDMI1" , |
536 | VC4_ENCODER_TYPE_DPI, |
537 | VC4_ENCODER_TYPE_DSI1, |
538 | VC4_ENCODER_TYPE_HDMI0, |
539 | VC4_ENCODER_TYPE_HDMI1), |
540 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0" , |
541 | VC4_ENCODER_TYPE_DPI, |
542 | VC4_ENCODER_TYPE_VEC, |
543 | VC4_ENCODER_TYPE_TXP, |
544 | VC4_ENCODER_TYPE_DSI1, |
545 | VC4_ENCODER_TYPE_HDMI0), |
546 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI1" , |
547 | VC4_ENCODER_TYPE_DPI, |
548 | VC4_ENCODER_TYPE_VEC, |
549 | VC4_ENCODER_TYPE_TXP, |
550 | VC4_ENCODER_TYPE_DSI1, |
551 | VC4_ENCODER_TYPE_HDMI1), |
552 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0, HDMI1" , |
553 | VC4_ENCODER_TYPE_DPI, |
554 | VC4_ENCODER_TYPE_VEC, |
555 | VC4_ENCODER_TYPE_TXP, |
556 | VC4_ENCODER_TYPE_HDMI0, |
557 | VC4_ENCODER_TYPE_HDMI1), |
558 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0, HDMI1" , |
559 | VC4_ENCODER_TYPE_DPI, |
560 | VC4_ENCODER_TYPE_VEC, |
561 | VC4_ENCODER_TYPE_DSI1, |
562 | VC4_ENCODER_TYPE_HDMI0, |
563 | VC4_ENCODER_TYPE_HDMI1), |
564 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0, HDMI1" , |
565 | VC4_ENCODER_TYPE_DPI, |
566 | VC4_ENCODER_TYPE_TXP, |
567 | VC4_ENCODER_TYPE_DSI1, |
568 | VC4_ENCODER_TYPE_HDMI0, |
569 | VC4_ENCODER_TYPE_HDMI1), |
570 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1" , |
571 | VC4_ENCODER_TYPE_DSI0, |
572 | VC4_ENCODER_TYPE_VEC, |
573 | VC4_ENCODER_TYPE_TXP, |
574 | VC4_ENCODER_TYPE_DSI1), |
575 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0" , |
576 | VC4_ENCODER_TYPE_DSI0, |
577 | VC4_ENCODER_TYPE_VEC, |
578 | VC4_ENCODER_TYPE_TXP, |
579 | VC4_ENCODER_TYPE_HDMI0), |
580 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI1" , |
581 | VC4_ENCODER_TYPE_DSI0, |
582 | VC4_ENCODER_TYPE_VEC, |
583 | VC4_ENCODER_TYPE_TXP, |
584 | VC4_ENCODER_TYPE_HDMI1), |
585 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0" , |
586 | VC4_ENCODER_TYPE_DSI0, |
587 | VC4_ENCODER_TYPE_VEC, |
588 | VC4_ENCODER_TYPE_DSI1, |
589 | VC4_ENCODER_TYPE_HDMI0), |
590 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI1" , |
591 | VC4_ENCODER_TYPE_DSI0, |
592 | VC4_ENCODER_TYPE_VEC, |
593 | VC4_ENCODER_TYPE_DSI1, |
594 | VC4_ENCODER_TYPE_HDMI1), |
595 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, HDMI0, HDMI1" , |
596 | VC4_ENCODER_TYPE_DSI0, |
597 | VC4_ENCODER_TYPE_VEC, |
598 | VC4_ENCODER_TYPE_HDMI0, |
599 | VC4_ENCODER_TYPE_HDMI1), |
600 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0" , |
601 | VC4_ENCODER_TYPE_DSI0, |
602 | VC4_ENCODER_TYPE_TXP, |
603 | VC4_ENCODER_TYPE_DSI1, |
604 | VC4_ENCODER_TYPE_HDMI0), |
605 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI1" , |
606 | VC4_ENCODER_TYPE_DSI0, |
607 | VC4_ENCODER_TYPE_TXP, |
608 | VC4_ENCODER_TYPE_DSI1, |
609 | VC4_ENCODER_TYPE_HDMI1), |
610 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, HDMI0, HDMI1" , |
611 | VC4_ENCODER_TYPE_DSI0, |
612 | VC4_ENCODER_TYPE_TXP, |
613 | VC4_ENCODER_TYPE_HDMI0, |
614 | VC4_ENCODER_TYPE_HDMI1), |
615 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, DSI1, HDMI0, HDMI1" , |
616 | VC4_ENCODER_TYPE_DSI0, |
617 | VC4_ENCODER_TYPE_DSI1, |
618 | VC4_ENCODER_TYPE_HDMI0, |
619 | VC4_ENCODER_TYPE_HDMI1), |
620 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0" , |
621 | VC4_ENCODER_TYPE_DSI0, |
622 | VC4_ENCODER_TYPE_VEC, |
623 | VC4_ENCODER_TYPE_TXP, |
624 | VC4_ENCODER_TYPE_DSI1, |
625 | VC4_ENCODER_TYPE_HDMI0), |
626 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI1" , |
627 | VC4_ENCODER_TYPE_DSI0, |
628 | VC4_ENCODER_TYPE_VEC, |
629 | VC4_ENCODER_TYPE_TXP, |
630 | VC4_ENCODER_TYPE_DSI1, |
631 | VC4_ENCODER_TYPE_HDMI1), |
632 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0, HDMI1" , |
633 | VC4_ENCODER_TYPE_DSI0, |
634 | VC4_ENCODER_TYPE_VEC, |
635 | VC4_ENCODER_TYPE_TXP, |
636 | VC4_ENCODER_TYPE_HDMI0, |
637 | VC4_ENCODER_TYPE_HDMI1), |
638 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0, HDMI1" , |
639 | VC4_ENCODER_TYPE_DSI0, |
640 | VC4_ENCODER_TYPE_VEC, |
641 | VC4_ENCODER_TYPE_DSI1, |
642 | VC4_ENCODER_TYPE_HDMI0, |
643 | VC4_ENCODER_TYPE_HDMI1), |
644 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0, HDMI1" , |
645 | VC4_ENCODER_TYPE_DSI0, |
646 | VC4_ENCODER_TYPE_TXP, |
647 | VC4_ENCODER_TYPE_DSI1, |
648 | VC4_ENCODER_TYPE_HDMI0, |
649 | VC4_ENCODER_TYPE_HDMI1), |
650 | VC5_PV_MUXING_TEST("More than 3 outputs: VEC, TXP, DSI1, HDMI0, HDMI1" , |
651 | VC4_ENCODER_TYPE_VEC, |
652 | VC4_ENCODER_TYPE_TXP, |
653 | VC4_ENCODER_TYPE_DSI1, |
654 | VC4_ENCODER_TYPE_HDMI0, |
655 | VC4_ENCODER_TYPE_HDMI1), |
656 | VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0, HDMI1" , |
657 | VC4_ENCODER_TYPE_DPI, |
658 | VC4_ENCODER_TYPE_VEC, |
659 | VC4_ENCODER_TYPE_TXP, |
660 | VC4_ENCODER_TYPE_DSI1, |
661 | VC4_ENCODER_TYPE_HDMI0, |
662 | VC4_ENCODER_TYPE_HDMI1), |
663 | VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0, HDMI1" , |
664 | VC4_ENCODER_TYPE_DSI0, |
665 | VC4_ENCODER_TYPE_VEC, |
666 | VC4_ENCODER_TYPE_TXP, |
667 | VC4_ENCODER_TYPE_DSI1, |
668 | VC4_ENCODER_TYPE_HDMI0, |
669 | VC4_ENCODER_TYPE_HDMI1), |
670 | }; |
671 | |
672 | KUNIT_ARRAY_PARAM(vc5_test_pv_muxing_invalid, |
673 | vc5_test_pv_muxing_invalid_params, |
674 | vc4_test_pv_muxing_desc); |
675 | |
676 | static void drm_vc4_test_pv_muxing(struct kunit *test) |
677 | { |
678 | const struct pv_muxing_param *params = test->param_value; |
679 | const struct pv_muxing_priv *priv = test->priv; |
680 | struct drm_atomic_state *state = priv->state; |
681 | unsigned int i; |
682 | int ret; |
683 | |
684 | for (i = 0; i < params->nencoders; i++) { |
685 | enum vc4_encoder_type enc_type = params->encoders[i]; |
686 | |
687 | ret = vc4_mock_atomic_add_output(test, state, type: enc_type); |
688 | KUNIT_ASSERT_EQ(test, ret, 0); |
689 | } |
690 | |
691 | ret = drm_atomic_check_only(state); |
692 | KUNIT_EXPECT_EQ(test, ret, 0); |
693 | |
694 | KUNIT_EXPECT_TRUE(test, |
695 | check_fifo_conflict(test, state)); |
696 | |
697 | for (i = 0; i < params->nencoders; i++) { |
698 | enum vc4_encoder_type enc_type = params->encoders[i]; |
699 | |
700 | KUNIT_EXPECT_TRUE(test, check_channel_for_encoder(test, state, enc_type, |
701 | params->check_fn)); |
702 | } |
703 | } |
704 | |
705 | static void drm_vc4_test_pv_muxing_invalid(struct kunit *test) |
706 | { |
707 | const struct pv_muxing_param *params = test->param_value; |
708 | const struct pv_muxing_priv *priv = test->priv; |
709 | struct drm_atomic_state *state = priv->state; |
710 | unsigned int i; |
711 | int ret; |
712 | |
713 | for (i = 0; i < params->nencoders; i++) { |
714 | enum vc4_encoder_type enc_type = params->encoders[i]; |
715 | |
716 | ret = vc4_mock_atomic_add_output(test, state, type: enc_type); |
717 | KUNIT_ASSERT_EQ(test, ret, 0); |
718 | } |
719 | |
720 | ret = drm_atomic_check_only(state); |
721 | KUNIT_EXPECT_LT(test, ret, 0); |
722 | } |
723 | |
724 | static int vc4_pv_muxing_test_init(struct kunit *test) |
725 | { |
726 | const struct pv_muxing_param *params = test->param_value; |
727 | struct drm_modeset_acquire_ctx *ctx; |
728 | struct pv_muxing_priv *priv; |
729 | struct drm_device *drm; |
730 | struct vc4_dev *vc4; |
731 | |
732 | priv = kunit_kzalloc(test, size: sizeof(*priv), GFP_KERNEL); |
733 | KUNIT_ASSERT_NOT_NULL(test, priv); |
734 | test->priv = priv; |
735 | |
736 | vc4 = params->mock_fn(test); |
737 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); |
738 | priv->vc4 = vc4; |
739 | |
740 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
741 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
742 | |
743 | drm = &vc4->base; |
744 | priv->state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); |
745 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->state); |
746 | |
747 | return 0; |
748 | } |
749 | |
750 | static struct kunit_case vc4_pv_muxing_tests[] = { |
751 | KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing, |
752 | vc4_test_pv_muxing_gen_params), |
753 | KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid, |
754 | vc4_test_pv_muxing_invalid_gen_params), |
755 | {} |
756 | }; |
757 | |
758 | static struct kunit_suite vc4_pv_muxing_test_suite = { |
759 | .name = "vc4-pv-muxing-combinations" , |
760 | .init = vc4_pv_muxing_test_init, |
761 | .test_cases = vc4_pv_muxing_tests, |
762 | }; |
763 | |
764 | static struct kunit_case vc5_pv_muxing_tests[] = { |
765 | KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing, |
766 | vc5_test_pv_muxing_gen_params), |
767 | KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid, |
768 | vc5_test_pv_muxing_invalid_gen_params), |
769 | {} |
770 | }; |
771 | |
772 | static struct kunit_suite vc5_pv_muxing_test_suite = { |
773 | .name = "vc5-pv-muxing-combinations" , |
774 | .init = vc4_pv_muxing_test_init, |
775 | .test_cases = vc5_pv_muxing_tests, |
776 | }; |
777 | |
778 | /* See |
779 | * https://lore.kernel.org/all/3e113525-aa89-b1e2-56b7-ca55bd41d057@samsung.com/ |
780 | * and |
781 | * https://lore.kernel.org/dri-devel/20200917121623.42023-1-maxime@cerno.tech/ |
782 | */ |
783 | static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *test) |
784 | { |
785 | struct drm_modeset_acquire_ctx *ctx; |
786 | struct drm_atomic_state *state; |
787 | struct vc4_crtc_state *new_vc4_crtc_state; |
788 | struct vc4_hvs_state *new_hvs_state; |
789 | unsigned int hdmi0_channel; |
790 | unsigned int hdmi1_channel; |
791 | struct drm_device *drm; |
792 | struct vc4_dev *vc4; |
793 | int ret; |
794 | |
795 | vc4 = vc5_mock_device(test); |
796 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); |
797 | |
798 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
799 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
800 | |
801 | drm = &vc4->base; |
802 | state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); |
803 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); |
804 | |
805 | ret = vc4_mock_atomic_add_output(test, state, type: VC4_ENCODER_TYPE_HDMI0); |
806 | KUNIT_ASSERT_EQ(test, ret, 0); |
807 | |
808 | ret = drm_atomic_check_only(state); |
809 | KUNIT_ASSERT_EQ(test, ret, 0); |
810 | |
811 | new_hvs_state = vc4_hvs_get_new_global_state(state); |
812 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state); |
813 | |
814 | new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, |
815 | type: VC4_ENCODER_TYPE_HDMI0); |
816 | KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state); |
817 | |
818 | hdmi0_channel = new_vc4_crtc_state->assigned_channel; |
819 | KUNIT_ASSERT_NE(test, hdmi0_channel, VC4_HVS_CHANNEL_DISABLED); |
820 | KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi0_channel].in_use); |
821 | |
822 | ret = drm_atomic_helper_swap_state(state, stall: false); |
823 | KUNIT_ASSERT_EQ(test, ret, 0); |
824 | |
825 | state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); |
826 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); |
827 | |
828 | ret = vc4_mock_atomic_add_output(test, state, type: VC4_ENCODER_TYPE_HDMI1); |
829 | KUNIT_ASSERT_EQ(test, ret, 0); |
830 | |
831 | ret = drm_atomic_check_only(state); |
832 | KUNIT_ASSERT_EQ(test, ret, 0); |
833 | |
834 | new_hvs_state = vc4_hvs_get_new_global_state(state); |
835 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state); |
836 | |
837 | new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, |
838 | type: VC4_ENCODER_TYPE_HDMI1); |
839 | KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state); |
840 | |
841 | hdmi1_channel = new_vc4_crtc_state->assigned_channel; |
842 | KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED); |
843 | KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use); |
844 | |
845 | KUNIT_EXPECT_NE(test, hdmi0_channel, hdmi1_channel); |
846 | } |
847 | |
848 | /* |
849 | * This test makes sure that we never change the FIFO of an active HVS |
850 | * channel if we disable a FIFO with a lower index. |
851 | * |
852 | * Doing so would result in a FIFO stall and would disrupt an output |
853 | * supposed to be unaffected by the commit. |
854 | */ |
855 | static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test) |
856 | { |
857 | struct drm_modeset_acquire_ctx *ctx; |
858 | struct drm_atomic_state *state; |
859 | struct vc4_crtc_state *new_vc4_crtc_state; |
860 | struct vc4_hvs_state *new_hvs_state; |
861 | unsigned int old_hdmi0_channel; |
862 | unsigned int old_hdmi1_channel; |
863 | struct drm_device *drm; |
864 | struct vc4_dev *vc4; |
865 | int ret; |
866 | |
867 | vc4 = vc5_mock_device(test); |
868 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); |
869 | |
870 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
871 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
872 | |
873 | drm = &vc4->base; |
874 | state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); |
875 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); |
876 | |
877 | ret = vc4_mock_atomic_add_output(test, state, type: VC4_ENCODER_TYPE_HDMI0); |
878 | KUNIT_ASSERT_EQ(test, ret, 0); |
879 | |
880 | ret = vc4_mock_atomic_add_output(test, state, type: VC4_ENCODER_TYPE_HDMI1); |
881 | KUNIT_ASSERT_EQ(test, ret, 0); |
882 | |
883 | ret = drm_atomic_check_only(state); |
884 | KUNIT_ASSERT_EQ(test, ret, 0); |
885 | |
886 | new_hvs_state = vc4_hvs_get_new_global_state(state); |
887 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state); |
888 | |
889 | new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, |
890 | type: VC4_ENCODER_TYPE_HDMI0); |
891 | KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state); |
892 | |
893 | old_hdmi0_channel = new_vc4_crtc_state->assigned_channel; |
894 | KUNIT_ASSERT_NE(test, old_hdmi0_channel, VC4_HVS_CHANNEL_DISABLED); |
895 | KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi0_channel].in_use); |
896 | |
897 | new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, |
898 | type: VC4_ENCODER_TYPE_HDMI1); |
899 | KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state); |
900 | |
901 | old_hdmi1_channel = new_vc4_crtc_state->assigned_channel; |
902 | KUNIT_ASSERT_NE(test, old_hdmi1_channel, VC4_HVS_CHANNEL_DISABLED); |
903 | KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi1_channel].in_use); |
904 | |
905 | ret = drm_atomic_helper_swap_state(state, stall: false); |
906 | KUNIT_ASSERT_EQ(test, ret, 0); |
907 | |
908 | state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); |
909 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); |
910 | |
911 | ret = vc4_mock_atomic_del_output(test, state, type: VC4_ENCODER_TYPE_HDMI0); |
912 | KUNIT_ASSERT_EQ(test, ret, 0); |
913 | |
914 | ret = drm_atomic_check_only(state); |
915 | KUNIT_ASSERT_EQ(test, ret, 0); |
916 | |
917 | new_hvs_state = vc4_hvs_get_new_global_state(state); |
918 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state); |
919 | |
920 | new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, |
921 | type: VC4_ENCODER_TYPE_HDMI1); |
922 | |
923 | if (new_vc4_crtc_state) { |
924 | unsigned int hdmi1_channel; |
925 | |
926 | hdmi1_channel = new_vc4_crtc_state->assigned_channel; |
927 | KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED); |
928 | KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use); |
929 | |
930 | KUNIT_EXPECT_EQ(test, old_hdmi1_channel, hdmi1_channel); |
931 | } |
932 | } |
933 | |
934 | /* |
935 | * Test that if we affect a single output, only the CRTC state of that |
936 | * output will be pulled in the global atomic state. |
937 | * |
938 | * This is relevant for two things: |
939 | * |
940 | * - If we don't have that state at all, we are unlikely to affect the |
941 | * FIFO muxing. This is somewhat redundant with |
942 | * drm_test_vc5_pv_muxing_bugs_stable_fifo() |
943 | * |
944 | * - KMS waits for page flips to occur on all the CRTC found in the |
945 | * CRTC state. Since the CRTC is unaffected, we would over-wait, but |
946 | * most importantly run into corner cases like waiting on an |
947 | * inactive CRTC that never completes. |
948 | */ |
949 | static void |
950 | drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state(struct kunit *test) |
951 | { |
952 | struct drm_modeset_acquire_ctx *ctx; |
953 | struct drm_atomic_state *state; |
954 | struct vc4_crtc_state *new_vc4_crtc_state; |
955 | struct drm_device *drm; |
956 | struct vc4_dev *vc4; |
957 | int ret; |
958 | |
959 | vc4 = vc5_mock_device(test); |
960 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4); |
961 | |
962 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
963 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
964 | |
965 | drm = &vc4->base; |
966 | state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); |
967 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); |
968 | |
969 | ret = vc4_mock_atomic_add_output(test, state, type: VC4_ENCODER_TYPE_HDMI0); |
970 | KUNIT_ASSERT_EQ(test, ret, 0); |
971 | |
972 | ret = drm_atomic_check_only(state); |
973 | KUNIT_ASSERT_EQ(test, ret, 0); |
974 | |
975 | ret = drm_atomic_helper_swap_state(state, stall: false); |
976 | KUNIT_ASSERT_EQ(test, ret, 0); |
977 | |
978 | state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); |
979 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); |
980 | |
981 | ret = vc4_mock_atomic_add_output(test, state, type: VC4_ENCODER_TYPE_HDMI1); |
982 | KUNIT_ASSERT_EQ(test, ret, 0); |
983 | |
984 | ret = drm_atomic_check_only(state); |
985 | KUNIT_ASSERT_EQ(test, ret, 0); |
986 | |
987 | new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, |
988 | type: VC4_ENCODER_TYPE_HDMI0); |
989 | KUNIT_EXPECT_NULL(test, new_vc4_crtc_state); |
990 | } |
991 | |
992 | static struct kunit_case vc5_pv_muxing_bugs_tests[] = { |
993 | KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable), |
994 | KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state), |
995 | KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_stable_fifo), |
996 | {} |
997 | }; |
998 | |
999 | static struct kunit_suite vc5_pv_muxing_bugs_test_suite = { |
1000 | .name = "vc5-pv-muxing-bugs" , |
1001 | .test_cases = vc5_pv_muxing_bugs_tests, |
1002 | }; |
1003 | |
1004 | kunit_test_suites( |
1005 | &vc4_pv_muxing_test_suite, |
1006 | &vc5_pv_muxing_test_suite, |
1007 | &vc5_pv_muxing_bugs_test_suite |
1008 | ); |
1009 | |