From: Aurabindo Pillai <[email protected]>

DM CRC parsing functions are an easy candidate for exploring the use of
KUnit unit-testing frameworks. Add a few tests for the same.

The test file and .kunitconfig are placed under amdgpu_dm/tests/ to
follow the convention of keeping test code separate from production
sources.

Assisted-by: Copilot:Claude-Opus-4.6

Reviewed-by: Harry Wentland <[email protected]>
Signed-off-by: Aurabindo Pillai <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
Signed-off-by: Ivan Lipski <[email protected]>
---
 drivers/gpu/drm/amd/display/Kconfig           |  12 ++
 .../gpu/drm/amd/display/amdgpu_dm/Makefile    |   5 +
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c |  17 ++-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h |   7 +
 .../amdgpu_dm/amdgpu_dm_kunit_helpers.h       |  19 +++
 .../amd/display/amdgpu_dm/tests/.kunitconfig  |  14 ++
 .../drm/amd/display/amdgpu_dm/tests/Makefile  |   7 +
 .../amdgpu_dm/tests/amdgpu_dm_crc_test.c      | 121 ++++++++++++++++++
 8 files changed, 198 insertions(+), 4 deletions(-)
 create mode 100644 
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_kunit_helpers.h
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
 create mode 100644 
drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crc_test.c

diff --git a/drivers/gpu/drm/amd/display/Kconfig 
b/drivers/gpu/drm/amd/display/Kconfig
index abd3b6564373..38323e574c6b 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -56,4 +56,16 @@ config DRM_AMD_SECURE_DISPLAY
          This option enables the calculation of crc of specific region via
          debugfs. Cooperate with specific DMCU FW.
 
+config DRM_AMD_DC_KUNIT_TEST
+       tristate "KUnit tests for the AMD DC display driver" if !KUNIT_ALL_TESTS
+       depends on DRM_AMD_DC && KUNIT && DEBUG_FS
+       default KUNIT_ALL_TESTS
+       help
+         This option enables KUnit tests for the AMD Display Core driver.
+         These tests validate core functionality like CRC source parsing,
+         color management, and other utility functions.
+
+         For more information on KUnit and unit tests in general, please
+         refer to the KUnit documentation in Documentation/dev-tools/kunit/.
+
 endmenu
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile 
b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
index 89350aa9ca7e..914f89af047c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
@@ -59,3 +59,8 @@ AMDGPU_DM = $(addprefix $(AMDDALPATH)/amdgpu_dm/,$(AMDGPUDM))
 
 AMD_DISPLAY_FILES += $(AMDGPU_DM)
 endif
+
+# KUnit tests as separate module
+ifneq ($(CONFIG_DRM_AMD_DC_KUNIT_TEST),)
+obj-y += $(AMDDALPATH)/amdgpu_dm/tests/
+endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index e9834d7b6534..3613e67d1085 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -33,6 +33,7 @@
 #include "amdgpu_securedisplay.h"
 #include "amdgpu_dm_psr.h"
 #include "amdgpu_dm_replay.h"
