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