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