1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /*
3 * KUnit tests for amdgpu_dm.c
4 *
5 * Copyright 2026 Advanced Micro Devices, Inc.
6 */
7
8 #include <kunit/test.h>
9 #include <linux/pci.h>
10 #include <drm/drm_atomic.h>
11 #include <drm/drm_connector.h>
12 #include <drm/drm_crtc.h>
13 #include <drm/drm_modes.h>
14 #include <drm/drm_writeback.h>
15
16 #include "dc.h"
17 #include "inc/core_types.h"
18 #include "amd_shared.h"
19 #include "amdgpu.h"
20 #include "amdgpu_mode.h"
21 #include "amdgpu_dm.h"
22 #include "amdgpu_dm_kunit_test_helpers.h"
23
24 /* Tests for simple DM callbacks */
25
26 /**
27 * dm_test_is_idle - Test placeholder idle callback returns true
28 * @test: The KUnit test context
29 */
dm_test_is_idle(struct kunit * test)30 static void dm_test_is_idle(struct kunit *test)
31 {
32 KUNIT_EXPECT_TRUE(test, dm_is_idle(NULL));
33 }
34
35 /**
36 * dm_test_wait_for_idle - Test placeholder wait-for-idle callback returns success
37 * @test: The KUnit test context
38 */
dm_test_wait_for_idle(struct kunit * test)39 static void dm_test_wait_for_idle(struct kunit *test)
40 {
41 KUNIT_EXPECT_EQ(test, dm_wait_for_idle(NULL), 0);
42 }
43
44 /**
45 * dm_test_soft_reset - Test placeholder soft-reset callback returns success
46 * @test: The KUnit test context
47 */
dm_test_soft_reset(struct kunit * test)48 static void dm_test_soft_reset(struct kunit *test)
49 {
50 KUNIT_EXPECT_EQ(test, dm_soft_reset(NULL), 0);
51 }
52
53 /**
54 * dm_test_set_clockgating_state - Test placeholder clockgating callback returns success
55 * @test: The KUnit test context
56 */
dm_test_set_clockgating_state(struct kunit * test)57 static void dm_test_set_clockgating_state(struct kunit *test)
58 {
59 KUNIT_EXPECT_EQ(test, dm_set_clockgating_state(NULL, AMD_CG_STATE_GATE), 0);
60 }
61
62 /**
63 * dm_test_set_powergating_state - Test placeholder powergating callback returns success
64 * @test: The KUnit test context
65 */
dm_test_set_powergating_state(struct kunit * test)66 static void dm_test_set_powergating_state(struct kunit *test)
67 {
68 KUNIT_EXPECT_EQ(test, dm_set_powergating_state(NULL, AMD_PG_STATE_GATE), 0);
69 }
70
71 /**
72 * dm_test_bandwidth_update - Test placeholder bandwidth update is callable
73 * @test: The KUnit test context
74 */
dm_test_bandwidth_update(struct kunit * test)75 static void dm_test_bandwidth_update(struct kunit *test)
76 {
77 dm_bandwidth_update(NULL);
78 }
79
80 /**
81 * dm_test_crtc_complete_writeback_no_connector - Test no writeback connector returns false
82 * @test: The KUnit test context
83 */
dm_test_crtc_complete_writeback_no_connector(struct kunit * test)84 static void dm_test_crtc_complete_writeback_no_connector(struct kunit *test)
85 {
86 struct amdgpu_crtc *acrtc;
87
88 acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
89 KUNIT_ASSERT_NOT_NULL(test, acrtc);
90
91 KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_complete_writeback(acrtc));
92 }
93
94 /**
95 * dm_test_crtc_complete_writeback_not_pending - Test non-pending writeback returns false
96 * @test: The KUnit test context
97 */
dm_test_crtc_complete_writeback_not_pending(struct kunit * test)98 static void dm_test_crtc_complete_writeback_not_pending(struct kunit *test)
99 {
100 struct amdgpu_crtc *acrtc;
101 struct drm_writeback_connector *wb_conn;
102
103 acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
104 KUNIT_ASSERT_NOT_NULL(test, acrtc);
105 wb_conn = kunit_kzalloc(test, sizeof(*wb_conn), GFP_KERNEL);
106 KUNIT_ASSERT_NOT_NULL(test, wb_conn);
107
108 spin_lock_init(&wb_conn->job_lock);
109 acrtc->wb_conn = wb_conn;
110 acrtc->wb_pending = false;
111
112 KUNIT_EXPECT_FALSE(test, amdgpu_dm_crtc_complete_writeback(acrtc));
113 }
114
115 /**
116 * dm_test_vblank_get_counter_out_of_range - Test out-of-range CRTC returns zero
117 * @test: The KUnit test context
118 */
dm_test_vblank_get_counter_out_of_range(struct kunit * test)119 static void dm_test_vblank_get_counter_out_of_range(struct kunit *test)
120 {
121 struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
122
123 adev->mode_info.num_crtc = 1;
124
125 KUNIT_EXPECT_EQ(test, dm_vblank_get_counter(adev, 1), 0U);
126 }
127
128 /**
129 * dm_test_vblank_get_counter_no_stream - Test missing stream returns zero
130 * @test: The KUnit test context
131 */
dm_test_vblank_get_counter_no_stream(struct kunit * test)132 static void dm_test_vblank_get_counter_no_stream(struct kunit *test)
133 {
134 struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
135 struct amdgpu_crtc *acrtc;
136
137 acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
138 KUNIT_ASSERT_NOT_NULL(test, acrtc);
139
140 adev->mode_info.num_crtc = 1;
141 adev->mode_info.crtcs[0] = acrtc;
142
143 KUNIT_EXPECT_EQ(test, dm_vblank_get_counter(adev, 0), 0U);
144 }
145
146 /**
147 * dm_test_crtc_get_scanoutpos_invalid_crtc - Test invalid CRTC returns -EINVAL
148 * @test: The KUnit test context
149 */
dm_test_crtc_get_scanoutpos_invalid_crtc(struct kunit * test)150 static void dm_test_crtc_get_scanoutpos_invalid_crtc(struct kunit *test)
151 {
152 struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
153 u32 vbl = 0;
154 u32 position = 0;
155
156 adev->mode_info.num_crtc = 1;
157
158 KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, -1, &vbl, &position),
159 -EINVAL);
160 KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 1, &vbl, &position),
161 -EINVAL);
162 }
163
164 /**
165 * dm_test_crtc_get_scanoutpos_no_stream - Test missing stream returns zero
166 * @test: The KUnit test context
167 */
dm_test_crtc_get_scanoutpos_no_stream(struct kunit * test)168 static void dm_test_crtc_get_scanoutpos_no_stream(struct kunit *test)
169 {
170 struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
171 struct amdgpu_crtc *acrtc;
172 u32 vbl = 0;
173 u32 position = 0;
174
175 acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
176 KUNIT_ASSERT_NOT_NULL(test, acrtc);
177
178 adev->mode_info.num_crtc = 1;
179 adev->mode_info.crtcs[0] = acrtc;
180
181 KUNIT_EXPECT_EQ(test, dm_crtc_get_scanoutpos(adev, 0, &vbl, &position), 0);
182 KUNIT_EXPECT_EQ(test, vbl, 0U);
183 KUNIT_EXPECT_EQ(test, position, 0U);
184 }
185
186 /**
187 * dm_test_atomic_get_new_state_empty - Test empty atomic state has no DM state
188 * @test: The KUnit test context
189 */
dm_test_atomic_get_new_state_empty(struct kunit * test)190 static void dm_test_atomic_get_new_state_empty(struct kunit *test)
191 {
192 struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
193 struct drm_atomic_commit *state;
194
195 state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
196 KUNIT_ASSERT_NOT_NULL(test, state);
197 state->dev = &adev->ddev;
198
199 KUNIT_EXPECT_NULL(test, dm_atomic_get_new_state(state));
200 }
201
202 /**
203 * dm_test_atomic_get_new_state_match - Test atomic state returns matching DM private state
204 * @test: The KUnit test context
205 */
dm_test_atomic_get_new_state_match(struct kunit * test)206 static void dm_test_atomic_get_new_state_match(struct kunit *test)
207 {
208 struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
209 struct dm_atomic_state *dm_state;
210 struct drm_atomic_commit *state;
211
212 state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
213 KUNIT_ASSERT_NOT_NULL(test, state);
214
215 dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
216 KUNIT_ASSERT_NOT_NULL(test, dm_state);
217
218 state->private_objs = kunit_kzalloc(test, sizeof(*state->private_objs),
219 GFP_KERNEL);
220 KUNIT_ASSERT_NOT_NULL(test, state->private_objs);
221
222 state->dev = &adev->ddev;
223 state->num_private_objs = 1;
224 state->private_objs[0].ptr = &adev->dm.atomic_obj;
225 state->private_objs[0].new_state = &dm_state->base;
226
227 KUNIT_EXPECT_PTR_EQ(test, dm_atomic_get_new_state(state), dm_state);
228 }
229
230 /**
231 * dm_test_atomic_destroy_state_no_context - Test destroying DM atomic state without a DC context
232 * @test: The KUnit test context
233 */
dm_test_atomic_destroy_state_no_context(struct kunit * test)234 static void dm_test_atomic_destroy_state_no_context(struct kunit *test)
235 {
236 struct dm_atomic_state *dm_state;
237
238 /*
239 * Use kzalloc(), not kunit_kzalloc(): dm_atomic_destroy_state() frees
240 * the state itself, so KUnit-managed memory would be double-freed.
241 */
242 dm_state = kzalloc_obj(*dm_state);
243 KUNIT_ASSERT_NOT_NULL(test, dm_state);
244
245 /* context == NULL: dc_state_release() is skipped and the state is freed. */
246 dm_atomic_destroy_state(NULL, &dm_state->base);
247 }
248
249 /* Tests for dm_plane_layer_index_cmp() */
250
251 /**
252 * dm_test_plane_layer_index_cmp_equal - Test Plane layer index cmp equal
253 * @test: The KUnit test context
254 */
dm_test_plane_layer_index_cmp_equal(struct kunit * test)255 static void dm_test_plane_layer_index_cmp_equal(struct kunit *test)
256 {
257 struct dc_plane_state *plane_a;
258 struct dc_plane_state *plane_b;
259 struct dc_surface_update sa, sb;
260
261 plane_a = kunit_kzalloc(test, sizeof(*plane_a), GFP_KERNEL);
262 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_a);
263 plane_b = kunit_kzalloc(test, sizeof(*plane_b), GFP_KERNEL);
264 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_b);
265
266 plane_a->layer_index = 5;
267 plane_b->layer_index = 5;
268 sa.surface = plane_a;
269 sb.surface = plane_b;
270
271 KUNIT_EXPECT_EQ(test, dm_plane_layer_index_cmp(&sa, &sb), 0);
272 }
273
274 /**
275 * dm_test_plane_layer_index_cmp_descending - Test Plane layer index cmp descending
276 * @test: The KUnit test context
277 */
dm_test_plane_layer_index_cmp_descending(struct kunit * test)278 static void dm_test_plane_layer_index_cmp_descending(struct kunit *test)
279 {
280 struct dc_plane_state *plane_a;
281 struct dc_plane_state *plane_b;
282 struct dc_surface_update sa, sb;
283
284 plane_a = kunit_kzalloc(test, sizeof(*plane_a), GFP_KERNEL);
285 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_a);
286 plane_b = kunit_kzalloc(test, sizeof(*plane_b), GFP_KERNEL);
287 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_b);
288
289 plane_a->layer_index = 3;
290 plane_b->layer_index = 7;
291 sa.surface = plane_a;
292 sb.surface = plane_b;
293
294 /* b has higher index, so cmp(a,b) = b - a > 0 (b sorts first) */
295 KUNIT_EXPECT_GT(test, dm_plane_layer_index_cmp(&sa, &sb), 0);
296 }
297
298 /**
299 * dm_test_plane_layer_index_cmp_ascending - Test Plane layer index cmp ascending
300 * @test: The KUnit test context
301 */
dm_test_plane_layer_index_cmp_ascending(struct kunit * test)302 static void dm_test_plane_layer_index_cmp_ascending(struct kunit *test)
303 {
304 struct dc_plane_state *plane_a;
305 struct dc_plane_state *plane_b;
306 struct dc_surface_update sa, sb;
307
308 plane_a = kunit_kzalloc(test, sizeof(*plane_a), GFP_KERNEL);
309 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_a);
310 plane_b = kunit_kzalloc(test, sizeof(*plane_b), GFP_KERNEL);
311 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_b);
312
313 plane_a->layer_index = 9;
314 plane_b->layer_index = 2;
315 sa.surface = plane_a;
316 sb.surface = plane_b;
317
318 /* a has higher index, so cmp(a,b) = b - a < 0 (a sorts first) */
319 KUNIT_EXPECT_LT(test, dm_plane_layer_index_cmp(&sa, &sb), 0);
320 }
321
322 /* Tests for fill_plane_color_attributes() */
323
324 /**
325 * dm_test_fill_color_attr_rgb_format - Test Fill color attr rgb format
326 * @test: The KUnit test context
327 */
dm_test_fill_color_attr_rgb_format(struct kunit * test)328 static void dm_test_fill_color_attr_rgb_format(struct kunit *test)
329 {
330 struct drm_plane_state plane_state = { 0 };
331 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
332 int ret;
333
334 /* RGB format: should return 0 and set SRGB regardless of encoding */
335 plane_state.color_encoding = DRM_COLOR_YCBCR_BT709;
336 plane_state.color_range = DRM_COLOR_YCBCR_FULL_RANGE;
337
338 ret = fill_plane_color_attributes(&plane_state,
339 SURFACE_PIXEL_FORMAT_GRPH_ARGB8888,
340 &color_space);
341 KUNIT_EXPECT_EQ(test, ret, 0);
342 KUNIT_EXPECT_EQ(test, (int)color_space, (int)COLOR_SPACE_SRGB);
343 }
344
345 /**
346 * dm_test_fill_color_attr_bt601_full - Test Fill color attr bt601 full
347 * @test: The KUnit test context
348 */
dm_test_fill_color_attr_bt601_full(struct kunit * test)349 static void dm_test_fill_color_attr_bt601_full(struct kunit *test)
350 {
351 struct drm_plane_state plane_state = { 0 };
352 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
353 int ret;
354
355 plane_state.color_encoding = DRM_COLOR_YCBCR_BT601;
356 plane_state.color_range = DRM_COLOR_YCBCR_FULL_RANGE;
357
358 ret = fill_plane_color_attributes(&plane_state,
359 SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr,
360 &color_space);
361 KUNIT_EXPECT_EQ(test, ret, 0);
362 KUNIT_EXPECT_EQ(test, (int)color_space, (int)COLOR_SPACE_YCBCR601);
363 }
364
365 /**
366 * dm_test_fill_color_attr_bt601_limited - Test Fill color attr bt601 limited
367 * @test: The KUnit test context
368 */
dm_test_fill_color_attr_bt601_limited(struct kunit * test)369 static void dm_test_fill_color_attr_bt601_limited(struct kunit *test)
370 {
371 struct drm_plane_state plane_state = { 0 };
372 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
373 int ret;
374
375 plane_state.color_encoding = DRM_COLOR_YCBCR_BT601;
376 plane_state.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
377
378 ret = fill_plane_color_attributes(&plane_state,
379 SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr,
380 &color_space);
381 KUNIT_EXPECT_EQ(test, ret, 0);
382 KUNIT_EXPECT_EQ(test, (int)color_space,
383 (int)COLOR_SPACE_YCBCR601_LIMITED);
384 }
385
386 /**
387 * dm_test_fill_color_attr_bt709_full - Test Fill color attr bt709 full
388 * @test: The KUnit test context
389 */
dm_test_fill_color_attr_bt709_full(struct kunit * test)390 static void dm_test_fill_color_attr_bt709_full(struct kunit *test)
391 {
392 struct drm_plane_state plane_state = { 0 };
393 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
394 int ret;
395
396 plane_state.color_encoding = DRM_COLOR_YCBCR_BT709;
397 plane_state.color_range = DRM_COLOR_YCBCR_FULL_RANGE;
398
399 ret = fill_plane_color_attributes(&plane_state,
400 SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr,
401 &color_space);
402 KUNIT_EXPECT_EQ(test, ret, 0);
403 KUNIT_EXPECT_EQ(test, (int)color_space, (int)COLOR_SPACE_YCBCR709);
404 }
405
406 /**
407 * dm_test_fill_color_attr_bt709_limited - Test Fill color attr bt709 limited
408 * @test: The KUnit test context
409 */
dm_test_fill_color_attr_bt709_limited(struct kunit * test)410 static void dm_test_fill_color_attr_bt709_limited(struct kunit *test)
411 {
412 struct drm_plane_state plane_state = { 0 };
413 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
414 int ret;
415
416 plane_state.color_encoding = DRM_COLOR_YCBCR_BT709;
417 plane_state.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
418
419 ret = fill_plane_color_attributes(&plane_state,
420 SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr,
421 &color_space);
422 KUNIT_EXPECT_EQ(test, ret, 0);
423 KUNIT_EXPECT_EQ(test, (int)color_space,
424 (int)COLOR_SPACE_YCBCR709_LIMITED);
425 }
426
427 /**
428 * dm_test_fill_color_attr_bt2020_full - Test Fill color attr bt2020 full
429 * @test: The KUnit test context
430 */
dm_test_fill_color_attr_bt2020_full(struct kunit * test)431 static void dm_test_fill_color_attr_bt2020_full(struct kunit *test)
432 {
433 struct drm_plane_state plane_state = { 0 };
434 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
435 int ret;
436
437 plane_state.color_encoding = DRM_COLOR_YCBCR_BT2020;
438 plane_state.color_range = DRM_COLOR_YCBCR_FULL_RANGE;
439
440 ret = fill_plane_color_attributes(&plane_state,
441 SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr,
442 &color_space);
443 KUNIT_EXPECT_EQ(test, ret, 0);
444 KUNIT_EXPECT_EQ(test, (int)color_space,
445 (int)COLOR_SPACE_2020_YCBCR_FULL);
446 }
447
448 /**
449 * dm_test_fill_color_attr_bt2020_limited - Test Fill color attr bt2020 limited
450 * @test: The KUnit test context
451 */
dm_test_fill_color_attr_bt2020_limited(struct kunit * test)452 static void dm_test_fill_color_attr_bt2020_limited(struct kunit *test)
453 {
454 struct drm_plane_state plane_state = { 0 };
455 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
456 int ret;
457
458 plane_state.color_encoding = DRM_COLOR_YCBCR_BT2020;
459 plane_state.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE;
460
461 ret = fill_plane_color_attributes(&plane_state,
462 SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr,
463 &color_space);
464 KUNIT_EXPECT_EQ(test, ret, 0);
465 KUNIT_EXPECT_EQ(test, (int)color_space,
466 (int)COLOR_SPACE_2020_YCBCR_LIMITED);
467 }
468
469 /**
470 * dm_test_fill_color_attr_invalid_encoding - Test Fill color attr invalid encoding
471 * @test: The KUnit test context
472 */
dm_test_fill_color_attr_invalid_encoding(struct kunit * test)473 static void dm_test_fill_color_attr_invalid_encoding(struct kunit *test)
474 {
475 struct drm_plane_state plane_state = { 0 };
476 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN;
477 int ret;
478
479 plane_state.color_encoding = 99;
480 plane_state.color_range = DRM_COLOR_YCBCR_FULL_RANGE;
481
482 ret = fill_plane_color_attributes(&plane_state,
483 SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr,
484 &color_space);
485 KUNIT_EXPECT_EQ(test, ret, -EINVAL);
486 }
487
488 /* Tests for modereset_required() */
489
490 /**
491 * dm_test_modereset_required_when_inactive_and_modeset - Test Modereset required when inactive and modeset
492 * @test: The KUnit test context
493 */
dm_test_modereset_required_when_inactive_and_modeset(struct kunit * test)494 static void dm_test_modereset_required_when_inactive_and_modeset(struct kunit *test)
495 {
496 struct drm_crtc_state crtc_state = { 0 };
497
498 crtc_state.active = false;
499 crtc_state.mode_changed = true;
500
501 KUNIT_EXPECT_TRUE(test, modereset_required(&crtc_state));
502 }
503
504 /**
505 * dm_test_modereset_not_required_when_active_and_modeset - Test Modereset not required when active and modeset
506 * @test: The KUnit test context
507 */
dm_test_modereset_not_required_when_active_and_modeset(struct kunit * test)508 static void dm_test_modereset_not_required_when_active_and_modeset(struct kunit *test)
509 {
510 struct drm_crtc_state crtc_state = { 0 };
511
512 crtc_state.active = true;
513 crtc_state.mode_changed = true;
514
515 KUNIT_EXPECT_FALSE(test, modereset_required(&crtc_state));
516 }
517
518 /**
519 * dm_test_modereset_not_required_when_inactive_without_modeset - Test Modereset not required when inactive without modeset
520 * @test: The KUnit test context
521 */
dm_test_modereset_not_required_when_inactive_without_modeset(struct kunit * test)522 static void dm_test_modereset_not_required_when_inactive_without_modeset(struct kunit *test)
523 {
524 struct drm_crtc_state crtc_state = { 0 };
525
526 crtc_state.active = false;
527 crtc_state.mode_changed = false;
528
529 KUNIT_EXPECT_FALSE(test, modereset_required(&crtc_state));
530 }
531
532 /* Tests for is_scaling_state_different() */
533
534 /**
535 * dm_test_scaling_state_same - Test identical scaling states compare equal
536 * @test: The KUnit test context
537 */
dm_test_scaling_state_same(struct kunit * test)538 static void dm_test_scaling_state_same(struct kunit *test)
539 {
540 struct dm_connector_state *a;
541 struct dm_connector_state *b;
542
543 a = kunit_kzalloc(test, sizeof(*a), GFP_KERNEL);
544 b = kunit_kzalloc(test, sizeof(*b), GFP_KERNEL);
545 KUNIT_ASSERT_NOT_NULL(test, a);
546 KUNIT_ASSERT_NOT_NULL(test, b);
547
548 a->scaling = RMX_FULL;
549 a->underscan_enable = false;
550 *b = *a;
551
552 KUNIT_EXPECT_FALSE(test, is_scaling_state_different(a, b));
553 }
554
555 /**
556 * dm_test_scaling_state_scaling_changed - Test differing scaling mode is detected
557 * @test: The KUnit test context
558 */
dm_test_scaling_state_scaling_changed(struct kunit * test)559 static void dm_test_scaling_state_scaling_changed(struct kunit *test)
560 {
561 struct dm_connector_state *a;
562 struct dm_connector_state *b;
563
564 a = kunit_kzalloc(test, sizeof(*a), GFP_KERNEL);
565 b = kunit_kzalloc(test, sizeof(*b), GFP_KERNEL);
566 KUNIT_ASSERT_NOT_NULL(test, a);
567 KUNIT_ASSERT_NOT_NULL(test, b);
568
569 a->scaling = RMX_FULL;
570 b->scaling = RMX_CENTER;
571
572 KUNIT_EXPECT_TRUE(test, is_scaling_state_different(a, b));
573 }
574
575 /**
576 * dm_test_scaling_state_underscan_enabled - Test enabling underscan with borders differs
577 * @test: The KUnit test context
578 */
dm_test_scaling_state_underscan_enabled(struct kunit * test)579 static void dm_test_scaling_state_underscan_enabled(struct kunit *test)
580 {
581 struct dm_connector_state *old_state;
582 struct dm_connector_state *new_state;
583
584 old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
585 new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
586 KUNIT_ASSERT_NOT_NULL(test, old_state);
587 KUNIT_ASSERT_NOT_NULL(test, new_state);
588
589 /* new enables underscan with non-zero borders, old has it disabled */
590 new_state->underscan_enable = true;
591 new_state->underscan_hborder = 16;
592 new_state->underscan_vborder = 16;
593 old_state->underscan_enable = false;
594
595 KUNIT_EXPECT_TRUE(test, is_scaling_state_different(new_state, old_state));
596 }
597
598 /**
599 * dm_test_scaling_state_underscan_disabled - Test disabling underscan with borders differs
600 * @test: The KUnit test context
601 */
dm_test_scaling_state_underscan_disabled(struct kunit * test)602 static void dm_test_scaling_state_underscan_disabled(struct kunit *test)
603 {
604 struct dm_connector_state *old_state;
605 struct dm_connector_state *new_state;
606
607 old_state = kunit_kzalloc(test, sizeof(*old_state), GFP_KERNEL);
608 new_state = kunit_kzalloc(test, sizeof(*new_state), GFP_KERNEL);
609 KUNIT_ASSERT_NOT_NULL(test, old_state);
610 KUNIT_ASSERT_NOT_NULL(test, new_state);
611
612 old_state->underscan_enable = true;
613 old_state->underscan_hborder = 16;
614 old_state->underscan_vborder = 16;
615 new_state->underscan_enable = false;
616
617 KUNIT_EXPECT_TRUE(test, is_scaling_state_different(new_state, old_state));
618 }
619
620 /**
621 * dm_test_scaling_state_underscan_border_changed - Test changed underscan borders differ
622 * @test: The KUnit test context
623 */
dm_test_scaling_state_underscan_border_changed(struct kunit * test)624 static void dm_test_scaling_state_underscan_border_changed(struct kunit *test)
625 {
626 struct dm_connector_state *a;
627 struct dm_connector_state *b;
628
629 a = kunit_kzalloc(test, sizeof(*a), GFP_KERNEL);
630 b = kunit_kzalloc(test, sizeof(*b), GFP_KERNEL);
631 KUNIT_ASSERT_NOT_NULL(test, a);
632 KUNIT_ASSERT_NOT_NULL(test, b);
633
634 a->underscan_enable = true;
635 a->underscan_hborder = 16;
636 a->underscan_vborder = 16;
637 *b = *a;
638 b->underscan_hborder = 32;
639
640 KUNIT_EXPECT_TRUE(test, is_scaling_state_different(a, b));
641 }
642
643 /* Tests for set_multisync_trigger_params() */
644
645 /**
646 * dm_test_multisync_trigger_disabled - Test disabled reset leaves params untouched
647 * @test: The KUnit test context
648 */
dm_test_multisync_trigger_disabled(struct kunit * test)649 static void dm_test_multisync_trigger_disabled(struct kunit *test)
650 {
651 struct dc_stream_state *stream;
652
653 stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
654 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
655
656 stream->triggered_crtc_reset.enabled = false;
657 stream->triggered_crtc_reset.event = CRTC_EVENT_VSYNC_FALLING;
658 stream->triggered_crtc_reset.delay = TRIGGER_DELAY_NEXT_LINE;
659
660 set_multisync_trigger_params(stream);
661
662 /* Nothing should change when the reset trigger is disabled */
663 KUNIT_EXPECT_EQ(test, (int)stream->triggered_crtc_reset.event,
664 (int)CRTC_EVENT_VSYNC_FALLING);
665 KUNIT_EXPECT_EQ(test, (int)stream->triggered_crtc_reset.delay,
666 (int)TRIGGER_DELAY_NEXT_LINE);
667 }
668
669 /**
670 * dm_test_multisync_trigger_rising - Test positive vsync polarity selects rising edge
671 * @test: The KUnit test context
672 */
dm_test_multisync_trigger_rising(struct kunit * test)673 static void dm_test_multisync_trigger_rising(struct kunit *test)
674 {
675 struct dc_stream_state *stream;
676 struct dc_stream_state *master;
677
678 stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
679 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
680 master = kunit_kzalloc(test, sizeof(*master), GFP_KERNEL);
681 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, master);
682
683 master->timing.flags.VSYNC_POSITIVE_POLARITY = 1;
684 stream->triggered_crtc_reset.enabled = true;
685 stream->triggered_crtc_reset.event_source = master;
686
687 set_multisync_trigger_params(stream);
688
689 KUNIT_EXPECT_EQ(test, (int)stream->triggered_crtc_reset.event,
690 (int)CRTC_EVENT_VSYNC_RISING);
691 KUNIT_EXPECT_EQ(test, (int)stream->triggered_crtc_reset.delay,
692 (int)TRIGGER_DELAY_NEXT_PIXEL);
693 }
694
695 /**
696 * dm_test_multisync_trigger_falling - Test negative vsync polarity selects falling edge
697 * @test: The KUnit test context
698 */
dm_test_multisync_trigger_falling(struct kunit * test)699 static void dm_test_multisync_trigger_falling(struct kunit *test)
700 {
701 struct dc_stream_state *stream;
702 struct dc_stream_state *master;
703
704 stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
705 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
706 master = kunit_kzalloc(test, sizeof(*master), GFP_KERNEL);
707 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, master);
708
709 master->timing.flags.VSYNC_POSITIVE_POLARITY = 0;
710 stream->triggered_crtc_reset.enabled = true;
711 stream->triggered_crtc_reset.event_source = master;
712
713 set_multisync_trigger_params(stream);
714
715 KUNIT_EXPECT_EQ(test, (int)stream->triggered_crtc_reset.event,
716 (int)CRTC_EVENT_VSYNC_FALLING);
717 KUNIT_EXPECT_EQ(test, (int)stream->triggered_crtc_reset.delay,
718 (int)TRIGGER_DELAY_NEXT_PIXEL);
719 }
720
721 /* Tests for set_master_stream() */
722
723 /**
724 * dm_test_master_stream_highest_refresh - Test highest refresh-rate stream becomes master
725 * @test: The KUnit test context
726 */
dm_test_master_stream_highest_refresh(struct kunit * test)727 static void dm_test_master_stream_highest_refresh(struct kunit *test)
728 {
729 struct dc_stream_state *stream0, *stream1;
730 struct dc_stream_state *stream_set[2];
731
732 stream0 = kunit_kzalloc(test, sizeof(*stream0), GFP_KERNEL);
733 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream0);
734 stream1 = kunit_kzalloc(test, sizeof(*stream1), GFP_KERNEL);
735 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream1);
736 stream_set[0] = stream0;
737 stream_set[1] = stream1;
738
739 /* stream0: 60Hz, stream1: 120Hz -> stream1 is master */
740 stream0->triggered_crtc_reset.enabled = true;
741 stream0->timing.pix_clk_100hz = 1485000;
742 stream0->timing.h_total = 2200;
743 stream0->timing.v_total = 1125;
744
745 stream1->triggered_crtc_reset.enabled = true;
746 stream1->timing.pix_clk_100hz = 2970000;
747 stream1->timing.h_total = 2200;
748 stream1->timing.v_total = 1125;
749
750 set_master_stream(stream_set, 2);
751
752 KUNIT_EXPECT_PTR_EQ(test, stream0->triggered_crtc_reset.event_source,
753 stream1);
754 KUNIT_EXPECT_PTR_EQ(test, stream1->triggered_crtc_reset.event_source,
755 stream1);
756 }
757
758 /**
759 * dm_test_master_stream_defaults_to_first - Test default master when none triggered
760 * @test: The KUnit test context
761 *
762 * When no stream has the reset trigger enabled, master_stream stays 0 and all
763 * streams point at the first stream as their event source.
764 */
dm_test_master_stream_defaults_to_first(struct kunit * test)765 static void dm_test_master_stream_defaults_to_first(struct kunit *test)
766 {
767 struct dc_stream_state *stream0, *stream1;
768 struct dc_stream_state *stream_set[2];
769
770 stream0 = kunit_kzalloc(test, sizeof(*stream0), GFP_KERNEL);
771 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream0);
772 stream1 = kunit_kzalloc(test, sizeof(*stream1), GFP_KERNEL);
773 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream1);
774 stream_set[0] = stream0;
775 stream_set[1] = stream1;
776
777 set_master_stream(stream_set, 2);
778
779 KUNIT_EXPECT_PTR_EQ(test, stream0->triggered_crtc_reset.event_source,
780 stream0);
781 KUNIT_EXPECT_PTR_EQ(test, stream1->triggered_crtc_reset.event_source,
782 stream0);
783 }
784
785 /* Tests for is_content_protection_different() */
786
787 struct dm_test_cp_ctx {
788 struct amdgpu_dm_connector *aconnector;
789 struct dm_connector_state *new_dm; /* also connector->state */
790 struct dm_connector_state *old_dm;
791 struct drm_crtc_state *new_crtc;
792 struct drm_crtc_state *old_crtc;
793 };
794
dm_test_cp_ctx_alloc(struct kunit * test)795 static struct dm_test_cp_ctx *dm_test_cp_ctx_alloc(struct kunit *test)
796 {
797 struct dm_test_cp_ctx *ctx;
798
799 ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
800 KUNIT_ASSERT_NOT_NULL(test, ctx);
801
802 ctx->aconnector = kunit_kzalloc(test, sizeof(*ctx->aconnector), GFP_KERNEL);
803 KUNIT_ASSERT_NOT_NULL(test, ctx->aconnector);
804 ctx->new_dm = kunit_kzalloc(test, sizeof(*ctx->new_dm), GFP_KERNEL);
805 KUNIT_ASSERT_NOT_NULL(test, ctx->new_dm);
806 ctx->old_dm = kunit_kzalloc(test, sizeof(*ctx->old_dm), GFP_KERNEL);
807 KUNIT_ASSERT_NOT_NULL(test, ctx->old_dm);
808 ctx->new_crtc = kunit_kzalloc(test, sizeof(*ctx->new_crtc), GFP_KERNEL);
809 KUNIT_ASSERT_NOT_NULL(test, ctx->new_crtc);
810 ctx->old_crtc = kunit_kzalloc(test, sizeof(*ctx->old_crtc), GFP_KERNEL);
811 KUNIT_ASSERT_NOT_NULL(test, ctx->old_crtc);
812
813 /* connector->state must be the new dm connector state */
814 ctx->aconnector->base.state = &ctx->new_dm->base;
815 ctx->aconnector->base.dpms = DRM_MODE_DPMS_ON;
816
817 return ctx;
818 }
819
dm_test_cp_diff(struct dm_test_cp_ctx * ctx)820 static bool dm_test_cp_diff(struct dm_test_cp_ctx *ctx)
821 {
822 return is_content_protection_different(ctx->new_crtc, ctx->old_crtc,
823 &ctx->new_dm->base,
824 &ctx->old_dm->base,
825 &ctx->aconnector->base, NULL);
826 }
827
828 /**
829 * dm_test_cp_diff_hdcp_type_change - Test an HDCP content-type change forces true
830 * @test: The KUnit test context
831 */
dm_test_cp_diff_hdcp_type_change(struct kunit * test)832 static void dm_test_cp_diff_hdcp_type_change(struct kunit *test)
833 {
834 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
835
836 ctx->old_dm->base.hdcp_content_type = 0;
837 ctx->new_dm->base.hdcp_content_type = 1;
838 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
839
840 KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx));
841 KUNIT_EXPECT_EQ(test, (int)ctx->new_dm->base.content_protection,
842 (int)DRM_MODE_CONTENT_PROTECTION_DESIRED);
843 }
844
845 /**
846 * dm_test_cp_diff_reenable_mode_changed - Test ENABLED->DESIRED with modeset forces true
847 * @test: The KUnit test context
848 */
dm_test_cp_diff_reenable_mode_changed(struct kunit * test)849 static void dm_test_cp_diff_reenable_mode_changed(struct kunit *test)
850 {
851 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
852
853 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
854 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
855 ctx->new_crtc->mode_changed = true;
856
857 KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx));
858 KUNIT_EXPECT_EQ(test, (int)ctx->new_dm->base.content_protection,
859 (int)DRM_MODE_CONTENT_PROTECTION_DESIRED);
860 }
861
862 /**
863 * dm_test_cp_diff_reenable_no_change - Test ENABLED->DESIRED without modeset restores ENABLED
864 * @test: The KUnit test context
865 */
dm_test_cp_diff_reenable_no_change(struct kunit * test)866 static void dm_test_cp_diff_reenable_no_change(struct kunit *test)
867 {
868 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
869
870 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
871 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
872 ctx->new_crtc->mode_changed = false;
873
874 KUNIT_EXPECT_FALSE(test, dm_test_cp_diff(ctx));
875 KUNIT_EXPECT_EQ(test, (int)ctx->new_dm->base.content_protection,
876 (int)DRM_MODE_CONTENT_PROTECTION_ENABLED);
877 }
878
879 /**
880 * dm_test_cp_diff_undesired - Test UNDESIRED->UNDESIRED needs no update
881 * @test: The KUnit test context
882 */
dm_test_cp_diff_undesired(struct kunit * test)883 static void dm_test_cp_diff_undesired(struct kunit *test)
884 {
885 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
886
887 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
888 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
889
890 KUNIT_EXPECT_FALSE(test, dm_test_cp_diff(ctx));
891 }
892
893 /**
894 * dm_test_cp_diff_desired_mode_changed - Test DESIRED->DESIRED with modeset forces true
895 * @test: The KUnit test context
896 */
dm_test_cp_diff_desired_mode_changed(struct kunit * test)897 static void dm_test_cp_diff_desired_mode_changed(struct kunit *test)
898 {
899 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
900
901 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
902 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
903 ctx->new_crtc->mode_changed = true;
904
905 KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx));
906 }
907
908 /**
909 * dm_test_cp_diff_desired_no_change - Test steady DESIRED->DESIRED needs no update
910 * @test: The KUnit test context
911 */
dm_test_cp_diff_desired_no_change(struct kunit * test)912 static void dm_test_cp_diff_desired_no_change(struct kunit *test)
913 {
914 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
915
916 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
917 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
918 ctx->new_crtc->mode_changed = false;
919
920 KUNIT_EXPECT_FALSE(test, dm_test_cp_diff(ctx));
921 }
922
923 /**
924 * dm_test_cp_diff_update_hdcp_hotplug - Test the update_hdcp hot-plug path forces true
925 * @test: The KUnit test context
926 */
dm_test_cp_diff_update_hdcp_hotplug(struct kunit * test)927 static void dm_test_cp_diff_update_hdcp_hotplug(struct kunit *test)
928 {
929 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
930 struct dc_sink *sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
931
932 KUNIT_ASSERT_NOT_NULL(test, sink);
933
934 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
935 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
936 ctx->new_dm->update_hdcp = true;
937 ctx->aconnector->base.dpms = DRM_MODE_DPMS_ON;
938 ctx->aconnector->dc_sink = sink;
939
940 KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx));
941 KUNIT_EXPECT_FALSE(test, ctx->new_dm->update_hdcp);
942 }
943
944 /**
945 * dm_test_cp_diff_stream_reenabled - Test the stream removed-and-re-enabled path forces true
946 * @test: The KUnit test context
947 */
dm_test_cp_diff_stream_reenabled(struct kunit * test)948 static void dm_test_cp_diff_stream_reenabled(struct kunit *test)
949 {
950 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
951 struct drm_crtc *crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
952
953 KUNIT_ASSERT_NOT_NULL(test, crtc);
954 crtc->enabled = true;
955
956 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
957 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
958 ctx->new_dm->update_hdcp = true;
959 ctx->old_dm->base.crtc = NULL;
960 ctx->new_dm->base.crtc = crtc;
961
962 KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx));
963 KUNIT_EXPECT_FALSE(test, ctx->new_dm->update_hdcp);
964 }
965
966 /**
967 * dm_test_cp_diff_s3_undesired_to_enabled - Test the S3 UNDESIRED->ENABLED path forces true
968 * @test: The KUnit test context
969 */
dm_test_cp_diff_s3_undesired_to_enabled(struct kunit * test)970 static void dm_test_cp_diff_s3_undesired_to_enabled(struct kunit *test)
971 {
972 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
973
974 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
975 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
976
977 KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx));
978 KUNIT_EXPECT_EQ(test, (int)ctx->new_dm->base.content_protection,
979 (int)DRM_MODE_CONTENT_PROTECTION_DESIRED);
980 }
981
982 /**
983 * dm_test_cp_diff_desired_to_enabled - Test DESIRED->ENABLED needs no update
984 * @test: The KUnit test context
985 */
dm_test_cp_diff_desired_to_enabled(struct kunit * test)986 static void dm_test_cp_diff_desired_to_enabled(struct kunit *test)
987 {
988 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
989
990 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
991 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
992
993 KUNIT_EXPECT_FALSE(test, dm_test_cp_diff(ctx));
994 }
995
996 /**
997 * dm_test_cp_diff_desired_to_undesired - Test DESIRED->UNDESIRED forces update
998 * @test: The KUnit test context
999 */
dm_test_cp_diff_desired_to_undesired(struct kunit * test)1000 static void dm_test_cp_diff_desired_to_undesired(struct kunit *test)
1001 {
1002 struct dm_test_cp_ctx *ctx = dm_test_cp_ctx_alloc(test);
1003
1004 ctx->old_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
1005 ctx->new_dm->base.content_protection = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
1006
1007 KUNIT_EXPECT_TRUE(test, dm_test_cp_diff(ctx));
1008 }
1009
1010 /* Tests for dm_enable_per_frame_crtc_master_sync() */
1011
1012 /**
1013 * dm_test_per_frame_master_sync_single_stream - Test fewer than two streams is a no-op
1014 * @test: The KUnit test context
1015 */
dm_test_per_frame_master_sync_single_stream(struct kunit * test)1016 static void dm_test_per_frame_master_sync_single_stream(struct kunit *test)
1017 {
1018 struct dc_state *context;
1019 struct dc_stream_state *stream;
1020
1021 context = kunit_kzalloc(test, sizeof(*context), GFP_KERNEL);
1022 KUNIT_ASSERT_NOT_NULL(test, context);
1023 stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
1024 KUNIT_ASSERT_NOT_NULL(test, stream);
1025
1026 stream->triggered_crtc_reset.enabled = true;
1027 context->streams[0] = stream;
1028 context->stream_count = 1;
1029
1030 dm_enable_per_frame_crtc_master_sync(context);
1031
1032 /* < 2 streams: early return, event_source stays NULL */
1033 KUNIT_EXPECT_NULL(test, stream->triggered_crtc_reset.event_source);
1034 }
1035
1036 /**
1037 * dm_test_per_frame_master_sync_two_streams - Test the master is picked and applied
1038 * @test: The KUnit test context
1039 */
dm_test_per_frame_master_sync_two_streams(struct kunit * test)1040 static void dm_test_per_frame_master_sync_two_streams(struct kunit *test)
1041 {
1042 struct dc_state *context;
1043 struct dc_stream_state *stream0, *stream1;
1044
1045 context = kunit_kzalloc(test, sizeof(*context), GFP_KERNEL);
1046 KUNIT_ASSERT_NOT_NULL(test, context);
1047 stream0 = kunit_kzalloc(test, sizeof(*stream0), GFP_KERNEL);
1048 KUNIT_ASSERT_NOT_NULL(test, stream0);
1049 stream1 = kunit_kzalloc(test, sizeof(*stream1), GFP_KERNEL);
1050 KUNIT_ASSERT_NOT_NULL(test, stream1);
1051
1052 /* stream0 60Hz, stream1 120Hz, both trigger-reset enabled */
1053 stream0->triggered_crtc_reset.enabled = true;
1054 stream0->timing.pix_clk_100hz = 1485000;
1055 stream0->timing.h_total = 2200;
1056 stream0->timing.v_total = 1125;
1057 stream1->triggered_crtc_reset.enabled = true;
1058 stream1->timing.pix_clk_100hz = 2970000;
1059 stream1->timing.h_total = 2200;
1060 stream1->timing.v_total = 1125;
1061 stream1->timing.flags.VSYNC_POSITIVE_POLARITY = 1;
1062
1063 context->streams[0] = stream0;
1064 context->streams[1] = stream1;
1065 context->stream_count = 2;
1066
1067 dm_enable_per_frame_crtc_master_sync(context);
1068
1069 /* set_master_stream picks the highest refresh (stream1) as event source */
1070 KUNIT_EXPECT_PTR_EQ(test, stream0->triggered_crtc_reset.event_source,
1071 stream1);
1072 KUNIT_EXPECT_PTR_EQ(test, stream1->triggered_crtc_reset.event_source,
1073 stream1);
1074 /* set_multisync_trigger_params applied to enabled streams */
1075 KUNIT_EXPECT_EQ(test, (int)stream0->triggered_crtc_reset.event,
1076 (int)CRTC_EVENT_VSYNC_RISING);
1077 KUNIT_EXPECT_EQ(test, (int)stream0->triggered_crtc_reset.delay,
1078 (int)TRIGGER_DELAY_NEXT_PIXEL);
1079 }
1080
1081 /**
1082 * dm_test_per_frame_master_sync_skips_null_stream - Test NULL stream entries are skipped
1083 * @test: The KUnit test context
1084 */
dm_test_per_frame_master_sync_skips_null_stream(struct kunit * test)1085 static void dm_test_per_frame_master_sync_skips_null_stream(struct kunit *test)
1086 {
1087 struct dc_state *context;
1088 struct dc_stream_state *stream;
1089
1090 context = kunit_kzalloc(test, sizeof(*context), GFP_KERNEL);
1091 KUNIT_ASSERT_NOT_NULL(test, context);
1092 stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
1093 KUNIT_ASSERT_NOT_NULL(test, stream);
1094
1095 stream->triggered_crtc_reset.enabled = true;
1096 stream->timing.pix_clk_100hz = 1485000;
1097 stream->timing.h_total = 2200;
1098 stream->timing.v_total = 1125;
1099 context->streams[0] = stream;
1100 context->streams[1] = NULL;
1101 context->stream_count = 2;
1102
1103 dm_enable_per_frame_crtc_master_sync(context);
1104
1105 KUNIT_EXPECT_PTR_EQ(test, stream->triggered_crtc_reset.event_source,
1106 stream);
1107 }
1108
1109 /* Tests for amdgpu_dm_apply_delay_after_dpcd_poweroff() */
1110
1111 /**
1112 * dm_test_apply_delay_null_sink - Test a NULL sink returns without delay
1113 * @test: The KUnit test context
1114 */
dm_test_apply_delay_null_sink(struct kunit * test)1115 static void dm_test_apply_delay_null_sink(struct kunit *test)
1116 {
1117 /* NULL sink: early return, no delay, no dereference */
1118 amdgpu_dm_apply_delay_after_dpcd_poweroff(NULL, NULL);
1119 }
1120
1121 /**
1122 * dm_test_apply_delay_zero_wait - Test a zero wait interval skips the delay
1123 * @test: The KUnit test context
1124 */
dm_test_apply_delay_zero_wait(struct kunit * test)1125 static void dm_test_apply_delay_zero_wait(struct kunit *test)
1126 {
1127 struct dc_sink *sink;
1128
1129 sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
1130 KUNIT_ASSERT_NOT_NULL(test, sink);
1131
1132 /* wait == 0: no msleep, adev is unused so NULL is safe */
1133 sink->edid_caps.panel_patch.wait_after_dpcd_poweroff_ms = 0;
1134 amdgpu_dm_apply_delay_after_dpcd_poweroff(NULL, sink);
1135 }
1136
1137 /**
1138 * dm_test_apply_delay_nonzero_wait - Test a non-zero wait interval executes delay path
1139 * @test: The KUnit test context
1140 */
dm_test_apply_delay_nonzero_wait(struct kunit * test)1141 static void dm_test_apply_delay_nonzero_wait(struct kunit *test)
1142 {
1143 struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
1144 struct dc_sink *sink;
1145
1146 sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
1147 KUNIT_ASSERT_NOT_NULL(test, sink);
1148
1149 sink->edid_caps.panel_patch.wait_after_dpcd_poweroff_ms = 1;
1150 amdgpu_dm_apply_delay_after_dpcd_poweroff(adev, sink);
1151 }
1152
1153 static struct kunit_case amdgpu_dm_tests[] = {
1154 /* Simple DM callbacks */
1155 KUNIT_CASE(dm_test_is_idle),
1156 KUNIT_CASE(dm_test_wait_for_idle),
1157 KUNIT_CASE(dm_test_soft_reset),
1158 KUNIT_CASE(dm_test_set_clockgating_state),
1159 KUNIT_CASE(dm_test_set_powergating_state),
1160 KUNIT_CASE(dm_test_bandwidth_update),
1161 KUNIT_CASE(dm_test_crtc_complete_writeback_no_connector),
1162 KUNIT_CASE(dm_test_crtc_complete_writeback_not_pending),
1163 KUNIT_CASE(dm_test_vblank_get_counter_out_of_range),
1164 KUNIT_CASE(dm_test_vblank_get_counter_no_stream),
1165 KUNIT_CASE(dm_test_crtc_get_scanoutpos_invalid_crtc),
1166 KUNIT_CASE(dm_test_crtc_get_scanoutpos_no_stream),
1167 KUNIT_CASE(dm_test_atomic_get_new_state_empty),
1168 KUNIT_CASE(dm_test_atomic_get_new_state_match),
1169 KUNIT_CASE(dm_test_atomic_destroy_state_no_context),
1170 /* dm_plane_layer_index_cmp */
1171 KUNIT_CASE(dm_test_plane_layer_index_cmp_equal),
1172 KUNIT_CASE(dm_test_plane_layer_index_cmp_descending),
1173 KUNIT_CASE(dm_test_plane_layer_index_cmp_ascending),
1174 /* fill_plane_color_attributes */
1175 KUNIT_CASE(dm_test_fill_color_attr_rgb_format),
1176 KUNIT_CASE(dm_test_fill_color_attr_bt601_full),
1177 KUNIT_CASE(dm_test_fill_color_attr_bt601_limited),
1178 KUNIT_CASE(dm_test_fill_color_attr_bt709_full),
1179 KUNIT_CASE(dm_test_fill_color_attr_bt709_limited),
1180 KUNIT_CASE(dm_test_fill_color_attr_bt2020_full),
1181 KUNIT_CASE(dm_test_fill_color_attr_bt2020_limited),
1182 KUNIT_CASE(dm_test_fill_color_attr_invalid_encoding),
1183 /* modereset_required */
1184 KUNIT_CASE(dm_test_modereset_required_when_inactive_and_modeset),
1185 KUNIT_CASE(dm_test_modereset_not_required_when_active_and_modeset),
1186 KUNIT_CASE(dm_test_modereset_not_required_when_inactive_without_modeset),
1187 /* is_scaling_state_different */
1188 KUNIT_CASE(dm_test_scaling_state_same),
1189 KUNIT_CASE(dm_test_scaling_state_scaling_changed),
1190 KUNIT_CASE(dm_test_scaling_state_underscan_enabled),
1191 KUNIT_CASE(dm_test_scaling_state_underscan_disabled),
1192 KUNIT_CASE(dm_test_scaling_state_underscan_border_changed),
1193 /* set_multisync_trigger_params */
1194 KUNIT_CASE(dm_test_multisync_trigger_disabled),
1195 KUNIT_CASE(dm_test_multisync_trigger_rising),
1196 KUNIT_CASE(dm_test_multisync_trigger_falling),
1197 /* set_master_stream */
1198 KUNIT_CASE(dm_test_master_stream_highest_refresh),
1199 KUNIT_CASE(dm_test_master_stream_defaults_to_first),
1200 /* is_content_protection_different */
1201 KUNIT_CASE(dm_test_cp_diff_hdcp_type_change),
1202 KUNIT_CASE(dm_test_cp_diff_reenable_mode_changed),
1203 KUNIT_CASE(dm_test_cp_diff_reenable_no_change),
1204 KUNIT_CASE(dm_test_cp_diff_undesired),
1205 KUNIT_CASE(dm_test_cp_diff_desired_mode_changed),
1206 KUNIT_CASE(dm_test_cp_diff_desired_no_change),
1207 KUNIT_CASE(dm_test_cp_diff_update_hdcp_hotplug),
1208 KUNIT_CASE(dm_test_cp_diff_stream_reenabled),
1209 KUNIT_CASE(dm_test_cp_diff_s3_undesired_to_enabled),
1210 KUNIT_CASE(dm_test_cp_diff_desired_to_enabled),
1211 KUNIT_CASE(dm_test_cp_diff_desired_to_undesired),
1212 /* dm_enable_per_frame_crtc_master_sync */
1213 KUNIT_CASE(dm_test_per_frame_master_sync_single_stream),
1214 KUNIT_CASE(dm_test_per_frame_master_sync_two_streams),
1215 KUNIT_CASE(dm_test_per_frame_master_sync_skips_null_stream),
1216 /* amdgpu_dm_apply_delay_after_dpcd_poweroff */
1217 KUNIT_CASE(dm_test_apply_delay_null_sink),
1218 KUNIT_CASE(dm_test_apply_delay_zero_wait),
1219 KUNIT_CASE(dm_test_apply_delay_nonzero_wait),
1220 {}
1221 };
1222
1223 static struct kunit_suite amdgpu_dm_test_suite = {
1224 .name = "amdgpu_dm",
1225 .test_cases = amdgpu_dm_tests,
1226 };
1227
1228 kunit_test_suite(amdgpu_dm_test_suite);
1229
1230 MODULE_AUTHOR("AMD");
1231 MODULE_DESCRIPTION("KUnit tests for amdgpu_dm");
1232 MODULE_LICENSE("Dual MIT/GPL");
1233