d690ebb9084b0e8e52fa997181aeef259b4bd497
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / vc4 / tests / vc4_test_pv_muxing.c
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_TXP0, 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_TXP0, 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, 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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0,
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
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_TXP0),
397         VC5_PV_MUXING_TEST("2 outputs: TXP, VEC",
398                            VC4_ENCODER_TYPE_TXP0,
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_TXP0),
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_TXP0,
419                            VC4_ENCODER_TYPE_DSI1),
420         VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI0",
421                            VC4_ENCODER_TYPE_DPI,
422                            VC4_ENCODER_TYPE_TXP0,
423                            VC4_ENCODER_TYPE_HDMI0),
424         VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI1",
425                            VC4_ENCODER_TYPE_DPI,
426                            VC4_ENCODER_TYPE_TXP0,
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_TXP0),
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_TXP0,
459                            VC4_ENCODER_TYPE_DSI1),
460         VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI0",
461                            VC4_ENCODER_TYPE_DSI0,
462                            VC4_ENCODER_TYPE_TXP0,
463                            VC4_ENCODER_TYPE_HDMI0),
464         VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI1",
465                            VC4_ENCODER_TYPE_DSI0,
466                            VC4_ENCODER_TYPE_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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_TXP0,
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                 struct vc4_dummy_output *output;
686                 enum vc4_encoder_type enc_type = params->encoders[i];
687
688                 output = vc4_mock_atomic_add_output(test, state, enc_type);
689                 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
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                 struct vc4_dummy_output *output;
716                 enum vc4_encoder_type enc_type = params->encoders[i];
717
718                 output = vc4_mock_atomic_add_output(test, state, enc_type);
719                 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
720         }
721
722         ret = drm_atomic_check_only(state);
723         KUNIT_EXPECT_LT(test, ret, 0);
724 }
725
726 static int vc4_pv_muxing_test_init(struct kunit *test)
727 {
728         const struct pv_muxing_param *params = test->param_value;
729         struct drm_modeset_acquire_ctx *ctx;
730         struct pv_muxing_priv *priv;
731         struct drm_device *drm;
732         struct vc4_dev *vc4;
733
734         priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
735         KUNIT_ASSERT_NOT_NULL(test, priv);
736         test->priv = priv;
737
738         vc4 = params->mock_fn(test);
739         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
740         priv->vc4 = vc4;
741
742         ctx = drm_kunit_helper_acquire_ctx_alloc(test);
743         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
744
745         drm = &vc4->base;
746         priv->state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
747         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->state);
748
749         return 0;
750 }
751
752 static struct kunit_case vc4_pv_muxing_tests[] = {
753         KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing,
754                          vc4_test_pv_muxing_gen_params),
755         KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid,
756                          vc4_test_pv_muxing_invalid_gen_params),
757         {}
758 };
759
760 static struct kunit_suite vc4_pv_muxing_test_suite = {
761         .name = "vc4-pv-muxing-combinations",
762         .init = vc4_pv_muxing_test_init,
763         .test_cases = vc4_pv_muxing_tests,
764 };
765
766 static struct kunit_case vc5_pv_muxing_tests[] = {
767         KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing,
768                          vc5_test_pv_muxing_gen_params),
769         KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid,
770                          vc5_test_pv_muxing_invalid_gen_params),
771         {}
772 };
773
774 static struct kunit_suite vc5_pv_muxing_test_suite = {
775         .name = "vc5-pv-muxing-combinations",
776         .init = vc4_pv_muxing_test_init,
777         .test_cases = vc5_pv_muxing_tests,
778 };
779
780 /* See
781  * https://lore.kernel.org/all/3e113525-aa89-b1e2-56b7-ca55bd41d057@samsung.com/
782  * and
783  * https://lore.kernel.org/dri-devel/20200917121623.42023-1-maxime@cerno.tech/
784  */
785 static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *test)
786 {
787         struct drm_modeset_acquire_ctx *ctx;
788         struct drm_atomic_state *state;
789         struct vc4_dummy_output *output;
790         struct vc4_crtc_state *new_vc4_crtc_state;
791         struct vc4_hvs_state *new_hvs_state;
792         unsigned int hdmi0_channel;
793         unsigned int hdmi1_channel;
794         struct drm_device *drm;
795         struct vc4_dev *vc4;
796         int ret;
797
798         vc4 = vc5_mock_device(test);
799         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
800
801         ctx = drm_kunit_helper_acquire_ctx_alloc(test);
802         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
803
804         drm = &vc4->base;
805         state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
806         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
807
808         output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
809         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
810
811         ret = drm_atomic_check_only(state);
812         KUNIT_ASSERT_EQ(test, ret, 0);
813
814         new_hvs_state = vc4_hvs_get_new_global_state(state);
815         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
816
817         new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
818                                                             VC4_ENCODER_TYPE_HDMI0);
819         KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
820
821         hdmi0_channel = new_vc4_crtc_state->assigned_channel;
822         KUNIT_ASSERT_NE(test, hdmi0_channel, VC4_HVS_CHANNEL_DISABLED);
823         KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi0_channel].in_use);
824
825         ret = drm_atomic_helper_swap_state(state, false);
826         KUNIT_ASSERT_EQ(test, ret, 0);
827
828         state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
829         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
830
831         output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
832         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
833
834         ret = drm_atomic_check_only(state);
835         KUNIT_ASSERT_EQ(test, ret, 0);
836
837         new_hvs_state = vc4_hvs_get_new_global_state(state);
838         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
839
840         new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
841                                                             VC4_ENCODER_TYPE_HDMI1);
842         KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
843
844         hdmi1_channel = new_vc4_crtc_state->assigned_channel;
845         KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
846         KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use);
847
848         KUNIT_EXPECT_NE(test, hdmi0_channel, hdmi1_channel);
849 }
850
851 /*
852  * This test makes sure that we never change the FIFO of an active HVS
853  * channel if we disable a FIFO with a lower index.
854  *
855  * Doing so would result in a FIFO stall and would disrupt an output
856  * supposed to be unaffected by the commit.
857  */
858 static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test)
859 {
860         struct drm_modeset_acquire_ctx *ctx;
861         struct drm_atomic_state *state;
862         struct vc4_dummy_output *output;
863         struct vc4_crtc_state *new_vc4_crtc_state;
864         struct vc4_hvs_state *new_hvs_state;
865         unsigned int old_hdmi0_channel;
866         unsigned int old_hdmi1_channel;
867         struct drm_device *drm;
868         struct vc4_dev *vc4;
869         int ret;
870
871         vc4 = vc5_mock_device(test);
872         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
873
874         ctx = drm_kunit_helper_acquire_ctx_alloc(test);
875         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
876
877         drm = &vc4->base;
878         state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
879         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
880
881         output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
882         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
883
884         output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
885         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
886
887         ret = drm_atomic_check_only(state);
888         KUNIT_ASSERT_EQ(test, ret, 0);
889
890         new_hvs_state = vc4_hvs_get_new_global_state(state);
891         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
892
893         new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
894                                                             VC4_ENCODER_TYPE_HDMI0);
895         KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
896
897         old_hdmi0_channel = new_vc4_crtc_state->assigned_channel;
898         KUNIT_ASSERT_NE(test, old_hdmi0_channel, VC4_HVS_CHANNEL_DISABLED);
899         KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi0_channel].in_use);
900
901         new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
902                                                             VC4_ENCODER_TYPE_HDMI1);
903         KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
904
905         old_hdmi1_channel = new_vc4_crtc_state->assigned_channel;
906         KUNIT_ASSERT_NE(test, old_hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
907         KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi1_channel].in_use);
908
909         ret = drm_atomic_helper_swap_state(state, false);
910         KUNIT_ASSERT_EQ(test, ret, 0);
911
912         state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
913         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
914
915         ret = vc4_mock_atomic_del_output(test, state, VC4_ENCODER_TYPE_HDMI0);
916         KUNIT_ASSERT_EQ(test, ret, 0);
917
918         ret = drm_atomic_check_only(state);
919         KUNIT_ASSERT_EQ(test, ret, 0);
920
921         new_hvs_state = vc4_hvs_get_new_global_state(state);
922         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
923
924         new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
925                                                             VC4_ENCODER_TYPE_HDMI1);
926
927         if (new_vc4_crtc_state) {
928                 unsigned int hdmi1_channel;
929
930                 hdmi1_channel = new_vc4_crtc_state->assigned_channel;
931                 KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
932                 KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use);
933
934                 KUNIT_EXPECT_EQ(test, old_hdmi1_channel, hdmi1_channel);
935         }
936 }
937
938 /*
939  * Test that if we affect a single output, only the CRTC state of that
940  * output will be pulled in the global atomic state.
941  *
942  * This is relevant for two things:
943  *
944  *   - If we don't have that state at all, we are unlikely to affect the
945  *     FIFO muxing. This is somewhat redundant with
946  *     drm_test_vc5_pv_muxing_bugs_stable_fifo()
947  *
948  *   - KMS waits for page flips to occur on all the CRTC found in the
949  *     CRTC state. Since the CRTC is unaffected, we would over-wait, but
950  *     most importantly run into corner cases like waiting on an
951  *     inactive CRTC that never completes.
952  */
953 static void
954 drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state(struct kunit *test)
955 {
956         struct drm_modeset_acquire_ctx *ctx;
957         struct drm_atomic_state *state;
958         struct vc4_dummy_output *output;
959         struct vc4_crtc_state *new_vc4_crtc_state;
960         struct drm_device *drm;
961         struct vc4_dev *vc4;
962         int ret;
963
964         vc4 = vc5_mock_device(test);
965         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
966
967         ctx = drm_kunit_helper_acquire_ctx_alloc(test);
968         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
969
970         drm = &vc4->base;
971         state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
972         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
973
974         output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
975         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
976
977         ret = drm_atomic_check_only(state);
978         KUNIT_ASSERT_EQ(test, ret, 0);
979
980         ret = drm_atomic_helper_swap_state(state, false);
981         KUNIT_ASSERT_EQ(test, ret, 0);
982
983         state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
984         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
985
986         output = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
987         KUNIT_ASSERT_NOT_ERR_OR_NULL(test, output);
988
989         ret = drm_atomic_check_only(state);
990         KUNIT_ASSERT_EQ(test, ret, 0);
991
992         new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
993                                                             VC4_ENCODER_TYPE_HDMI0);
994         KUNIT_EXPECT_NULL(test, new_vc4_crtc_state);
995 }
996
997 static struct kunit_case vc5_pv_muxing_bugs_tests[] = {
998         KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable),
999         KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state),
1000         KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_stable_fifo),
1001         {}
1002 };
1003
1004 static struct kunit_suite vc5_pv_muxing_bugs_test_suite = {
1005         .name = "vc5-pv-muxing-bugs",
1006         .test_cases = vc5_pv_muxing_bugs_tests,
1007 };
1008
1009 kunit_test_suites(
1010         &vc4_pv_muxing_test_suite,
1011         &vc5_pv_muxing_test_suite,
1012         &vc5_pv_muxing_bugs_test_suite
1013 );