bcm27xx: 6.1: add kernel patches
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-6.1 / 950-0504-drm-vc4-tests-Add-unit-test-suite-for-the-PV-muxing.patch
1 From 27aebda6c6498ff8f948b9cc8facef30f522af33 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Mon, 14 Nov 2022 16:06:22 +0100
4 Subject: [PATCH] drm/vc4: tests: Add unit test suite for the PV muxing
5
6 The HVS to PixelValve muxing code is fairly error prone and has a bunch
7 of arbitrary constraints due to the hardware setup.
8
9 Let's create a test suite that makes sure that the possible combinations
10 work and the invalid ones don't.
11
12 Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
13 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
14 ---
15 drivers/gpu/drm/vc4/Makefile | 3 +-
16 drivers/gpu/drm/vc4/tests/vc4_mock.h | 9 +-
17 drivers/gpu/drm/vc4/tests/vc4_mock_output.c | 49 +-
18 .../gpu/drm/vc4/tests/vc4_test_pv_muxing.c | 1039 +++++++++++++++++
19 4 files changed, 1091 insertions(+), 9 deletions(-)
20 create mode 100644 drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c
21
22 --- a/drivers/gpu/drm/vc4/Makefile
23 +++ b/drivers/gpu/drm/vc4/Makefile
24 @@ -30,7 +30,8 @@ vc4-$(CONFIG_DRM_VC4_KUNIT_TEST) += \
25 tests/vc4_mock.o \
26 tests/vc4_mock_crtc.o \
27 tests/vc4_mock_output.o \
28 - tests/vc4_mock_plane.o
29 + tests/vc4_mock_plane.o \
30 + tests/vc4_test_pv_muxing.o
31
32 vc4-$(CONFIG_DEBUG_FS) += vc4_debugfs.o
33
34 --- a/drivers/gpu/drm/vc4/tests/vc4_mock.h
35 +++ b/drivers/gpu/drm/vc4/tests/vc4_mock.h
36 @@ -53,8 +53,11 @@ struct vc4_dummy_output *vc4_dummy_outpu
37 struct vc4_dev *vc4_mock_device(struct kunit *test);
38 struct vc4_dev *vc5_mock_device(struct kunit *test);
39
40 -int vc4_mock_atomic_add_output(struct kunit *test, struct drm_device *drm,
41 - enum vc4_encoder_type type,
42 - struct drm_atomic_state *state);
43 +int vc4_mock_atomic_add_output(struct kunit *test,
44 + struct drm_atomic_state *state,
45 + enum vc4_encoder_type type);
46 +int vc4_mock_atomic_del_output(struct kunit *test,
47 + struct drm_atomic_state *state,
48 + enum vc4_encoder_type type);
49
50 #endif // VC4_MOCK_H_
51 --- a/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
52 +++ b/drivers/gpu/drm/vc4/tests/vc4_mock_output.c
53 @@ -61,16 +61,17 @@ static const struct drm_display_mode def
54 DRM_SIMPLE_MODE(640, 480, 64, 48)
55 };
56
57 -int vc4_mock_atomic_add_output(struct kunit *test, struct drm_device *drm,
58 - enum vc4_encoder_type type,
59 - struct drm_atomic_state *state)
60 +int vc4_mock_atomic_add_output(struct kunit *test,
61 + struct drm_atomic_state *state,
62 + enum vc4_encoder_type type)
63 {
64 + struct drm_device *drm = state->dev;
65 + struct drm_connector_state *conn_state;
66 + struct drm_crtc_state *crtc_state;
67 struct vc4_dummy_output *output;
68 struct drm_connector *conn;
69 - struct drm_connector_state *conn_state;
70 struct drm_encoder *encoder;
71 struct drm_crtc *crtc;
72 - struct drm_crtc_state *crtc_state;
73 int ret;
74
75 encoder = vc4_find_encoder_by_type(drm, type);
76 @@ -97,3 +98,41 @@ int vc4_mock_atomic_add_output(struct ku
77
78 return 0;
79 }
80 +
81 +int vc4_mock_atomic_del_output(struct kunit *test,
82 + struct drm_atomic_state *state,
83 + enum vc4_encoder_type type)
84 +{
85 + struct drm_device *drm = state->dev;
86 + struct drm_connector_state *conn_state;
87 + struct drm_crtc_state *crtc_state;
88 + struct vc4_dummy_output *output;
89 + struct drm_connector *conn;
90 + struct drm_encoder *encoder;
91 + struct drm_crtc *crtc;
92 + int ret;
93 +
94 + encoder = vc4_find_encoder_by_type(drm, type);
95 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder);
96 +
97 + crtc = vc4_find_crtc_for_encoder(test, drm, encoder);
98 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
99 +
100 + crtc_state = drm_atomic_get_crtc_state(state, crtc);
101 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
102 +
103 + crtc_state->active = false;
104 +
105 + ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
106 + KUNIT_ASSERT_EQ(test, ret, 0);
107 +
108 + output = container_of(encoder, struct vc4_dummy_output, encoder.base);
109 + conn = &output->connector;
110 + conn_state = drm_atomic_get_connector_state(state, conn);
111 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
112 +
113 + ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
114 + KUNIT_ASSERT_EQ(test, ret, 0);
115 +
116 + return 0;
117 +}
118 --- /dev/null
119 +++ b/drivers/gpu/drm/vc4/tests/vc4_test_pv_muxing.c
120 @@ -0,0 +1,1039 @@
121 +// SPDX-License-Identifier: GPL-2.0
122 +
123 +#include <drm/drm_atomic.h>
124 +#include <drm/drm_atomic_helper.h>
125 +#include <drm/drm_atomic_state_helper.h>
126 +#include <drm/drm_atomic_uapi.h>
127 +#include <drm/drm_crtc.h>
128 +#include <drm/drm_drv.h>
129 +#include <drm/drm_fourcc.h>
130 +#include <drm/drm_kunit_helpers.h>
131 +#include <drm/drm_mode.h>
132 +#include <drm/drm_modeset_helper_vtables.h>
133 +#include <drm/drm_plane.h>
134 +
135 +#include <kunit/test.h>
136 +
137 +#include "../vc4_drv.h"
138 +
139 +#include "vc4_mock.h"
140 +
141 +struct pv_muxing_priv {
142 + struct vc4_dev *vc4;
143 + struct drm_modeset_acquire_ctx ctx;
144 + struct drm_atomic_state *state;
145 +};
146 +
147 +static bool check_fifo_conflict(struct kunit *test,
148 + const struct drm_atomic_state *state)
149 +{
150 + struct vc4_hvs_state *hvs_state;
151 + unsigned int used_fifos = 0;
152 + unsigned int i;
153 +
154 + hvs_state = vc4_hvs_get_new_global_state(state);
155 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hvs_state);
156 +
157 + for (i = 0; i < HVS_NUM_CHANNELS; i++) {
158 + if (!hvs_state->fifo_state[i].in_use)
159 + continue;
160 +
161 + KUNIT_EXPECT_FALSE(test, used_fifos & BIT(i));
162 + used_fifos |= BIT(i);
163 + }
164 +
165 + return true;
166 +}
167 +
168 +struct encoder_constraint {
169 + enum vc4_encoder_type type;
170 + unsigned int *channels;
171 + size_t nchannels;
172 +};
173 +
174 +#define ENCODER_CONSTRAINT(_type, ...) \
175 + { \
176 + .type = _type, \
177 + .channels = (unsigned int[]) { __VA_ARGS__ }, \
178 + .nchannels = sizeof((unsigned int[]) { __VA_ARGS__ }) / \
179 + sizeof(unsigned int), \
180 + }
181 +
182 +static bool __check_encoder_constraints(const struct encoder_constraint *constraints,
183 + size_t nconstraints,
184 + enum vc4_encoder_type type,
185 + unsigned int channel)
186 +{
187 + unsigned int i;
188 +
189 + for (i = 0; i < nconstraints; i++) {
190 + const struct encoder_constraint *constraint = &constraints[i];
191 + unsigned int j;
192 +
193 + if (constraint->type != type)
194 + continue;
195 +
196 + for (j = 0; j < constraint->nchannels; j++) {
197 + unsigned int _channel = constraint->channels[j];
198 +
199 + if (channel != _channel)
200 + continue;
201 +
202 + return true;
203 + }
204 + }
205 +
206 + return false;
207 +}
208 +
209 +static const struct encoder_constraint vc4_encoder_constraints[] = {
210 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0),
211 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0),
212 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 1),
213 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1),
214 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 2),
215 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 2),
216 +};
217 +
218 +static const struct encoder_constraint vc5_encoder_constraints[] = {
219 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DPI, 0),
220 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI0, 0),
221 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_VEC, 1),
222 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_TXP, 0, 2),
223 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_DSI1, 0, 1, 2),
224 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI0, 0, 1, 2),
225 + ENCODER_CONSTRAINT(VC4_ENCODER_TYPE_HDMI1, 0, 1, 2),
226 +};
227 +
228 +static bool check_vc4_encoder_constraints(enum vc4_encoder_type type, unsigned int channel)
229 +{
230 + return __check_encoder_constraints(vc4_encoder_constraints,
231 + ARRAY_SIZE(vc4_encoder_constraints),
232 + type, channel);
233 +}
234 +
235 +static bool check_vc5_encoder_constraints(enum vc4_encoder_type type, unsigned int channel)
236 +{
237 + return __check_encoder_constraints(vc5_encoder_constraints,
238 + ARRAY_SIZE(vc5_encoder_constraints),
239 + type, channel);
240 +}
241 +
242 +static struct vc4_crtc_state *
243 +get_vc4_crtc_state_for_encoder(struct kunit *test,
244 + const struct drm_atomic_state *state,
245 + enum vc4_encoder_type type)
246 +{
247 + struct drm_device *drm = state->dev;
248 + struct drm_crtc_state *new_crtc_state;
249 + struct drm_encoder *encoder;
250 + struct drm_crtc *crtc;
251 +
252 + encoder = vc4_find_encoder_by_type(drm, type);
253 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, encoder);
254 +
255 + crtc = vc4_find_crtc_for_encoder(test, drm, encoder);
256 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
257 +
258 + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
259 + if (!new_crtc_state)
260 + return NULL;
261 +
262 + return to_vc4_crtc_state(new_crtc_state);
263 +}
264 +
265 +static bool check_channel_for_encoder(struct kunit *test,
266 + const struct drm_atomic_state *state,
267 + enum vc4_encoder_type type,
268 + bool (*check_fn)(enum vc4_encoder_type type, unsigned int channel))
269 +{
270 + struct vc4_crtc_state *new_vc4_crtc_state;
271 + struct vc4_hvs_state *new_hvs_state;
272 + unsigned int channel;
273 +
274 + new_hvs_state = vc4_hvs_get_new_global_state(state);
275 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
276 +
277 + new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state, type);
278 + KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
279 +
280 + channel = new_vc4_crtc_state->assigned_channel;
281 + KUNIT_EXPECT_NE(test, channel, VC4_HVS_CHANNEL_DISABLED);
282 +
283 + KUNIT_EXPECT_TRUE(test, new_hvs_state->fifo_state[channel].in_use);
284 +
285 + KUNIT_EXPECT_TRUE(test, check_fn(type, channel));
286 +
287 + return true;
288 +}
289 +
290 +struct pv_muxing_param {
291 + const char *name;
292 + struct vc4_dev *(*mock_fn)(struct kunit *test);
293 + bool (*check_fn)(enum vc4_encoder_type type, unsigned int channel);
294 + enum vc4_encoder_type *encoders;
295 + size_t nencoders;
296 +};
297 +
298 +static void vc4_test_pv_muxing_desc(const struct pv_muxing_param *t, char *desc)
299 +{
300 + strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
301 +}
302 +
303 +#define PV_MUXING_TEST(_name, _mock_fn, _check_fn, ...) \
304 + { \
305 + .name = _name, \
306 + .mock_fn = &_mock_fn, \
307 + .check_fn = &_check_fn, \
308 + .encoders = (enum vc4_encoder_type[]) { __VA_ARGS__ }, \
309 + .nencoders = sizeof((enum vc4_encoder_type[]) { __VA_ARGS__ }) / \
310 + sizeof(enum vc4_encoder_type), \
311 + }
312 +
313 +#define VC4_PV_MUXING_TEST(_name, ...) \
314 + PV_MUXING_TEST(_name, vc4_mock_device, check_vc4_encoder_constraints, __VA_ARGS__)
315 +
316 +#define VC5_PV_MUXING_TEST(_name, ...) \
317 + PV_MUXING_TEST(_name, vc5_mock_device, check_vc5_encoder_constraints, __VA_ARGS__)
318 +
319 +static const struct pv_muxing_param vc4_test_pv_muxing_params[] = {
320 + VC4_PV_MUXING_TEST("1 output: DSI0",
321 + VC4_ENCODER_TYPE_DSI0),
322 + VC4_PV_MUXING_TEST("1 output: DPI",
323 + VC4_ENCODER_TYPE_DPI),
324 + VC4_PV_MUXING_TEST("1 output: HDMI0",
325 + VC4_ENCODER_TYPE_HDMI0),
326 + VC4_PV_MUXING_TEST("1 output: VEC",
327 + VC4_ENCODER_TYPE_VEC),
328 + VC4_PV_MUXING_TEST("1 output: DSI1",
329 + VC4_ENCODER_TYPE_DSI1),
330 + VC4_PV_MUXING_TEST("1 output: TXP",
331 + VC4_ENCODER_TYPE_TXP),
332 + VC4_PV_MUXING_TEST("2 outputs: DSI0, HDMI0",
333 + VC4_ENCODER_TYPE_DSI0,
334 + VC4_ENCODER_TYPE_HDMI0),
335 + VC4_PV_MUXING_TEST("2 outputs: DSI0, VEC",
336 + VC4_ENCODER_TYPE_DSI0,
337 + VC4_ENCODER_TYPE_VEC),
338 + VC4_PV_MUXING_TEST("2 outputs: DSI0, DSI1",
339 + VC4_ENCODER_TYPE_DSI0,
340 + VC4_ENCODER_TYPE_DSI1),
341 + VC4_PV_MUXING_TEST("2 outputs: DSI0, TXP",
342 + VC4_ENCODER_TYPE_DSI0,
343 + VC4_ENCODER_TYPE_TXP),
344 + VC4_PV_MUXING_TEST("2 outputs: DPI, HDMI0",
345 + VC4_ENCODER_TYPE_DPI,
346 + VC4_ENCODER_TYPE_HDMI0),
347 + VC4_PV_MUXING_TEST("2 outputs: DPI, VEC",
348 + VC4_ENCODER_TYPE_DPI,
349 + VC4_ENCODER_TYPE_VEC),
350 + VC4_PV_MUXING_TEST("2 outputs: DPI, DSI1",
351 + VC4_ENCODER_TYPE_DPI,
352 + VC4_ENCODER_TYPE_DSI1),
353 + VC4_PV_MUXING_TEST("2 outputs: DPI, TXP",
354 + VC4_ENCODER_TYPE_DPI,
355 + VC4_ENCODER_TYPE_TXP),
356 + VC4_PV_MUXING_TEST("2 outputs: HDMI0, DSI1",
357 + VC4_ENCODER_TYPE_HDMI0,
358 + VC4_ENCODER_TYPE_DSI1),
359 + VC4_PV_MUXING_TEST("2 outputs: HDMI0, TXP",
360 + VC4_ENCODER_TYPE_HDMI0,
361 + VC4_ENCODER_TYPE_TXP),
362 + VC4_PV_MUXING_TEST("2 outputs: VEC, DSI1",
363 + VC4_ENCODER_TYPE_VEC,
364 + VC4_ENCODER_TYPE_DSI1),
365 + VC4_PV_MUXING_TEST("2 outputs: VEC, TXP",
366 + VC4_ENCODER_TYPE_VEC,
367 + VC4_ENCODER_TYPE_TXP),
368 + VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, DSI1",
369 + VC4_ENCODER_TYPE_DSI0,
370 + VC4_ENCODER_TYPE_HDMI0,
371 + VC4_ENCODER_TYPE_DSI1),
372 + VC4_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, TXP",
373 + VC4_ENCODER_TYPE_DSI0,
374 + VC4_ENCODER_TYPE_HDMI0,
375 + VC4_ENCODER_TYPE_TXP),
376 + VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1",
377 + VC4_ENCODER_TYPE_DSI0,
378 + VC4_ENCODER_TYPE_VEC,
379 + VC4_ENCODER_TYPE_DSI1),
380 + VC4_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP",
381 + VC4_ENCODER_TYPE_DSI0,
382 + VC4_ENCODER_TYPE_VEC,
383 + VC4_ENCODER_TYPE_TXP),
384 + VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, DSI1",
385 + VC4_ENCODER_TYPE_DPI,
386 + VC4_ENCODER_TYPE_HDMI0,
387 + VC4_ENCODER_TYPE_DSI1),
388 + VC4_PV_MUXING_TEST("3 outputs: DPI, HDMI0, TXP",
389 + VC4_ENCODER_TYPE_DPI,
390 + VC4_ENCODER_TYPE_HDMI0,
391 + VC4_ENCODER_TYPE_TXP),
392 + VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1",
393 + VC4_ENCODER_TYPE_DPI,
394 + VC4_ENCODER_TYPE_VEC,
395 + VC4_ENCODER_TYPE_DSI1),
396 + VC4_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP",
397 + VC4_ENCODER_TYPE_DPI,
398 + VC4_ENCODER_TYPE_VEC,
399 + VC4_ENCODER_TYPE_TXP),
400 +};
401 +
402 +KUNIT_ARRAY_PARAM(vc4_test_pv_muxing,
403 + vc4_test_pv_muxing_params,
404 + vc4_test_pv_muxing_desc);
405 +
406 +static const struct pv_muxing_param vc4_test_pv_muxing_invalid_params[] = {
407 + VC4_PV_MUXING_TEST("DPI/DSI0 Conflict",
408 + VC4_ENCODER_TYPE_DPI,
409 + VC4_ENCODER_TYPE_DSI0),
410 + VC4_PV_MUXING_TEST("TXP/DSI1 Conflict",
411 + VC4_ENCODER_TYPE_TXP,
412 + VC4_ENCODER_TYPE_DSI1),
413 + VC4_PV_MUXING_TEST("HDMI0/VEC Conflict",
414 + VC4_ENCODER_TYPE_HDMI0,
415 + VC4_ENCODER_TYPE_VEC),
416 + VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, HDMI0, DSI1, TXP",
417 + VC4_ENCODER_TYPE_DSI0,
418 + VC4_ENCODER_TYPE_HDMI0,
419 + VC4_ENCODER_TYPE_DSI1,
420 + VC4_ENCODER_TYPE_TXP),
421 + VC4_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, TXP",
422 + VC4_ENCODER_TYPE_DSI0,
423 + VC4_ENCODER_TYPE_VEC,
424 + VC4_ENCODER_TYPE_DSI1,
425 + VC4_ENCODER_TYPE_TXP),
426 + VC4_PV_MUXING_TEST("More than 3 outputs: DPI, HDMI0, DSI1, TXP",
427 + VC4_ENCODER_TYPE_DPI,
428 + VC4_ENCODER_TYPE_HDMI0,
429 + VC4_ENCODER_TYPE_DSI1,
430 + VC4_ENCODER_TYPE_TXP),
431 + VC4_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, TXP",
432 + VC4_ENCODER_TYPE_DPI,
433 + VC4_ENCODER_TYPE_VEC,
434 + VC4_ENCODER_TYPE_DSI1,
435 + VC4_ENCODER_TYPE_TXP),
436 +};
437 +
438 +KUNIT_ARRAY_PARAM(vc4_test_pv_muxing_invalid,
439 + vc4_test_pv_muxing_invalid_params,
440 + vc4_test_pv_muxing_desc);
441 +
442 +static const struct pv_muxing_param vc5_test_pv_muxing_params[] = {
443 + VC5_PV_MUXING_TEST("1 output: DPI",
444 + VC4_ENCODER_TYPE_DPI),
445 + VC5_PV_MUXING_TEST("1 output: DSI0",
446 + VC4_ENCODER_TYPE_DSI0),
447 + VC5_PV_MUXING_TEST("1 output: DSI1",
448 + VC4_ENCODER_TYPE_DSI1),
449 + VC5_PV_MUXING_TEST("1 output: HDMI0",
450 + VC4_ENCODER_TYPE_HDMI0),
451 + VC5_PV_MUXING_TEST("1 output: HDMI1",
452 + VC4_ENCODER_TYPE_HDMI1),
453 + VC5_PV_MUXING_TEST("1 output: VEC",
454 + VC4_ENCODER_TYPE_VEC),
455 + VC5_PV_MUXING_TEST("2 outputs: DPI, DSI1",
456 + VC4_ENCODER_TYPE_DPI,
457 + VC4_ENCODER_TYPE_DSI1),
458 + VC5_PV_MUXING_TEST("2 outputs: DPI, HDMI0",
459 + VC4_ENCODER_TYPE_DPI,
460 + VC4_ENCODER_TYPE_HDMI0),
461 + VC5_PV_MUXING_TEST("2 outputs: DPI, HDMI1",
462 + VC4_ENCODER_TYPE_DPI,
463 + VC4_ENCODER_TYPE_HDMI1),
464 + VC5_PV_MUXING_TEST("2 outputs: DPI, TXP",
465 + VC4_ENCODER_TYPE_DPI,
466 + VC4_ENCODER_TYPE_TXP),
467 + VC5_PV_MUXING_TEST("2 outputs: DPI, VEC",
468 + VC4_ENCODER_TYPE_DPI,
469 + VC4_ENCODER_TYPE_VEC),
470 + VC5_PV_MUXING_TEST("2 outputs: DPI, DSI1",
471 + VC4_ENCODER_TYPE_DPI,
472 + VC4_ENCODER_TYPE_DSI1),
473 + VC5_PV_MUXING_TEST("2 outputs: DSI0, DSI1",
474 + VC4_ENCODER_TYPE_DSI0,
475 + VC4_ENCODER_TYPE_DSI1),
476 + VC5_PV_MUXING_TEST("2 outputs: DSI0, HDMI0",
477 + VC4_ENCODER_TYPE_DSI0,
478 + VC4_ENCODER_TYPE_HDMI0),
479 + VC5_PV_MUXING_TEST("2 outputs: DSI0, HDMI1",
480 + VC4_ENCODER_TYPE_DSI0,
481 + VC4_ENCODER_TYPE_HDMI1),
482 + VC5_PV_MUXING_TEST("2 outputs: DSI0, TXP",
483 + VC4_ENCODER_TYPE_DSI0,
484 + VC4_ENCODER_TYPE_TXP),
485 + VC5_PV_MUXING_TEST("2 outputs: DSI0, VEC",
486 + VC4_ENCODER_TYPE_DSI0,
487 + VC4_ENCODER_TYPE_VEC),
488 + VC5_PV_MUXING_TEST("2 outputs: DSI0, DSI1",
489 + VC4_ENCODER_TYPE_DSI0,
490 + VC4_ENCODER_TYPE_DSI1),
491 + VC5_PV_MUXING_TEST("2 outputs: DSI1, VEC",
492 + VC4_ENCODER_TYPE_DSI1,
493 + VC4_ENCODER_TYPE_VEC),
494 + VC5_PV_MUXING_TEST("2 outputs: DSI1, TXP",
495 + VC4_ENCODER_TYPE_DSI1,
496 + VC4_ENCODER_TYPE_TXP),
497 + VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI0",
498 + VC4_ENCODER_TYPE_DSI1,
499 + VC4_ENCODER_TYPE_HDMI0),
500 + VC5_PV_MUXING_TEST("2 outputs: DSI1, HDMI1",
501 + VC4_ENCODER_TYPE_DSI1,
502 + VC4_ENCODER_TYPE_HDMI1),
503 + VC5_PV_MUXING_TEST("2 outputs: HDMI0, VEC",
504 + VC4_ENCODER_TYPE_HDMI0,
505 + VC4_ENCODER_TYPE_VEC),
506 + VC5_PV_MUXING_TEST("2 outputs: HDMI0, TXP",
507 + VC4_ENCODER_TYPE_HDMI0,
508 + VC4_ENCODER_TYPE_TXP),
509 + VC5_PV_MUXING_TEST("2 outputs: HDMI0, HDMI1",
510 + VC4_ENCODER_TYPE_HDMI0,
511 + VC4_ENCODER_TYPE_HDMI1),
512 + VC5_PV_MUXING_TEST("2 outputs: HDMI1, VEC",
513 + VC4_ENCODER_TYPE_HDMI1,
514 + VC4_ENCODER_TYPE_VEC),
515 + VC5_PV_MUXING_TEST("2 outputs: HDMI1, TXP",
516 + VC4_ENCODER_TYPE_HDMI1,
517 + VC4_ENCODER_TYPE_TXP),
518 + VC5_PV_MUXING_TEST("2 outputs: TXP, VEC",
519 + VC4_ENCODER_TYPE_TXP,
520 + VC4_ENCODER_TYPE_VEC),
521 + VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, TXP",
522 + VC4_ENCODER_TYPE_DPI,
523 + VC4_ENCODER_TYPE_VEC,
524 + VC4_ENCODER_TYPE_TXP),
525 + VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, DSI1",
526 + VC4_ENCODER_TYPE_DPI,
527 + VC4_ENCODER_TYPE_VEC,
528 + VC4_ENCODER_TYPE_DSI1),
529 + VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, HDMI0",
530 + VC4_ENCODER_TYPE_DPI,
531 + VC4_ENCODER_TYPE_VEC,
532 + VC4_ENCODER_TYPE_HDMI0),
533 + VC5_PV_MUXING_TEST("3 outputs: DPI, VEC, HDMI1",
534 + VC4_ENCODER_TYPE_DPI,
535 + VC4_ENCODER_TYPE_VEC,
536 + VC4_ENCODER_TYPE_HDMI1),
537 + VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, DSI1",
538 + VC4_ENCODER_TYPE_DPI,
539 + VC4_ENCODER_TYPE_TXP,
540 + VC4_ENCODER_TYPE_DSI1),
541 + VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI0",
542 + VC4_ENCODER_TYPE_DPI,
543 + VC4_ENCODER_TYPE_TXP,
544 + VC4_ENCODER_TYPE_HDMI0),
545 + VC5_PV_MUXING_TEST("3 outputs: DPI, TXP, HDMI1",
546 + VC4_ENCODER_TYPE_DPI,
547 + VC4_ENCODER_TYPE_TXP,
548 + VC4_ENCODER_TYPE_HDMI1),
549 + VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI0",
550 + VC4_ENCODER_TYPE_DPI,
551 + VC4_ENCODER_TYPE_DSI1,
552 + VC4_ENCODER_TYPE_HDMI0),
553 + VC5_PV_MUXING_TEST("3 outputs: DPI, DSI1, HDMI1",
554 + VC4_ENCODER_TYPE_DPI,
555 + VC4_ENCODER_TYPE_DSI1,
556 + VC4_ENCODER_TYPE_HDMI1),
557 + VC5_PV_MUXING_TEST("3 outputs: DPI, HDMI0, HDMI1",
558 + VC4_ENCODER_TYPE_DPI,
559 + VC4_ENCODER_TYPE_HDMI0,
560 + VC4_ENCODER_TYPE_HDMI1),
561 + VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, TXP",
562 + VC4_ENCODER_TYPE_DSI0,
563 + VC4_ENCODER_TYPE_VEC,
564 + VC4_ENCODER_TYPE_TXP),
565 + VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, DSI1",
566 + VC4_ENCODER_TYPE_DSI0,
567 + VC4_ENCODER_TYPE_VEC,
568 + VC4_ENCODER_TYPE_DSI1),
569 + VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, HDMI0",
570 + VC4_ENCODER_TYPE_DSI0,
571 + VC4_ENCODER_TYPE_VEC,
572 + VC4_ENCODER_TYPE_HDMI0),
573 + VC5_PV_MUXING_TEST("3 outputs: DSI0, VEC, HDMI1",
574 + VC4_ENCODER_TYPE_DSI0,
575 + VC4_ENCODER_TYPE_VEC,
576 + VC4_ENCODER_TYPE_HDMI1),
577 + VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, DSI1",
578 + VC4_ENCODER_TYPE_DSI0,
579 + VC4_ENCODER_TYPE_TXP,
580 + VC4_ENCODER_TYPE_DSI1),
581 + VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI0",
582 + VC4_ENCODER_TYPE_DSI0,
583 + VC4_ENCODER_TYPE_TXP,
584 + VC4_ENCODER_TYPE_HDMI0),
585 + VC5_PV_MUXING_TEST("3 outputs: DSI0, TXP, HDMI1",
586 + VC4_ENCODER_TYPE_DSI0,
587 + VC4_ENCODER_TYPE_TXP,
588 + VC4_ENCODER_TYPE_HDMI1),
589 + VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI0",
590 + VC4_ENCODER_TYPE_DSI0,
591 + VC4_ENCODER_TYPE_DSI1,
592 + VC4_ENCODER_TYPE_HDMI0),
593 + VC5_PV_MUXING_TEST("3 outputs: DSI0, DSI1, HDMI1",
594 + VC4_ENCODER_TYPE_DSI0,
595 + VC4_ENCODER_TYPE_DSI1,
596 + VC4_ENCODER_TYPE_HDMI1),
597 + VC5_PV_MUXING_TEST("3 outputs: DSI0, HDMI0, HDMI1",
598 + VC4_ENCODER_TYPE_DSI0,
599 + VC4_ENCODER_TYPE_HDMI0,
600 + VC4_ENCODER_TYPE_HDMI1),
601 +};
602 +
603 +KUNIT_ARRAY_PARAM(vc5_test_pv_muxing,
604 + vc5_test_pv_muxing_params,
605 + vc4_test_pv_muxing_desc);
606 +
607 +static const struct pv_muxing_param vc5_test_pv_muxing_invalid_params[] = {
608 + VC5_PV_MUXING_TEST("DPI/DSI0 Conflict",
609 + VC4_ENCODER_TYPE_DPI,
610 + VC4_ENCODER_TYPE_DSI0),
611 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1",
612 + VC4_ENCODER_TYPE_DPI,
613 + VC4_ENCODER_TYPE_VEC,
614 + VC4_ENCODER_TYPE_TXP,
615 + VC4_ENCODER_TYPE_DSI1),
616 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0",
617 + VC4_ENCODER_TYPE_DPI,
618 + VC4_ENCODER_TYPE_VEC,
619 + VC4_ENCODER_TYPE_TXP,
620 + VC4_ENCODER_TYPE_HDMI0),
621 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI1",
622 + VC4_ENCODER_TYPE_DPI,
623 + VC4_ENCODER_TYPE_VEC,
624 + VC4_ENCODER_TYPE_TXP,
625 + VC4_ENCODER_TYPE_HDMI1),
626 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0",
627 + VC4_ENCODER_TYPE_DPI,
628 + VC4_ENCODER_TYPE_VEC,
629 + VC4_ENCODER_TYPE_DSI1,
630 + VC4_ENCODER_TYPE_HDMI0),
631 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI1",
632 + VC4_ENCODER_TYPE_DPI,
633 + VC4_ENCODER_TYPE_VEC,
634 + VC4_ENCODER_TYPE_DSI1,
635 + VC4_ENCODER_TYPE_HDMI1),
636 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, HDMI0, HDMI1",
637 + VC4_ENCODER_TYPE_DPI,
638 + VC4_ENCODER_TYPE_VEC,
639 + VC4_ENCODER_TYPE_HDMI0,
640 + VC4_ENCODER_TYPE_HDMI1),
641 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0",
642 + VC4_ENCODER_TYPE_DPI,
643 + VC4_ENCODER_TYPE_TXP,
644 + VC4_ENCODER_TYPE_DSI1,
645 + VC4_ENCODER_TYPE_HDMI0),
646 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI1",
647 + VC4_ENCODER_TYPE_DPI,
648 + VC4_ENCODER_TYPE_TXP,
649 + VC4_ENCODER_TYPE_DSI1,
650 + VC4_ENCODER_TYPE_HDMI1),
651 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, HDMI0, HDMI1",
652 + VC4_ENCODER_TYPE_DPI,
653 + VC4_ENCODER_TYPE_TXP,
654 + VC4_ENCODER_TYPE_HDMI0,
655 + VC4_ENCODER_TYPE_HDMI1),
656 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, DSI1, HDMI0, HDMI1",
657 + VC4_ENCODER_TYPE_DPI,
658 + VC4_ENCODER_TYPE_DSI1,
659 + VC4_ENCODER_TYPE_HDMI0,
660 + VC4_ENCODER_TYPE_HDMI1),
661 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0",
662 + VC4_ENCODER_TYPE_DPI,
663 + VC4_ENCODER_TYPE_VEC,
664 + VC4_ENCODER_TYPE_TXP,
665 + VC4_ENCODER_TYPE_DSI1,
666 + VC4_ENCODER_TYPE_HDMI0),
667 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI1",
668 + VC4_ENCODER_TYPE_DPI,
669 + VC4_ENCODER_TYPE_VEC,
670 + VC4_ENCODER_TYPE_TXP,
671 + VC4_ENCODER_TYPE_DSI1,
672 + VC4_ENCODER_TYPE_HDMI1),
673 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, HDMI0, HDMI1",
674 + VC4_ENCODER_TYPE_DPI,
675 + VC4_ENCODER_TYPE_VEC,
676 + VC4_ENCODER_TYPE_TXP,
677 + VC4_ENCODER_TYPE_HDMI0,
678 + VC4_ENCODER_TYPE_HDMI1),
679 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, DSI1, HDMI0, HDMI1",
680 + VC4_ENCODER_TYPE_DPI,
681 + VC4_ENCODER_TYPE_VEC,
682 + VC4_ENCODER_TYPE_DSI1,
683 + VC4_ENCODER_TYPE_HDMI0,
684 + VC4_ENCODER_TYPE_HDMI1),
685 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, TXP, DSI1, HDMI0, HDMI1",
686 + VC4_ENCODER_TYPE_DPI,
687 + VC4_ENCODER_TYPE_TXP,
688 + VC4_ENCODER_TYPE_DSI1,
689 + VC4_ENCODER_TYPE_HDMI0,
690 + VC4_ENCODER_TYPE_HDMI1),
691 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1",
692 + VC4_ENCODER_TYPE_DSI0,
693 + VC4_ENCODER_TYPE_VEC,
694 + VC4_ENCODER_TYPE_TXP,
695 + VC4_ENCODER_TYPE_DSI1),
696 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0",
697 + VC4_ENCODER_TYPE_DSI0,
698 + VC4_ENCODER_TYPE_VEC,
699 + VC4_ENCODER_TYPE_TXP,
700 + VC4_ENCODER_TYPE_HDMI0),
701 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI1",
702 + VC4_ENCODER_TYPE_DSI0,
703 + VC4_ENCODER_TYPE_VEC,
704 + VC4_ENCODER_TYPE_TXP,
705 + VC4_ENCODER_TYPE_HDMI1),
706 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0",
707 + VC4_ENCODER_TYPE_DSI0,
708 + VC4_ENCODER_TYPE_VEC,
709 + VC4_ENCODER_TYPE_DSI1,
710 + VC4_ENCODER_TYPE_HDMI0),
711 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI1",
712 + VC4_ENCODER_TYPE_DSI0,
713 + VC4_ENCODER_TYPE_VEC,
714 + VC4_ENCODER_TYPE_DSI1,
715 + VC4_ENCODER_TYPE_HDMI1),
716 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, HDMI0, HDMI1",
717 + VC4_ENCODER_TYPE_DSI0,
718 + VC4_ENCODER_TYPE_VEC,
719 + VC4_ENCODER_TYPE_HDMI0,
720 + VC4_ENCODER_TYPE_HDMI1),
721 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0",
722 + VC4_ENCODER_TYPE_DSI0,
723 + VC4_ENCODER_TYPE_TXP,
724 + VC4_ENCODER_TYPE_DSI1,
725 + VC4_ENCODER_TYPE_HDMI0),
726 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI1",
727 + VC4_ENCODER_TYPE_DSI0,
728 + VC4_ENCODER_TYPE_TXP,
729 + VC4_ENCODER_TYPE_DSI1,
730 + VC4_ENCODER_TYPE_HDMI1),
731 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, HDMI0, HDMI1",
732 + VC4_ENCODER_TYPE_DSI0,
733 + VC4_ENCODER_TYPE_TXP,
734 + VC4_ENCODER_TYPE_HDMI0,
735 + VC4_ENCODER_TYPE_HDMI1),
736 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, DSI1, HDMI0, HDMI1",
737 + VC4_ENCODER_TYPE_DSI0,
738 + VC4_ENCODER_TYPE_DSI1,
739 + VC4_ENCODER_TYPE_HDMI0,
740 + VC4_ENCODER_TYPE_HDMI1),
741 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0",
742 + VC4_ENCODER_TYPE_DSI0,
743 + VC4_ENCODER_TYPE_VEC,
744 + VC4_ENCODER_TYPE_TXP,
745 + VC4_ENCODER_TYPE_DSI1,
746 + VC4_ENCODER_TYPE_HDMI0),
747 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI1",
748 + VC4_ENCODER_TYPE_DSI0,
749 + VC4_ENCODER_TYPE_VEC,
750 + VC4_ENCODER_TYPE_TXP,
751 + VC4_ENCODER_TYPE_DSI1,
752 + VC4_ENCODER_TYPE_HDMI1),
753 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, HDMI0, HDMI1",
754 + VC4_ENCODER_TYPE_DSI0,
755 + VC4_ENCODER_TYPE_VEC,
756 + VC4_ENCODER_TYPE_TXP,
757 + VC4_ENCODER_TYPE_HDMI0,
758 + VC4_ENCODER_TYPE_HDMI1),
759 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, DSI1, HDMI0, HDMI1",
760 + VC4_ENCODER_TYPE_DSI0,
761 + VC4_ENCODER_TYPE_VEC,
762 + VC4_ENCODER_TYPE_DSI1,
763 + VC4_ENCODER_TYPE_HDMI0,
764 + VC4_ENCODER_TYPE_HDMI1),
765 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, TXP, DSI1, HDMI0, HDMI1",
766 + VC4_ENCODER_TYPE_DSI0,
767 + VC4_ENCODER_TYPE_TXP,
768 + VC4_ENCODER_TYPE_DSI1,
769 + VC4_ENCODER_TYPE_HDMI0,
770 + VC4_ENCODER_TYPE_HDMI1),
771 + VC5_PV_MUXING_TEST("More than 3 outputs: VEC, TXP, DSI1, HDMI0, HDMI1",
772 + VC4_ENCODER_TYPE_VEC,
773 + VC4_ENCODER_TYPE_TXP,
774 + VC4_ENCODER_TYPE_DSI1,
775 + VC4_ENCODER_TYPE_HDMI0,
776 + VC4_ENCODER_TYPE_HDMI1),
777 + VC5_PV_MUXING_TEST("More than 3 outputs: DPI, VEC, TXP, DSI1, HDMI0, HDMI1",
778 + VC4_ENCODER_TYPE_DPI,
779 + VC4_ENCODER_TYPE_VEC,
780 + VC4_ENCODER_TYPE_TXP,
781 + VC4_ENCODER_TYPE_DSI1,
782 + VC4_ENCODER_TYPE_HDMI0,
783 + VC4_ENCODER_TYPE_HDMI1),
784 + VC5_PV_MUXING_TEST("More than 3 outputs: DSI0, VEC, TXP, DSI1, HDMI0, HDMI1",
785 + VC4_ENCODER_TYPE_DSI0,
786 + VC4_ENCODER_TYPE_VEC,
787 + VC4_ENCODER_TYPE_TXP,
788 + VC4_ENCODER_TYPE_DSI1,
789 + VC4_ENCODER_TYPE_HDMI0,
790 + VC4_ENCODER_TYPE_HDMI1),
791 +};
792 +
793 +KUNIT_ARRAY_PARAM(vc5_test_pv_muxing_invalid,
794 + vc5_test_pv_muxing_invalid_params,
795 + vc4_test_pv_muxing_desc);
796 +
797 +static void drm_vc4_test_pv_muxing(struct kunit *test)
798 +{
799 + const struct pv_muxing_param *params = test->param_value;
800 + const struct pv_muxing_priv *priv = test->priv;
801 + struct drm_atomic_state *state = priv->state;
802 + unsigned int i;
803 + int ret;
804 +
805 + for (i = 0; i < params->nencoders; i++) {
806 + enum vc4_encoder_type enc_type = params->encoders[i];
807 +
808 + ret = vc4_mock_atomic_add_output(test, state, enc_type);
809 + KUNIT_ASSERT_EQ(test, ret, 0);
810 + }
811 +
812 + ret = drm_atomic_check_only(state);
813 + KUNIT_EXPECT_EQ(test, ret, 0);
814 +
815 + KUNIT_EXPECT_TRUE(test,
816 + check_fifo_conflict(test, state));
817 +
818 + for (i = 0; i < params->nencoders; i++) {
819 + enum vc4_encoder_type enc_type = params->encoders[i];
820 +
821 + KUNIT_EXPECT_TRUE(test, check_channel_for_encoder(test, state, enc_type,
822 + params->check_fn));
823 + }
824 +}
825 +
826 +static void drm_vc4_test_pv_muxing_invalid(struct kunit *test)
827 +{
828 + const struct pv_muxing_param *params = test->param_value;
829 + const struct pv_muxing_priv *priv = test->priv;
830 + struct drm_atomic_state *state = priv->state;
831 + unsigned int i;
832 + int ret;
833 +
834 + for (i = 0; i < params->nencoders; i++) {
835 + enum vc4_encoder_type enc_type = params->encoders[i];
836 +
837 + ret = vc4_mock_atomic_add_output(test, state, enc_type);
838 + KUNIT_ASSERT_EQ(test, ret, 0);
839 + }
840 +
841 + ret = drm_atomic_check_only(state);
842 + KUNIT_EXPECT_LT(test, ret, 0);
843 +}
844 +
845 +static int vc4_pv_muxing_test_init(struct kunit *test)
846 +{
847 + const struct pv_muxing_param *params = test->param_value;
848 + struct drm_atomic_state *state;
849 + struct pv_muxing_priv *priv;
850 + struct drm_device *drm;
851 + struct vc4_dev *vc4;
852 +
853 + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
854 + KUNIT_ASSERT_NOT_NULL(test, priv);
855 + test->priv = priv;
856 +
857 + vc4 = params->mock_fn(test);
858 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
859 + priv->vc4 = vc4;
860 +
861 + drm_modeset_acquire_init(&priv->ctx, 0);
862 +
863 + drm = &vc4->base;
864 + state = drm_atomic_state_alloc(drm);
865 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
866 +
867 + state->acquire_ctx = &priv->ctx;
868 +
869 + priv->state = state;
870 +
871 + return 0;
872 +}
873 +
874 +static void vc4_pv_muxing_test_exit(struct kunit *test)
875 +{
876 + struct pv_muxing_priv *priv = test->priv;
877 + struct vc4_dev *vc4 = priv->vc4;
878 + struct drm_device *drm = &vc4->base;
879 + struct drm_atomic_state *state = priv->state;
880 +
881 + drm_atomic_state_put(state);
882 + drm_modeset_drop_locks(&priv->ctx);
883 + drm_modeset_acquire_fini(&priv->ctx);
884 + drm_dev_unregister(drm);
885 + drm_kunit_helper_free_device(test, vc4->dev);
886 +}
887 +
888 +static struct kunit_case vc4_pv_muxing_tests[] = {
889 + KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing,
890 + vc4_test_pv_muxing_gen_params),
891 + KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid,
892 + vc4_test_pv_muxing_invalid_gen_params),
893 + {}
894 +};
895 +
896 +static struct kunit_suite vc4_pv_muxing_test_suite = {
897 + .name = "vc4-pv-muxing-combinations",
898 + .init = vc4_pv_muxing_test_init,
899 + .exit = vc4_pv_muxing_test_exit,
900 + .test_cases = vc4_pv_muxing_tests,
901 +};
902 +
903 +static struct kunit_case vc5_pv_muxing_tests[] = {
904 + KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing,
905 + vc5_test_pv_muxing_gen_params),
906 + KUNIT_CASE_PARAM(drm_vc4_test_pv_muxing_invalid,
907 + vc5_test_pv_muxing_invalid_gen_params),
908 + {}
909 +};
910 +
911 +static struct kunit_suite vc5_pv_muxing_test_suite = {
912 + .name = "vc5-pv-muxing-combinations",
913 + .init = vc4_pv_muxing_test_init,
914 + .exit = vc4_pv_muxing_test_exit,
915 + .test_cases = vc5_pv_muxing_tests,
916 +};
917 +
918 +/* See
919 + * https://lore.kernel.org/all/3e113525-aa89-b1e2-56b7-ca55bd41d057@samsung.com/
920 + * and
921 + * https://lore.kernel.org/dri-devel/20200917121623.42023-1-maxime@cerno.tech/
922 + */
923 +static void drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable(struct kunit *test)
924 +{
925 + struct drm_modeset_acquire_ctx ctx;
926 + struct drm_atomic_state *state;
927 + struct vc4_crtc_state *new_vc4_crtc_state;
928 + struct vc4_hvs_state *new_hvs_state;
929 + unsigned int hdmi0_channel;
930 + unsigned int hdmi1_channel;
931 + struct drm_device *drm;
932 + struct vc4_dev *vc4;
933 + int ret;
934 +
935 + vc4 = vc5_mock_device(test);
936 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
937 +
938 + drm_modeset_acquire_init(&ctx, 0);
939 +
940 + drm = &vc4->base;
941 + state = drm_atomic_state_alloc(drm);
942 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
943 +
944 + state->acquire_ctx = &ctx;
945 +
946 + ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
947 + KUNIT_ASSERT_EQ(test, ret, 0);
948 +
949 + ret = drm_atomic_check_only(state);
950 + KUNIT_ASSERT_EQ(test, ret, 0);
951 +
952 + new_hvs_state = vc4_hvs_get_new_global_state(state);
953 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
954 +
955 + new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
956 + VC4_ENCODER_TYPE_HDMI0);
957 + KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
958 +
959 + hdmi0_channel = new_vc4_crtc_state->assigned_channel;
960 + KUNIT_ASSERT_NE(test, hdmi0_channel, VC4_HVS_CHANNEL_DISABLED);
961 + KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi0_channel].in_use);
962 +
963 + ret = drm_atomic_helper_swap_state(state, false);
964 + KUNIT_ASSERT_EQ(test, ret, 0);
965 +
966 + drm_atomic_state_put(state);
967 +
968 + state = drm_atomic_state_alloc(drm);
969 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
970 +
971 + state->acquire_ctx = &ctx;
972 +
973 + ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
974 + KUNIT_ASSERT_EQ(test, ret, 0);
975 +
976 + ret = drm_atomic_check_only(state);
977 + KUNIT_ASSERT_EQ(test, ret, 0);
978 +
979 + new_hvs_state = vc4_hvs_get_new_global_state(state);
980 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
981 +
982 + new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
983 + VC4_ENCODER_TYPE_HDMI1);
984 + KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
985 +
986 + hdmi1_channel = new_vc4_crtc_state->assigned_channel;
987 + KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
988 + KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use);
989 +
990 + KUNIT_EXPECT_NE(test, hdmi0_channel, hdmi1_channel);
991 +
992 + drm_atomic_state_put(state);
993 + drm_modeset_drop_locks(&ctx);
994 + drm_modeset_acquire_fini(&ctx);
995 + drm_dev_unregister(drm);
996 + drm_kunit_helper_free_device(test, vc4->dev);
997 +}
998 +
999 +static void drm_test_vc5_pv_muxing_bugs_stable_fifo(struct kunit *test)
1000 +{
1001 + struct drm_modeset_acquire_ctx ctx;
1002 + struct drm_atomic_state *state;
1003 + struct vc4_crtc_state *new_vc4_crtc_state;
1004 + struct vc4_hvs_state *new_hvs_state;
1005 + unsigned int old_hdmi0_channel;
1006 + unsigned int old_hdmi1_channel;
1007 + struct drm_device *drm;
1008 + struct vc4_dev *vc4;
1009 + int ret;
1010 +
1011 + vc4 = vc5_mock_device(test);
1012 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
1013 +
1014 + drm_modeset_acquire_init(&ctx, 0);
1015 +
1016 + drm = &vc4->base;
1017 + state = drm_atomic_state_alloc(drm);
1018 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1019 +
1020 + state->acquire_ctx = &ctx;
1021 +
1022 + ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
1023 + KUNIT_ASSERT_EQ(test, ret, 0);
1024 +
1025 + ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
1026 + KUNIT_ASSERT_EQ(test, ret, 0);
1027 +
1028 + ret = drm_atomic_check_only(state);
1029 + KUNIT_ASSERT_EQ(test, ret, 0);
1030 +
1031 + new_hvs_state = vc4_hvs_get_new_global_state(state);
1032 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
1033 +
1034 + new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
1035 + VC4_ENCODER_TYPE_HDMI0);
1036 + KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
1037 +
1038 + old_hdmi0_channel = new_vc4_crtc_state->assigned_channel;
1039 + KUNIT_ASSERT_NE(test, old_hdmi0_channel, VC4_HVS_CHANNEL_DISABLED);
1040 + KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi0_channel].in_use);
1041 +
1042 + new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
1043 + VC4_ENCODER_TYPE_HDMI1);
1044 + KUNIT_ASSERT_NOT_NULL(test, new_vc4_crtc_state);
1045 +
1046 + old_hdmi1_channel = new_vc4_crtc_state->assigned_channel;
1047 + KUNIT_ASSERT_NE(test, old_hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
1048 + KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[old_hdmi1_channel].in_use);
1049 +
1050 + ret = drm_atomic_helper_swap_state(state, false);
1051 + KUNIT_ASSERT_EQ(test, ret, 0);
1052 +
1053 + drm_atomic_state_put(state);
1054 +
1055 + state = drm_atomic_state_alloc(drm);
1056 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1057 +
1058 + state->acquire_ctx = &ctx;
1059 +
1060 + ret = vc4_mock_atomic_del_output(test, state, VC4_ENCODER_TYPE_HDMI0);
1061 + KUNIT_ASSERT_EQ(test, ret, 0);
1062 +
1063 + ret = drm_atomic_check_only(state);
1064 + KUNIT_ASSERT_EQ(test, ret, 0);
1065 +
1066 + new_hvs_state = vc4_hvs_get_new_global_state(state);
1067 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_hvs_state);
1068 +
1069 + new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
1070 + VC4_ENCODER_TYPE_HDMI1);
1071 +
1072 + if (new_vc4_crtc_state) {
1073 + unsigned int hdmi1_channel;
1074 +
1075 + hdmi1_channel = new_vc4_crtc_state->assigned_channel;
1076 + KUNIT_ASSERT_NE(test, hdmi1_channel, VC4_HVS_CHANNEL_DISABLED);
1077 + KUNIT_ASSERT_TRUE(test, new_hvs_state->fifo_state[hdmi1_channel].in_use);
1078 +
1079 + KUNIT_EXPECT_EQ(test, old_hdmi1_channel, hdmi1_channel);
1080 + }
1081 +
1082 + drm_atomic_state_put(state);
1083 + drm_modeset_drop_locks(&ctx);
1084 + drm_modeset_acquire_fini(&ctx);
1085 + drm_dev_unregister(drm);
1086 + drm_kunit_helper_free_device(test, vc4->dev);
1087 +}
1088 +
1089 +static void
1090 +drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state(struct kunit *test)
1091 +{
1092 + struct drm_modeset_acquire_ctx ctx;
1093 + struct drm_atomic_state *state;
1094 + struct vc4_crtc_state *new_vc4_crtc_state;
1095 + struct drm_device *drm;
1096 + struct vc4_dev *vc4;
1097 + int ret;
1098 +
1099 + vc4 = vc5_mock_device(test);
1100 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, vc4);
1101 +
1102 + drm_modeset_acquire_init(&ctx, 0);
1103 +
1104 + drm = &vc4->base;
1105 + state = drm_atomic_state_alloc(drm);
1106 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1107 +
1108 + state->acquire_ctx = &ctx;
1109 +
1110 + ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI0);
1111 + KUNIT_ASSERT_EQ(test, ret, 0);
1112 +
1113 + ret = drm_atomic_check_only(state);
1114 + KUNIT_ASSERT_EQ(test, ret, 0);
1115 +
1116 + ret = drm_atomic_helper_swap_state(state, false);
1117 + KUNIT_ASSERT_EQ(test, ret, 0);
1118 +
1119 + drm_atomic_state_put(state);
1120 +
1121 + state = drm_atomic_state_alloc(drm);
1122 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1123 +
1124 + state->acquire_ctx = &ctx;
1125 +
1126 + ret = vc4_mock_atomic_add_output(test, state, VC4_ENCODER_TYPE_HDMI1);
1127 + KUNIT_ASSERT_EQ(test, ret, 0);
1128 +
1129 + ret = drm_atomic_check_only(state);
1130 + KUNIT_ASSERT_EQ(test, ret, 0);
1131 +
1132 + new_vc4_crtc_state = get_vc4_crtc_state_for_encoder(test, state,
1133 + VC4_ENCODER_TYPE_HDMI0);
1134 + KUNIT_EXPECT_NULL(test, new_vc4_crtc_state);
1135 +
1136 + drm_atomic_state_put(state);
1137 + drm_modeset_drop_locks(&ctx);
1138 + drm_modeset_acquire_fini(&ctx);
1139 + drm_dev_unregister(drm);
1140 + drm_kunit_helper_free_device(test, vc4->dev);
1141 +}
1142 +
1143 +static struct kunit_case vc5_pv_muxing_bugs_tests[] = {
1144 + KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable),
1145 + KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_subsequent_crtc_enable_too_many_crtc_state),
1146 + KUNIT_CASE(drm_test_vc5_pv_muxing_bugs_stable_fifo),
1147 + {}
1148 +};
1149 +
1150 +static struct kunit_suite vc5_pv_muxing_bugs_test_suite = {
1151 + .name = "vc5-pv-muxing-bugs",
1152 + .test_cases = vc5_pv_muxing_bugs_tests,
1153 +};
1154 +
1155 +kunit_test_suites(
1156 + &vc4_pv_muxing_test_suite,
1157 + &vc5_pv_muxing_test_suite,
1158 + &vc5_pv_muxing_bugs_test_suite
1159 +);