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