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