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

source code of linux/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c