Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/vc4: tests: Add unit test suite for the PV muxing

The HVS to PixelValve muxing code is fairly error prone and has a bunch
of arbitrary constraints due to the hardware setup.

Let's create a test suite that makes sure that the possible combinations
work and the invalid ones don't.

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Maíra Canal <mcanal@igalia.com>
Link: https://lore.kernel.org/r/20221123-rpi-kunit-tests-v3-19-4615a663a84a@cerno.tech
Signed-off-by: Maxime Ripard <maxime@cerno.tech>

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