xref: /linux/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c (revision 0ce92d548b44649a8de706f9bb9e74a4ed2f18a7)
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 
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 
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 
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 
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 *
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 
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 
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 
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 
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 
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  */
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  */
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
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