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
21struct pv_muxing_priv {
22	struct vc4_dev *vc4;
23	struct drm_atomic_state *state;
24};
25
26static 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
47struct 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
61static 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
88static 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
97static 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
107static 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
114static 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
121static struct vc4_crtc_state *
122get_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
144static 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
169struct 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
177static 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
198static 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
281KUNIT_ARRAY_PARAM(vc4_test_pv_muxing,
282		  vc4_test_pv_muxing_params,
283		  vc4_test_pv_muxing_desc);
284
285static 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
317KUNIT_ARRAY_PARAM(vc4_test_pv_muxing_invalid,
318		  vc4_test_pv_muxing_invalid_params,
319		  vc4_test_pv_muxing_desc);
320
321static 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
482KUNIT_ARRAY_PARAM(vc5_test_pv_muxing,
483		  vc5_test_pv_muxing_params,
484		  vc4_test_pv_muxing_desc);
485
486static 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
672KUNIT_ARRAY_PARAM(vc5_test_pv_muxing_invalid,
673		  vc5_test_pv_muxing_invalid_params,
674		  vc4_test_pv_muxing_desc);
675
676static 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
705static 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
724static 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
750static 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
758static 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
764static 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
772static 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 */
783static 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 */
855static 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 */
949static void
950drm_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
992static 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
999static 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
1004kunit_test_suites(
1005	&vc4_pv_muxing_test_suite,
1006	&vc5_pv_muxing_test_suite,
1007	&vc5_pv_muxing_bugs_test_suite
1008);
1009