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