xref: /linux/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_test.c (revision 1fc5a74b108fc90951890ec513ac81869f5eaff1)
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