xref: /linux/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c (revision 40288c9206c17eb66a603262e06a58d300d0f279)
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /*
3  * KUnit tests for amdgpu_dm_helpers.c
4  *
5  * Copyright 2026 Advanced Micro Devices, Inc.
6  */
7 
8 #include <kunit/test.h>
9 #include <drm/drm_edid.h>
10 #include <drm/drm_kunit_helpers.h>
11 #include <drm/display/drm_dp_mst_helper.h>
12 
13 #include "dc.h"
14 #include "core_types.h"
15 #include "amdgpu.h"
16 #include "amdgpu_mode.h"
17 #include "amdgpu_dm.h"
18 #include "amdgpu_dm_mst_types.h"
19 #include "dc_bios_types.h"
20 #include "dm_helpers.h"
21 #include "ddc_service_types.h"
22 #include "dmub_cmd.h"
23 #include "amdgpu_dm_helpers.h"
24 #include "amdgpu_dm_kunit_test_helpers.h"
25 
26 /* Tests for edid_extract_panel_id() */
27 
28 /**
29  * dm_test_edid_extract_panel_id_basic - Test Edid extract panel id basic
30  * @test: The KUnit test context
31  */
dm_test_edid_extract_panel_id_basic(struct kunit * test)32 static void dm_test_edid_extract_panel_id_basic(struct kunit *test)
33 {
34 	struct edid *edid;
35 	u32 panel_id;
36 
37 	edid = kunit_kzalloc(test, sizeof(*edid), GFP_KERNEL);
38 	KUNIT_ASSERT_NOT_NULL(test, edid);
39 
40 	edid->mfg_id[0] = 0x12;
41 	edid->mfg_id[1] = 0x34;
42 	edid->prod_code[0] = 0xAB;
43 	edid->prod_code[1] = 0xCD;
44 
45 	panel_id = edid_extract_panel_id(edid);
46 
47 	/*
48 	 * Expected: (0x12 << 24) | (0x34 << 16) | EDID_PRODUCT_ID(edid)
49 	 * EDID_PRODUCT_ID = prod_code[0] | (prod_code[1] << 8) = 0xAB | 0xCD00 = 0xCDAB
50 	 * Result: 0x12340000 | 0x0000CDAB = 0x1234CDAB
51 	 */
52 	KUNIT_EXPECT_EQ(test, panel_id, (u32)0x1234CDAB);
53 }
54 
55 /**
56  * dm_test_edid_extract_panel_id_zeros - Test Edid extract panel id zeros
57  * @test: The KUnit test context
58  */
dm_test_edid_extract_panel_id_zeros(struct kunit * test)59 static void dm_test_edid_extract_panel_id_zeros(struct kunit *test)
60 {
61 	struct edid *edid;
62 
63 	edid = kunit_kzalloc(test, sizeof(*edid), GFP_KERNEL);
64 	KUNIT_ASSERT_NOT_NULL(test, edid);
65 
66 	KUNIT_EXPECT_EQ(test, edid_extract_panel_id(edid), 0U);
67 }
68 
69 /* Tests for apply_edid_quirks() */
70 
71 /*
72  * Build an EDID whose extracted panel id equals @panel_id. Inverse of
73  * edid_extract_panel_id(): mfg_id holds the top 16 bits, prod_code the
74  * low 16 bits (prod_code[0] | prod_code[1] << 8).
75  */
dm_test_edid_with_panel_id(struct kunit * test,u32 panel_id)76 static struct edid *dm_test_edid_with_panel_id(struct kunit *test, u32 panel_id)
77 {
78 	struct edid *edid;
79 
80 	edid = kunit_kzalloc(test, sizeof(*edid), GFP_KERNEL);
81 	KUNIT_ASSERT_NOT_NULL(test, edid);
82 
83 	edid->mfg_id[0] = (panel_id >> 24) & 0xff;
84 	edid->mfg_id[1] = (panel_id >> 16) & 0xff;
85 	edid->prod_code[0] = panel_id & 0xff;
86 	edid->prod_code[1] = (panel_id >> 8) & 0xff;
87 
88 	return edid;
89 }
90 
91 /*
92  * Wire a connector-backed link so apply_edid_quirks() can resolve
93  * link->priv->base.dev for its drm_dbg_driver() calls.
94  */
dm_test_quirk_link(struct kunit * test)95 static struct dc_link *dm_test_quirk_link(struct kunit *test)
96 {
97 	struct amdgpu_dm_connector *aconnector;
98 	struct amdgpu_device *adev;
99 	struct dc_link *link;
100 
101 	adev = dm_kunit_alloc_adev(test);
102 	link = dm_kunit_alloc_link(test);
103 	aconnector = dm_kunit_alloc_connector(test, adev, NULL);
104 	link->priv = aconnector;
105 
106 	return link;
107 }
108 
109 /**
110  * dm_test_apply_edid_quirks_dpcd_poweroff_delay - Test GBT 0x3215 delay quirk
111  * @test: The KUnit test context
112  */
dm_test_apply_edid_quirks_dpcd_poweroff_delay(struct kunit * test)113 static void dm_test_apply_edid_quirks_dpcd_poweroff_delay(struct kunit *test)
114 {
115 	struct dc_edid_caps edid_caps = {0};
116 	struct dc_link *link = dm_test_quirk_link(test);
117 	struct edid *edid = dm_test_edid_with_panel_id(test,
118 			drm_edid_encode_panel_id('G', 'B', 'T', 0x3215));
119 
120 	apply_edid_quirks(link, edid, &edid_caps);
121 
122 	KUNIT_EXPECT_EQ(test, edid_caps.panel_patch.wait_after_dpcd_poweroff_ms, 10000U);
123 }
124 
125 /**
126  * dm_test_apply_edid_quirks_disable_fams - Test SAM panel FAMS-disable quirk
127  * @test: The KUnit test context
128  */
dm_test_apply_edid_quirks_disable_fams(struct kunit * test)129 static void dm_test_apply_edid_quirks_disable_fams(struct kunit *test)
130 {
131 	struct dc_edid_caps edid_caps = {0};
132 	struct dc_link *link = dm_test_quirk_link(test);
133 	struct edid *edid = dm_test_edid_with_panel_id(test,
134 			drm_edid_encode_panel_id('S', 'A', 'M', 0x0E5E));
135 
136 	apply_edid_quirks(link, edid, &edid_caps);
137 
138 	KUNIT_EXPECT_TRUE(test, edid_caps.panel_patch.disable_fams);
139 }
140 
141 /**
142  * dm_test_apply_edid_quirks_remove_sink_ext_caps - Test AUO 0x317 clear quirk
143  * @test: The KUnit test context
144  */
dm_test_apply_edid_quirks_remove_sink_ext_caps(struct kunit * test)145 static void dm_test_apply_edid_quirks_remove_sink_ext_caps(struct kunit *test)
146 {
147 	struct dc_edid_caps edid_caps = {0};
148 	struct dc_link *link = dm_test_quirk_link(test);
149 	struct edid *edid = dm_test_edid_with_panel_id(test,
150 			drm_edid_encode_panel_id('A', 'U', 'O', 0xA7AB));
151 
152 	apply_edid_quirks(link, edid, &edid_caps);
153 
154 	KUNIT_EXPECT_TRUE(test, edid_caps.panel_patch.remove_sink_ext_caps);
155 }
156 
157 /**
158  * dm_test_apply_edid_quirks_disable_colorimetry - Test SDC VSC-disable quirk
159  * @test: The KUnit test context
160  */
dm_test_apply_edid_quirks_disable_colorimetry(struct kunit * test)161 static void dm_test_apply_edid_quirks_disable_colorimetry(struct kunit *test)
162 {
163 	struct dc_edid_caps edid_caps = {0};
164 	struct dc_link *link = dm_test_quirk_link(test);
165 	struct edid *edid = dm_test_edid_with_panel_id(test,
166 			drm_edid_encode_panel_id('S', 'D', 'C', 0x4154));
167 
168 	apply_edid_quirks(link, edid, &edid_caps);
169 
170 	KUNIT_EXPECT_TRUE(test, edid_caps.panel_patch.disable_colorimetry);
171 }
172 
173 /**
174  * dm_test_apply_edid_quirks_skip_phy_ssc - Test DEL 0x4147 PHY SSC quirk
175  * @test: The KUnit test context
176  */
dm_test_apply_edid_quirks_skip_phy_ssc(struct kunit * test)177 static void dm_test_apply_edid_quirks_skip_phy_ssc(struct kunit *test)
178 {
179 	struct dc_edid_caps edid_caps = {0};
180 	struct dc_link *link = dm_test_quirk_link(test);
181 	struct edid *edid = dm_test_edid_with_panel_id(test,
182 			drm_edid_encode_panel_id('D', 'E', 'L', 0x4147));
183 
184 	apply_edid_quirks(link, edid, &edid_caps);
185 
186 	KUNIT_EXPECT_TRUE(test, link->wa_flags.skip_phy_ssc_reduction);
187 }
188 
189 /**
190  * dm_test_apply_edid_quirks_unknown_noop - Test unknown panel id is a no-op
191  * @test: The KUnit test context
192  */
dm_test_apply_edid_quirks_unknown_noop(struct kunit * test)193 static void dm_test_apply_edid_quirks_unknown_noop(struct kunit *test)
194 {
195 	struct dc_edid_caps edid_caps = {0};
196 	struct dc_link *link = dm_test_quirk_link(test);
197 	struct edid *edid = dm_test_edid_with_panel_id(test,
198 			drm_edid_encode_panel_id('X', 'Y', 'Z', 0x0000));
199 
200 	apply_edid_quirks(link, edid, &edid_caps);
201 
202 	/* default: branch leaves every quirk field untouched */
203 	KUNIT_EXPECT_EQ(test, edid_caps.panel_patch.wait_after_dpcd_poweroff_ms, 0U);
204 	KUNIT_EXPECT_FALSE(test, edid_caps.panel_patch.disable_fams);
205 	KUNIT_EXPECT_FALSE(test, edid_caps.panel_patch.remove_sink_ext_caps);
206 	KUNIT_EXPECT_FALSE(test, edid_caps.panel_patch.disable_colorimetry);
207 	KUNIT_EXPECT_FALSE(test, link->wa_flags.skip_phy_ssc_reduction);
208 }
209 
210 /* Tests for dm_helpers_parse_edid_caps() */
211 
212 /*
213  * Build a minimal valid base EDID block into @dc_edid. When @good_checksum is
214  * false the final checksum byte is corrupted so drm_edid_is_valid() fails.
215  *
216  *   manufacturer_id = 0xAC10, product_id = 0x1234, serial = 0x12345678,
217  *   week = 10, year (raw) = 30, digital input, no CEA extension.
218  */
dm_test_fill_base_edid(struct dc_edid * dc_edid,bool good_checksum)219 static void dm_test_fill_base_edid(struct dc_edid *dc_edid, bool good_checksum)
220 {
221 	static const u8 header[8] = {
222 		0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
223 	};
224 	u8 *raw = dc_edid->raw_edid;
225 	int sum = 0;
226 	int i;
227 
228 	memset(raw, 0, EDID_LENGTH);
229 	memcpy(raw, header, sizeof(header));
230 
231 	raw[8] = 0x10;	raw[9] = 0xAC;		/* mfg_id    -> 0xAC10 */
232 	raw[10] = 0x34;	raw[11] = 0x12;		/* prod_code -> 0x1234 */
233 	raw[12] = 0x78;	raw[13] = 0x56;		/* serial    -> 0x12345678 */
234 	raw[14] = 0x34;	raw[15] = 0x12;
235 	raw[16] = 10;				/* mfg_week */
236 	raw[17] = 30;				/* mfg_year (raw) */
237 	raw[18] = 1;				/* version */
238 	raw[19] = 4;				/* revision */
239 	raw[20] = DRM_EDID_INPUT_DIGITAL;	/* digital input */
240 	raw[126] = 0;				/* no extensions */
241 
242 	for (i = 0; i < EDID_LENGTH - 1; i++)
243 		sum += raw[i];
244 	raw[127] = (256 - (sum % 256)) % 256;
245 	if (!good_checksum)
246 		raw[127] ^= 0xFF;		/* corrupt checksum */
247 
248 	dc_edid->length = EDID_LENGTH;
249 }
250 
251 /**
252  * dm_test_parse_edid_caps_null_edid - Test NULL edid returns EDID_BAD_INPUT
253  * @test: The KUnit test context
254  */
dm_test_parse_edid_caps_null_edid(struct kunit * test)255 static void dm_test_parse_edid_caps_null_edid(struct kunit *test)
256 {
257 	struct dc_edid_caps edid_caps = {0};
258 	struct dc_link *link = dm_test_quirk_link(test);
259 
260 	KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, NULL, &edid_caps), EDID_BAD_INPUT);
261 }
262 
263 /**
264  * dm_test_parse_edid_caps_null_caps - Test NULL edid_caps returns EDID_BAD_INPUT
265  * @test: The KUnit test context
266  */
dm_test_parse_edid_caps_null_caps(struct kunit * test)267 static void dm_test_parse_edid_caps_null_caps(struct kunit *test)
268 {
269 	struct dc_link *link = dm_test_quirk_link(test);
270 	struct dc_edid *dc_edid;
271 
272 	dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL);
273 	KUNIT_ASSERT_NOT_NULL(test, dc_edid);
274 	dm_test_fill_base_edid(dc_edid, true);
275 
276 	KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, NULL), EDID_BAD_INPUT);
277 }
278 
279 /**
280  * dm_test_parse_edid_caps_valid - Test field extraction from a valid EDID
281  * @test: The KUnit test context
282  */
dm_test_parse_edid_caps_valid(struct kunit * test)283 static void dm_test_parse_edid_caps_valid(struct kunit *test)
284 {
285 	struct dc_link *link = dm_test_quirk_link(test);
286 	struct dc_edid_caps *edid_caps;
287 	struct dc_edid *dc_edid;
288 
289 	dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL);
290 	KUNIT_ASSERT_NOT_NULL(test, dc_edid);
291 	edid_caps = kunit_kzalloc(test, sizeof(*edid_caps), GFP_KERNEL);
292 	KUNIT_ASSERT_NOT_NULL(test, edid_caps);
293 
294 	dm_test_fill_base_edid(dc_edid, true);
295 
296 	KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, edid_caps), EDID_OK);
297 	KUNIT_EXPECT_EQ(test, edid_caps->manufacturer_id, 0xAC10);
298 	KUNIT_EXPECT_EQ(test, edid_caps->product_id, 0x1234);
299 	KUNIT_EXPECT_EQ(test, edid_caps->serial_number, 0x12345678U);
300 	KUNIT_EXPECT_EQ(test, edid_caps->manufacture_week, 10);
301 	KUNIT_EXPECT_EQ(test, edid_caps->manufacture_year, 30);
302 	KUNIT_EXPECT_FALSE(test, edid_caps->analog);
303 }
304 
305 /**
306  * dm_test_parse_edid_caps_bad_checksum - Test bad checksum still parses fields
307  * @test: The KUnit test context
308  */
dm_test_parse_edid_caps_bad_checksum(struct kunit * test)309 static void dm_test_parse_edid_caps_bad_checksum(struct kunit *test)
310 {
311 	struct dc_link *link = dm_test_quirk_link(test);
312 	struct dc_edid_caps *edid_caps;
313 	struct dc_edid *dc_edid;
314 
315 	dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL);
316 	KUNIT_ASSERT_NOT_NULL(test, dc_edid);
317 	edid_caps = kunit_kzalloc(test, sizeof(*edid_caps), GFP_KERNEL);
318 	KUNIT_ASSERT_NOT_NULL(test, edid_caps);
319 
320 	dm_test_fill_base_edid(dc_edid, false);
321 
322 	/* Invalid checksum -> EDID_BAD_CHECKSUM but fields are still parsed */
323 	KUNIT_EXPECT_EQ(test,
324 			dm_helpers_parse_edid_caps(link, dc_edid, edid_caps),
325 			EDID_BAD_CHECKSUM);
326 	KUNIT_EXPECT_EQ(test, edid_caps->manufacturer_id, 0xAC10);
327 	KUNIT_EXPECT_EQ(test, edid_caps->product_id, 0x1234);
328 }
329 
330 /**
331  * dm_test_parse_edid_caps_hdmi_frl - Test HDMI/FRL branch via connector info
332  * @test: The KUnit test context
333  *
334  * Drives the edid_caps->edid_hdmi path by marking the connector as HDMI and
335  * providing a fake dc with FRL enabled, so populate_hdmi_info_from_connector()
336  * is exercised inside dm_helpers_parse_edid_caps().
337  */
dm_test_parse_edid_caps_hdmi_frl(struct kunit * test)338 static void dm_test_parse_edid_caps_hdmi_frl(struct kunit *test)
339 {
340 	struct dc_link *link = dm_test_quirk_link(test);
341 	struct amdgpu_dm_connector *aconnector = link->priv;
342 	struct drm_connector *connector = &aconnector->base;
343 	struct dc_edid_caps *edid_caps;
344 	struct dc_edid *dc_edid;
345 	struct dc *dc;
346 
347 	dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL);
348 	KUNIT_ASSERT_NOT_NULL(test, dc_edid);
349 	edid_caps = kunit_kzalloc(test, sizeof(*edid_caps), GFP_KERNEL);
350 	KUNIT_ASSERT_NOT_NULL(test, edid_caps);
351 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
352 	KUNIT_ASSERT_NOT_NULL(test, dc);
353 
354 	link->dc = dc;
355 	dc->config.enable_frl = true;
356 
357 	dm_test_fill_base_edid(dc_edid, true);
358 
359 	/* Drive the HDMI/FRL branch */
360 	connector->display_info.is_hdmi = true;
361 	connector->display_info.rgb_quant_range_selectable = true;
362 	connector->display_info.hdmi.scdc.supported = true;
363 	connector->display_info.hdmi.max_lanes = 4;
364 	connector->display_info.hdmi.max_frl_rate_per_lane = 12;
365 
366 	KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, edid_caps), EDID_OK);
367 	KUNIT_EXPECT_TRUE(test, edid_caps->edid_hdmi);
368 	KUNIT_EXPECT_EQ(test, edid_caps->qs_bit, 1);
369 	KUNIT_EXPECT_TRUE(test, edid_caps->scdc_present);
370 	/* max_lanes 4 + max_frl_rate_per_lane 12 -> rate index 6 */
371 	KUNIT_EXPECT_EQ(test, edid_caps->max_frl_rate, 6);
372 }
373 
374 /**
375  * dm_test_parse_edid_caps_hdmi_frl_dsc - Test HDMI FRL DSC sub-branch
376  * @test: The KUnit test context
377  *
378  * Sets the connector's HDMI DSC capability so populate_hdmi_info_from_connector()
379  * reports frl_dsc_support, exercising the frl_dsc_support log path.
380  */
dm_test_parse_edid_caps_hdmi_frl_dsc(struct kunit * test)381 static void dm_test_parse_edid_caps_hdmi_frl_dsc(struct kunit *test)
382 {
383 	struct dc_link *link = dm_test_quirk_link(test);
384 	struct amdgpu_dm_connector *aconnector = link->priv;
385 	struct drm_connector *connector = &aconnector->base;
386 	struct dc_edid_caps *edid_caps;
387 	struct dc_edid *dc_edid;
388 	struct dc *dc;
389 
390 	dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL);
391 	KUNIT_ASSERT_NOT_NULL(test, dc_edid);
392 	edid_caps = kunit_kzalloc(test, sizeof(*edid_caps), GFP_KERNEL);
393 	KUNIT_ASSERT_NOT_NULL(test, edid_caps);
394 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
395 	KUNIT_ASSERT_NOT_NULL(test, dc);
396 
397 	link->dc = dc;
398 	dc->config.enable_frl = true;
399 
400 	dm_test_fill_base_edid(dc_edid, true);
401 
402 	connector->display_info.is_hdmi = true;
403 	/* Drive the frl_dsc_support sub-branch */
404 	connector->display_info.hdmi.dsc_cap.v_1p2 = true;
405 	connector->display_info.hdmi.dsc_cap.bpc_supported = 10;
406 
407 	KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, edid_caps), EDID_OK);
408 	KUNIT_EXPECT_TRUE(test, edid_caps->frl_dsc_support);
409 	KUNIT_EXPECT_TRUE(test, edid_caps->frl_dsc_10bpc);
410 }
411 
412 /*
413  * Build a 2-block EDID: a valid base block plus a CTA-861 extension block
414  * carrying one LPCM Short Audio Descriptor and, when @with_speaker is set, a
415  * Speaker Allocation Data Block, so the audio/speaker parsing code is
416  * exercised.
417  */
dm_test_fill_cea_edid(struct dc_edid * dc_edid,bool with_speaker)418 static void dm_test_fill_cea_edid(struct dc_edid *dc_edid, bool with_speaker)
419 {
420 	u8 *raw = dc_edid->raw_edid;
421 	u8 *ext = raw + EDID_LENGTH;
422 	u8 dtd_offset;
423 	int sum = 0;
424 	int i;
425 
426 	/* Base block, flagged as having one extension */
427 	dm_test_fill_base_edid(dc_edid, true);
428 	raw[126] = 1;
429 	for (i = 0; i < EDID_LENGTH - 1; i++)
430 		sum += raw[i];
431 	raw[127] = (256 - (sum % 256)) % 256;
432 
433 	/* Audio DB spans [4,7]; optional Speaker Alloc DB spans [8,11] */
434 	dtd_offset = with_speaker ? 12 : 8;
435 
436 	/* CTA-861 extension block */
437 	memset(ext, 0, EDID_LENGTH);
438 	ext[0] = 0x02;			/* CTA extension tag */
439 	ext[1] = 0x03;			/* revision 3 */
440 	ext[2] = dtd_offset;		/* DTD offset; end of data blocks */
441 	ext[3] = 0x00;			/* no native DTDs / feature flags */
442 	/* Audio Data Block: tag 1, length 3, one LPCM SAD */
443 	ext[4] = (1 << 5) | 3;
444 	ext[5] = (1 << 3) | 1;		/* format 1 (LPCM), 2 channels */
445 	ext[6] = 0x07;			/* 32 / 44.1 / 48 kHz */
446 	ext[7] = 0x07;			/* 16 / 20 / 24-bit */
447 	if (with_speaker) {
448 		/* Speaker Allocation Data Block: tag 4, length 3 */
449 		ext[8] = (4 << 5) | 3;
450 		ext[9] = 0x01;		/* front left / front right */
451 	}
452 
453 	sum = 0;
454 	for (i = 0; i < EDID_LENGTH - 1; i++)
455 		sum += ext[i];
456 	ext[127] = (256 - (sum % 256)) % 256;
457 
458 	dc_edid->length = 2 * EDID_LENGTH;
459 }
460 
461 /**
462  * dm_test_parse_edid_caps_cea_audio - Test CEA audio/speaker block parsing
463  * @test: The KUnit test context
464  */
dm_test_parse_edid_caps_cea_audio(struct kunit * test)465 static void dm_test_parse_edid_caps_cea_audio(struct kunit *test)
466 {
467 	struct dc_link *link = dm_test_quirk_link(test);
468 	struct dc_edid_caps *edid_caps;
469 	struct dc_edid *dc_edid;
470 
471 	dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL);
472 	KUNIT_ASSERT_NOT_NULL(test, dc_edid);
473 	edid_caps = kunit_kzalloc(test, sizeof(*edid_caps), GFP_KERNEL);
474 	KUNIT_ASSERT_NOT_NULL(test, edid_caps);
475 
476 	dm_test_fill_cea_edid(dc_edid, true);
477 
478 	KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, edid_caps), EDID_OK);
479 	KUNIT_EXPECT_EQ(test, edid_caps->audio_mode_count, 1);
480 	KUNIT_EXPECT_EQ(test, edid_caps->audio_modes[0].format_code, 1);
481 	KUNIT_EXPECT_EQ(test, edid_caps->audio_modes[0].channel_count, 2);
482 	KUNIT_EXPECT_EQ(test, edid_caps->audio_modes[0].sample_rate, 0x07);
483 	KUNIT_EXPECT_EQ(test, edid_caps->audio_modes[0].sample_size, 0x07);
484 	KUNIT_EXPECT_EQ(test, edid_caps->speaker_flags, 0x01);
485 }
486 
487 /**
488  * dm_test_parse_edid_caps_cea_no_speaker - Test default speaker flags path
489  * @test: The KUnit test context
490  *
491  * Audio data block present but no Speaker Allocation Data Block, so
492  * speaker_flags falls back to DEFAULT_SPEAKER_LOCATION.
493  */
dm_test_parse_edid_caps_cea_no_speaker(struct kunit * test)494 static void dm_test_parse_edid_caps_cea_no_speaker(struct kunit *test)
495 {
496 	struct dc_link *link = dm_test_quirk_link(test);
497 	struct dc_edid_caps *edid_caps;
498 	struct dc_edid *dc_edid;
499 
500 	dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL);
501 	KUNIT_ASSERT_NOT_NULL(test, dc_edid);
502 	edid_caps = kunit_kzalloc(test, sizeof(*edid_caps), GFP_KERNEL);
503 	KUNIT_ASSERT_NOT_NULL(test, edid_caps);
504 
505 	dm_test_fill_cea_edid(dc_edid, false);
506 
507 	KUNIT_EXPECT_EQ(test, dm_helpers_parse_edid_caps(link, dc_edid, edid_caps), EDID_OK);
508 	KUNIT_EXPECT_EQ(test, edid_caps->audio_mode_count, 1);
509 	KUNIT_EXPECT_EQ(test, edid_caps->speaker_flags, DEFAULT_SPEAKER_LOCATION);
510 }
511 
512 /* Tests for ACPI and VBIOS EDID readers */
513 
514 /**
515  * dm_test_probe_acpi_edid_no_companion - Test ACPI probe without companion
516  * @test: The KUnit test context
517  */
dm_test_probe_acpi_edid_no_companion(struct kunit * test)518 static void dm_test_probe_acpi_edid_no_companion(struct kunit *test)
519 {
520 	struct amdgpu_dm_connector *aconnector;
521 	struct amdgpu_device *adev;
522 	u8 buf[EDID_LENGTH] = {0};
523 
524 	adev = dm_kunit_alloc_adev(test);
525 	aconnector = dm_kunit_alloc_connector(test, adev, NULL);
526 
527 	KUNIT_EXPECT_EQ(test,
528 			dm_helpers_probe_acpi_edid(&aconnector->base, buf, 0, sizeof(buf)),
529 			-ENODEV);
530 }
531 
532 /**
533  * dm_test_read_acpi_edid_debug_mask_disabled - Test debug mask early return
534  * @test: The KUnit test context
535  */
dm_test_read_acpi_edid_debug_mask_disabled(struct kunit * test)536 static void dm_test_read_acpi_edid_debug_mask_disabled(struct kunit *test)
537 {
538 	struct amdgpu_dm_connector *aconnector;
539 	struct amdgpu_device *adev;
540 	uint old_debug_mask;
541 
542 	adev = dm_kunit_alloc_adev(test);
543 	aconnector = dm_kunit_alloc_connector(test, adev, NULL);
544 	old_debug_mask = dm_helpers_get_dc_debug_mask();
545 
546 	dm_helpers_set_dc_debug_mask(old_debug_mask | DC_DISABLE_ACPI_EDID);
547 	KUNIT_EXPECT_NULL(test, dm_helpers_read_acpi_edid(aconnector));
548 	dm_helpers_set_dc_debug_mask(old_debug_mask);
549 }
550 
551 /**
552  * dm_test_read_acpi_edid_non_panel_connector - Test non-panel connector skip
553  * @test: The KUnit test context
554  */
dm_test_read_acpi_edid_non_panel_connector(struct kunit * test)555 static void dm_test_read_acpi_edid_non_panel_connector(struct kunit *test)
556 {
557 	struct amdgpu_dm_connector *aconnector;
558 	struct amdgpu_device *adev;
559 
560 	adev = dm_kunit_alloc_adev(test);
561 	aconnector = dm_kunit_alloc_connector(test, adev, NULL);
562 	aconnector->base.connector_type = DRM_MODE_CONNECTOR_HDMIA;
563 
564 	KUNIT_EXPECT_NULL(test, dm_helpers_read_acpi_edid(aconnector));
565 }
566 
567 /**
568  * dm_test_read_acpi_edid_force_off - Test forced-off connector skip
569  * @test: The KUnit test context
570  */
dm_test_read_acpi_edid_force_off(struct kunit * test)571 static void dm_test_read_acpi_edid_force_off(struct kunit *test)
572 {
573 	struct amdgpu_dm_connector *aconnector;
574 	struct amdgpu_device *adev;
575 
576 	adev = dm_kunit_alloc_adev(test);
577 	aconnector = dm_kunit_alloc_connector(test, adev, NULL);
578 	aconnector->base.connector_type = DRM_MODE_CONNECTOR_eDP;
579 	aconnector->base.force = DRM_FORCE_OFF;
580 
581 	KUNIT_EXPECT_NULL(test, dm_helpers_read_acpi_edid(aconnector));
582 }
583 
584 struct dm_test_vbios_edid {
585 	struct dc_bios bios;
586 	enum bp_result result;
587 	const u8 *fake_edid;
588 	u16 fake_edid_size;
589 	u16 width_mm;
590 	u16 height_mm;
591 };
592 
dm_test_get_embedded_panel_info(struct dc_bios * bios,struct embedded_panel_info * info)593 static enum bp_result dm_test_get_embedded_panel_info(struct dc_bios *bios,
594 						      struct embedded_panel_info *info)
595 {
596 	struct dm_test_vbios_edid *fixture;
597 
598 	fixture = container_of(bios, struct dm_test_vbios_edid, bios);
599 	if (fixture->result != BP_RESULT_OK)
600 		return fixture->result;
601 
602 	info->fake_edid = fixture->fake_edid;
603 	info->fake_edid_size = fixture->fake_edid_size;
604 	info->panel_width_mm = fixture->width_mm;
605 	info->panel_height_mm = fixture->height_mm;
606 
607 	return BP_RESULT_OK;
608 }
609 
610 static const struct dc_vbios_funcs dm_test_vbios_edid_funcs = {
611 	.get_embedded_panel_info = dm_test_get_embedded_panel_info,
612 };
613 
dm_test_setup_vbios_link(struct kunit * test,struct dc_link ** link_out,struct amdgpu_dm_connector ** aconnector_out,struct dm_test_vbios_edid ** fixture_out)614 static void dm_test_setup_vbios_link(struct kunit *test,
615 				     struct dc_link **link_out,
616 				     struct amdgpu_dm_connector **aconnector_out,
617 				     struct dm_test_vbios_edid **fixture_out)
618 {
619 	struct dm_test_vbios_edid *fixture;
620 	struct amdgpu_dm_connector *aconnector;
621 	struct amdgpu_device *adev;
622 	struct dc_context *ctx;
623 	struct dc_link *link;
624 
625 	adev = dm_kunit_alloc_adev(test);
626 	link = dm_kunit_alloc_link(test);
627 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
628 	KUNIT_ASSERT_NOT_NULL(test, ctx);
629 	fixture = kunit_kzalloc(test, sizeof(*fixture), GFP_KERNEL);
630 	KUNIT_ASSERT_NOT_NULL(test, fixture);
631 	aconnector = dm_kunit_alloc_connector(test, adev, link);
632 
633 	fixture->bios.funcs = &dm_test_vbios_edid_funcs;
634 	fixture->result = BP_RESULT_OK;
635 	ctx->dc_bios = &fixture->bios;
636 	link->ctx = ctx;
637 	link->priv = aconnector;
638 	link->connector_signal = SIGNAL_TYPE_EDP;
639 
640 	*link_out = link;
641 	*aconnector_out = aconnector;
642 	*fixture_out = fixture;
643 }
644 
645 /**
646  * dm_test_read_vbios_edid_non_embedded - Test non-embedded signal skip
647  * @test: The KUnit test context
648  */
dm_test_read_vbios_edid_non_embedded(struct kunit * test)649 static void dm_test_read_vbios_edid_non_embedded(struct kunit *test)
650 {
651 	struct dm_test_vbios_edid *fixture;
652 	struct amdgpu_dm_connector *aconnector;
653 	struct dc_link *link;
654 
655 	dm_test_setup_vbios_link(test, &link, &aconnector, &fixture);
656 	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
657 
658 	KUNIT_EXPECT_NULL(test,
659 			  dm_helpers_read_vbios_hardcoded_edid(link, aconnector));
660 }
661 
662 /**
663  * dm_test_read_vbios_edid_missing_callback - Test missing callback skip
664  * @test: The KUnit test context
665  */
dm_test_read_vbios_edid_missing_callback(struct kunit * test)666 static void dm_test_read_vbios_edid_missing_callback(struct kunit *test)
667 {
668 	static const struct dc_vbios_funcs empty_funcs;
669 	struct dm_test_vbios_edid *fixture;
670 	struct amdgpu_dm_connector *aconnector;
671 	struct dc_link *link;
672 
673 	dm_test_setup_vbios_link(test, &link, &aconnector, &fixture);
674 	fixture->bios.funcs = &empty_funcs;
675 
676 	KUNIT_EXPECT_NULL(test,
677 			  dm_helpers_read_vbios_hardcoded_edid(link, aconnector));
678 }
679 
680 /**
681  * dm_test_read_vbios_edid_callback_error - Test callback failure skip
682  * @test: The KUnit test context
683  */
dm_test_read_vbios_edid_callback_error(struct kunit * test)684 static void dm_test_read_vbios_edid_callback_error(struct kunit *test)
685 {
686 	struct dm_test_vbios_edid *fixture;
687 	struct amdgpu_dm_connector *aconnector;
688 	struct dc_link *link;
689 
690 	dm_test_setup_vbios_link(test, &link, &aconnector, &fixture);
691 	fixture->result = BP_RESULT_BADINPUT;
692 
693 	KUNIT_EXPECT_NULL(test,
694 			  dm_helpers_read_vbios_hardcoded_edid(link, aconnector));
695 }
696 
697 /**
698  * dm_test_read_vbios_edid_missing_fake_edid - Test missing fake EDID skip
699  * @test: The KUnit test context
700  */
dm_test_read_vbios_edid_missing_fake_edid(struct kunit * test)701 static void dm_test_read_vbios_edid_missing_fake_edid(struct kunit *test)
702 {
703 	struct dm_test_vbios_edid *fixture;
704 	struct amdgpu_dm_connector *aconnector;
705 	struct dc_link *link;
706 
707 	dm_test_setup_vbios_link(test, &link, &aconnector, &fixture);
708 	fixture->fake_edid = NULL;
709 	fixture->fake_edid_size = 0;
710 
711 	KUNIT_EXPECT_NULL(test,
712 			  dm_helpers_read_vbios_hardcoded_edid(link, aconnector));
713 }
714 
715 /**
716  * dm_test_read_vbios_edid_invalid_fake_edid - Test invalid fake EDID skip
717  * @test: The KUnit test context
718  */
dm_test_read_vbios_edid_invalid_fake_edid(struct kunit * test)719 static void dm_test_read_vbios_edid_invalid_fake_edid(struct kunit *test)
720 {
721 	struct dm_test_vbios_edid *fixture;
722 	struct amdgpu_dm_connector *aconnector;
723 	struct dc_edid *dc_edid;
724 	struct dc_link *link;
725 
726 	dm_test_setup_vbios_link(test, &link, &aconnector, &fixture);
727 	dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL);
728 	KUNIT_ASSERT_NOT_NULL(test, dc_edid);
729 	dm_test_fill_base_edid(dc_edid, false);
730 	fixture->fake_edid = dc_edid->raw_edid;
731 	fixture->fake_edid_size = EDID_LENGTH;
732 
733 	KUNIT_EXPECT_NULL(test,
734 			  dm_helpers_read_vbios_hardcoded_edid(link, aconnector));
735 }
736 
737 /**
738  * dm_test_read_vbios_edid_valid - Test valid fake EDID updates display size
739  * @test: The KUnit test context
740  */
dm_test_read_vbios_edid_valid(struct kunit * test)741 static void dm_test_read_vbios_edid_valid(struct kunit *test)
742 {
743 	struct dm_test_vbios_edid *fixture;
744 	struct amdgpu_dm_connector *aconnector;
745 	const struct drm_edid *edid;
746 	struct dc_edid *dc_edid;
747 	struct dc_link *link;
748 
749 	dm_test_setup_vbios_link(test, &link, &aconnector, &fixture);
750 	dc_edid = kunit_kzalloc(test, sizeof(*dc_edid), GFP_KERNEL);
751 	KUNIT_ASSERT_NOT_NULL(test, dc_edid);
752 	dm_test_fill_base_edid(dc_edid, true);
753 	fixture->fake_edid = dc_edid->raw_edid;
754 	fixture->fake_edid_size = EDID_LENGTH;
755 	fixture->width_mm = 301;
756 	fixture->height_mm = 201;
757 
758 	edid = dm_helpers_read_vbios_hardcoded_edid(link, aconnector);
759 
760 	KUNIT_ASSERT_NOT_NULL(test, edid);
761 	KUNIT_EXPECT_EQ(test, aconnector->base.display_info.width_mm, 301U);
762 	KUNIT_EXPECT_EQ(test, aconnector->base.display_info.height_mm, 201U);
763 	drm_edid_free(edid);
764 }
765 
766 /* Tests for dm_is_freesync_pcon_whitelist() */
767 
768 /**
769  * dm_test_freesync_pcon_whitelist_all_known - Test all known Freesync Pcon whitelist entries
770  * @test: The KUnit test context
771  *
772  * Iterates over the driver's whitelist table directly so that any ID added
773  * to dm_freesync_pcon_whitelist[] is automatically covered by this test.
774  */
dm_test_freesync_pcon_whitelist_all_known(struct kunit * test)775 static void dm_test_freesync_pcon_whitelist_all_known(struct kunit *test)
776 {
777 	u32 i;
778 
779 	for (i = 0; i < dm_freesync_pcon_whitelist_count(); i++)
780 		KUNIT_EXPECT_TRUE(test,
781 				  dm_is_freesync_pcon_whitelist(dm_freesync_pcon_whitelist[i]));
782 }
783 
784 /**
785  * dm_test_freesync_pcon_whitelist_not_in_list - Test Freesync pcon whitelist not in list
786  * @test: The KUnit test context
787  */
dm_test_freesync_pcon_whitelist_not_in_list(struct kunit * test)788 static void dm_test_freesync_pcon_whitelist_not_in_list(struct kunit *test)
789 {
790 	/* 0xFFFFFF is not a known whitelist device */
791 	KUNIT_EXPECT_FALSE(test, dm_is_freesync_pcon_whitelist(0xFFFFFF));
792 }
793 
794 /**
795  * dm_test_freesync_pcon_whitelist_zero - Test Freesync pcon whitelist zero
796  * @test: The KUnit test context
797  */
dm_test_freesync_pcon_whitelist_zero(struct kunit * test)798 static void dm_test_freesync_pcon_whitelist_zero(struct kunit *test)
799 {
800 	KUNIT_EXPECT_FALSE(test, dm_is_freesync_pcon_whitelist(0));
801 }
802 
803 /* Tests for populate_hdmi_info_from_connector() */
804 
805 /**
806  * dm_test_populate_hdmi_scdc_present_true - Test Populate hdmi scdc present true
807  * @test: The KUnit test context
808  */
dm_test_populate_hdmi_scdc_present_true(struct kunit * test)809 static void dm_test_populate_hdmi_scdc_present_true(struct kunit *test)
810 {
811 	struct drm_hdmi_info *hdmi;
812 	struct dc_edid_caps *caps;
813 
814 	hdmi = kunit_kzalloc(test, sizeof(*hdmi), GFP_KERNEL);
815 	KUNIT_ASSERT_NOT_NULL(test, hdmi);
816 	caps = kunit_kzalloc(test, sizeof(*caps), GFP_KERNEL);
817 	KUNIT_ASSERT_NOT_NULL(test, caps);
818 
819 	hdmi->scdc.supported = true;
820 
821 	populate_hdmi_info_from_connector(true, hdmi, caps);
822 
823 	KUNIT_EXPECT_TRUE(test, caps->scdc_present);
824 }
825 
826 /**
827  * dm_test_populate_hdmi_scdc_present_false - Test Populate hdmi scdc present false
828  * @test: The KUnit test context
829  */
dm_test_populate_hdmi_scdc_present_false(struct kunit * test)830 static void dm_test_populate_hdmi_scdc_present_false(struct kunit *test)
831 {
832 	struct drm_hdmi_info *hdmi;
833 	struct dc_edid_caps *caps;
834 
835 	hdmi = kunit_kzalloc(test, sizeof(*hdmi), GFP_KERNEL);
836 	KUNIT_ASSERT_NOT_NULL(test, hdmi);
837 	caps = kunit_kzalloc(test, sizeof(*caps), GFP_KERNEL);
838 	KUNIT_ASSERT_NOT_NULL(test, caps);
839 
840 	hdmi->scdc.supported = false;
841 	caps->scdc_present = true; /* pre-set to confirm it gets cleared */
842 
843 	populate_hdmi_info_from_connector(true, hdmi, caps);
844 
845 	KUNIT_EXPECT_FALSE(test, caps->scdc_present);
846 }
847 
848 /**
849  * dm_test_populate_hdmi_frl_dsc_10bpc - Test HDMI FRL DSC 10 bpc caps
850  * @test: The KUnit test context
851  */
dm_test_populate_hdmi_frl_dsc_10bpc(struct kunit * test)852 static void dm_test_populate_hdmi_frl_dsc_10bpc(struct kunit *test)
853 {
854 	struct drm_hdmi_info *hdmi;
855 	struct dc_edid_caps *caps;
856 
857 	hdmi = kunit_kzalloc(test, sizeof(*hdmi), GFP_KERNEL);
858 	KUNIT_ASSERT_NOT_NULL(test, hdmi);
859 	caps = kunit_kzalloc(test, sizeof(*caps), GFP_KERNEL);
860 	KUNIT_ASSERT_NOT_NULL(test, caps);
861 
862 	hdmi->max_lanes = 4;
863 	hdmi->max_frl_rate_per_lane = 12;
864 	hdmi->dsc_cap.v_1p2 = true;
865 	hdmi->dsc_cap.bpc_supported = 10;
866 	hdmi->dsc_cap.all_bpp = true;
867 	hdmi->dsc_cap.native_420 = true;
868 	hdmi->dsc_cap.max_slices = 8;
869 	hdmi->dsc_cap.clk_per_slice = 400;
870 	hdmi->dsc_cap.max_lanes = 4;
871 	hdmi->dsc_cap.max_frl_rate_per_lane = 10;
872 	hdmi->dsc_cap.total_chunk_kbytes = 7;
873 
874 	populate_hdmi_info_from_connector(true, hdmi, caps);
875 
876 	KUNIT_EXPECT_EQ(test, caps->max_frl_rate, 6);
877 	KUNIT_EXPECT_TRUE(test, caps->frl_dsc_support);
878 	KUNIT_EXPECT_TRUE(test, caps->frl_dsc_10bpc);
879 	KUNIT_EXPECT_FALSE(test, caps->frl_dsc_12bpc);
880 	KUNIT_EXPECT_TRUE(test, caps->frl_dsc_all_bpp);
881 	KUNIT_EXPECT_TRUE(test, caps->frl_dsc_native_420);
882 	KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_slices, 5);
883 	KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_frl_rate, 5);
884 	KUNIT_EXPECT_EQ(test, caps->frl_dsc_total_chunk_kbytes, 7);
885 }
886 
887 /**
888  * dm_test_populate_hdmi_frl_dsc_12bpc - Test HDMI FRL DSC 12 bpc caps
889  * @test: The KUnit test context
890  */
dm_test_populate_hdmi_frl_dsc_12bpc(struct kunit * test)891 static void dm_test_populate_hdmi_frl_dsc_12bpc(struct kunit *test)
892 {
893 	struct drm_hdmi_info *hdmi;
894 	struct dc_edid_caps *caps;
895 
896 	hdmi = kunit_kzalloc(test, sizeof(*hdmi), GFP_KERNEL);
897 	KUNIT_ASSERT_NOT_NULL(test, hdmi);
898 	caps = kunit_kzalloc(test, sizeof(*caps), GFP_KERNEL);
899 	KUNIT_ASSERT_NOT_NULL(test, caps);
900 
901 	hdmi->max_lanes = 3;
902 	hdmi->max_frl_rate_per_lane = 6;
903 	hdmi->dsc_cap.v_1p2 = true;
904 	hdmi->dsc_cap.bpc_supported = 12;
905 	hdmi->dsc_cap.max_slices = 16;
906 	hdmi->dsc_cap.clk_per_slice = 400;
907 	hdmi->dsc_cap.max_lanes = 3;
908 	hdmi->dsc_cap.max_frl_rate_per_lane = 3;
909 
910 	populate_hdmi_info_from_connector(true, hdmi, caps);
911 
912 	KUNIT_EXPECT_EQ(test, caps->max_frl_rate, 2);
913 	KUNIT_EXPECT_TRUE(test, caps->frl_dsc_support);
914 	KUNIT_EXPECT_TRUE(test, caps->frl_dsc_10bpc);
915 	KUNIT_EXPECT_TRUE(test, caps->frl_dsc_12bpc);
916 	KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_slices, 7);
917 	KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_frl_rate, 1);
918 }
919 
920 /**
921  * dm_test_populate_hdmi_frl_dsc_unknown_values - Test HDMI FRL DSC unknown values
922  * @test: The KUnit test context
923  */
dm_test_populate_hdmi_frl_dsc_unknown_values(struct kunit * test)924 static void dm_test_populate_hdmi_frl_dsc_unknown_values(struct kunit *test)
925 {
926 	struct drm_hdmi_info *hdmi;
927 	struct dc_edid_caps *caps;
928 
929 	hdmi = kunit_kzalloc(test, sizeof(*hdmi), GFP_KERNEL);
930 	KUNIT_ASSERT_NOT_NULL(test, hdmi);
931 	caps = kunit_kzalloc(test, sizeof(*caps), GFP_KERNEL);
932 	KUNIT_ASSERT_NOT_NULL(test, caps);
933 
934 	hdmi->max_lanes = 2;
935 	hdmi->max_frl_rate_per_lane = 3;
936 	hdmi->dsc_cap.v_1p2 = true;
937 	hdmi->dsc_cap.bpc_supported = 8;
938 	hdmi->dsc_cap.max_slices = 3;
939 	hdmi->dsc_cap.clk_per_slice = 340;
940 	hdmi->dsc_cap.max_lanes = 2;
941 	hdmi->dsc_cap.max_frl_rate_per_lane = 12;
942 
943 	populate_hdmi_info_from_connector(true, hdmi, caps);
944 
945 	KUNIT_EXPECT_EQ(test, caps->max_frl_rate, 0);
946 	KUNIT_EXPECT_TRUE(test, caps->frl_dsc_support);
947 	KUNIT_EXPECT_FALSE(test, caps->frl_dsc_10bpc);
948 	KUNIT_EXPECT_FALSE(test, caps->frl_dsc_12bpc);
949 	KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_slices, 0);
950 	KUNIT_EXPECT_EQ(test, caps->frl_dsc_max_frl_rate, 0);
951 }
952 
953 /* Tests for dm_get_adaptive_sync_support_type() */
954 
955 /**
956  * dm_test_adaptive_sync_type_none_default - Test Adaptive sync type none default
957  * @test: The KUnit test context
958  */
dm_test_adaptive_sync_type_none_default(struct kunit * test)959 static void dm_test_adaptive_sync_type_none_default(struct kunit *test)
960 {
961 	struct dc_link *link;
962 
963 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
964 	KUNIT_ASSERT_NOT_NULL(test, link);
965 
966 	/* dongle_type = 0 (DISPLAY_DONGLE_NONE) → default case → TYPE_NONE */
967 	KUNIT_EXPECT_EQ(test,
968 			(int)dm_get_adaptive_sync_support_type(link),
969 			(int)ADAPTIVE_SYNC_TYPE_NONE);
970 }
971 
972 /**
973  * dm_test_adaptive_sync_type_converter_no_conditions - Converter without caps
974  * @test: The KUnit test context
975  */
dm_test_adaptive_sync_type_converter_no_conditions(struct kunit * test)976 static void dm_test_adaptive_sync_type_converter_no_conditions(struct kunit *test)
977 {
978 	struct dc_link *link;
979 
980 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
981 	KUNIT_ASSERT_NOT_NULL(test, link);
982 
983 	/* HDMI converter but no adaptive sync cap → still NONE */
984 	link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER;
985 
986 	KUNIT_EXPECT_EQ(test,
987 			(int)dm_get_adaptive_sync_support_type(link),
988 			(int)ADAPTIVE_SYNC_TYPE_NONE);
989 }
990 
991 /**
992  * dm_test_adaptive_sync_type_converter_partial_conditions - Partial caps
993  * @test: The KUnit test context
994  */
dm_test_adaptive_sync_type_converter_partial_conditions(struct kunit * test)995 static void dm_test_adaptive_sync_type_converter_partial_conditions(struct kunit *test)
996 {
997 	struct dc_link *link;
998 
999 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1000 	KUNIT_ASSERT_NOT_NULL(test, link);
1001 
1002 	/* Cap set and whitelist ID, but allow_invalid_MSA_timing_param = false */
1003 	link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER;
1004 	link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT = 1;
1005 	link->dpcd_caps.allow_invalid_MSA_timing_param = false;
1006 	link->dpcd_caps.branch_dev_id = DP_BRANCH_DEVICE_ID_0060AD;
1007 
1008 	KUNIT_EXPECT_EQ(test,
1009 			(int)dm_get_adaptive_sync_support_type(link),
1010 			(int)ADAPTIVE_SYNC_TYPE_NONE);
1011 }
1012 
1013 /**
1014  * dm_test_adaptive_sync_type_pcon_whitelist - Test Adaptive sync type pcon whitelist
1015  * @test: The KUnit test context
1016  */
dm_test_adaptive_sync_type_pcon_whitelist(struct kunit * test)1017 static void dm_test_adaptive_sync_type_pcon_whitelist(struct kunit *test)
1018 {
1019 	struct dc_link *link;
1020 
1021 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1022 	KUNIT_ASSERT_NOT_NULL(test, link);
1023 
1024 	/* All conditions met → FREESYNC_TYPE_PCON_IN_WHITELIST */
1025 	link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER;
1026 	link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT = 1;
1027 	link->dpcd_caps.allow_invalid_MSA_timing_param = true;
1028 	link->dpcd_caps.branch_dev_id = DP_BRANCH_DEVICE_ID_0060AD;
1029 
1030 	KUNIT_EXPECT_EQ(test,
1031 			(int)dm_get_adaptive_sync_support_type(link),
1032 			(int)FREESYNC_TYPE_PCON_IN_WHITELIST);
1033 }
1034 
1035 /**
1036  * dm_test_adaptive_sync_type_converter_nonwhitelist - Converter not whitelisted
1037  * @test: The KUnit test context
1038  */
dm_test_adaptive_sync_type_converter_nonwhitelist(struct kunit * test)1039 static void dm_test_adaptive_sync_type_converter_nonwhitelist(struct kunit *test)
1040 {
1041 	struct dc_link *link;
1042 
1043 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1044 	KUNIT_ASSERT_NOT_NULL(test, link);
1045 
1046 	/* All conditions met but branch_dev_id not in whitelist → NONE */
1047 	link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER;
1048 	link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT = 1;
1049 	link->dpcd_caps.allow_invalid_MSA_timing_param = true;
1050 	link->dpcd_caps.branch_dev_id = 0xFFFFFF;
1051 
1052 	KUNIT_EXPECT_EQ(test,
1053 			(int)dm_get_adaptive_sync_support_type(link),
1054 			(int)ADAPTIVE_SYNC_TYPE_NONE);
1055 }
1056 
1057 /* Tests for dm_helpers_is_fullscreen() and dm_helpers_is_hdr_on() */
1058 
1059 /**
1060  * dm_test_helpers_is_fullscreen_returns_false - Test Helpers is fullscreen returns false
1061  * @test: The KUnit test context
1062  */
dm_test_helpers_is_fullscreen_returns_false(struct kunit * test)1063 static void dm_test_helpers_is_fullscreen_returns_false(struct kunit *test)
1064 {
1065 	/* Stub — always returns false */
1066 	KUNIT_EXPECT_FALSE(test, dm_helpers_is_fullscreen(NULL, NULL));
1067 }
1068 
1069 /**
1070  * dm_test_helpers_is_hdr_on_returns_false - Test Helpers is hdr on returns false
1071  * @test: The KUnit test context
1072  */
dm_test_helpers_is_hdr_on_returns_false(struct kunit * test)1073 static void dm_test_helpers_is_hdr_on_returns_false(struct kunit *test)
1074 {
1075 	/* Stub — always returns false */
1076 	KUNIT_EXPECT_FALSE(test, dm_helpers_is_hdr_on(NULL, NULL));
1077 }
1078 
1079 /* Tests for get_max_frl_rate() */
1080 
1081 /**
1082  * dm_test_get_max_frl_rate_3lanes_3gbps - Test Get max frl rate 3lanes 3gbps
1083  * @test: The KUnit test context
1084  */
dm_test_get_max_frl_rate_3lanes_3gbps(struct kunit * test)1085 static void dm_test_get_max_frl_rate_3lanes_3gbps(struct kunit *test)
1086 {
1087 	KUNIT_EXPECT_EQ(test, get_max_frl_rate(3, 3), 1);
1088 }
1089 
1090 /**
1091  * dm_test_get_max_frl_rate_3lanes_6gbps - Test Get max frl rate 3lanes 6gbps
1092  * @test: The KUnit test context
1093  */
dm_test_get_max_frl_rate_3lanes_6gbps(struct kunit * test)1094 static void dm_test_get_max_frl_rate_3lanes_6gbps(struct kunit *test)
1095 {
1096 	KUNIT_EXPECT_EQ(test, get_max_frl_rate(3, 6), 2);
1097 }
1098 
1099 /**
1100  * dm_test_get_max_frl_rate_4lanes_6gbps - Test Get max frl rate 4lanes 6gbps
1101  * @test: The KUnit test context
1102  */
dm_test_get_max_frl_rate_4lanes_6gbps(struct kunit * test)1103 static void dm_test_get_max_frl_rate_4lanes_6gbps(struct kunit *test)
1104 {
1105 	KUNIT_EXPECT_EQ(test, get_max_frl_rate(4, 6), 3);
1106 }
1107 
1108 /**
1109  * dm_test_get_max_frl_rate_4lanes_8gbps - Test Get max frl rate 4lanes 8gbps
1110  * @test: The KUnit test context
1111  */
dm_test_get_max_frl_rate_4lanes_8gbps(struct kunit * test)1112 static void dm_test_get_max_frl_rate_4lanes_8gbps(struct kunit *test)
1113 {
1114 	KUNIT_EXPECT_EQ(test, get_max_frl_rate(4, 8), 4);
1115 }
1116 
1117 /**
1118  * dm_test_get_max_frl_rate_4lanes_10gbps - Test Get max frl rate 4lanes 10gbps
1119  * @test: The KUnit test context
1120  */
dm_test_get_max_frl_rate_4lanes_10gbps(struct kunit * test)1121 static void dm_test_get_max_frl_rate_4lanes_10gbps(struct kunit *test)
1122 {
1123 	KUNIT_EXPECT_EQ(test, get_max_frl_rate(4, 10), 5);
1124 }
1125 
1126 /**
1127  * dm_test_get_max_frl_rate_4lanes_12gbps - Test Get max frl rate 4lanes 12gbps
1128  * @test: The KUnit test context
1129  */
dm_test_get_max_frl_rate_4lanes_12gbps(struct kunit * test)1130 static void dm_test_get_max_frl_rate_4lanes_12gbps(struct kunit *test)
1131 {
1132 	KUNIT_EXPECT_EQ(test, get_max_frl_rate(4, 12), 6);
1133 }
1134 
1135 /**
1136  * dm_test_get_max_frl_rate_unknown - Test Get max frl rate unknown
1137  * @test: The KUnit test context
1138  */
dm_test_get_max_frl_rate_unknown(struct kunit * test)1139 static void dm_test_get_max_frl_rate_unknown(struct kunit *test)
1140 {
1141 	/* Unknown lane/rate combination → 0 */
1142 	KUNIT_EXPECT_EQ(test, get_max_frl_rate(2, 3), 0);
1143 }
1144 
1145 /* Tests for dm_dtn_log_begin() / dm_dtn_log_append_v() / dm_dtn_log_end() */
1146 
1147 /**
1148  * dm_test_dtn_log_buffer_accumulates - Test DTN log buffer accumulation
1149  * @test: The KUnit test context
1150  */
dm_test_dtn_log_buffer_accumulates(struct kunit * test)1151 static void dm_test_dtn_log_buffer_accumulates(struct kunit *test)
1152 {
1153 	struct dc_log_buffer_ctx log_ctx = {0};
1154 
1155 	dm_dtn_log_begin(NULL, &log_ctx);
1156 	dm_dtn_log_append_v(NULL, &log_ctx, "x=%d\n", 7);
1157 	dm_dtn_log_end(NULL, &log_ctx);
1158 
1159 	KUNIT_ASSERT_NOT_NULL(test, log_ctx.buf);
1160 	KUNIT_EXPECT_STREQ(test, log_ctx.buf, "[dtn begin]\nx=7\n[dtn end]\n");
1161 	KUNIT_EXPECT_EQ(test, log_ctx.pos, strlen("[dtn begin]\nx=7\n[dtn end]\n"));
1162 
1163 	kvfree(log_ctx.buf);
1164 }
1165 
1166 /**
1167  * dm_test_dtn_log_null_ctx_no_crash - Test DTN log helpers with NULL log buffer
1168  * @test: The KUnit test context
1169  */
dm_test_dtn_log_null_ctx_no_crash(struct kunit * test)1170 static void dm_test_dtn_log_null_ctx_no_crash(struct kunit *test)
1171 {
1172 	/* NULL log_ctx redirects to dmesg and must not dereference a buffer */
1173 	dm_dtn_log_begin(NULL, NULL);
1174 	dm_dtn_log_append_v(NULL, NULL, "value %d\n", 1);
1175 	dm_dtn_log_end(NULL, NULL);
1176 
1177 	KUNIT_EXPECT_TRUE(test, true);
1178 }
1179 
1180 /* Tests for dm_helpers_dp_read_dpcd() / dm_helpers_dp_write_dpcd() */
1181 
1182 /**
1183  * dm_test_dp_read_dpcd_null_priv - Test DPCD read returns false without connector
1184  * @test: The KUnit test context
1185  */
dm_test_dp_read_dpcd_null_priv(struct kunit * test)1186 static void dm_test_dp_read_dpcd_null_priv(struct kunit *test)
1187 {
1188 	struct dc_link *link;
1189 	uint8_t data = 0;
1190 
1191 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1192 	KUNIT_ASSERT_NOT_NULL(test, link);
1193 
1194 	/* link->priv (aconnector) is NULL → early return false */
1195 	KUNIT_EXPECT_FALSE(test,
1196 			   dm_helpers_dp_read_dpcd(NULL, link, 0, &data, sizeof(data)));
1197 }
1198 
1199 /**
1200  * dm_test_dp_write_dpcd_null_priv - Test DPCD write returns false without connector
1201  * @test: The KUnit test context
1202  */
dm_test_dp_write_dpcd_null_priv(struct kunit * test)1203 static void dm_test_dp_write_dpcd_null_priv(struct kunit *test)
1204 {
1205 	struct dc_link *link;
1206 	uint8_t data = 0;
1207 
1208 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1209 	KUNIT_ASSERT_NOT_NULL(test, link);
1210 
1211 	/* link->priv (aconnector) is NULL → early return false */
1212 	KUNIT_EXPECT_FALSE(test,
1213 			   dm_helpers_dp_write_dpcd(NULL, link, 0, &data, sizeof(data)));
1214 }
1215 
1216 /*
1217  * Stub AUX transfer that ACKs every transaction (zero-filling reads), so
1218  * drm_dp_dpcd_read()/drm_dp_dpcd_write() report the full transfer size.
1219  */
dm_test_dpcd_ack_transfer(struct drm_dp_aux * aux,struct drm_dp_aux_msg * msg)1220 static ssize_t dm_test_dpcd_ack_transfer(struct drm_dp_aux *aux,
1221 					 struct drm_dp_aux_msg *msg)
1222 {
1223 	if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
1224 		memset(msg->buffer, 0, msg->size);
1225 	msg->reply = DP_AUX_NATIVE_REPLY_ACK;
1226 	return msg->size;
1227 }
1228 
1229 /*
1230  * Wire a connector-backed link with a working AUX channel so the DPCD
1231  * read/write helpers can complete a real transaction.
1232  */
dm_test_dpcd_link(struct kunit * test)1233 static struct dc_link *dm_test_dpcd_link(struct kunit *test)
1234 {
1235 	struct amdgpu_dm_connector *aconnector;
1236 	struct amdgpu_device *adev;
1237 	struct dc_link *link;
1238 
1239 	adev = dm_kunit_alloc_adev(test);
1240 	KUNIT_ASSERT_NOT_NULL(test, adev);
1241 
1242 	link = dm_kunit_alloc_link(test);
1243 	aconnector = dm_kunit_alloc_connector(test, adev, NULL);
1244 
1245 	aconnector->dm_dp_aux.aux.drm_dev = &adev->ddev;
1246 	aconnector->dm_dp_aux.aux.transfer = dm_test_dpcd_ack_transfer;
1247 	drm_dp_aux_init(&aconnector->dm_dp_aux.aux);
1248 
1249 	link->priv = aconnector;
1250 
1251 	return link;
1252 }
1253 
1254 /**
1255  * dm_test_dp_read_dpcd_success - Test DPCD read returns true on ACKed transfer
1256  * @test: The KUnit test context
1257  */
dm_test_dp_read_dpcd_success(struct kunit * test)1258 static void dm_test_dp_read_dpcd_success(struct kunit *test)
1259 {
1260 	struct dc_link *link = dm_test_dpcd_link(test);
1261 	uint8_t data = 0;
1262 
1263 	KUNIT_EXPECT_TRUE(test,
1264 			  dm_helpers_dp_read_dpcd(NULL, link, 0, &data, sizeof(data)));
1265 }
1266 
1267 /**
1268  * dm_test_dp_write_dpcd_success - Test DPCD write returns true on ACKed transfer
1269  * @test: The KUnit test context
1270  */
dm_test_dp_write_dpcd_success(struct kunit * test)1271 static void dm_test_dp_write_dpcd_success(struct kunit *test)
1272 {
1273 	struct dc_link *link = dm_test_dpcd_link(test);
1274 	uint8_t data = 0;
1275 
1276 	KUNIT_EXPECT_TRUE(test,
1277 			  dm_helpers_dp_write_dpcd(NULL, link, 0, &data, sizeof(data)));
1278 }
1279 
1280 /* Tests for dm_helpers_execute_fused_io() */
1281 
1282 /**
1283  * dm_test_execute_fused_io_null_dmub_srv - Test fused IO fails without DMUB service
1284  * @test: The KUnit test context
1285  */
dm_test_execute_fused_io_null_dmub_srv(struct kunit * test)1286 static void dm_test_execute_fused_io_null_dmub_srv(struct kunit *test)
1287 {
1288 	struct amdgpu_device *adev;
1289 	struct dc_context *ctx;
1290 	struct dc_link *link;
1291 	union dmub_rb_cmd *commands;
1292 
1293 	adev = dm_kunit_alloc_adev(test);
1294 	KUNIT_ASSERT_NOT_NULL(test, adev);
1295 	mutex_init(&adev->dm.dpia_aux_lock);
1296 	spin_lock_init(&adev->dm.dmub_lock);
1297 
1298 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
1299 	KUNIT_ASSERT_NOT_NULL(test, ctx);
1300 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1301 	KUNIT_ASSERT_NOT_NULL(test, link);
1302 	commands = kunit_kzalloc(test, sizeof(*commands), GFP_KERNEL);
1303 	KUNIT_ASSERT_NOT_NULL(test, commands);
1304 
1305 	ctx->driver_context = adev;
1306 	link->ctx = ctx;
1307 	commands[0].fused_io.request.u.aux.ddc_line = 0;
1308 
1309 	KUNIT_EXPECT_FALSE(test, dm_helpers_execute_fused_io(ctx, link, commands, 1, 1));
1310 }
1311 
1312 struct dm_test_synaptics_aux {
1313 	struct drm_dp_aux aux;
1314 	u32 fail_address;
1315 	u32 last_dpcd_write_address;
1316 	u8 rc_result;
1317 	u8 dpcd_read_value;
1318 	u8 dpcd_write_value;
1319 	u8 last_rc_data[16];
1320 	u8 read_rc_data[16];
1321 	u8 last_rc_command;
1322 	u8 rc_commands[32];
1323 	u8 dsc_enable_values[8];
1324 	u32 last_rc_offset;
1325 	u32 last_rc_length;
1326 	unsigned int rc_data_writes;
1327 	unsigned int rc_data_reads;
1328 	unsigned int rc_command_reads;
1329 	unsigned int rc_result_reads;
1330 	unsigned int rc_command_count;
1331 	unsigned int downspread_reads;
1332 	unsigned int downspread_writes;
1333 	unsigned int dsc_enable_writes;
1334 };
1335 
dm_test_synaptics_aux_transfer(struct drm_dp_aux * aux,struct drm_dp_aux_msg * msg)1336 static ssize_t dm_test_synaptics_aux_transfer(struct drm_dp_aux *aux,
1337 					      struct drm_dp_aux_msg *msg)
1338 {
1339 	struct dm_test_synaptics_aux *fixture;
1340 	u8 request;
1341 	u8 *buffer;
1342 	size_t copy_size;
1343 	unsigned int index;
1344 
1345 	fixture = container_of(aux, struct dm_test_synaptics_aux, aux);
1346 	request = msg->request & ~DP_AUX_I2C_MOT;
1347 	buffer = msg->buffer;
1348 
1349 	if (fixture->fail_address == msg->address)
1350 		return -EIO;
1351 
1352 	if (request == DP_AUX_NATIVE_WRITE) {
1353 		switch (msg->address) {
1354 		case DP_DOWNSPREAD_CTRL:
1355 			fixture->last_dpcd_write_address = msg->address;
1356 			if (msg->size)
1357 				fixture->dpcd_write_value = buffer[0];
1358 			fixture->downspread_writes++;
1359 			break;
1360 		case SYNAPTICS_RC_DATA:
1361 			copy_size = min_t(size_t, msg->size, sizeof(fixture->last_rc_data));
1362 			memset(fixture->last_rc_data, 0, sizeof(fixture->last_rc_data));
1363 			memcpy(fixture->last_rc_data, buffer, copy_size);
1364 			fixture->rc_data_writes++;
1365 			break;
1366 		case SYNAPTICS_RC_OFFSET:
1367 			if (msg->size >= 4)
1368 				fixture->last_rc_offset = buffer[0] | buffer[1] << 8 |
1369 							  buffer[2] << 16 | buffer[3] << 24;
1370 			break;
1371 		case SYNAPTICS_RC_LENGTH:
1372 			if (msg->size >= 2)
1373 				fixture->last_rc_length = buffer[0] | buffer[1] << 8;
1374 			break;
1375 		case SYNAPTICS_RC_COMMAND:
1376 			fixture->last_rc_command = buffer[0];
1377 			if (fixture->rc_command_count < ARRAY_SIZE(fixture->rc_commands)) {
1378 				fixture->rc_commands[fixture->rc_command_count] = buffer[0] & 0x7f;
1379 				fixture->rc_command_count++;
1380 			}
1381 			break;
1382 		case DP_DSC_ENABLE:
1383 			if (fixture->dsc_enable_writes < ARRAY_SIZE(fixture->dsc_enable_values)) {
1384 				fixture->dsc_enable_values[fixture->dsc_enable_writes] = buffer[0];
1385 				fixture->dsc_enable_writes++;
1386 			}
1387 			break;
1388 		}
1389 		msg->reply = DP_AUX_NATIVE_REPLY_ACK;
1390 		return msg->size;
1391 	}
1392 
1393 	if (request == DP_AUX_NATIVE_READ) {
1394 		memset(buffer, 0, msg->size);
1395 		switch (msg->address) {
1396 		case DP_DOWNSPREAD_CTRL:
1397 			if (msg->size)
1398 				buffer[0] = fixture->dpcd_read_value;
1399 			fixture->downspread_reads++;
1400 			break;
1401 		case SYNAPTICS_RC_COMMAND:
1402 			if (msg->size)
1403 				buffer[0] = fixture->last_rc_command & 0x7f;
1404 			fixture->rc_command_reads++;
1405 			break;
1406 		case SYNAPTICS_RC_RESULT:
1407 			if (msg->size)
1408 				buffer[0] = fixture->rc_result;
1409 			fixture->rc_result_reads++;
1410 			break;
1411 		case SYNAPTICS_RC_DATA:
1412 			copy_size = min_t(size_t, msg->size, sizeof(fixture->read_rc_data));
1413 			for (index = 0; index < copy_size; index++)
1414 				buffer[index] = fixture->read_rc_data[index];
1415 			fixture->rc_data_reads++;
1416 			break;
1417 		}
1418 		msg->reply = DP_AUX_NATIVE_REPLY_ACK;
1419 		return msg->size;
1420 	}
1421 
1422 	msg->reply = DP_AUX_NATIVE_REPLY_ACK;
1423 	return msg->size;
1424 }
1425 
1426 static struct dm_test_synaptics_aux *dm_test_current_aux_recorder;
1427 
dm_test_current_aux_transfer(struct drm_dp_aux * aux,struct drm_dp_aux_msg * msg)1428 static ssize_t dm_test_current_aux_transfer(struct drm_dp_aux *aux,
1429 					    struct drm_dp_aux_msg *msg)
1430 {
1431 	return dm_test_synaptics_aux_transfer(&dm_test_current_aux_recorder->aux, msg);
1432 }
1433 
dm_test_alloc_synaptics_aux_with_dev(struct kunit * test,struct drm_device * drm_dev)1434 static struct dm_test_synaptics_aux *dm_test_alloc_synaptics_aux_with_dev(struct kunit *test,
1435 								 struct drm_device *drm_dev)
1436 {
1437 	struct dm_test_synaptics_aux *fixture;
1438 	unsigned int index;
1439 
1440 	fixture = kunit_kzalloc(test, sizeof(*fixture), GFP_KERNEL);
1441 	KUNIT_ASSERT_NOT_NULL(test, fixture);
1442 
1443 	for (index = 0; index < ARRAY_SIZE(fixture->read_rc_data); index++)
1444 		fixture->read_rc_data[index] = 0x03;
1445 
1446 	fixture->rc_result = 0;
1447 	fixture->aux.drm_dev = drm_dev;
1448 	fixture->aux.transfer = dm_test_synaptics_aux_transfer;
1449 	drm_dp_aux_init(&fixture->aux);
1450 
1451 	return fixture;
1452 }
1453 
dm_test_alloc_synaptics_aux(struct kunit * test)1454 static struct dm_test_synaptics_aux *dm_test_alloc_synaptics_aux(struct kunit *test)
1455 {
1456 	struct amdgpu_device *adev;
1457 
1458 	adev = dm_kunit_alloc_adev(test);
1459 	KUNIT_ASSERT_NOT_NULL(test, adev);
1460 
1461 	return dm_test_alloc_synaptics_aux_with_dev(test, &adev->ddev);
1462 }
1463 
dm_test_expect_synaptics_commands(struct kunit * test,struct dm_test_synaptics_aux * fixture,const u8 * expected_commands,unsigned int expected_count)1464 static void dm_test_expect_synaptics_commands(struct kunit *test,
1465 					      struct dm_test_synaptics_aux *fixture,
1466 					      const u8 *expected_commands,
1467 					      unsigned int expected_count)
1468 {
1469 	unsigned int index;
1470 
1471 	KUNIT_ASSERT_EQ(test, fixture->rc_command_count, expected_count);
1472 
1473 	for (index = 0; index < expected_count; index++)
1474 		KUNIT_EXPECT_EQ(test, fixture->rc_commands[index], expected_commands[index]);
1475 }
1476 
dm_test_setup_synaptics_stream(struct dc_stream_state * stream,struct dc_link * link)1477 static void dm_test_setup_synaptics_stream(struct dc_stream_state *stream,
1478 						  struct dc_link *link)
1479 {
1480 	stream->link = link;
1481 	stream->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
1482 	link->dpcd_caps.branch_dev_id = DP_BRANCH_DEVICE_ID_90CC24;
1483 	link->dpcd_caps.dpcd_rev.raw = DP_DPCD_REV_14;
1484 	link->dpcd_caps.sink_count.bits.SINK_COUNT = 2;
1485 	memcpy(link->dpcd_caps.branch_dev_name, "SYNA", 4);
1486 }
1487 
1488 /**
1489  * dm_test_execute_synaptics_rc_command_write_success - Test RC write success
1490  * @test: The KUnit test context
1491  */
dm_test_execute_synaptics_rc_command_write_success(struct kunit * test)1492 static void dm_test_execute_synaptics_rc_command_write_success(struct kunit *test)
1493 {
1494 	struct dm_test_synaptics_aux *fixture;
1495 	u8 data[5] = { 'P', 'R', 'I', 'U', 'S' };
1496 
1497 	fixture = dm_test_alloc_synaptics_aux(test);
1498 
1499 	KUNIT_EXPECT_TRUE(test, execute_synaptics_rc_command(&fixture->aux, true,
1500 							     0x01, sizeof(data), 0x123456,
1501 							     data));
1502 	KUNIT_EXPECT_EQ(test, memcmp(fixture->last_rc_data, data, sizeof(data)), 0);
1503 	KUNIT_EXPECT_EQ(test, fixture->last_rc_offset, 0x123456U);
1504 	KUNIT_EXPECT_EQ(test, fixture->last_rc_length, (u32)sizeof(data));
1505 	KUNIT_EXPECT_EQ(test, fixture->last_rc_command, (u8)0x81);
1506 	KUNIT_EXPECT_EQ(test, fixture->rc_command_reads, 1U);
1507 	KUNIT_EXPECT_EQ(test, fixture->rc_result_reads, 1U);
1508 }
1509 
1510 /**
1511  * dm_test_execute_synaptics_rc_command_read_success - Test RC read success
1512  * @test: The KUnit test context
1513  */
dm_test_execute_synaptics_rc_command_read_success(struct kunit * test)1514 static void dm_test_execute_synaptics_rc_command_read_success(struct kunit *test)
1515 {
1516 	struct dm_test_synaptics_aux *fixture;
1517 	u8 data[4] = { 0 };
1518 	u8 expected[4] = { 0xa5, 0x5a, 0xc3, 0x3c };
1519 
1520 	fixture = dm_test_alloc_synaptics_aux(test);
1521 	memcpy(fixture->read_rc_data, expected, sizeof(expected));
1522 
1523 	KUNIT_EXPECT_TRUE(test, execute_synaptics_rc_command(&fixture->aux, false,
1524 							     0x31, sizeof(data), 0x220998,
1525 							     data));
1526 	KUNIT_EXPECT_EQ(test, memcmp(data, expected, sizeof(expected)), 0);
1527 	KUNIT_EXPECT_EQ(test, fixture->rc_data_writes, 0U);
1528 	KUNIT_EXPECT_EQ(test, fixture->rc_data_reads, 1U);
1529 	KUNIT_EXPECT_EQ(test, fixture->last_rc_offset, 0x220998U);
1530 	KUNIT_EXPECT_EQ(test, fixture->last_rc_length, (u32)sizeof(data));
1531 }
1532 
1533 /**
1534  * dm_test_execute_synaptics_rc_command_write_fail - Test RC write failure
1535  * @test: The KUnit test context
1536  */
dm_test_execute_synaptics_rc_command_write_fail(struct kunit * test)1537 static void dm_test_execute_synaptics_rc_command_write_fail(struct kunit *test)
1538 {
1539 	struct dm_test_synaptics_aux *fixture;
1540 	u8 data = 0;
1541 
1542 	fixture = dm_test_alloc_synaptics_aux(test);
1543 	fixture->fail_address = SYNAPTICS_RC_LENGTH;
1544 
1545 	KUNIT_EXPECT_FALSE(test, execute_synaptics_rc_command(&fixture->aux, true,
1546 							      0x01, sizeof(data), 0, &data));
1547 	KUNIT_EXPECT_EQ(test, fixture->rc_command_count, 0U);
1548 }
1549 
1550 /**
1551  * dm_test_apply_synaptics_fifo_reset_wa_full - Test full FIFO reset sequence
1552  * @test: The KUnit test context
1553  */
dm_test_apply_synaptics_fifo_reset_wa_full(struct kunit * test)1554 static void dm_test_apply_synaptics_fifo_reset_wa_full(struct kunit *test)
1555 {
1556 	static const u8 expected_commands[] = {
1557 		0x01, 0x31, 0x21, 0x31, 0x21, 0x31, 0x21,
1558 		0x31, 0x21, 0x31, 0x31, 0x21, 0x02,
1559 	};
1560 	struct dm_test_synaptics_aux *fixture;
1561 
1562 	fixture = dm_test_alloc_synaptics_aux(test);
1563 
1564 	apply_synaptics_fifo_reset_wa(&fixture->aux);
1565 
1566 	dm_test_expect_synaptics_commands(test, fixture, expected_commands,
1567 					  ARRAY_SIZE(expected_commands));
1568 	KUNIT_EXPECT_EQ(test, fixture->rc_result_reads, (unsigned int)ARRAY_SIZE(expected_commands));
1569 }
1570 
1571 /**
1572  * dm_test_apply_synaptics_fifo_reset_wa_first_fail - Test FIFO reset early exit
1573  * @test: The KUnit test context
1574  */
dm_test_apply_synaptics_fifo_reset_wa_first_fail(struct kunit * test)1575 static void dm_test_apply_synaptics_fifo_reset_wa_first_fail(struct kunit *test)
1576 {
1577 	struct dm_test_synaptics_aux *fixture;
1578 
1579 	fixture = dm_test_alloc_synaptics_aux(test);
1580 	fixture->rc_result = 0xff;
1581 
1582 	apply_synaptics_fifo_reset_wa(&fixture->aux);
1583 
1584 	KUNIT_EXPECT_EQ(test, fixture->rc_command_count, 1U);
1585 	KUNIT_EXPECT_EQ(test, fixture->rc_commands[0], (u8)0x01);
1586 }
1587 
dm_test_write_dsc_enable_synaptics(struct kunit * test,bool link_active,bool enable,bool synaptics_branch,unsigned int expected_dsc_writes,unsigned int expected_rc_commands)1588 static void dm_test_write_dsc_enable_synaptics(struct kunit *test,
1589 					       bool link_active,
1590 					       bool enable,
1591 					       bool synaptics_branch,
1592 					       unsigned int expected_dsc_writes,
1593 					       unsigned int expected_rc_commands)
1594 {
1595 	struct dm_test_synaptics_aux *fixture;
1596 	struct dc_stream_state *stream;
1597 	struct dc_link *link;
1598 	u8 ret;
1599 
1600 	fixture = dm_test_alloc_synaptics_aux(test);
1601 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
1602 	KUNIT_ASSERT_NOT_NULL(test, stream);
1603 	link = dm_kunit_alloc_link(test);
1604 
1605 	dm_test_setup_synaptics_stream(stream, link);
1606 	link->link_status.link_active = link_active;
1607 	if (!synaptics_branch)
1608 		memcpy(link->dpcd_caps.branch_dev_name, "ABCD", 4);
1609 
1610 	ret = write_dsc_enable_synaptics_non_virtual_dpcd_mst(&fixture->aux, stream, enable);
1611 
1612 	KUNIT_EXPECT_EQ(test, ret, expected_dsc_writes ? 1 : 0);
1613 	KUNIT_EXPECT_EQ(test, fixture->dsc_enable_writes, expected_dsc_writes);
1614 	KUNIT_EXPECT_EQ(test, fixture->rc_command_count, expected_rc_commands);
1615 	if (expected_dsc_writes)
1616 		KUNIT_EXPECT_EQ(test, fixture->dsc_enable_values[0], enable ? 1 : 0);
1617 }
1618 
1619 /**
1620  * dm_test_write_dsc_enable_synaptics_enable_inactive - Test enable plus FIFO reset
1621  * @test: The KUnit test context
1622  */
dm_test_write_dsc_enable_synaptics_enable_inactive(struct kunit * test)1623 static void dm_test_write_dsc_enable_synaptics_enable_inactive(struct kunit *test)
1624 {
1625 	dm_test_write_dsc_enable_synaptics(test, false, true, true, 1, 13);
1626 }
1627 
1628 /**
1629  * dm_test_write_dsc_enable_synaptics_enable_active - Test enable skips FIFO reset
1630  * @test: The KUnit test context
1631  */
dm_test_write_dsc_enable_synaptics_enable_active(struct kunit * test)1632 static void dm_test_write_dsc_enable_synaptics_enable_active(struct kunit *test)
1633 {
1634 	dm_test_write_dsc_enable_synaptics(test, true, true, true, 1, 0);
1635 }
1636 
1637 /**
1638  * dm_test_write_dsc_enable_synaptics_disable_inactive - Test inactive disable writes DPCD
1639  * @test: The KUnit test context
1640  */
dm_test_write_dsc_enable_synaptics_disable_inactive(struct kunit * test)1641 static void dm_test_write_dsc_enable_synaptics_disable_inactive(struct kunit *test)
1642 {
1643 	dm_test_write_dsc_enable_synaptics(test, false, false, true, 1, 0);
1644 }
1645 
1646 /**
1647  * dm_test_write_dsc_enable_synaptics_disable_active - Test active disable skips DPCD
1648  * @test: The KUnit test context
1649  */
dm_test_write_dsc_enable_synaptics_disable_active(struct kunit * test)1650 static void dm_test_write_dsc_enable_synaptics_disable_active(struct kunit *test)
1651 {
1652 	dm_test_write_dsc_enable_synaptics(test, true, false, true, 0, 0);
1653 }
1654 
1655 /**
1656  * dm_test_write_dsc_enable_synaptics_enable_non_synaptics - Test non-Synaptics enable
1657  * @test: The KUnit test context
1658  */
dm_test_write_dsc_enable_synaptics_enable_non_synaptics(struct kunit * test)1659 static void dm_test_write_dsc_enable_synaptics_enable_non_synaptics(struct kunit *test)
1660 {
1661 	dm_test_write_dsc_enable_synaptics(test, false, true, false, 1, 0);
1662 }
1663 
1664 /**
1665  * dm_test_dp_write_dsc_enable_routes_synaptics - Test public DSC helper workaround route
1666  * @test: The KUnit test context
1667  */
dm_test_dp_write_dsc_enable_routes_synaptics(struct kunit * test)1668 static void dm_test_dp_write_dsc_enable_routes_synaptics(struct kunit *test)
1669 {
1670 	struct dm_test_synaptics_aux *fixture;
1671 	struct amdgpu_dm_connector *aconnector;
1672 	struct dc_stream_state *stream;
1673 	struct dc_link *link;
1674 
1675 	fixture = dm_test_alloc_synaptics_aux(test);
1676 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
1677 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
1678 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
1679 	KUNIT_ASSERT_NOT_NULL(test, stream);
1680 	link = dm_kunit_alloc_link(test);
1681 
1682 	dm_test_setup_synaptics_stream(stream, link);
1683 	stream->dm_stream_context = aconnector;
1684 	aconnector->dc_link = link;
1685 	aconnector->dsc_aux = &fixture->aux;
1686 
1687 	KUNIT_EXPECT_TRUE(test, dm_helpers_dp_write_dsc_enable(NULL, stream, true));
1688 	KUNIT_EXPECT_EQ(test, fixture->dsc_enable_writes, 1U);
1689 	KUNIT_EXPECT_EQ(test, fixture->dsc_enable_values[0], (u8)1);
1690 	KUNIT_EXPECT_EQ(test, fixture->rc_command_count, 13U);
1691 }
1692 
1693 /* Tests for dm_helpers_dp_mst_start_top_mgr() / dm_helpers_dp_mst_stop_top_mgr() */
1694 
1695 /**
1696  * dm_test_mst_start_top_mgr_null_priv - Test MST start returns false without connector
1697  * @test: The KUnit test context
1698  */
dm_test_mst_start_top_mgr_null_priv(struct kunit * test)1699 static void dm_test_mst_start_top_mgr_null_priv(struct kunit *test)
1700 {
1701 	struct dc_link *link;
1702 
1703 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1704 	KUNIT_ASSERT_NOT_NULL(test, link);
1705 
1706 	KUNIT_EXPECT_FALSE(test, dm_helpers_dp_mst_start_top_mgr(NULL, link, false));
1707 }
1708 
1709 /**
1710  * dm_test_mst_stop_top_mgr_null_priv - Test MST stop returns false without connector
1711  * @test: The KUnit test context
1712  */
dm_test_mst_stop_top_mgr_null_priv(struct kunit * test)1713 static void dm_test_mst_stop_top_mgr_null_priv(struct kunit *test)
1714 {
1715 	struct dc_link *link;
1716 
1717 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1718 	KUNIT_ASSERT_NOT_NULL(test, link);
1719 
1720 	KUNIT_EXPECT_FALSE(test, dm_helpers_dp_mst_stop_top_mgr(NULL, link));
1721 }
1722 
1723 /**
1724  * dm_test_mst_start_top_mgr_boot - Test MST start boot path on a connector-backed link
1725  * @test: The KUnit test context
1726  *
1727  * Uses the DRM KUnit mock device to back the connector so the link is a
1728  * realistic connector-backed link. The boot path short-circuits and returns
1729  * true without touching the MST topology manager.
1730  */
dm_test_mst_start_top_mgr_boot(struct kunit * test)1731 static void dm_test_mst_start_top_mgr_boot(struct kunit *test)
1732 {
1733 	struct amdgpu_dm_connector *aconnector;
1734 	struct amdgpu_device *adev;
1735 	struct dc_link *link;
1736 
1737 	adev = dm_kunit_alloc_adev(test);
1738 
1739 	link = dm_kunit_alloc_link(test);
1740 
1741 	aconnector = dm_kunit_alloc_connector(test, adev, NULL);
1742 
1743 	link->priv = aconnector;
1744 
1745 	KUNIT_EXPECT_TRUE(test, dm_helpers_dp_mst_start_top_mgr(NULL, link, true));
1746 }
1747 
1748 /* Tests for dm_helpers_dp_write_hblank_reduction() */
1749 
1750 /**
1751  * dm_test_dp_write_hblank_reduction_false - Test hblank reduction stub returns false
1752  * @test: The KUnit test context
1753  */
dm_test_dp_write_hblank_reduction_false(struct kunit * test)1754 static void dm_test_dp_write_hblank_reduction_false(struct kunit *test)
1755 {
1756 	KUNIT_EXPECT_FALSE(test, dm_helpers_dp_write_hblank_reduction(NULL, NULL));
1757 }
1758 
1759 /* Tests for get_dsc_max_slices() */
1760 
1761 /**
1762  * dm_test_get_dsc_max_slices_1_340 - Test 1 slice at 340 MHz
1763  * @test: The KUnit test context
1764  */
dm_test_get_dsc_max_slices_1_340(struct kunit * test)1765 static void dm_test_get_dsc_max_slices_1_340(struct kunit *test)
1766 {
1767 	KUNIT_EXPECT_EQ(test, get_dsc_max_slices(1, 340), 1);
1768 }
1769 
1770 /**
1771  * dm_test_get_dsc_max_slices_2_340 - Test 2 slices at 340 MHz
1772  * @test: The KUnit test context
1773  */
dm_test_get_dsc_max_slices_2_340(struct kunit * test)1774 static void dm_test_get_dsc_max_slices_2_340(struct kunit *test)
1775 {
1776 	KUNIT_EXPECT_EQ(test, get_dsc_max_slices(2, 340), 2);
1777 }
1778 
1779 /**
1780  * dm_test_get_dsc_max_slices_4_340 - Test 4 slices at 340 MHz
1781  * @test: The KUnit test context
1782  */
dm_test_get_dsc_max_slices_4_340(struct kunit * test)1783 static void dm_test_get_dsc_max_slices_4_340(struct kunit *test)
1784 {
1785 	KUNIT_EXPECT_EQ(test, get_dsc_max_slices(4, 340), 3);
1786 }
1787 
1788 /**
1789  * dm_test_get_dsc_max_slices_8_340 - Test 8 slices at 340 MHz
1790  * @test: The KUnit test context
1791  */
dm_test_get_dsc_max_slices_8_340(struct kunit * test)1792 static void dm_test_get_dsc_max_slices_8_340(struct kunit *test)
1793 {
1794 	KUNIT_EXPECT_EQ(test, get_dsc_max_slices(8, 340), 4);
1795 }
1796 
1797 /**
1798  * dm_test_get_dsc_max_slices_8_400 - Test 8 slices at 400 MHz
1799  * @test: The KUnit test context
1800  */
dm_test_get_dsc_max_slices_8_400(struct kunit * test)1801 static void dm_test_get_dsc_max_slices_8_400(struct kunit *test)
1802 {
1803 	KUNIT_EXPECT_EQ(test, get_dsc_max_slices(8, 400), 5);
1804 }
1805 
1806 /**
1807  * dm_test_get_dsc_max_slices_12_400 - Test 12 slices at 400 MHz
1808  * @test: The KUnit test context
1809  */
dm_test_get_dsc_max_slices_12_400(struct kunit * test)1810 static void dm_test_get_dsc_max_slices_12_400(struct kunit *test)
1811 {
1812 	KUNIT_EXPECT_EQ(test, get_dsc_max_slices(12, 400), 6);
1813 }
1814 
1815 /**
1816  * dm_test_get_dsc_max_slices_16_400 - Test 16 slices at 400 MHz
1817  * @test: The KUnit test context
1818  */
dm_test_get_dsc_max_slices_16_400(struct kunit * test)1819 static void dm_test_get_dsc_max_slices_16_400(struct kunit *test)
1820 {
1821 	KUNIT_EXPECT_EQ(test, get_dsc_max_slices(16, 400), 7);
1822 }
1823 
1824 /**
1825  * dm_test_get_dsc_max_slices_unknown - Test unknown combination returns 0
1826  * @test: The KUnit test context
1827  */
dm_test_get_dsc_max_slices_unknown(struct kunit * test)1828 static void dm_test_get_dsc_max_slices_unknown(struct kunit *test)
1829 {
1830 	KUNIT_EXPECT_EQ(test, get_dsc_max_slices(3, 340), 0);
1831 	KUNIT_EXPECT_EQ(test, get_dsc_max_slices(1, 400), 0);
1832 }
1833 
1834 /* Tests for dm_helpers_init_panel_settings() */
1835 
1836 /**
1837  * dm_test_init_panel_settings_pps - Test panel power sequence settings init
1838  * @test: The KUnit test context
1839  */
dm_test_init_panel_settings_pps(struct kunit * test)1840 static void dm_test_init_panel_settings_pps(struct kunit *test)
1841 {
1842 	struct dc_panel_config panel_config = {0};
1843 	struct dc_sink *sink;
1844 
1845 	sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
1846 	KUNIT_ASSERT_NOT_NULL(test, sink);
1847 
1848 	sink->edid_caps.panel_patch.extra_t3_ms = 100;
1849 	sink->edid_caps.panel_patch.extra_t7_ms = 200;
1850 	sink->edid_caps.panel_patch.extra_delay_backlight_off = 50;
1851 	sink->edid_caps.panel_patch.extra_t12_ms = 300;
1852 
1853 	dm_helpers_init_panel_settings(NULL, &panel_config, sink);
1854 
1855 	KUNIT_EXPECT_EQ(test, panel_config.pps.extra_t3_ms, 100U);
1856 	KUNIT_EXPECT_EQ(test, panel_config.pps.extra_t7_ms, 200U);
1857 	KUNIT_EXPECT_EQ(test, panel_config.pps.extra_delay_backlight_off, 50U);
1858 	KUNIT_EXPECT_EQ(test, panel_config.pps.extra_post_t7_ms, 0U);
1859 	KUNIT_EXPECT_EQ(test, panel_config.pps.extra_pre_t11_ms, 0U);
1860 	KUNIT_EXPECT_EQ(test, panel_config.pps.extra_t12_ms, 300U);
1861 	KUNIT_EXPECT_EQ(test, panel_config.pps.extra_post_OUI_ms, 0U);
1862 }
1863 
1864 /**
1865  * dm_test_init_panel_settings_dsc - Test DSC defaults in panel settings init
1866  * @test: The KUnit test context
1867  */
dm_test_init_panel_settings_dsc(struct kunit * test)1868 static void dm_test_init_panel_settings_dsc(struct kunit *test)
1869 {
1870 	struct dc_panel_config panel_config;
1871 	struct dc_sink *sink;
1872 
1873 	memset(&panel_config, 0xFF, sizeof(panel_config));
1874 
1875 	sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
1876 	KUNIT_ASSERT_NOT_NULL(test, sink);
1877 
1878 	dm_helpers_init_panel_settings(NULL, &panel_config, sink);
1879 
1880 	KUNIT_EXPECT_FALSE(test, panel_config.dsc.disable_dsc_edp);
1881 	KUNIT_EXPECT_EQ(test, panel_config.dsc.force_dsc_edp_policy, 0U);
1882 }
1883 
1884 /* Tests for dm_helpers_override_panel_settings() */
1885 
1886 /**
1887  * dm_test_override_panel_settings_debug_mask_disables_dsc - Test DSC mask
1888  * @test: The KUnit test context
1889  */
dm_test_override_panel_settings_debug_mask_disables_dsc(struct kunit * test)1890 static void dm_test_override_panel_settings_debug_mask_disables_dsc(struct kunit *test)
1891 {
1892 	struct dc_context *ctx;
1893 	struct dc_link *link;
1894 	struct dc *dc;
1895 	uint old_debug_mask;
1896 
1897 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
1898 	KUNIT_ASSERT_NOT_NULL(test, ctx);
1899 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
1900 	KUNIT_ASSERT_NOT_NULL(test, dc);
1901 	link = dm_kunit_alloc_link(test);
1902 	ctx->dc = dc;
1903 	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
1904 
1905 	old_debug_mask = dm_helpers_get_dc_debug_mask();
1906 	dm_helpers_set_dc_debug_mask(old_debug_mask | DC_DISABLE_DSC);
1907 	dm_helpers_override_panel_settings(ctx, link);
1908 	dm_helpers_set_dc_debug_mask(old_debug_mask);
1909 
1910 	KUNIT_EXPECT_TRUE(test, link->panel_config.dsc.disable_dsc_edp);
1911 }
1912 
1913 /**
1914  * dm_test_override_panel_settings_second_edp_disables_psr - Test eDP index 1
1915  * @test: The KUnit test context
1916  */
dm_test_override_panel_settings_second_edp_disables_psr(struct kunit * test)1917 static void dm_test_override_panel_settings_second_edp_disables_psr(struct kunit *test)
1918 {
1919 	struct dc_context *ctx;
1920 	struct dc_link *first_link;
1921 	struct dc_link *second_link;
1922 	struct dc *dc;
1923 
1924 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
1925 	KUNIT_ASSERT_NOT_NULL(test, ctx);
1926 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
1927 	KUNIT_ASSERT_NOT_NULL(test, dc);
1928 	first_link = dm_kunit_alloc_link(test);
1929 	second_link = dm_kunit_alloc_link(test);
1930 
1931 	ctx->dc = dc;
1932 	dc->link_count = 2;
1933 	dc->links[0] = first_link;
1934 	dc->links[1] = second_link;
1935 	first_link->connector_signal = SIGNAL_TYPE_EDP;
1936 	second_link->connector_signal = SIGNAL_TYPE_EDP;
1937 
1938 	dm_helpers_override_panel_settings(ctx, second_link);
1939 
1940 	KUNIT_EXPECT_TRUE(test, second_link->panel_config.psr.disable_psr);
1941 	KUNIT_EXPECT_TRUE(test, second_link->panel_config.psr.disallow_psrsu);
1942 	KUNIT_EXPECT_TRUE(test, second_link->panel_config.psr.disallow_replay);
1943 }
1944 
1945 /* Tests for fill_dc_mst_payload_table_from_drm() */
1946 
1947 /**
1948  * dm_test_fill_mst_payload_table_enable - Test payload table fill on enable
1949  * @test: The KUnit test context
1950  */
dm_test_fill_mst_payload_table_enable(struct kunit * test)1951 static void dm_test_fill_mst_payload_table_enable(struct kunit *test)
1952 {
1953 	struct dc_link *link;
1954 	struct drm_dp_mst_atomic_payload payload = {0};
1955 	struct dc_dp_mst_stream_allocation_table table = {0};
1956 
1957 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1958 	KUNIT_ASSERT_NOT_NULL(test, link);
1959 
1960 	/* Pre-existing allocation in the link table */
1961 	link->mst_stream_alloc_table.stream_count = 1;
1962 	link->mst_stream_alloc_table.stream_allocations[0].vcp_id = 1;
1963 	link->mst_stream_alloc_table.stream_allocations[0].slot_count = 4;
1964 
1965 	/* New payload to add */
1966 	payload.vcpi = 2;
1967 	payload.time_slots = 8;
1968 
1969 	fill_dc_mst_payload_table_from_drm(link, true, &payload, &table);
1970 
1971 	/* Should contain both the pre-existing and new allocation */
1972 	KUNIT_EXPECT_EQ(test, table.stream_count, 2);
1973 	KUNIT_EXPECT_EQ(test, table.stream_allocations[0].vcp_id, 1);
1974 	KUNIT_EXPECT_EQ(test, table.stream_allocations[0].slot_count, 4);
1975 	KUNIT_EXPECT_EQ(test, table.stream_allocations[1].vcp_id, 2);
1976 	KUNIT_EXPECT_EQ(test, table.stream_allocations[1].slot_count, 8);
1977 }
1978 
1979 /**
1980  * dm_test_fill_mst_payload_table_disable - Test payload table fill on disable
1981  * @test: The KUnit test context
1982  */
dm_test_fill_mst_payload_table_disable(struct kunit * test)1983 static void dm_test_fill_mst_payload_table_disable(struct kunit *test)
1984 {
1985 	struct dc_link *link;
1986 	struct drm_dp_mst_atomic_payload payload = {0};
1987 	struct dc_dp_mst_stream_allocation_table table = {0};
1988 
1989 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
1990 	KUNIT_ASSERT_NOT_NULL(test, link);
1991 
1992 	/* Two existing allocations in the link table */
1993 	link->mst_stream_alloc_table.stream_count = 2;
1994 	link->mst_stream_alloc_table.stream_allocations[0].vcp_id = 1;
1995 	link->mst_stream_alloc_table.stream_allocations[0].slot_count = 4;
1996 	link->mst_stream_alloc_table.stream_allocations[1].vcp_id = 2;
1997 	link->mst_stream_alloc_table.stream_allocations[1].slot_count = 8;
1998 
1999 	/* Remove vcp_id 1 */
2000 	payload.vcpi = 1;
2001 	payload.time_slots = 4;
2002 
2003 	fill_dc_mst_payload_table_from_drm(link, false, &payload, &table);
2004 
2005 	/* Only vcp_id 2 should remain */
2006 	KUNIT_EXPECT_EQ(test, table.stream_count, 1);
2007 	KUNIT_EXPECT_EQ(test, table.stream_allocations[0].vcp_id, 2);
2008 	KUNIT_EXPECT_EQ(test, table.stream_allocations[0].slot_count, 8);
2009 }
2010 
2011 /**
2012  * dm_test_fill_mst_payload_table_empty - Test payload table fill when empty
2013  * @test: The KUnit test context
2014  */
dm_test_fill_mst_payload_table_empty(struct kunit * test)2015 static void dm_test_fill_mst_payload_table_empty(struct kunit *test)
2016 {
2017 	struct dc_link *link;
2018 	struct drm_dp_mst_atomic_payload payload = {0};
2019 	struct dc_dp_mst_stream_allocation_table table = {0};
2020 
2021 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2022 	KUNIT_ASSERT_NOT_NULL(test, link);
2023 
2024 	/* Enable on an empty table */
2025 	payload.vcpi = 5;
2026 	payload.time_slots = 12;
2027 
2028 	fill_dc_mst_payload_table_from_drm(link, true, &payload, &table);
2029 
2030 	KUNIT_EXPECT_EQ(test, table.stream_count, 1);
2031 	KUNIT_EXPECT_EQ(test, table.stream_allocations[0].vcp_id, 5);
2032 	KUNIT_EXPECT_EQ(test, table.stream_allocations[0].slot_count, 12);
2033 }
2034 
2035 /* Tests for dm_helpers_submit_i2c() */
2036 
2037 /**
2038  * dm_test_submit_i2c_null_priv - Test i2c submit returns false without connector
2039  * @test: The KUnit test context
2040  */
dm_test_submit_i2c_null_priv(struct kunit * test)2041 static void dm_test_submit_i2c_null_priv(struct kunit *test)
2042 {
2043 	struct dc_link *link;
2044 	struct i2c_command cmd = {0};
2045 
2046 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2047 	KUNIT_ASSERT_NOT_NULL(test, link);
2048 
2049 	KUNIT_EXPECT_FALSE(test, dm_helpers_submit_i2c(NULL, link, &cmd));
2050 }
2051 
2052 struct dm_test_i2c_adapter {
2053 	struct i2c_adapter base;
2054 	struct kunit *test;
2055 	struct i2c_payload *expected_payloads;
2056 	int expected_num;
2057 	int ret;
2058 	int calls;
2059 };
2060 
dm_test_i2c_lock_bus(struct i2c_adapter * adapter,unsigned int flags)2061 static void dm_test_i2c_lock_bus(struct i2c_adapter *adapter,
2062 					 unsigned int flags)
2063 {
2064 	rt_mutex_lock(&adapter->bus_lock);
2065 }
2066 
dm_test_i2c_trylock_bus(struct i2c_adapter * adapter,unsigned int flags)2067 static int dm_test_i2c_trylock_bus(struct i2c_adapter *adapter,
2068 					   unsigned int flags)
2069 {
2070 	return rt_mutex_trylock(&adapter->bus_lock);
2071 }
2072 
dm_test_i2c_unlock_bus(struct i2c_adapter * adapter,unsigned int flags)2073 static void dm_test_i2c_unlock_bus(struct i2c_adapter *adapter,
2074 					   unsigned int flags)
2075 {
2076 	rt_mutex_unlock(&adapter->bus_lock);
2077 }
2078 
2079 static const struct i2c_lock_operations dm_test_i2c_lock_ops = {
2080 	.lock_bus = dm_test_i2c_lock_bus,
2081 	.trylock_bus = dm_test_i2c_trylock_bus,
2082 	.unlock_bus = dm_test_i2c_unlock_bus,
2083 };
2084 
dm_test_i2c_master_xfer(struct i2c_adapter * adapter,struct i2c_msg * msgs,int num)2085 static int dm_test_i2c_master_xfer(struct i2c_adapter *adapter,
2086 					   struct i2c_msg *msgs,
2087 					   int num)
2088 {
2089 	struct dm_test_i2c_adapter *fake;
2090 	int i;
2091 
2092 	fake = container_of(adapter, struct dm_test_i2c_adapter, base);
2093 	fake->calls++;
2094 
2095 	KUNIT_EXPECT_EQ(fake->test, num, fake->expected_num);
2096 
2097 	for (i = 0; i < num; i++) {
2098 		KUNIT_EXPECT_EQ(fake->test, msgs[i].flags,
2099 				 fake->expected_payloads[i].write ? 0 : I2C_M_RD);
2100 		KUNIT_EXPECT_EQ(fake->test, msgs[i].addr,
2101 				 (u16)fake->expected_payloads[i].address);
2102 		KUNIT_EXPECT_EQ(fake->test, msgs[i].len,
2103 				 (u16)fake->expected_payloads[i].length);
2104 		KUNIT_EXPECT_PTR_EQ(fake->test, msgs[i].buf,
2105 				    fake->expected_payloads[i].data);
2106 	}
2107 
2108 	return fake->ret;
2109 }
2110 
2111 static const struct i2c_algorithm dm_test_i2c_algorithm = {
2112 	.master_xfer = dm_test_i2c_master_xfer,
2113 };
2114 
2115 struct dm_test_mccs_i2c_adapter {
2116 	struct i2c_adapter base;
2117 	u8 write_data[16];
2118 	u8 read_reply[11];
2119 	int write_ret;
2120 	int read_ret;
2121 	unsigned int write_len;
2122 	unsigned int writes;
2123 	unsigned int reads;
2124 };
2125 
dm_test_mccs_i2c_master_xfer(struct i2c_adapter * adapter,struct i2c_msg * msgs,int num)2126 static int dm_test_mccs_i2c_master_xfer(struct i2c_adapter *adapter,
2127 						struct i2c_msg *msgs,
2128 						int num)
2129 {
2130 	struct dm_test_mccs_i2c_adapter *fake;
2131 	struct i2c_msg *msg = msgs;
2132 	size_t copy_len;
2133 
2134 	fake = container_of(adapter, struct dm_test_mccs_i2c_adapter, base);
2135 
2136 	if (num != 1)
2137 		return 0;
2138 
2139 	if (msg->flags & I2C_M_RD) {
2140 		fake->reads++;
2141 		if (fake->read_ret != 1)
2142 			return fake->read_ret;
2143 
2144 		copy_len = min_t(size_t, msg->len, sizeof(fake->read_reply));
2145 		memcpy(msg->buf, fake->read_reply, copy_len);
2146 		return 1;
2147 	}
2148 
2149 	fake->writes++;
2150 	if (fake->write_ret != 1)
2151 		return fake->write_ret;
2152 
2153 	copy_len = min_t(size_t, msg->len, sizeof(fake->write_data));
2154 	memcpy(fake->write_data, msg->buf, copy_len);
2155 	fake->write_len = copy_len;
2156 
2157 	return 1;
2158 }
2159 
2160 static const struct i2c_algorithm dm_test_mccs_i2c_algorithm = {
2161 	.master_xfer = dm_test_mccs_i2c_master_xfer,
2162 };
2163 
dm_test_alloc_mccs_i2c(struct kunit * test)2164 static struct dm_test_mccs_i2c_adapter *dm_test_alloc_mccs_i2c(struct kunit *test)
2165 {
2166 	struct dm_test_mccs_i2c_adapter *fake;
2167 
2168 	fake = kunit_kzalloc(test, sizeof(*fake), GFP_KERNEL);
2169 	KUNIT_ASSERT_NOT_NULL(test, fake);
2170 
2171 	fake->base.algo = &dm_test_mccs_i2c_algorithm;
2172 	fake->base.lock_ops = &dm_test_i2c_lock_ops;
2173 	fake->write_ret = 1;
2174 	fake->read_ret = 1;
2175 	rt_mutex_init(&fake->base.bus_lock);
2176 	rt_mutex_init(&fake->base.mux_lock);
2177 
2178 	return fake;
2179 }
2180 
dm_test_mccs_checksum(const u8 * data,unsigned int len)2181 static u8 dm_test_mccs_checksum(const u8 *data, unsigned int len)
2182 {
2183 	u8 checksum = 0x6e;
2184 	unsigned int i;
2185 
2186 	for (i = 0; i < len; i++)
2187 		checksum ^= data[i];
2188 
2189 	return checksum;
2190 }
2191 
dm_test_submit_i2c_transfer(struct kunit * test,bool full_transfer)2192 static void dm_test_submit_i2c_transfer(struct kunit *test,
2193 					bool full_transfer)
2194 {
2195 	struct amdgpu_dm_connector *aconnector;
2196 	struct dm_test_i2c_adapter *fake;
2197 	struct dc_link *link;
2198 	u8 write_data[2] = { 0x12, 0x34 };
2199 	u8 read_data[3] = { 0 };
2200 	struct i2c_payload payloads[] = {
2201 		{ true, 0x50, sizeof(write_data), write_data },
2202 		{ false, 0x51, sizeof(read_data), read_data },
2203 	};
2204 	struct i2c_command cmd = {
2205 		.payloads = payloads,
2206 		.number_of_payloads = ARRAY_SIZE(payloads),
2207 	};
2208 
2209 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2210 	KUNIT_ASSERT_NOT_NULL(test, link);
2211 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
2212 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
2213 	fake = kunit_kzalloc(test, sizeof(*fake), GFP_KERNEL);
2214 	KUNIT_ASSERT_NOT_NULL(test, fake);
2215 
2216 	fake->test = test;
2217 	fake->expected_payloads = payloads;
2218 	fake->expected_num = ARRAY_SIZE(payloads);
2219 	fake->ret = full_transfer ? ARRAY_SIZE(payloads) : 1;
2220 	fake->base.algo = &dm_test_i2c_algorithm;
2221 	fake->base.lock_ops = &dm_test_i2c_lock_ops;
2222 	rt_mutex_init(&fake->base.bus_lock);
2223 	rt_mutex_init(&fake->base.mux_lock);
2224 
2225 	aconnector->i2c = (struct amdgpu_i2c_adapter *)fake;
2226 	link->priv = aconnector;
2227 
2228 	KUNIT_EXPECT_EQ(test, dm_helpers_submit_i2c(NULL, link, &cmd), full_transfer);
2229 	KUNIT_EXPECT_EQ(test, fake->calls, 1);
2230 }
2231 
2232 /**
2233  * dm_test_submit_i2c_success - Test payloads are mapped to i2c_msg array
2234  * @test: The KUnit test context
2235  */
dm_test_submit_i2c_success(struct kunit * test)2236 static void dm_test_submit_i2c_success(struct kunit *test)
2237 {
2238 	dm_test_submit_i2c_transfer(test, true);
2239 }
2240 
2241 /**
2242  * dm_test_submit_i2c_partial_transfer - Test short i2c transfer returns false
2243  * @test: The KUnit test context
2244  */
dm_test_submit_i2c_partial_transfer(struct kunit * test)2245 static void dm_test_submit_i2c_partial_transfer(struct kunit *test)
2246 {
2247 	dm_test_submit_i2c_transfer(test, false);
2248 }
2249 
2250 /* Tests for dm_helper_dmub_aux_transfer_sync() */
2251 
2252 /**
2253  * dm_test_dmub_aux_transfer_sync_hpd_discon - Test aux transfer with HPD disconnected
2254  * @test: The KUnit test context
2255  */
dm_test_dmub_aux_transfer_sync_hpd_discon(struct kunit * test)2256 static void dm_test_dmub_aux_transfer_sync_hpd_discon(struct kunit *test)
2257 {
2258 	struct dc_link *link;
2259 	struct dc_context *ctx;
2260 	struct aux_payload payload = {0};
2261 	enum aux_return_code_type result = AUX_RET_SUCCESS;
2262 	int ret;
2263 
2264 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2265 	KUNIT_ASSERT_NOT_NULL(test, link);
2266 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2267 	KUNIT_ASSERT_NOT_NULL(test, ctx);
2268 
2269 	link->hpd_status = false;
2270 
2271 	ret = dm_helper_dmub_aux_transfer_sync(ctx, link, &payload, &result);
2272 
2273 	KUNIT_EXPECT_EQ(test, ret, -1);
2274 	KUNIT_EXPECT_EQ(test, (int)result, (int)AUX_RET_ERROR_HPD_DISCON);
2275 }
2276 
2277 /* Tests for empty stub functions (must not crash) */
2278 
2279 /**
2280  * dm_test_dp_update_branch_info_no_crash - Test empty stub does not crash
2281  * @test: The KUnit test context
2282  */
dm_test_dp_update_branch_info_no_crash(struct kunit * test)2283 static void dm_test_dp_update_branch_info_no_crash(struct kunit *test)
2284 {
2285 	dm_helpers_dp_update_branch_info(NULL, NULL);
2286 	KUNIT_EXPECT_TRUE(test, true);
2287 }
2288 
2289 /**
2290  * dm_test_mst_poll_pending_down_reply_no_crash - Test empty stub does not crash
2291  * @test: The KUnit test context
2292  */
dm_test_mst_poll_pending_down_reply_no_crash(struct kunit * test)2293 static void dm_test_mst_poll_pending_down_reply_no_crash(struct kunit *test)
2294 {
2295 	dm_helpers_dp_mst_poll_pending_down_reply(NULL, NULL);
2296 	KUNIT_EXPECT_TRUE(test, true);
2297 }
2298 
2299 /**
2300  * dm_test_mst_clear_payload_alloc_table_no_crash - Test empty stub does not crash
2301  * @test: The KUnit test context
2302  */
dm_test_mst_clear_payload_alloc_table_no_crash(struct kunit * test)2303 static void dm_test_mst_clear_payload_alloc_table_no_crash(struct kunit *test)
2304 {
2305 	dm_helpers_dp_mst_clear_payload_allocation_table(NULL, NULL);
2306 	KUNIT_EXPECT_TRUE(test, true);
2307 }
2308 
2309 /**
2310  * dm_test_set_dcn_clocks_no_crash - Test empty stub does not crash
2311  * @test: The KUnit test context
2312  */
dm_test_set_dcn_clocks_no_crash(struct kunit * test)2313 static void dm_test_set_dcn_clocks_no_crash(struct kunit *test)
2314 {
2315 	dm_set_dcn_clocks(NULL, NULL);
2316 	KUNIT_EXPECT_TRUE(test, true);
2317 }
2318 
2319 /**
2320  * dm_test_dmu_timeout_no_crash - Test empty stub does not crash
2321  * @test: The KUnit test context
2322  */
dm_test_dmu_timeout_no_crash(struct kunit * test)2323 static void dm_test_dmu_timeout_no_crash(struct kunit *test)
2324 {
2325 	dm_helpers_dmu_timeout(NULL);
2326 	KUNIT_EXPECT_TRUE(test, true);
2327 }
2328 
2329 /**
2330  * dm_test_smu_timeout_no_crash - Test empty stub does not crash
2331  * @test: The KUnit test context
2332  */
dm_test_smu_timeout_no_crash(struct kunit * test)2333 static void dm_test_smu_timeout_no_crash(struct kunit *test)
2334 {
2335 	dm_helpers_smu_timeout(NULL, 0, 0, 0);
2336 	KUNIT_EXPECT_TRUE(test, true);
2337 }
2338 
2339 /**
2340  * dm_test_set_phyd32clk_no_crash - Test empty stub does not crash
2341  * @test: The KUnit test context
2342  */
dm_test_set_phyd32clk_no_crash(struct kunit * test)2343 static void dm_test_set_phyd32clk_no_crash(struct kunit *test)
2344 {
2345 	dm_set_phyd32clk(NULL, 0);
2346 	KUNIT_EXPECT_TRUE(test, true);
2347 }
2348 
2349 /**
2350  * dm_test_mst_update_branch_bandwidth_no_crash - Test empty stub does not crash
2351  * @test: The KUnit test context
2352  */
dm_test_mst_update_branch_bandwidth_no_crash(struct kunit * test)2353 static void dm_test_mst_update_branch_bandwidth_no_crash(struct kunit *test)
2354 {
2355 	dm_helpers_dp_mst_update_branch_bandwidth(NULL, NULL);
2356 	KUNIT_EXPECT_TRUE(test, true);
2357 }
2358 
2359 /* Tests for MST functions null-connector early returns */
2360 
2361 /**
2362  * dm_test_mst_write_payload_alloc_table_null_ctx - Test null connector returns false
2363  * @test: The KUnit test context
2364  */
dm_test_mst_write_payload_alloc_table_null_ctx(struct kunit * test)2365 static void dm_test_mst_write_payload_alloc_table_null_ctx(struct kunit *test)
2366 {
2367 	struct dc_stream_state *stream;
2368 
2369 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
2370 	KUNIT_ASSERT_NOT_NULL(test, stream);
2371 
2372 	/* dm_stream_context is NULL → aconnector is NULL → return false */
2373 	KUNIT_EXPECT_FALSE(test,
2374 			   dm_helpers_dp_mst_write_payload_allocation_table(NULL, stream, NULL, true));
2375 }
2376 
2377 /**
2378  * dm_test_mst_poll_for_act_null_ctx - Test null connector returns ACT_FAILED
2379  * @test: The KUnit test context
2380  */
dm_test_mst_poll_for_act_null_ctx(struct kunit * test)2381 static void dm_test_mst_poll_for_act_null_ctx(struct kunit *test)
2382 {
2383 	struct dc_stream_state *stream;
2384 
2385 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
2386 	KUNIT_ASSERT_NOT_NULL(test, stream);
2387 
2388 	KUNIT_EXPECT_EQ(test,
2389 			(int)dm_helpers_dp_mst_poll_for_allocation_change_trigger(NULL, stream),
2390 			(int)ACT_FAILED);
2391 }
2392 
2393 /**
2394  * dm_test_mst_send_payload_alloc_null_ctx - Test null connector does not crash
2395  * @test: The KUnit test context
2396  */
dm_test_mst_send_payload_alloc_null_ctx(struct kunit * test)2397 static void dm_test_mst_send_payload_alloc_null_ctx(struct kunit *test)
2398 {
2399 	struct dc_stream_state *stream;
2400 
2401 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
2402 	KUNIT_ASSERT_NOT_NULL(test, stream);
2403 
2404 	/* Should early-return without crash */
2405 	dm_helpers_dp_mst_send_payload_allocation(NULL, stream);
2406 	KUNIT_EXPECT_TRUE(test, true);
2407 }
2408 
2409 /**
2410  * dm_test_mst_update_mgr_dealloc_null_ctx - Test null connector does not crash
2411  * @test: The KUnit test context
2412  */
dm_test_mst_update_mgr_dealloc_null_ctx(struct kunit * test)2413 static void dm_test_mst_update_mgr_dealloc_null_ctx(struct kunit *test)
2414 {
2415 	struct dc_stream_state *stream;
2416 
2417 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
2418 	KUNIT_ASSERT_NOT_NULL(test, stream);
2419 
2420 	dm_helpers_dp_mst_update_mst_mgr_for_deallocation(NULL, stream);
2421 	KUNIT_EXPECT_TRUE(test, true);
2422 }
2423 
2424 /**
2425  * dm_test_is_dp_sink_present_null_priv - Test null connector returns true
2426  * @test: The KUnit test context
2427  */
dm_test_is_dp_sink_present_null_priv(struct kunit * test)2428 static void dm_test_is_dp_sink_present_null_priv(struct kunit *test)
2429 {
2430 	struct dc_link *link;
2431 
2432 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2433 	KUNIT_ASSERT_NOT_NULL(test, link);
2434 
2435 	/* NULL priv → DRM_ERROR + return true */
2436 	KUNIT_EXPECT_TRUE(test, dm_helpers_is_dp_sink_present(link));
2437 }
2438 
2439 /* Tests for dm_helpers_dmub_outbox_interrupt_control() */
2440 
2441 /**
2442  * dm_test_dmub_outbox_interrupt_control_null_dc - Test outbox irq control with NULL dc
2443  * @test: The KUnit test context
2444  *
2445  * amdgpu_dm_irq_set() is NULL-safe and returns false when dc is NULL, so the
2446  * helper returns false without touching real interrupt hardware.
2447  */
dm_test_dmub_outbox_interrupt_control_null_dc(struct kunit * test)2448 static void dm_test_dmub_outbox_interrupt_control_null_dc(struct kunit *test)
2449 {
2450 	struct amdgpu_device *adev;
2451 	struct dc_context *ctx;
2452 
2453 	adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
2454 	KUNIT_ASSERT_NOT_NULL(test, adev);
2455 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2456 	KUNIT_ASSERT_NOT_NULL(test, ctx);
2457 	ctx->driver_context = adev;
2458 
2459 	/* adev->dm.dc is NULL → amdgpu_dm_irq_set returns false */
2460 	KUNIT_EXPECT_FALSE(test, dm_helpers_dmub_outbox_interrupt_control(ctx, true));
2461 	KUNIT_EXPECT_FALSE(test, dm_helpers_dmub_outbox_interrupt_control(ctx, false));
2462 }
2463 
2464 /* Tests for dm_helpers_mst_enable_stream_features() */
2465 
2466 /**
2467  * dm_test_mst_enable_stream_features_aux_disabled - Test early return when aux disabled
2468  * @test: The KUnit test context
2469  */
dm_test_mst_enable_stream_features_aux_disabled(struct kunit * test)2470 static void dm_test_mst_enable_stream_features_aux_disabled(struct kunit *test)
2471 {
2472 	struct dc_stream_state *stream;
2473 	struct dc_link *link;
2474 
2475 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2476 	KUNIT_ASSERT_NOT_NULL(test, link);
2477 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
2478 	KUNIT_ASSERT_NOT_NULL(test, stream);
2479 
2480 	stream->link = link;
2481 	link->aux_access_disabled = true;
2482 
2483 	/* aux_access_disabled → early return without DPCD access */
2484 	dm_helpers_mst_enable_stream_features(stream);
2485 	KUNIT_EXPECT_TRUE(test, true);
2486 }
2487 
2488 /**
2489  * dm_test_mst_enable_stream_features_writes_downspread - Test MSA ignore write
2490  * @test: The KUnit test context
2491  */
dm_test_mst_enable_stream_features_writes_downspread(struct kunit * test)2492 static void dm_test_mst_enable_stream_features_writes_downspread(struct kunit *test)
2493 {
2494 	struct dm_test_synaptics_aux *fixture;
2495 	struct amdgpu_dm_connector *aconnector;
2496 	struct dc_stream_state *stream;
2497 	struct amdgpu_device *adev;
2498 	struct dc_link *link;
2499 
2500 	adev = dm_kunit_alloc_adev(test);
2501 	fixture = dm_test_alloc_synaptics_aux_with_dev(test, &adev->ddev);
2502 	aconnector = dm_kunit_alloc_connector(test, adev, NULL);
2503 	link = dm_kunit_alloc_link(test);
2504 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
2505 	KUNIT_ASSERT_NOT_NULL(test, stream);
2506 
2507 	dm_test_current_aux_recorder = fixture;
2508 	aconnector->dm_dp_aux.aux.drm_dev = &adev->ddev;
2509 	aconnector->dm_dp_aux.aux.transfer = dm_test_current_aux_transfer;
2510 	drm_dp_aux_init(&aconnector->dm_dp_aux.aux);
2511 	link->priv = aconnector;
2512 	stream->link = link;
2513 	stream->ignore_msa_timing_param = true;
2514 
2515 	dm_helpers_mst_enable_stream_features(stream);
2516 
2517 	KUNIT_EXPECT_EQ(test, fixture->downspread_reads, 1U);
2518 	KUNIT_EXPECT_EQ(test, fixture->downspread_writes, 1U);
2519 	KUNIT_EXPECT_EQ(test, fixture->last_dpcd_write_address,
2520 			 DP_DOWNSPREAD_CTRL);
2521 	KUNIT_EXPECT_EQ(test, fixture->dpcd_write_value, (u8)BIT(7));
2522 }
2523 
2524 /* Tests for dm_helpers_enable_periodic_detection() */
2525 
2526 struct dm_test_idle_work {
2527 	struct idle_workqueue base;
2528 	bool ran;
2529 };
2530 
dm_test_idle_work_func(struct work_struct * work)2531 static void dm_test_idle_work_func(struct work_struct *work)
2532 {
2533 	struct dm_test_idle_work *idle_work;
2534 
2535 	idle_work = container_of(work, struct dm_test_idle_work, base.work);
2536 	idle_work->ran = true;
2537 }
2538 
2539 /**
2540  * dm_test_enable_periodic_detection_no_workqueue - Test no-op without idle workqueue
2541  * @test: The KUnit test context
2542  */
dm_test_enable_periodic_detection_no_workqueue(struct kunit * test)2543 static void dm_test_enable_periodic_detection_no_workqueue(struct kunit *test)
2544 {
2545 	struct amdgpu_device *adev;
2546 	struct dc_context *ctx;
2547 
2548 	adev = dm_kunit_alloc_adev(test);
2549 
2550 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2551 	KUNIT_ASSERT_NOT_NULL(test, ctx);
2552 	ctx->driver_context = adev;
2553 
2554 	/* adev->dm.idle_workqueue is NULL → no-op, no crash */
2555 	dm_helpers_enable_periodic_detection(ctx, true);
2556 	KUNIT_EXPECT_TRUE(test, true);
2557 }
2558 
2559 /**
2560  * dm_test_enable_periodic_detection_updates_enable - Test idle work enable flag
2561  * @test: The KUnit test context
2562  *
2563  * Keeps idle_workqueue->running set so the helper only updates the enable flag
2564  * and does not queue the idle worker.
2565  */
dm_test_enable_periodic_detection_updates_enable(struct kunit * test)2566 static void dm_test_enable_periodic_detection_updates_enable(struct kunit *test)
2567 {
2568 	struct idle_workqueue *idle_work;
2569 	struct amdgpu_device *adev;
2570 	struct dc_context *ctx;
2571 
2572 	adev = dm_kunit_alloc_adev(test);
2573 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2574 	KUNIT_ASSERT_NOT_NULL(test, ctx);
2575 	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
2576 	KUNIT_ASSERT_NOT_NULL(test, idle_work);
2577 
2578 	ctx->driver_context = adev;
2579 	adev->dm.idle_workqueue = idle_work;
2580 	idle_work->running = true;
2581 
2582 	dm_helpers_enable_periodic_detection(ctx, true);
2583 	KUNIT_EXPECT_TRUE(test, idle_work->enable);
2584 
2585 	dm_helpers_enable_periodic_detection(ctx, false);
2586 	KUNIT_EXPECT_FALSE(test, idle_work->enable);
2587 }
2588 
2589 /**
2590  * dm_test_enable_periodic_detection_schedules_work - Test headless schedule path
2591  * @test: The KUnit test context
2592  */
dm_test_enable_periodic_detection_schedules_work(struct kunit * test)2593 static void dm_test_enable_periodic_detection_schedules_work(struct kunit *test)
2594 {
2595 	struct dm_test_idle_work *idle_work;
2596 	struct amdgpu_device *adev;
2597 	struct dc_context *ctx;
2598 
2599 	adev = dm_kunit_alloc_adev(test);
2600 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2601 	KUNIT_ASSERT_NOT_NULL(test, ctx);
2602 	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
2603 	KUNIT_ASSERT_NOT_NULL(test, idle_work);
2604 
2605 	ctx->driver_context = adev;
2606 	adev->dm.ddev = &adev->ddev;
2607 	adev->dm.idle_workqueue = &idle_work->base;
2608 	INIT_WORK(&idle_work->base.work, dm_test_idle_work_func);
2609 
2610 	dm_helpers_enable_periodic_detection(ctx, true);
2611 	flush_work(&idle_work->base.work);
2612 
2613 	KUNIT_EXPECT_TRUE(test, idle_work->base.enable);
2614 	KUNIT_EXPECT_TRUE(test, idle_work->ran);
2615 }
2616 
2617 /* Tests for dm_helpers_read_mccs_caps() */
2618 
2619 /**
2620  * dm_test_read_mccs_caps_null_ctx - Test early return with NULL context
2621  * @test: The KUnit test context
2622  */
dm_test_read_mccs_caps_null_ctx(struct kunit * test)2623 static void dm_test_read_mccs_caps_null_ctx(struct kunit *test)
2624 {
2625 	/* NULL ctx → early return, no crash */
2626 	dm_helpers_read_mccs_caps(NULL, NULL, NULL);
2627 	KUNIT_EXPECT_TRUE(test, true);
2628 }
2629 
2630 /**
2631  * dm_test_read_mccs_caps_null_link - Test early return with NULL link
2632  * @test: The KUnit test context
2633  */
dm_test_read_mccs_caps_null_link(struct kunit * test)2634 static void dm_test_read_mccs_caps_null_link(struct kunit *test)
2635 {
2636 	struct amdgpu_device *adev;
2637 	struct dc_context *ctx;
2638 	struct dc_sink *sink;
2639 
2640 	adev = dm_kunit_alloc_adev(test);
2641 
2642 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2643 	KUNIT_ASSERT_NOT_NULL(test, ctx);
2644 	ctx->driver_context = adev;
2645 	sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
2646 	KUNIT_ASSERT_NOT_NULL(test, sink);
2647 
2648 	/* link is NULL → drm_dbg_driver + return */
2649 	dm_helpers_read_mccs_caps(ctx, NULL, sink);
2650 	KUNIT_EXPECT_TRUE(test, true);
2651 }
2652 
2653 /**
2654  * dm_test_read_mccs_caps_no_vcp_code - Test no-vcp-code path clears freesync support
2655  * @test: The KUnit test context
2656  *
2657  * With freesync_vcp_code == 0 the i2c/MCCS path is skipped entirely and the
2658  * function only clears sink->mccs_caps.freesync_supported.
2659  */
dm_test_read_mccs_caps_no_vcp_code(struct kunit * test)2660 static void dm_test_read_mccs_caps_no_vcp_code(struct kunit *test)
2661 {
2662 	struct amdgpu_device *adev;
2663 	struct dc_context *ctx;
2664 	struct dc_link *link;
2665 	struct dc_sink *sink;
2666 
2667 	adev = dm_kunit_alloc_adev(test);
2668 
2669 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2670 	KUNIT_ASSERT_NOT_NULL(test, ctx);
2671 	ctx->driver_context = adev;
2672 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2673 	KUNIT_ASSERT_NOT_NULL(test, link);
2674 	sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
2675 	KUNIT_ASSERT_NOT_NULL(test, sink);
2676 
2677 	sink->edid_caps.freesync_vcp_code = 0;
2678 	sink->mccs_caps.freesync_supported = true; /* should be cleared */
2679 
2680 	dm_helpers_read_mccs_caps(ctx, link, sink);
2681 
2682 	KUNIT_EXPECT_FALSE(test, sink->mccs_caps.freesync_supported);
2683 }
2684 
2685 /*
2686  * Allocate and wire the adev/ctx/link/sink/connector/i2c objects shared by the
2687  * MCCS read/set tests so each test only configures the fields it exercises.
2688  */
2689 struct dm_test_mccs_fixture {
2690 	struct amdgpu_device *adev;
2691 	struct dc_context *ctx;
2692 	struct dc_link *link;
2693 	struct dc_sink *sink;
2694 	struct amdgpu_dm_connector *aconnector;
2695 	struct dm_test_mccs_i2c_adapter *fake;
2696 };
2697 
dm_test_alloc_mccs_fixture(struct kunit * test)2698 static struct dm_test_mccs_fixture dm_test_alloc_mccs_fixture(struct kunit *test)
2699 {
2700 	struct dm_test_mccs_fixture fixture;
2701 
2702 	fixture.adev = dm_kunit_alloc_adev(test);
2703 	KUNIT_ASSERT_NOT_NULL(test, fixture.adev);
2704 	fixture.ctx = kunit_kzalloc(test, sizeof(*fixture.ctx), GFP_KERNEL);
2705 	KUNIT_ASSERT_NOT_NULL(test, fixture.ctx);
2706 	fixture.link = kunit_kzalloc(test, sizeof(*fixture.link), GFP_KERNEL);
2707 	KUNIT_ASSERT_NOT_NULL(test, fixture.link);
2708 	fixture.sink = kunit_kzalloc(test, sizeof(*fixture.sink), GFP_KERNEL);
2709 	KUNIT_ASSERT_NOT_NULL(test, fixture.sink);
2710 	fixture.aconnector = kunit_kzalloc(test, sizeof(*fixture.aconnector), GFP_KERNEL);
2711 	KUNIT_ASSERT_NOT_NULL(test, fixture.aconnector);
2712 	fixture.fake = dm_test_alloc_mccs_i2c(test);
2713 
2714 	fixture.ctx->driver_context = fixture.adev;
2715 	fixture.aconnector->i2c = (struct amdgpu_i2c_adapter *)fixture.fake;
2716 	fixture.link->priv = fixture.aconnector;
2717 
2718 	return fixture;
2719 }
2720 
2721 /**
2722  * dm_test_read_mccs_caps_i2c_vcp_request - Test MCCS VCP request packet
2723  * @test: The KUnit test context
2724  */
dm_test_read_mccs_caps_i2c_vcp_request(struct kunit * test)2725 static void dm_test_read_mccs_caps_i2c_vcp_request(struct kunit *test)
2726 {
2727 	static const u8 expected_prefix[] = { 0x51, 0x82, 0x01, 0xe3 };
2728 	struct dm_test_mccs_fixture fixture = dm_test_alloc_mccs_fixture(test);
2729 	struct dm_test_mccs_i2c_adapter *fake = fixture.fake;
2730 	struct dc_context *ctx = fixture.ctx;
2731 	struct dc_link *link = fixture.link;
2732 	struct dc_sink *sink = fixture.sink;
2733 
2734 	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
2735 	link->dpcd_caps.dpcd_rev.raw = DP_DPCD_REV_14;
2736 	link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER;
2737 	link->dpcd_caps.branch_dev_id = DP_BRANCH_DEVICE_ID_0060AD;
2738 	link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT = 1;
2739 	sink->edid_caps.freesync_vcp_code = 0xe3;
2740 	fake->read_reply[1] = 0x82;
2741 	fake->read_reply[9] = 0x01;
2742 
2743 	dm_helpers_read_mccs_caps(ctx, link, sink);
2744 
2745 	KUNIT_EXPECT_TRUE(test, sink->mccs_caps.freesync_supported);
2746 	KUNIT_EXPECT_EQ(test, fake->writes, 1U);
2747 	KUNIT_EXPECT_EQ(test, fake->reads, 1U);
2748 	KUNIT_EXPECT_EQ(test, fake->write_len, (unsigned int)sizeof(expected_prefix) + 1);
2749 	KUNIT_EXPECT_EQ(test, memcmp(fake->write_data, expected_prefix,
2750 					     sizeof(expected_prefix)), 0);
2751 	KUNIT_EXPECT_EQ(test, fake->write_data[4],
2752 			dm_test_mccs_checksum(expected_prefix, sizeof(expected_prefix)));
2753 }
2754 
2755 /**
2756  * dm_test_read_mccs_caps_hdmi_vcp_request - Test local HDMI MCCS path
2757  * @test: The KUnit test context
2758  */
dm_test_read_mccs_caps_hdmi_vcp_request(struct kunit * test)2759 static void dm_test_read_mccs_caps_hdmi_vcp_request(struct kunit *test)
2760 {
2761 	struct dm_test_mccs_fixture fixture = dm_test_alloc_mccs_fixture(test);
2762 	struct dm_test_mccs_i2c_adapter *fake = fixture.fake;
2763 	struct dc_context *ctx = fixture.ctx;
2764 	struct dc_link *link = fixture.link;
2765 	struct dc_sink *sink = fixture.sink;
2766 
2767 	link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
2768 	sink->edid_caps.freesync_vcp_code = 0xe3;
2769 	fake->read_reply[1] = 0x82;
2770 	fake->read_reply[9] = 0x01;
2771 
2772 	dm_helpers_read_mccs_caps(ctx, link, sink);
2773 
2774 	KUNIT_EXPECT_TRUE(test, sink->mccs_caps.freesync_supported);
2775 	KUNIT_EXPECT_EQ(test, fake->writes, 1U);
2776 	KUNIT_EXPECT_EQ(test, fake->reads, 1U);
2777 }
2778 
2779 /**
2780  * dm_test_read_mccs_caps_legacy_pcon_vcp_request - Test legacy PCON path
2781  * @test: The KUnit test context
2782  */
dm_test_read_mccs_caps_legacy_pcon_vcp_request(struct kunit * test)2783 static void dm_test_read_mccs_caps_legacy_pcon_vcp_request(struct kunit *test)
2784 {
2785 	struct dm_test_mccs_fixture fixture = dm_test_alloc_mccs_fixture(test);
2786 	struct dm_test_mccs_i2c_adapter *fake = fixture.fake;
2787 	struct dc_context *ctx = fixture.ctx;
2788 	struct dc_link *link = fixture.link;
2789 	struct dc_sink *sink = fixture.sink;
2790 
2791 	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
2792 	link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
2793 	sink->edid_caps.freesync_vcp_code = 0xe3;
2794 	fake->read_reply[1] = 0x82;
2795 	fake->read_reply[9] = 0x01;
2796 
2797 	dm_helpers_read_mccs_caps(ctx, link, sink);
2798 
2799 	KUNIT_EXPECT_TRUE(test, sink->mccs_caps.freesync_supported);
2800 	KUNIT_EXPECT_EQ(test, fake->writes, 1U);
2801 	KUNIT_EXPECT_EQ(test, fake->reads, 1U);
2802 }
2803 
2804 /**
2805  * dm_test_read_mccs_caps_i2c_failure - Test VCP request retry failure
2806  * @test: The KUnit test context
2807  */
dm_test_read_mccs_caps_i2c_failure(struct kunit * test)2808 static void dm_test_read_mccs_caps_i2c_failure(struct kunit *test)
2809 {
2810 	struct dm_test_mccs_fixture fixture = dm_test_alloc_mccs_fixture(test);
2811 	struct dm_test_mccs_i2c_adapter *fake = fixture.fake;
2812 	struct dc_context *ctx = fixture.ctx;
2813 	struct dc_link *link = fixture.link;
2814 	struct dc_sink *sink = fixture.sink;
2815 
2816 	fixture.aconnector->base.dev = &fixture.adev->ddev;
2817 	link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
2818 	link->dpcd_caps.dpcd_rev.raw = DP_DPCD_REV_14;
2819 	link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_HDMI_CONVERTER;
2820 	link->dpcd_caps.branch_dev_id = DP_BRANCH_DEVICE_ID_0060AD;
2821 	link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.bits.ADAPTIVE_SYNC_SDP_SUPPORT = 1;
2822 	sink->edid_caps.freesync_vcp_code = 0xe3;
2823 	fake->write_ret = 0;
2824 
2825 	dm_helpers_read_mccs_caps(ctx, link, sink);
2826 
2827 	KUNIT_EXPECT_FALSE(test, sink->mccs_caps.freesync_supported);
2828 	KUNIT_EXPECT_EQ(test, fake->writes, 5U);
2829 	KUNIT_EXPECT_EQ(test, fake->reads, 0U);
2830 }
2831 
2832 /* Tests for dm_helpers_mccs_vcp_set() */
2833 
2834 /**
2835  * dm_test_mccs_vcp_set_null_ctx - Test early return with NULL context
2836  * @test: The KUnit test context
2837  */
dm_test_mccs_vcp_set_null_ctx(struct kunit * test)2838 static void dm_test_mccs_vcp_set_null_ctx(struct kunit *test)
2839 {
2840 	/* NULL ctx → early return, no crash */
2841 	dm_helpers_mccs_vcp_set(NULL, NULL, NULL);
2842 	KUNIT_EXPECT_TRUE(test, true);
2843 }
2844 
2845 /**
2846  * dm_test_mccs_vcp_set_not_supported - Test early return when freesync unsupported
2847  * @test: The KUnit test context
2848  */
dm_test_mccs_vcp_set_not_supported(struct kunit * test)2849 static void dm_test_mccs_vcp_set_not_supported(struct kunit *test)
2850 {
2851 	struct amdgpu_device *adev;
2852 	struct dc_context *ctx;
2853 	struct dc_link *link;
2854 	struct dc_sink *sink;
2855 
2856 	adev = dm_kunit_alloc_adev(test);
2857 
2858 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2859 	KUNIT_ASSERT_NOT_NULL(test, ctx);
2860 	ctx->driver_context = adev;
2861 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
2862 	KUNIT_ASSERT_NOT_NULL(test, link);
2863 	sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
2864 	KUNIT_ASSERT_NOT_NULL(test, sink);
2865 
2866 	sink->mccs_caps.freesync_supported = false;
2867 
2868 	/* freesync not supported → early return without i2c */
2869 	dm_helpers_mccs_vcp_set(ctx, link, sink);
2870 	KUNIT_EXPECT_TRUE(test, true);
2871 }
2872 
2873 /**
2874  * dm_test_mccs_vcp_set_null_link - Test early return with NULL link
2875  * @test: The KUnit test context
2876  */
dm_test_mccs_vcp_set_null_link(struct kunit * test)2877 static void dm_test_mccs_vcp_set_null_link(struct kunit *test)
2878 {
2879 	struct amdgpu_device *adev;
2880 	struct dc_context *ctx;
2881 	struct dc_sink *sink;
2882 
2883 	adev = dm_kunit_alloc_adev(test);
2884 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
2885 	KUNIT_ASSERT_NOT_NULL(test, ctx);
2886 	sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
2887 	KUNIT_ASSERT_NOT_NULL(test, sink);
2888 
2889 	ctx->driver_context = adev;
2890 	dm_helpers_mccs_vcp_set(ctx, NULL, sink);
2891 	KUNIT_EXPECT_TRUE(test, true);
2892 }
2893 
2894 /**
2895  * dm_test_mccs_vcp_set_i2c_packet - Test MCCS VCP set packet
2896  * @test: The KUnit test context
2897  */
dm_test_mccs_vcp_set_i2c_packet(struct kunit * test)2898 static void dm_test_mccs_vcp_set_i2c_packet(struct kunit *test)
2899 {
2900 	static const u8 expected_prefix[] = {
2901 		0x51, 0x84, 0x03, 0xe3, 0x01, 0x01,
2902 	};
2903 	struct dm_test_mccs_fixture fixture = dm_test_alloc_mccs_fixture(test);
2904 	struct dm_test_mccs_i2c_adapter *fake = fixture.fake;
2905 	struct dc_context *ctx = fixture.ctx;
2906 	struct dc_link *link = fixture.link;
2907 	struct dc_sink *sink = fixture.sink;
2908 
2909 	sink->mccs_caps.freesync_supported = true;
2910 	sink->edid_caps.freesync_vcp_code = 0xe3;
2911 
2912 	dm_helpers_mccs_vcp_set(ctx, link, sink);
2913 
2914 	KUNIT_EXPECT_EQ(test, fake->writes, 1U);
2915 	KUNIT_EXPECT_EQ(test, fake->reads, 0U);
2916 	KUNIT_EXPECT_EQ(test, fake->write_len, (unsigned int)sizeof(expected_prefix) + 1);
2917 	KUNIT_EXPECT_EQ(test, memcmp(fake->write_data, expected_prefix,
2918 					     sizeof(expected_prefix)), 0);
2919 	KUNIT_EXPECT_EQ(test, fake->write_data[6],
2920 			dm_test_mccs_checksum(expected_prefix, sizeof(expected_prefix)));
2921 }
2922 
2923 /**
2924  * dm_test_mccs_vcp_set_i2c_failure - Test VCP set retry failure path
2925  * @test: The KUnit test context
2926  */
dm_test_mccs_vcp_set_i2c_failure(struct kunit * test)2927 static void dm_test_mccs_vcp_set_i2c_failure(struct kunit *test)
2928 {
2929 	struct dm_test_mccs_fixture fixture = dm_test_alloc_mccs_fixture(test);
2930 	struct dm_test_mccs_i2c_adapter *fake = fixture.fake;
2931 	struct dc_context *ctx = fixture.ctx;
2932 	struct dc_link *link = fixture.link;
2933 	struct dc_sink *sink = fixture.sink;
2934 
2935 	sink->mccs_caps.freesync_supported = true;
2936 	sink->edid_caps.freesync_vcp_code = 0xe3;
2937 	fake->write_ret = 0;
2938 
2939 	dm_helpers_mccs_vcp_set(ctx, link, sink);
2940 
2941 	KUNIT_EXPECT_EQ(test, fake->writes, 5U);
2942 	KUNIT_EXPECT_EQ(test, fake->reads, 0U);
2943 }
2944 
2945 /* Tests for dm_helpers_construct_old_payload() */
2946 
2947 /**
2948  * dm_test_construct_old_payload_empty_list - Test PBN/time-slot calc, empty list
2949  * @test: The KUnit test context
2950  *
2951  * With no other payloads, next_payload_vc_start stays at mgr->next_start_slot,
2952  * so allocated time_slots = next_start_slot - vc_start_slot.
2953  */
dm_test_construct_old_payload_empty_list(struct kunit * test)2954 static void dm_test_construct_old_payload_empty_list(struct kunit *test)
2955 {
2956 	struct drm_dp_mst_topology_mgr *mgr;
2957 	struct drm_dp_mst_topology_state *mst_state;
2958 	struct drm_dp_mst_atomic_payload *new_payload;
2959 	struct drm_dp_mst_atomic_payload *old_payload;
2960 
2961 	mgr = kunit_kzalloc(test, sizeof(*mgr), GFP_KERNEL);
2962 	KUNIT_ASSERT_NOT_NULL(test, mgr);
2963 	mst_state = kunit_kzalloc(test, sizeof(*mst_state), GFP_KERNEL);
2964 	KUNIT_ASSERT_NOT_NULL(test, mst_state);
2965 	new_payload = kunit_kzalloc(test, sizeof(*new_payload), GFP_KERNEL);
2966 	KUNIT_ASSERT_NOT_NULL(test, new_payload);
2967 	old_payload = kunit_kzalloc(test, sizeof(*old_payload), GFP_KERNEL);
2968 	KUNIT_ASSERT_NOT_NULL(test, old_payload);
2969 
2970 	INIT_LIST_HEAD(&mst_state->payloads);
2971 	mgr->next_start_slot = 10;
2972 	mst_state->pbn_div.full = 5 << 12;	/* dfixed_trunc → 5 PBN/slot */
2973 	new_payload->vc_start_slot = 3;
2974 
2975 	dm_helpers_construct_old_payload(mgr, mst_state, new_payload,
2976 					 old_payload);
2977 
2978 	/* 10 - 3 = 7 slots, 7 * 5 = 35 PBN */
2979 	KUNIT_EXPECT_EQ(test, old_payload->time_slots, 7);
2980 	KUNIT_EXPECT_EQ(test, old_payload->pbn, 35);
2981 }
2982 
2983 /**
2984  * dm_test_construct_old_payload_intervening - Test calc with an intervening payload
2985  * @test: The KUnit test context
2986  *
2987  * A payload whose vc_start_slot falls between the new payload and the manager's
2988  * next_start_slot narrows the allocated time-slot window.
2989  */
dm_test_construct_old_payload_intervening(struct kunit * test)2990 static void dm_test_construct_old_payload_intervening(struct kunit *test)
2991 {
2992 	struct drm_dp_mst_topology_mgr *mgr;
2993 	struct drm_dp_mst_topology_state *mst_state;
2994 	struct drm_dp_mst_atomic_payload *new_payload;
2995 	struct drm_dp_mst_atomic_payload *other_payload;
2996 	struct drm_dp_mst_atomic_payload *old_payload;
2997 
2998 	mgr = kunit_kzalloc(test, sizeof(*mgr), GFP_KERNEL);
2999 	KUNIT_ASSERT_NOT_NULL(test, mgr);
3000 	mst_state = kunit_kzalloc(test, sizeof(*mst_state), GFP_KERNEL);
3001 	KUNIT_ASSERT_NOT_NULL(test, mst_state);
3002 	new_payload = kunit_kzalloc(test, sizeof(*new_payload), GFP_KERNEL);
3003 	KUNIT_ASSERT_NOT_NULL(test, new_payload);
3004 	other_payload = kunit_kzalloc(test, sizeof(*other_payload), GFP_KERNEL);
3005 	KUNIT_ASSERT_NOT_NULL(test, other_payload);
3006 	old_payload = kunit_kzalloc(test, sizeof(*old_payload), GFP_KERNEL);
3007 	KUNIT_ASSERT_NOT_NULL(test, old_payload);
3008 
3009 	INIT_LIST_HEAD(&mst_state->payloads);
3010 	mgr->next_start_slot = 10;
3011 	mst_state->pbn_div.full = 5 << 12;
3012 	new_payload->vc_start_slot = 3;
3013 
3014 	/* other payload at slot 6 (between 3 and 10) narrows window to 6 */
3015 	other_payload->vc_start_slot = 6;
3016 	list_add_tail(&other_payload->next, &mst_state->payloads);
3017 
3018 	dm_helpers_construct_old_payload(mgr, mst_state, new_payload,
3019 					 old_payload);
3020 
3021 	/* 6 - 3 = 3 slots, 3 * 5 = 15 PBN */
3022 	KUNIT_EXPECT_EQ(test, old_payload->time_slots, 3);
3023 	KUNIT_EXPECT_EQ(test, old_payload->pbn, 15);
3024 }
3025 
3026 /* Tests for dm_helpers_dp_mst_write_payload_allocation_table() success path */
3027 
3028 /**
3029  * dm_test_write_payload_alloc_table_success - Exercise the MST success path
3030  * @test: The KUnit test context
3031  * @enable: true for the add-payload path, false for the remove-payload path
3032  *
3033  * Builds a minimal MST topology-state fixture so the helper traverses past the
3034  * early NULL checks and runs the real DRM MST payload helpers
3035  * (drm_dp_add_payload_part1 / drm_dp_remove_payload_part1). With
3036  * mgr->mst_primary == NULL the topology walk fails gracefully, so no remote
3037  * DPCD/AUX traffic is generated, and the helper still returns true.
3038  */
dm_test_write_payload_alloc_table_success(struct kunit * test,bool enable)3039 static void dm_test_write_payload_alloc_table_success(struct kunit *test,
3040 						      bool enable)
3041 {
3042 	struct amdgpu_device *adev;
3043 	struct amdgpu_dm_connector *aconnector;
3044 	struct drm_dp_mst_topology_mgr *mgr;
3045 	struct drm_dp_mst_topology_state *mst_state;
3046 	struct drm_dp_mst_atomic_payload *payload;
3047 	struct drm_dp_mst_port *port;
3048 	struct dc_stream_state *stream;
3049 	struct dc_link *link;
3050 	struct dc_dp_mst_stream_allocation_table table = { 0 };
3051 	bool ret;
3052 
3053 	adev = dm_kunit_alloc_adev(test);
3054 	KUNIT_ASSERT_NOT_NULL(test, adev);
3055 
3056 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3057 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3058 	mst_state = kunit_kzalloc(test, sizeof(*mst_state), GFP_KERNEL);
3059 	KUNIT_ASSERT_NOT_NULL(test, mst_state);
3060 	payload = kunit_kzalloc(test, sizeof(*payload), GFP_KERNEL);
3061 	KUNIT_ASSERT_NOT_NULL(test, payload);
3062 	port = kunit_kzalloc(test, sizeof(*port), GFP_KERNEL);
3063 	KUNIT_ASSERT_NOT_NULL(test, port);
3064 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3065 	KUNIT_ASSERT_NOT_NULL(test, stream);
3066 	link = kunit_kzalloc(test, sizeof(*link), GFP_KERNEL);
3067 	KUNIT_ASSERT_NOT_NULL(test, link);
3068 
3069 	/* aconnector acts as its own MST root for this fixture */
3070 	aconnector->mst_root = aconnector;
3071 	aconnector->mst_output_port = port;
3072 
3073 	mgr = &aconnector->mst_mgr;
3074 	mutex_init(&mgr->lock);
3075 	mgr->dev = &adev->ddev;
3076 	mgr->mst_primary = NULL;		/* topology walk fails gracefully */
3077 	mgr->base.state = &mst_state->base;
3078 
3079 	INIT_LIST_HEAD(&mst_state->payloads);
3080 	mst_state->pbn_div.full = 5 << 12;	/* dfixed_trunc → 5 PBN/slot */
3081 
3082 	/* payload found by drm_atomic_get_mst_payload_state via matching port */
3083 	payload->port = port;
3084 	payload->vcpi = 1;
3085 	payload->vc_start_slot = 1;
3086 	payload->time_slots = 2;
3087 	list_add_tail(&payload->next, &mst_state->payloads);
3088 
3089 	/* pre-existing HW allocation so the disable path finds a VCPI to clear */
3090 	link->mst_stream_alloc_table.stream_count = 1;
3091 	link->mst_stream_alloc_table.stream_allocations[0].vcp_id = 1;
3092 	link->mst_stream_alloc_table.stream_allocations[0].slot_count = 2;
3093 
3094 	stream->dm_stream_context = aconnector;
3095 	stream->link = link;
3096 
3097 	ret = dm_helpers_dp_mst_write_payload_allocation_table(NULL, stream,
3098 							       &table, enable);
3099 
3100 	KUNIT_EXPECT_TRUE(test, ret);
3101 
3102 	if (enable)
3103 		/* add path keeps the old entry and appends the new payload */
3104 		KUNIT_EXPECT_EQ(test, table.stream_count, 2);
3105 	else
3106 		/* remove path clears the only entry */
3107 		KUNIT_EXPECT_EQ(test, table.stream_count, 0);
3108 }
3109 
3110 /**
3111  * dm_test_write_payload_alloc_table_enable - Test add-payload success path
3112  * @test: The KUnit test context
3113  */
dm_test_write_payload_alloc_table_enable(struct kunit * test)3114 static void dm_test_write_payload_alloc_table_enable(struct kunit *test)
3115 {
3116 	dm_test_write_payload_alloc_table_success(test, true);
3117 }
3118 
3119 /**
3120  * dm_test_write_payload_alloc_table_disable - Test remove-payload success path
3121  * @test: The KUnit test context
3122  */
dm_test_write_payload_alloc_table_disable(struct kunit * test)3123 static void dm_test_write_payload_alloc_table_disable(struct kunit *test)
3124 {
3125 	dm_test_write_payload_alloc_table_success(test, false);
3126 }
3127 
3128 /* Tests for dm_helpers_dp_mst_poll_for_allocation_change_trigger() */
3129 
3130 /*
3131  * Stub AUX transfer that ACKs a DPCD read of the payload-table update status
3132  * with the ACT-handled bit set, so drm_dp_check_act_status() returns 0.
3133  */
dm_test_act_aux_transfer_handled(struct drm_dp_aux * aux,struct drm_dp_aux_msg * msg)3134 static ssize_t dm_test_act_aux_transfer_handled(struct drm_dp_aux *aux,
3135 						struct drm_dp_aux_msg *msg)
3136 {
3137 	if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ) {
3138 		memset(msg->buffer, 0, msg->size);
3139 		if (msg->size > 0)
3140 			((u8 *)msg->buffer)[0] = DP_PAYLOAD_ACT_HANDLED;
3141 	}
3142 	msg->reply = DP_AUX_NATIVE_REPLY_ACK;
3143 	return msg->size;
3144 }
3145 
3146 /*
3147  * Stub AUX transfer that fails every transaction, so the ACT status read
3148  * returns an error and drm_dp_check_act_status() returns non-zero.
3149  */
dm_test_act_aux_transfer_fail(struct drm_dp_aux * aux,struct drm_dp_aux_msg * msg)3150 static ssize_t dm_test_act_aux_transfer_fail(struct drm_dp_aux *aux,
3151 					     struct drm_dp_aux_msg *msg)
3152 {
3153 	return -EIO;
3154 }
3155 
3156 /**
3157  * dm_test_mst_start_top_mgr_set_mst_fail - Test MST start failure path
3158  * @test: The KUnit test context
3159  *
3160  * With a connector-backed link and a failing AUX channel, the non-boot
3161  * path calls drm_dp_mst_topology_mgr_set_mst(true), which fails to read the
3162  * DPCD caps and returns a negative error, so the helper returns false.
3163  */
dm_test_mst_start_top_mgr_set_mst_fail(struct kunit * test)3164 static void dm_test_mst_start_top_mgr_set_mst_fail(struct kunit *test)
3165 {
3166 	struct amdgpu_device *adev;
3167 	struct amdgpu_dm_connector *aconnector;
3168 	struct drm_dp_aux *aux;
3169 	struct dc_link *link;
3170 
3171 	adev = dm_kunit_alloc_adev(test);
3172 	KUNIT_ASSERT_NOT_NULL(test, adev);
3173 
3174 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3175 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3176 	aux = kunit_kzalloc(test, sizeof(*aux), GFP_KERNEL);
3177 	KUNIT_ASSERT_NOT_NULL(test, aux);
3178 	link = dm_kunit_alloc_link(test);
3179 
3180 	aux->drm_dev = &adev->ddev;
3181 	aux->transfer = dm_test_act_aux_transfer_fail;
3182 	drm_dp_aux_init(aux);
3183 
3184 	mutex_init(&aconnector->mst_mgr.lock);
3185 	aconnector->mst_mgr.dev = &adev->ddev;
3186 	aconnector->mst_mgr.aux = aux;
3187 	link->priv = aconnector;
3188 
3189 	KUNIT_EXPECT_FALSE(test, dm_helpers_dp_mst_start_top_mgr(NULL, link, false));
3190 }
3191 
3192 /**
3193  * dm_test_mst_stop_top_mgr_active - Test MST stop on an active topology manager
3194  * @test: The KUnit test context
3195  *
3196  * With mst_state set, the helper calls drm_dp_mst_topology_mgr_set_mst(false)
3197  * to disable MST and clears the link lane count. The helper always returns
3198  * false.
3199  */
dm_test_mst_stop_top_mgr_active(struct kunit * test)3200 static void dm_test_mst_stop_top_mgr_active(struct kunit *test)
3201 {
3202 	struct amdgpu_device *adev;
3203 	struct amdgpu_dm_connector *aconnector;
3204 	struct drm_dp_aux *aux;
3205 	struct dc_link *link;
3206 
3207 	adev = dm_kunit_alloc_adev(test);
3208 	KUNIT_ASSERT_NOT_NULL(test, adev);
3209 
3210 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3211 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3212 	aux = kunit_kzalloc(test, sizeof(*aux), GFP_KERNEL);
3213 	KUNIT_ASSERT_NOT_NULL(test, aux);
3214 	link = dm_kunit_alloc_link(test);
3215 
3216 	aux->drm_dev = &adev->ddev;
3217 	aux->transfer = dm_test_act_aux_transfer_handled;
3218 	drm_dp_aux_init(aux);
3219 
3220 	mutex_init(&aconnector->mst_mgr.lock);
3221 	aconnector->mst_mgr.dev = &adev->ddev;
3222 	aconnector->mst_mgr.aux = aux;
3223 	aconnector->mst_mgr.mst_state = true;
3224 	link->cur_link_settings.lane_count = 4;
3225 	link->priv = aconnector;
3226 
3227 	KUNIT_EXPECT_FALSE(test, dm_helpers_dp_mst_stop_top_mgr(NULL, link));
3228 	KUNIT_EXPECT_EQ(test, link->cur_link_settings.lane_count, 0);
3229 }
3230 
3231 /**
3232  * dm_test_poll_for_act_no_mst_state - Test ACT poll bails when MST not started
3233  * @test: The KUnit test context
3234  *
3235  * With mst_root set but mst_mgr->mst_state false, the helper returns
3236  * ACT_FAILED before touching the AUX channel.
3237  */
dm_test_poll_for_act_no_mst_state(struct kunit * test)3238 static void dm_test_poll_for_act_no_mst_state(struct kunit *test)
3239 {
3240 	struct amdgpu_dm_connector *aconnector;
3241 	struct dc_stream_state *stream;
3242 
3243 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3244 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3245 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3246 	KUNIT_ASSERT_NOT_NULL(test, stream);
3247 
3248 	aconnector->mst_root = aconnector;
3249 	aconnector->mst_mgr.mst_state = false;
3250 	stream->dm_stream_context = aconnector;
3251 
3252 	KUNIT_EXPECT_EQ(test,
3253 			(int)dm_helpers_dp_mst_poll_for_allocation_change_trigger(NULL, stream),
3254 			(int)ACT_FAILED);
3255 }
3256 
3257 /**
3258  * dm_test_poll_for_act_success - Test ACT poll success path
3259  * @test: The KUnit test context
3260  *
3261  * With MST started and the AUX channel reporting ACT handled,
3262  * drm_dp_check_act_status() returns 0 and the helper returns ACT_SUCCESS.
3263  */
dm_test_poll_for_act_success(struct kunit * test)3264 static void dm_test_poll_for_act_success(struct kunit *test)
3265 {
3266 	struct amdgpu_device *adev;
3267 	struct amdgpu_dm_connector *aconnector;
3268 	struct drm_dp_aux *aux;
3269 	struct dc_stream_state *stream;
3270 
3271 	adev = dm_kunit_alloc_adev(test);
3272 	KUNIT_ASSERT_NOT_NULL(test, adev);
3273 
3274 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3275 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3276 	aux = kunit_kzalloc(test, sizeof(*aux), GFP_KERNEL);
3277 	KUNIT_ASSERT_NOT_NULL(test, aux);
3278 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3279 	KUNIT_ASSERT_NOT_NULL(test, stream);
3280 
3281 	aux->drm_dev = &adev->ddev;
3282 	aux->transfer = dm_test_act_aux_transfer_handled;
3283 	drm_dp_aux_init(aux);
3284 
3285 	aconnector->mst_root = aconnector;
3286 	aconnector->mst_mgr.mst_state = true;
3287 	aconnector->mst_mgr.aux = aux;
3288 	stream->dm_stream_context = aconnector;
3289 
3290 	KUNIT_EXPECT_EQ(test,
3291 			(int)dm_helpers_dp_mst_poll_for_allocation_change_trigger(NULL, stream),
3292 			(int)ACT_SUCCESS);
3293 }
3294 
3295 /**
3296  * dm_test_poll_for_act_status_failed - Test ACT poll failure path
3297  * @test: The KUnit test context
3298  *
3299  * With MST started but the AUX channel failing, drm_dp_check_act_status()
3300  * returns non-zero and the helper returns ACT_FAILED.
3301  */
dm_test_poll_for_act_status_failed(struct kunit * test)3302 static void dm_test_poll_for_act_status_failed(struct kunit *test)
3303 {
3304 	struct amdgpu_device *adev;
3305 	struct amdgpu_dm_connector *aconnector;
3306 	struct drm_dp_aux *aux;
3307 	struct dc_stream_state *stream;
3308 
3309 	adev = dm_kunit_alloc_adev(test);
3310 	KUNIT_ASSERT_NOT_NULL(test, adev);
3311 
3312 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3313 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3314 	aux = kunit_kzalloc(test, sizeof(*aux), GFP_KERNEL);
3315 	KUNIT_ASSERT_NOT_NULL(test, aux);
3316 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3317 	KUNIT_ASSERT_NOT_NULL(test, stream);
3318 
3319 	aux->drm_dev = &adev->ddev;
3320 	aux->transfer = dm_test_act_aux_transfer_fail;
3321 	drm_dp_aux_init(aux);
3322 
3323 	aconnector->mst_root = aconnector;
3324 	aconnector->mst_mgr.mst_state = true;
3325 	aconnector->mst_mgr.aux = aux;
3326 	stream->dm_stream_context = aconnector;
3327 
3328 	KUNIT_EXPECT_EQ(test,
3329 			(int)dm_helpers_dp_mst_poll_for_allocation_change_trigger(NULL, stream),
3330 			(int)ACT_FAILED);
3331 }
3332 
3333 /* Tests for dm_helpers_dp_mst_send_payload_allocation() */
3334 
3335 /**
3336  * dm_test_mst_send_payload_alloc_part2_fail - Exercise the failure branch
3337  * @test: The KUnit test context
3338  *
3339  * Builds a minimal MST topology-state fixture so the helper runs past the early
3340  * NULL checks and calls drm_dp_add_payload_part2(). The payload's allocation
3341  * status is left at its default (not DRM_DP_MST_PAYLOAD_ALLOCATION_DFP), so
3342  * drm_dp_add_payload_part2() returns -EIO without any remote DPCD/AUX traffic.
3343  * The non-zero return drives the failure branch, which clears the
3344  * MST_ALLOCATE_NEW_PAYLOAD status bit.
3345  */
dm_test_mst_send_payload_alloc_part2_fail(struct kunit * test)3346 static void dm_test_mst_send_payload_alloc_part2_fail(struct kunit *test)
3347 {
3348 	struct amdgpu_device *adev;
3349 	struct amdgpu_dm_connector *aconnector;
3350 	struct drm_dp_mst_topology_mgr *mgr;
3351 	struct drm_dp_mst_topology_state *mst_state;
3352 	struct drm_dp_mst_atomic_payload *payload;
3353 	struct drm_dp_mst_port *port;
3354 	struct dc_stream_state *stream;
3355 
3356 	adev = dm_kunit_alloc_adev(test);
3357 	KUNIT_ASSERT_NOT_NULL(test, adev);
3358 
3359 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3360 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3361 	mst_state = kunit_kzalloc(test, sizeof(*mst_state), GFP_KERNEL);
3362 	KUNIT_ASSERT_NOT_NULL(test, mst_state);
3363 	payload = kunit_kzalloc(test, sizeof(*payload), GFP_KERNEL);
3364 	KUNIT_ASSERT_NOT_NULL(test, payload);
3365 	port = kunit_kzalloc(test, sizeof(*port), GFP_KERNEL);
3366 	KUNIT_ASSERT_NOT_NULL(test, port);
3367 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3368 	KUNIT_ASSERT_NOT_NULL(test, stream);
3369 
3370 	/* aconnector acts as its own MST root for this fixture */
3371 	aconnector->mst_root = aconnector;
3372 	aconnector->mst_output_port = port;
3373 	/* drm_dp_add_payload_part2() logs port->connector->name on failure */
3374 	port->connector = &aconnector->base;
3375 
3376 	mgr = &aconnector->mst_mgr;
3377 	mgr->dev = &adev->ddev;
3378 	mgr->base.state = &mst_state->base;
3379 
3380 	INIT_LIST_HEAD(&mst_state->payloads);
3381 
3382 	/* payload found by drm_atomic_get_mst_payload_state via matching port */
3383 	payload->port = port;
3384 	list_add_tail(&payload->next, &mst_state->payloads);
3385 
3386 	/* pre-set the bit so we can observe it being cleared on failure */
3387 	aconnector->mst_status = MST_ALLOCATE_NEW_PAYLOAD;
3388 
3389 	stream->dm_stream_context = aconnector;
3390 	dm_helpers_dp_mst_send_payload_allocation(NULL, stream);
3391 
3392 	KUNIT_EXPECT_EQ(test,
3393 			aconnector->mst_status & MST_ALLOCATE_NEW_PAYLOAD, 0);
3394 }
3395 
3396 /* Tests for dm_helpers_dp_mst_update_mst_mgr_for_deallocation() */
3397 
3398 /**
3399  * dm_test_mst_update_mgr_dealloc_success - Exercise the deallocation path
3400  * @test: The KUnit test context
3401  *
3402  * Builds a minimal MST topology-state fixture so the helper runs past the early
3403  * NULL checks through dm_helpers_construct_old_payload() and
3404  * drm_dp_remove_payload_part2(), both of which are pure list/slot math with no
3405  * remote DPCD/AUX traffic. Afterwards MST_CLEAR_ALLOCATED_PAYLOAD must be set,
3406  * MST_ALLOCATE_NEW_PAYLOAD cleared, and the payload's slot released.
3407  */
dm_test_mst_update_mgr_dealloc_success(struct kunit * test)3408 static void dm_test_mst_update_mgr_dealloc_success(struct kunit *test)
3409 {
3410 	struct amdgpu_dm_connector *aconnector;
3411 	struct drm_dp_mst_topology_mgr *mgr;
3412 	struct drm_dp_mst_topology_state *mst_state;
3413 	struct drm_dp_mst_atomic_payload *payload;
3414 	struct drm_dp_mst_port *port;
3415 	struct dc_stream_state *stream;
3416 
3417 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3418 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3419 	mst_state = kunit_kzalloc(test, sizeof(*mst_state), GFP_KERNEL);
3420 	KUNIT_ASSERT_NOT_NULL(test, mst_state);
3421 	payload = kunit_kzalloc(test, sizeof(*payload), GFP_KERNEL);
3422 	KUNIT_ASSERT_NOT_NULL(test, payload);
3423 	port = kunit_kzalloc(test, sizeof(*port), GFP_KERNEL);
3424 	KUNIT_ASSERT_NOT_NULL(test, port);
3425 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3426 	KUNIT_ASSERT_NOT_NULL(test, stream);
3427 
3428 	/* aconnector acts as its own MST root for this fixture */
3429 	aconnector->mst_root = aconnector;
3430 	aconnector->mst_output_port = port;
3431 
3432 	mgr = &aconnector->mst_mgr;
3433 	mgr->base.state = &mst_state->base;
3434 	mgr->next_start_slot = 10;
3435 	mgr->payload_count = 1;
3436 
3437 	INIT_LIST_HEAD(&mst_state->payloads);
3438 	mst_state->pbn_div.full = 5 << 12;	/* dfixed_trunc → 5 PBN/slot */
3439 
3440 	/* payload found by drm_atomic_get_mst_payload_state via matching port */
3441 	payload->port = port;
3442 	payload->vc_start_slot = 3;
3443 	payload->time_slots = 7;
3444 	list_add_tail(&payload->next, &mst_state->payloads);
3445 
3446 	/* pre-set the bit so we can observe it being cleared */
3447 	aconnector->mst_status = MST_ALLOCATE_NEW_PAYLOAD;
3448 
3449 	stream->dm_stream_context = aconnector;
3450 	dm_helpers_dp_mst_update_mst_mgr_for_deallocation(NULL, stream);
3451 
3452 	KUNIT_EXPECT_EQ(test,
3453 			aconnector->mst_status & MST_CLEAR_ALLOCATED_PAYLOAD,
3454 			(int)MST_CLEAR_ALLOCATED_PAYLOAD);
3455 	KUNIT_EXPECT_EQ(test,
3456 			aconnector->mst_status & MST_ALLOCATE_NEW_PAYLOAD, 0);
3457 	/* drm_dp_remove_payload_part2() releases the payload's slot */
3458 	KUNIT_EXPECT_EQ(test, payload->vc_start_slot, -1);
3459 }
3460 
3461 /* Tests for dm_helpers_dp_write_dsc_enable() */
3462 
3463 /**
3464  * dm_test_dp_write_dsc_enable_mst_no_aux - Test MST early return without dsc_aux
3465  * @test: The KUnit test context
3466  */
dm_test_dp_write_dsc_enable_mst_no_aux(struct kunit * test)3467 static void dm_test_dp_write_dsc_enable_mst_no_aux(struct kunit *test)
3468 {
3469 	struct amdgpu_dm_connector *aconnector;
3470 	struct dc_stream_state *stream;
3471 
3472 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3473 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3474 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3475 	KUNIT_ASSERT_NOT_NULL(test, stream);
3476 
3477 	stream->dm_stream_context = aconnector;
3478 	stream->signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
3479 	aconnector->dsc_aux = NULL;
3480 
3481 	/* MST signal with NULL dsc_aux → return false */
3482 	KUNIT_EXPECT_FALSE(test, dm_helpers_dp_write_dsc_enable(NULL, stream, true));
3483 }
3484 
3485 /**
3486  * dm_test_dp_write_dsc_enable_non_dp - Test non-DP signal returns false
3487  * @test: The KUnit test context
3488  *
3489  * For an HDMI signal neither the MST nor the DP/eDP block runs, so ret stays 0.
3490  */
dm_test_dp_write_dsc_enable_non_dp(struct kunit * test)3491 static void dm_test_dp_write_dsc_enable_non_dp(struct kunit *test)
3492 {
3493 	struct amdgpu_dm_connector *aconnector;
3494 	struct dc_stream_state *stream;
3495 
3496 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3497 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3498 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3499 	KUNIT_ASSERT_NOT_NULL(test, stream);
3500 
3501 	stream->dm_stream_context = aconnector;
3502 	stream->signal = SIGNAL_TYPE_HDMI_TYPE_A;
3503 
3504 	/* Non-DP/MST signal → no DPCD write, ret stays 0 (false) */
3505 	KUNIT_EXPECT_FALSE(test, dm_helpers_dp_write_dsc_enable(NULL, stream, true));
3506 }
3507 
3508 struct dm_test_dsc_aux_pair {
3509 	struct dm_test_synaptics_aux *main;
3510 	struct dm_test_synaptics_aux *passthrough;
3511 };
3512 
dm_test_alloc_dsc_connector(struct kunit * test,struct dc_link * link)3513 static struct amdgpu_dm_connector *dm_test_alloc_dsc_connector(struct kunit *test,
3514 						       struct dc_link *link)
3515 {
3516 	struct amdgpu_dm_connector *aconnector;
3517 
3518 	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
3519 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
3520 	aconnector->dc_link = link;
3521 
3522 	return aconnector;
3523 }
3524 
dm_test_alloc_dsc_stream(struct kunit * test,struct dc_link * link,enum signal_type signal)3525 static struct dc_stream_state *dm_test_alloc_dsc_stream(struct kunit *test,
3526 						       struct dc_link *link,
3527 						       enum signal_type signal)
3528 {
3529 	struct dc_stream_state *stream;
3530 	struct dc_sink *sink;
3531 
3532 	stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
3533 	KUNIT_ASSERT_NOT_NULL(test, stream);
3534 	sink = kunit_kzalloc(test, sizeof(*sink), GFP_KERNEL);
3535 	KUNIT_ASSERT_NOT_NULL(test, sink);
3536 
3537 	stream->link = link;
3538 	stream->signal = signal;
3539 	stream->sink = sink;
3540 	sink->link = link;
3541 
3542 	return stream;
3543 }
3544 
dm_test_dp_write_dsc_enable_mst(struct kunit * test,bool enable,bool passthrough)3545 static struct dm_test_dsc_aux_pair dm_test_dp_write_dsc_enable_mst(struct kunit *test,
3546 							   bool enable,
3547 							   bool passthrough)
3548 {
3549 	struct dm_test_dsc_aux_pair aux_pair;
3550 	struct amdgpu_dm_connector *aconnector;
3551 	struct drm_dp_mst_port *port;
3552 	struct dc_stream_state *stream;
3553 	struct dc_link *link;
3554 	bool ret;
3555 
3556 	link = dm_kunit_alloc_link(test);
3557 	aconnector = dm_test_alloc_dsc_connector(test, link);
3558 	stream = dm_test_alloc_dsc_stream(test, link, SIGNAL_TYPE_DISPLAY_PORT_MST);
3559 	port = kunit_kzalloc(test, sizeof(*port), GFP_KERNEL);
3560 	KUNIT_ASSERT_NOT_NULL(test, port);
3561 	aux_pair.main = dm_test_alloc_synaptics_aux_with_dev(test, NULL);
3562 	aux_pair.passthrough = dm_test_alloc_synaptics_aux_with_dev(test, NULL);
3563 
3564 	stream->dm_stream_context = aconnector;
3565 	aconnector->dsc_aux = &aux_pair.main->aux;
3566 	aconnector->mst_output_port = port;
3567 	if (passthrough)
3568 		port->passthrough_aux = &aux_pair.passthrough->aux;
3569 
3570 	ret = dm_helpers_dp_write_dsc_enable(NULL, stream, enable);
3571 
3572 	KUNIT_EXPECT_TRUE(test, ret);
3573 	KUNIT_EXPECT_EQ(test, aux_pair.main->dsc_enable_writes, 1U);
3574 	KUNIT_EXPECT_EQ(test, aux_pair.main->dsc_enable_values[0], enable ? 1 : 0);
3575 	KUNIT_EXPECT_EQ(test, aux_pair.passthrough->dsc_enable_writes,
3576 			 passthrough ? 1U : 0U);
3577 	if (passthrough)
3578 		KUNIT_EXPECT_EQ(test, aux_pair.passthrough->dsc_enable_values[0], enable ? 2 : 0);
3579 
3580 	return aux_pair;
3581 }
3582 
3583 /**
3584  * dm_test_dp_write_dsc_enable_mst_enable_decode_only - Test MST enable decoding write
3585  * @test: The KUnit test context
3586  */
dm_test_dp_write_dsc_enable_mst_enable_decode_only(struct kunit * test)3587 static void dm_test_dp_write_dsc_enable_mst_enable_decode_only(struct kunit *test)
3588 {
3589 	dm_test_dp_write_dsc_enable_mst(test, true, false);
3590 }
3591 
3592 /**
3593  * dm_test_dp_write_dsc_enable_mst_enable_passthrough - Test MST enable passthrough write
3594  * @test: The KUnit test context
3595  */
dm_test_dp_write_dsc_enable_mst_enable_passthrough(struct kunit * test)3596 static void dm_test_dp_write_dsc_enable_mst_enable_passthrough(struct kunit *test)
3597 {
3598 	dm_test_dp_write_dsc_enable_mst(test, true, true);
3599 }
3600 
3601 /**
3602  * dm_test_dp_write_dsc_enable_mst_disable_decode_only - Test MST disable decoding write
3603  * @test: The KUnit test context
3604  */
dm_test_dp_write_dsc_enable_mst_disable_decode_only(struct kunit * test)3605 static void dm_test_dp_write_dsc_enable_mst_disable_decode_only(struct kunit *test)
3606 {
3607 	dm_test_dp_write_dsc_enable_mst(test, false, false);
3608 }
3609 
3610 /**
3611  * dm_test_dp_write_dsc_enable_mst_disable_passthrough - Test MST disable passthrough write
3612  * @test: The KUnit test context
3613  */
dm_test_dp_write_dsc_enable_mst_disable_passthrough(struct kunit * test)3614 static void dm_test_dp_write_dsc_enable_mst_disable_passthrough(struct kunit *test)
3615 {
3616 	dm_test_dp_write_dsc_enable_mst(test, false, true);
3617 }
3618 
dm_test_dp_write_dsc_enable_sst(struct kunit * test,enum display_dongle_type dongle_type,bool enable,u8 expected_value)3619 static void dm_test_dp_write_dsc_enable_sst(struct kunit *test,
3620 					   enum display_dongle_type dongle_type,
3621 					   bool enable,
3622 					   u8 expected_value)
3623 {
3624 	struct dm_test_synaptics_aux *fixture;
3625 	struct amdgpu_dm_connector *aconnector;
3626 	struct dc_stream_state *stream;
3627 	struct dc_link *link;
3628 	bool ret;
3629 
3630 	link = dm_kunit_alloc_link(test);
3631 	aconnector = dm_test_alloc_dsc_connector(test, link);
3632 	stream = dm_test_alloc_dsc_stream(test, link, SIGNAL_TYPE_DISPLAY_PORT);
3633 	fixture = dm_test_alloc_synaptics_aux_with_dev(test, NULL);
3634 
3635 	stream->dm_stream_context = aconnector;
3636 	link->priv = aconnector;
3637 	link->dpcd_caps.dongle_type = dongle_type;
3638 	dm_test_current_aux_recorder = fixture;
3639 	aconnector->dm_dp_aux.aux.transfer = dm_test_current_aux_transfer;
3640 	drm_dp_aux_init(&aconnector->dm_dp_aux.aux);
3641 
3642 	ret = dm_helpers_dp_write_dsc_enable(NULL, stream, enable);
3643 
3644 	KUNIT_EXPECT_TRUE(test, ret);
3645 	KUNIT_EXPECT_EQ(test, fixture->dsc_enable_writes, 1U);
3646 	KUNIT_EXPECT_EQ(test, fixture->dsc_enable_values[0], expected_value);
3647 }
3648 
3649 /**
3650  * dm_test_dp_write_dsc_enable_sst_rx_enable - Test SST RX enable DPCD write
3651  * @test: The KUnit test context
3652  */
dm_test_dp_write_dsc_enable_sst_rx_enable(struct kunit * test)3653 static void dm_test_dp_write_dsc_enable_sst_rx_enable(struct kunit *test)
3654 {
3655 	dm_test_dp_write_dsc_enable_sst(test, DISPLAY_DONGLE_NONE, true, 1);
3656 }
3657 
3658 /**
3659  * dm_test_dp_write_dsc_enable_sst_rx_disable - Test SST RX disable DPCD write
3660  * @test: The KUnit test context
3661  */
dm_test_dp_write_dsc_enable_sst_rx_disable(struct kunit * test)3662 static void dm_test_dp_write_dsc_enable_sst_rx_disable(struct kunit *test)
3663 {
3664 	dm_test_dp_write_dsc_enable_sst(test, DISPLAY_DONGLE_NONE, false, 0);
3665 }
3666 
3667 /**
3668  * dm_test_dp_write_dsc_enable_pcon_enable - Test DP-HDMI PCON enable DPCD write
3669  * @test: The KUnit test context
3670  */
dm_test_dp_write_dsc_enable_pcon_enable(struct kunit * test)3671 static void dm_test_dp_write_dsc_enable_pcon_enable(struct kunit *test)
3672 {
3673 	dm_test_dp_write_dsc_enable_sst(test, DISPLAY_DONGLE_DP_HDMI_CONVERTER, true, 1);
3674 }
3675 
3676 /**
3677  * dm_test_dp_write_dsc_enable_pcon_disable - Test DP-HDMI PCON disable DPCD write
3678  * @test: The KUnit test context
3679  */
dm_test_dp_write_dsc_enable_pcon_disable(struct kunit * test)3680 static void dm_test_dp_write_dsc_enable_pcon_disable(struct kunit *test)
3681 {
3682 	dm_test_dp_write_dsc_enable_sst(test, DISPLAY_DONGLE_DP_HDMI_CONVERTER, false, 0);
3683 }
3684 
3685 /* Tests for dm_helpers_dp_handle_test_pattern_request() */
3686 
3687 /**
3688  * dm_test_dp_handle_test_pattern_no_pipe - Test no matching pipe returns false
3689  * @test: The KUnit test context
3690  */
dm_test_dp_handle_test_pattern_no_pipe(struct kunit * test)3691 static void dm_test_dp_handle_test_pattern_no_pipe(struct kunit *test)
3692 {
3693 	union link_test_pattern test_pattern = {0};
3694 	union test_misc test_params = {0};
3695 	struct amdgpu_dm_connector *aconnector;
3696 	struct amdgpu_device *adev;
3697 	struct dc_context *ctx;
3698 	struct dc_state *state;
3699 	struct dc_link *link;
3700 	struct dc *dc;
3701 
3702 	adev = dm_kunit_alloc_adev(test);
3703 	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
3704 	KUNIT_ASSERT_NOT_NULL(test, ctx);
3705 	dc = kunit_kzalloc(test, sizeof(*dc), GFP_KERNEL);
3706 	KUNIT_ASSERT_NOT_NULL(test, dc);
3707 	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
3708 	KUNIT_ASSERT_NOT_NULL(test, state);
3709 	link = dm_kunit_alloc_link(test);
3710 	aconnector = dm_kunit_alloc_connector(test, adev, link);
3711 
3712 	ctx->dc = dc;
3713 	dc->current_state = state;
3714 	link->dc = dc;
3715 	link->priv = aconnector;
3716 
3717 	KUNIT_EXPECT_FALSE(test,
3718 			dm_helpers_dp_handle_test_pattern_request(ctx, link,
3719 							       test_pattern,
3720 							       test_params));
3721 }
3722 
3723 static struct kunit_case amdgpu_dm_helpers_test_cases[] = {
3724 	/* edid_extract_panel_id */
3725 	KUNIT_CASE(dm_test_edid_extract_panel_id_basic),
3726 	KUNIT_CASE(dm_test_edid_extract_panel_id_zeros),
3727 	/* apply_edid_quirks */
3728 	KUNIT_CASE(dm_test_apply_edid_quirks_dpcd_poweroff_delay),
3729 	KUNIT_CASE(dm_test_apply_edid_quirks_disable_fams),
3730 	KUNIT_CASE(dm_test_apply_edid_quirks_remove_sink_ext_caps),
3731 	KUNIT_CASE(dm_test_apply_edid_quirks_disable_colorimetry),
3732 	KUNIT_CASE(dm_test_apply_edid_quirks_skip_phy_ssc),
3733 	KUNIT_CASE(dm_test_apply_edid_quirks_unknown_noop),
3734 	/* dm_helpers_parse_edid_caps */
3735 	KUNIT_CASE(dm_test_parse_edid_caps_null_edid),
3736 	KUNIT_CASE(dm_test_parse_edid_caps_null_caps),
3737 	KUNIT_CASE(dm_test_parse_edid_caps_valid),
3738 	KUNIT_CASE(dm_test_parse_edid_caps_bad_checksum),
3739 	KUNIT_CASE(dm_test_parse_edid_caps_hdmi_frl),
3740 	KUNIT_CASE(dm_test_parse_edid_caps_hdmi_frl_dsc),
3741 	KUNIT_CASE(dm_test_parse_edid_caps_cea_audio),
3742 	KUNIT_CASE(dm_test_parse_edid_caps_cea_no_speaker),
3743 	/* ACPI / VBIOS / local EDID readers */
3744 	KUNIT_CASE(dm_test_probe_acpi_edid_no_companion),
3745 	KUNIT_CASE(dm_test_read_acpi_edid_debug_mask_disabled),
3746 	KUNIT_CASE(dm_test_read_acpi_edid_non_panel_connector),
3747 	KUNIT_CASE(dm_test_read_acpi_edid_force_off),
3748 	KUNIT_CASE(dm_test_read_vbios_edid_non_embedded),
3749 	KUNIT_CASE(dm_test_read_vbios_edid_missing_callback),
3750 	KUNIT_CASE(dm_test_read_vbios_edid_callback_error),
3751 	KUNIT_CASE(dm_test_read_vbios_edid_missing_fake_edid),
3752 	KUNIT_CASE(dm_test_read_vbios_edid_invalid_fake_edid),
3753 	KUNIT_CASE(dm_test_read_vbios_edid_valid),
3754 	/* dm_is_freesync_pcon_whitelist */
3755 	KUNIT_CASE(dm_test_freesync_pcon_whitelist_all_known),
3756 	KUNIT_CASE(dm_test_freesync_pcon_whitelist_not_in_list),
3757 	KUNIT_CASE(dm_test_freesync_pcon_whitelist_zero),
3758 	/* populate_hdmi_info_from_connector */
3759 	KUNIT_CASE(dm_test_populate_hdmi_scdc_present_true),
3760 	KUNIT_CASE(dm_test_populate_hdmi_scdc_present_false),
3761 	KUNIT_CASE(dm_test_populate_hdmi_frl_dsc_10bpc),
3762 	KUNIT_CASE(dm_test_populate_hdmi_frl_dsc_12bpc),
3763 	KUNIT_CASE(dm_test_populate_hdmi_frl_dsc_unknown_values),
3764 	/* dm_get_adaptive_sync_support_type */
3765 	KUNIT_CASE(dm_test_adaptive_sync_type_none_default),
3766 	KUNIT_CASE(dm_test_adaptive_sync_type_converter_no_conditions),
3767 	KUNIT_CASE(dm_test_adaptive_sync_type_converter_partial_conditions),
3768 	KUNIT_CASE(dm_test_adaptive_sync_type_pcon_whitelist),
3769 	KUNIT_CASE(dm_test_adaptive_sync_type_converter_nonwhitelist),
3770 	/* dm_helpers_is_fullscreen / dm_helpers_is_hdr_on */
3771 	KUNIT_CASE(dm_test_helpers_is_fullscreen_returns_false),
3772 	KUNIT_CASE(dm_test_helpers_is_hdr_on_returns_false),
3773 	/* get_max_frl_rate */
3774 	KUNIT_CASE(dm_test_get_max_frl_rate_3lanes_3gbps),
3775 	KUNIT_CASE(dm_test_get_max_frl_rate_3lanes_6gbps),
3776 	KUNIT_CASE(dm_test_get_max_frl_rate_4lanes_6gbps),
3777 	KUNIT_CASE(dm_test_get_max_frl_rate_4lanes_8gbps),
3778 	KUNIT_CASE(dm_test_get_max_frl_rate_4lanes_10gbps),
3779 	KUNIT_CASE(dm_test_get_max_frl_rate_4lanes_12gbps),
3780 	KUNIT_CASE(dm_test_get_max_frl_rate_unknown),
3781 	/* dm_dtn_log_begin / dm_dtn_log_append_v / dm_dtn_log_end */
3782 	KUNIT_CASE(dm_test_dtn_log_buffer_accumulates),
3783 	KUNIT_CASE(dm_test_dtn_log_null_ctx_no_crash),
3784 	/* dm_helpers_dp_read_dpcd / dm_helpers_dp_write_dpcd */
3785 	KUNIT_CASE(dm_test_dp_read_dpcd_null_priv),
3786 	KUNIT_CASE(dm_test_dp_write_dpcd_null_priv),
3787 	KUNIT_CASE(dm_test_dp_read_dpcd_success),
3788 	KUNIT_CASE(dm_test_dp_write_dpcd_success),
3789 	/* dm_helpers_execute_fused_io */
3790 	KUNIT_CASE(dm_test_execute_fused_io_null_dmub_srv),
3791 	/* Synaptics RC/FIFO/DSC helpers */
3792 	KUNIT_CASE(dm_test_execute_synaptics_rc_command_write_success),
3793 	KUNIT_CASE(dm_test_execute_synaptics_rc_command_read_success),
3794 	KUNIT_CASE(dm_test_execute_synaptics_rc_command_write_fail),
3795 	KUNIT_CASE(dm_test_apply_synaptics_fifo_reset_wa_full),
3796 	KUNIT_CASE(dm_test_apply_synaptics_fifo_reset_wa_first_fail),
3797 	KUNIT_CASE(dm_test_write_dsc_enable_synaptics_enable_inactive),
3798 	KUNIT_CASE(dm_test_write_dsc_enable_synaptics_enable_active),
3799 	KUNIT_CASE(dm_test_write_dsc_enable_synaptics_disable_inactive),
3800 	KUNIT_CASE(dm_test_write_dsc_enable_synaptics_disable_active),
3801 	KUNIT_CASE(dm_test_write_dsc_enable_synaptics_enable_non_synaptics),
3802 	KUNIT_CASE(dm_test_dp_write_dsc_enable_routes_synaptics),
3803 	/* dm_helpers_dp_mst_start_top_mgr / dm_helpers_dp_mst_stop_top_mgr */
3804 	KUNIT_CASE(dm_test_mst_start_top_mgr_null_priv),
3805 	KUNIT_CASE(dm_test_mst_stop_top_mgr_null_priv),
3806 	KUNIT_CASE(dm_test_mst_start_top_mgr_boot),
3807 	KUNIT_CASE(dm_test_mst_start_top_mgr_set_mst_fail),
3808 	KUNIT_CASE(dm_test_mst_stop_top_mgr_active),
3809 	/* dm_helpers_dp_write_hblank_reduction */
3810 	KUNIT_CASE(dm_test_dp_write_hblank_reduction_false),
3811 	/* get_dsc_max_slices */
3812 	KUNIT_CASE(dm_test_get_dsc_max_slices_1_340),
3813 	KUNIT_CASE(dm_test_get_dsc_max_slices_2_340),
3814 	KUNIT_CASE(dm_test_get_dsc_max_slices_4_340),
3815 	KUNIT_CASE(dm_test_get_dsc_max_slices_8_340),
3816 	KUNIT_CASE(dm_test_get_dsc_max_slices_8_400),
3817 	KUNIT_CASE(dm_test_get_dsc_max_slices_12_400),
3818 	KUNIT_CASE(dm_test_get_dsc_max_slices_16_400),
3819 	KUNIT_CASE(dm_test_get_dsc_max_slices_unknown),
3820 	/* dm_helpers_init_panel_settings */
3821 	KUNIT_CASE(dm_test_init_panel_settings_pps),
3822 	KUNIT_CASE(dm_test_init_panel_settings_dsc),
3823 	/* dm_helpers_override_panel_settings */
3824 	KUNIT_CASE(dm_test_override_panel_settings_debug_mask_disables_dsc),
3825 	KUNIT_CASE(dm_test_override_panel_settings_second_edp_disables_psr),
3826 	/* fill_dc_mst_payload_table_from_drm */
3827 	KUNIT_CASE(dm_test_fill_mst_payload_table_enable),
3828 	KUNIT_CASE(dm_test_fill_mst_payload_table_disable),
3829 	KUNIT_CASE(dm_test_fill_mst_payload_table_empty),
3830 	/* dm_helpers_submit_i2c */
3831 	KUNIT_CASE(dm_test_submit_i2c_null_priv),
3832 	KUNIT_CASE(dm_test_submit_i2c_success),
3833 	KUNIT_CASE(dm_test_submit_i2c_partial_transfer),
3834 	/* dm_helper_dmub_aux_transfer_sync */
3835 	KUNIT_CASE(dm_test_dmub_aux_transfer_sync_hpd_discon),
3836 	/* Empty stub functions */
3837 	KUNIT_CASE(dm_test_dp_update_branch_info_no_crash),
3838 	KUNIT_CASE(dm_test_mst_poll_pending_down_reply_no_crash),
3839 	KUNIT_CASE(dm_test_mst_clear_payload_alloc_table_no_crash),
3840 	KUNIT_CASE(dm_test_set_dcn_clocks_no_crash),
3841 	KUNIT_CASE(dm_test_dmu_timeout_no_crash),
3842 	KUNIT_CASE(dm_test_smu_timeout_no_crash),
3843 	KUNIT_CASE(dm_test_set_phyd32clk_no_crash),
3844 	KUNIT_CASE(dm_test_mst_update_branch_bandwidth_no_crash),
3845 	/* dm_helpers_dp_mst_write_payload_allocation_table success path */
3846 	KUNIT_CASE(dm_test_write_payload_alloc_table_enable),
3847 	KUNIT_CASE(dm_test_write_payload_alloc_table_disable),
3848 	/* MST null-connector early returns */
3849 	KUNIT_CASE(dm_test_mst_write_payload_alloc_table_null_ctx),
3850 	KUNIT_CASE(dm_test_mst_poll_for_act_null_ctx),
3851 	/* dm_helpers_dp_mst_poll_for_allocation_change_trigger success/fail */
3852 	KUNIT_CASE(dm_test_poll_for_act_no_mst_state),
3853 	KUNIT_CASE(dm_test_poll_for_act_success),
3854 	KUNIT_CASE(dm_test_poll_for_act_status_failed),
3855 	KUNIT_CASE(dm_test_mst_send_payload_alloc_null_ctx),
3856 	KUNIT_CASE(dm_test_mst_update_mgr_dealloc_null_ctx),
3857 	/* dm_helpers_dp_mst_send_payload_allocation failure path */
3858 	KUNIT_CASE(dm_test_mst_send_payload_alloc_part2_fail),
3859 	/* dm_helpers_dp_mst_update_mst_mgr_for_deallocation success path */
3860 	KUNIT_CASE(dm_test_mst_update_mgr_dealloc_success),
3861 	/* dm_helpers_is_dp_sink_present */
3862 	KUNIT_CASE(dm_test_is_dp_sink_present_null_priv),
3863 	/* dm_helpers_dmub_outbox_interrupt_control */
3864 	KUNIT_CASE(dm_test_dmub_outbox_interrupt_control_null_dc),
3865 	/* dm_helpers_mst_enable_stream_features */
3866 	KUNIT_CASE(dm_test_mst_enable_stream_features_aux_disabled),
3867 	KUNIT_CASE(dm_test_mst_enable_stream_features_writes_downspread),
3868 	/* dm_helpers_enable_periodic_detection */
3869 	KUNIT_CASE(dm_test_enable_periodic_detection_no_workqueue),
3870 	KUNIT_CASE(dm_test_enable_periodic_detection_updates_enable),
3871 	KUNIT_CASE(dm_test_enable_periodic_detection_schedules_work),
3872 	/* dm_helpers_read_mccs_caps */
3873 	KUNIT_CASE(dm_test_read_mccs_caps_null_ctx),
3874 	KUNIT_CASE(dm_test_read_mccs_caps_null_link),
3875 	KUNIT_CASE(dm_test_read_mccs_caps_no_vcp_code),
3876 	KUNIT_CASE(dm_test_read_mccs_caps_i2c_vcp_request),
3877 	KUNIT_CASE(dm_test_read_mccs_caps_hdmi_vcp_request),
3878 	KUNIT_CASE(dm_test_read_mccs_caps_legacy_pcon_vcp_request),
3879 	KUNIT_CASE(dm_test_read_mccs_caps_i2c_failure),
3880 	/* dm_helpers_mccs_vcp_set */
3881 	KUNIT_CASE(dm_test_mccs_vcp_set_null_ctx),
3882 	KUNIT_CASE(dm_test_mccs_vcp_set_not_supported),
3883 	KUNIT_CASE(dm_test_mccs_vcp_set_null_link),
3884 	KUNIT_CASE(dm_test_mccs_vcp_set_i2c_packet),
3885 	KUNIT_CASE(dm_test_mccs_vcp_set_i2c_failure),
3886 	/* dm_helpers_construct_old_payload */
3887 	KUNIT_CASE(dm_test_construct_old_payload_empty_list),
3888 	KUNIT_CASE(dm_test_construct_old_payload_intervening),
3889 	/* dm_helpers_dp_write_dsc_enable */
3890 	KUNIT_CASE(dm_test_dp_write_dsc_enable_mst_no_aux),
3891 	KUNIT_CASE(dm_test_dp_write_dsc_enable_non_dp),
3892 	KUNIT_CASE(dm_test_dp_write_dsc_enable_mst_enable_decode_only),
3893 	KUNIT_CASE(dm_test_dp_write_dsc_enable_mst_enable_passthrough),
3894 	KUNIT_CASE(dm_test_dp_write_dsc_enable_mst_disable_decode_only),
3895 	KUNIT_CASE(dm_test_dp_write_dsc_enable_mst_disable_passthrough),
3896 	KUNIT_CASE(dm_test_dp_write_dsc_enable_sst_rx_enable),
3897 	KUNIT_CASE(dm_test_dp_write_dsc_enable_sst_rx_disable),
3898 	KUNIT_CASE(dm_test_dp_write_dsc_enable_pcon_enable),
3899 	KUNIT_CASE(dm_test_dp_write_dsc_enable_pcon_disable),
3900 	/* dm_helpers_dp_handle_test_pattern_request */
3901 	KUNIT_CASE(dm_test_dp_handle_test_pattern_no_pipe),
3902 	{}
3903 };
3904 
3905 static struct kunit_suite amdgpu_dm_helpers_test_suite = {
3906 	.name = "amdgpu_dm_helpers",
3907 	.test_cases = amdgpu_dm_helpers_test_cases,
3908 };
3909 
3910 kunit_test_suite(amdgpu_dm_helpers_test_suite);
3911 
3912 MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_helpers");
3913 MODULE_LICENSE("Dual MIT/GPL");
3914