+#include "amdgpu_dm_kunit_helpers.h"
 
 static const char *const pipe_crc_sources[] = {
        "none",
@@ -43,7 +44,8 @@ static const char *const pipe_crc_sources[] = {
        "auto",
 };
 
-static enum amdgpu_dm_pipe_crc_source dm_parse_crc_source(const char *source)
+STATIC_IFN_KUNIT
+enum amdgpu_dm_pipe_crc_source dm_parse_crc_source(const char *source)
 {
        if (!source || !strcmp(source, "none"))
                return AMDGPU_DM_PIPE_CRC_SOURCE_NONE;
@@ -58,25 +60,32 @@ static enum amdgpu_dm_pipe_crc_source 
dm_parse_crc_source(const char *source)
 
        return AMDGPU_DM_PIPE_CRC_SOURCE_INVALID;
 }
+EXPORT_IF_KUNIT(dm_parse_crc_source);
 
-static bool dm_is_crc_source_crtc(enum amdgpu_dm_pipe_crc_source src)
+STATIC_IFN_KUNIT
+bool dm_is_crc_source_crtc(enum amdgpu_dm_pipe_crc_source src)
 {
        return (src == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC) ||
               (src == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER);
 }
+EXPORT_IF_KUNIT(dm_is_crc_source_crtc);
 
-static bool dm_is_crc_source_dprx(enum amdgpu_dm_pipe_crc_source src)
+STATIC_IFN_KUNIT
+bool dm_is_crc_source_dprx(enum amdgpu_dm_pipe_crc_source src)
 {
        return (src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX) ||
               (src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER);
 }
+EXPORT_IF_KUNIT(dm_is_crc_source_dprx);
 
-static bool dm_need_crc_dither(enum amdgpu_dm_pipe_crc_source src)
+STATIC_IFN_KUNIT
+bool dm_need_crc_dither(enum amdgpu_dm_pipe_crc_source src)
 {
        return (src == AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER) ||
               (src == AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER) ||
               (src == AMDGPU_DM_PIPE_CRC_SOURCE_NONE);
 }
+EXPORT_IF_KUNIT(dm_need_crc_dither);
 
 const char *const *amdgpu_dm_crtc_get_crc_sources(struct drm_crtc *crtc,
                                                  size_t *count)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
index 8538513ea879..76731ee44e13 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
@@ -148,4 +148,11 @@ void amdgpu_dm_crtc_secure_display_create_contexts(struct 
amdgpu_device *adev);
 #define amdgpu_dm_crtc_secure_display_create_contexts(x)
 #endif
 
+#ifdef CONFIG_DRM_AMD_DC_KUNIT_TEST
+enum amdgpu_dm_pipe_crc_source dm_parse_crc_source(const char *source);
+bool dm_is_crc_source_crtc(enum amdgpu_dm_pipe_crc_source src);
+bool dm_is_crc_source_dprx(enum amdgpu_dm_pipe_crc_source src);
+bool dm_need_crc_dither(enum amdgpu_dm_pipe_crc_source src);
+#endif
+
 #endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_kunit_helpers.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_kunit_helpers.h
new file mode 100644
index 000000000000..4b2864375105
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_kunit_helpers.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ */
+
+#ifndef AMDGPU_DM_KUNIT_HELPERS_H
+#define AMDGPU_DM_KUNIT_HELPERS_H
+
+#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
+#define STATIC_IFN_KUNIT
+#define INLINE_IFN_KUNIT inline
+#define EXPORT_IF_KUNIT(symbol) EXPORT_SYMBOL(symbol)
+#else
+#define STATIC_IFN_KUNIT static
+#define INLINE_IFN_KUNIT
+#define EXPORT_IF_KUNIT(symbol)
+#endif
+
+#endif /* AMDGPU_DM_KUNIT_HELPERS_H */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig
new file mode 100644
index 000000000000..36676326ade4
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/.kunitconfig
@@ -0,0 +1,14 @@
+CONFIG_KUNIT=y
+CONFIG_PCI=y
+CONFIG_DRM=y
+CONFIG_DRM_AMDGPU=y
+CONFIG_DRM_AMD_DC=y
+CONFIG_DEBUG_FS=y
+CONFIG_DRM_AMD_DC_KUNIT_TEST=y
+CONFIG_FW_LOADER=y
+CONFIG_DRM_KMS_HELPER=y
+CONFIG_DRM_TTM=y
+CONFIG_HWMON=y
+CONFIG_I2C=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_CRC16=y
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
new file mode 100644
index 000000000000..1238d8832fa3
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for amdgpu_dm KUnit tests.
+
+ccflags-y += -I$(src)/..
+
+obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_crc_test.o
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crc_test.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crc_test.c
new file mode 100644
index 000000000000..bba8b1a8fa1c
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crc_test.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * KUnit tests for amdgpu_dm_crc.c
+ *
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ */
+
+#include <kunit/test.h>
+
+#include "amdgpu_dm_crc.h"
+
+static void dm_test_parse_crc_source_none(struct kunit *test)
+{
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_NONE, 
dm_parse_crc_source("none"));
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_NONE, 
dm_parse_crc_source(NULL));
+}
+
+static void dm_test_parse_crc_source_crtc(struct kunit *test)
+{
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_CRTC, 
dm_parse_crc_source("crtc"));
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_CRTC, 
dm_parse_crc_source("auto"));
+}
+
+static void dm_test_parse_crc_source_dprx(struct kunit *test)
+{
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_DPRX, 
dm_parse_crc_source("dprx"));
+}
+
+static void dm_test_parse_crc_source_crtc_dither(struct kunit *test)
+{
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER,
+                       dm_parse_crc_source("crtc dither"));
+}
+
+static void dm_test_parse_crc_source_dprx_dither(struct kunit *test)
+{
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER,
+                       dm_parse_crc_source("dprx dither"));
+}
+
+static void dm_test_parse_crc_source_invalid(struct kunit *test)
+{
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_INVALID,
+                       dm_parse_crc_source("invalid"));
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_INVALID,
+                       dm_parse_crc_source("unknown"));
+       KUNIT_EXPECT_EQ(test, AMDGPU_DM_PIPE_CRC_SOURCE_INVALID,
+                       dm_parse_crc_source(""));
+}
+
+static void dm_test_is_crc_source_crtc(struct kunit *test)
+{
+       KUNIT_EXPECT_TRUE(test, 
dm_is_crc_source_crtc(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC));
+       KUNIT_EXPECT_TRUE(test, 
dm_is_crc_source_crtc(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER));
+
+       KUNIT_EXPECT_FALSE(test, 
dm_is_crc_source_crtc(AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+       KUNIT_EXPECT_FALSE(test, 
dm_is_crc_source_crtc(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX));
+       KUNIT_EXPECT_FALSE(test, 
dm_is_crc_source_crtc(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER));
+       KUNIT_EXPECT_FALSE(test, 
dm_is_crc_source_crtc(AMDGPU_DM_PIPE_CRC_SOURCE_INVALID));
+}
+
+static void dm_test_is_crc_source_dprx(struct kunit *test)
+{
+       KUNIT_EXPECT_TRUE(test, 
dm_is_crc_source_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX));
+       KUNIT_EXPECT_TRUE(test, 
dm_is_crc_source_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER));
+
+       KUNIT_EXPECT_FALSE(test, 
dm_is_crc_source_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+       KUNIT_EXPECT_FALSE(test, 
dm_is_crc_source_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC));
+       KUNIT_EXPECT_FALSE(test, 
dm_is_crc_source_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER));
+       KUNIT_EXPECT_FALSE(test, 
dm_is_crc_source_dprx(AMDGPU_DM_PIPE_CRC_SOURCE_INVALID));
+}
+
+static void dm_test_need_crc_dither(struct kunit *test)
+{
+       KUNIT_EXPECT_TRUE(test, 
dm_need_crc_dither(AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+       KUNIT_EXPECT_TRUE(test, 
dm_need_crc_dither(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER));
+       KUNIT_EXPECT_TRUE(test, 
dm_need_crc_dither(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER));
+
+       KUNIT_EXPECT_FALSE(test, 
dm_need_crc_dither(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC));
+       KUNIT_EXPECT_FALSE(test, 
dm_need_crc_dither(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX));
+       KUNIT_EXPECT_FALSE(test, 
dm_need_crc_dither(AMDGPU_DM_PIPE_CRC_SOURCE_INVALID));
+}
+
+static void dm_test_is_valid_crc_source(struct kunit *test)
+{
+       KUNIT_EXPECT_TRUE(test, 
amdgpu_dm_is_valid_crc_source(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC));
+       KUNIT_EXPECT_TRUE(test, 
amdgpu_dm_is_valid_crc_source(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX));
+       KUNIT_EXPECT_TRUE(test,
+                         
amdgpu_dm_is_valid_crc_source(AMDGPU_DM_PIPE_CRC_SOURCE_CRTC_DITHER));
+       KUNIT_EXPECT_TRUE(test,
+                         
amdgpu_dm_is_valid_crc_source(AMDGPU_DM_PIPE_CRC_SOURCE_DPRX_DITHER));
+
+       KUNIT_EXPECT_FALSE(test, 
amdgpu_dm_is_valid_crc_source(AMDGPU_DM_PIPE_CRC_SOURCE_NONE));
+       KUNIT_EXPECT_FALSE(test, 
amdgpu_dm_is_valid_crc_source(AMDGPU_DM_PIPE_CRC_SOURCE_MAX));
+       KUNIT_EXPECT_FALSE(test, 
amdgpu_dm_is_valid_crc_source(AMDGPU_DM_PIPE_CRC_SOURCE_INVALID));
+}
+
+static struct kunit_case dm_crc_test_cases[] = {
+       KUNIT_CASE(dm_test_parse_crc_source_none),
+       KUNIT_CASE(dm_test_parse_crc_source_crtc),
+       KUNIT_CASE(dm_test_parse_crc_source_dprx),
+       KUNIT_CASE(dm_test_parse_crc_source_crtc_dither),
+       KUNIT_CASE(dm_test_parse_crc_source_dprx_dither),
+       KUNIT_CASE(dm_test_parse_crc_source_invalid),
+       KUNIT_CASE(dm_test_is_crc_source_crtc),
+       KUNIT_CASE(dm_test_is_crc_source_dprx),
+       KUNIT_CASE(dm_test_need_crc_dither),
+       KUNIT_CASE(dm_test_is_valid_crc_source),
+       {}
+};
+
+static struct kunit_suite dm_crc_test_suite = {
+       .name = "amdgpu_dm_crc",
+       .test_cases = dm_crc_test_cases,
+};
+
+kunit_test_suite(dm_crc_test_suite);
+
+MODULE_LICENSE("Dual MIT/GPL");
+MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_crc");
+MODULE_AUTHOR("AMD");
-- 
2.43.0

Reply via email to