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