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