mirror of
https://github.com/torvalds/linux.git
synced 2026-10-13 22:01:02 +02:00
drm/amd/display: Add KUnit tests for writeback connector
[WHAT] Add KUnit tests for amdgpu_dm_wb_encoder_atomic_check() and amdgpu_dm_wb_connector_get_modes(). Tests cover null job, null fb, size mismatch, format validation, and mode count bounds using DRM KUnit mock devices. Assisted-by: Copilot:Claude-Opus-4.6 Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com> Signed-off-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
042b0a3980
commit
948739e14f
|
|
@ -29,6 +29,7 @@
|
|||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm.h"
|
||||
#include "amdgpu_dm_wb.h"
|
||||
#include "amdgpu_dm_kunit_helpers.h"
|
||||
#include "amdgpu_display.h"
|
||||
#include "dc.h"
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ static const u32 amdgpu_dm_wb_formats[] = {
|
|||
DRM_FORMAT_XRGB2101010,
|
||||
};
|
||||
|
||||
static int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
STATIC_IFN_KUNIT int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
|
|
@ -74,13 +75,15 @@ static int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_wb_encoder_atomic_check);
|
||||
|
||||
|
||||
static int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector)
|
||||
STATIC_IFN_KUNIT int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
/* Maximum resolution supported by DWB */
|
||||
return drm_add_modes_noedid(connector, 3840, 2160);
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_wb_connector_get_modes);
|
||||
|
||||
static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector,
|
||||
struct drm_writeback_job *job)
|
||||
|
|
|
|||
|
|
@ -29,8 +29,21 @@
|
|||
|
||||
#include <drm/drm_writeback.h>
|
||||
|
||||
struct amdgpu_display_manager;
|
||||
struct amdgpu_dm_wb_connector;
|
||||
|
||||
int amdgpu_dm_wb_connector_init(struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_dm_wb_connector *dm_wbcon,
|
||||
uint32_t link_index);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
|
||||
int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state);
|
||||
int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -16,3 +16,4 @@ obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_colorop_test.o
|
|||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_psr_test.o
|
||||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_replay_test.o
|
||||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_ism_test.o
|
||||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_wb_test.o
|
||||
|
|
|
|||
336
drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
Normal file
336
drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_wb_test.c
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
/*
|
||||
* KUnit tests for amdgpu_dm_wb.c
|
||||
*
|
||||
* Copyright 2026 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_kunit_helpers.h>
|
||||
#include <drm/drm_mode.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_writeback.h>
|
||||
|
||||
#include "amdgpu_dm_wb.h"
|
||||
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
static struct drm_crtc_state *alloc_test_crtc_state(struct kunit *test,
|
||||
int hdisplay, int vdisplay)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, crtc_state);
|
||||
|
||||
crtc_state->mode.hdisplay = hdisplay;
|
||||
crtc_state->mode.vdisplay = vdisplay;
|
||||
|
||||
return crtc_state;
|
||||
}
|
||||
|
||||
static struct drm_connector_state *alloc_test_conn_state(struct kunit *test,
|
||||
int fb_width,
|
||||
int fb_height,
|
||||
u32 format)
|
||||
{
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_writeback_job *job;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_format_info *fmt_info;
|
||||
|
||||
conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, conn_state);
|
||||
|
||||
job = kunit_kzalloc(test, sizeof(*job), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, job);
|
||||
|
||||
fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, fb);
|
||||
|
||||
fmt_info = kunit_kzalloc(test, sizeof(*fmt_info), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, fmt_info);
|
||||
|
||||
fb->width = fb_width;
|
||||
fb->height = fb_height;
|
||||
fmt_info->format = format;
|
||||
fb->format = fmt_info;
|
||||
|
||||
job->fb = fb;
|
||||
conn_state->writeback_job = job;
|
||||
|
||||
return conn_state;
|
||||
}
|
||||
|
||||
/* Tests for amdgpu_dm_wb_encoder_atomic_check */
|
||||
|
||||
/**
|
||||
* dm_test_wb_atomic_check_no_job - Verify early return when no writeback job
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When conn_state->writeback_job is NULL, no writeback is requested and the
|
||||
* function should return 0 without further validation.
|
||||
*/
|
||||
static void dm_test_wb_atomic_check_no_job(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector_state *conn_state;
|
||||
int ret;
|
||||
|
||||
crtc_state = alloc_test_crtc_state(test, 1920, 1080);
|
||||
conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, conn_state);
|
||||
|
||||
/* No writeback_job — should return 0 */
|
||||
conn_state->writeback_job = NULL;
|
||||
ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
|
||||
KUNIT_EXPECT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_wb_atomic_check_no_fb - Verify early return when job has no framebuffer
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When a writeback job exists but job->fb is NULL, the function should return 0
|
||||
* without validating dimensions or pixel format.
|
||||
*/
|
||||
static void dm_test_wb_atomic_check_no_fb(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_writeback_job *job;
|
||||
int ret;
|
||||
|
||||
crtc_state = alloc_test_crtc_state(test, 1920, 1080);
|
||||
conn_state = kunit_kzalloc(test, sizeof(*conn_state), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, conn_state);
|
||||
|
||||
job = kunit_kzalloc(test, sizeof(*job), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, job);
|
||||
|
||||
/* writeback_job exists but no fb — should return 0 */
|
||||
job->fb = NULL;
|
||||
conn_state->writeback_job = job;
|
||||
ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
|
||||
KUNIT_EXPECT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_wb_atomic_check_valid - Verify success with matching size and supported format
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When the framebuffer dimensions match the CRTC mode and the pixel format is
|
||||
* in the supported formats list, the function should return 0.
|
||||
*/
|
||||
static void dm_test_wb_atomic_check_valid(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector_state *conn_state;
|
||||
int ret;
|
||||
|
||||
crtc_state = alloc_test_crtc_state(test, 1920, 1080);
|
||||
conn_state = alloc_test_conn_state(test, 1920, 1080,
|
||||
DRM_FORMAT_XRGB2101010);
|
||||
|
||||
ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
|
||||
KUNIT_EXPECT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_wb_atomic_check_size_mismatch - Verify rejection when both dimensions differ
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When both framebuffer width and height differ from the CRTC mode, the
|
||||
* function should return -EINVAL.
|
||||
*/
|
||||
static void dm_test_wb_atomic_check_size_mismatch(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector_state *conn_state;
|
||||
int ret;
|
||||
|
||||
/* FB is 3840x2160 but mode is 1920x1080 */
|
||||
crtc_state = alloc_test_crtc_state(test, 1920, 1080);
|
||||
conn_state = alloc_test_conn_state(test, 3840, 2160,
|
||||
DRM_FORMAT_XRGB2101010);
|
||||
|
||||
ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
|
||||
KUNIT_EXPECT_EQ(test, ret, -EINVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_wb_atomic_check_width_mismatch - Verify rejection when width alone differs
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When only the framebuffer width differs from the CRTC mode hdisplay, the
|
||||
* function should return -EINVAL.
|
||||
*/
|
||||
static void dm_test_wb_atomic_check_width_mismatch(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector_state *conn_state;
|
||||
int ret;
|
||||
|
||||
/* Width doesn't match */
|
||||
crtc_state = alloc_test_crtc_state(test, 1920, 1080);
|
||||
conn_state = alloc_test_conn_state(test, 1280, 1080,
|
||||
DRM_FORMAT_XRGB2101010);
|
||||
|
||||
ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
|
||||
KUNIT_EXPECT_EQ(test, ret, -EINVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_wb_atomic_check_height_mismatch - Verify rejection when height alone differs
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When only the framebuffer height differs from the CRTC mode vdisplay, the
|
||||
* function should return -EINVAL.
|
||||
*/
|
||||
static void dm_test_wb_atomic_check_height_mismatch(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector_state *conn_state;
|
||||
int ret;
|
||||
|
||||
/* Height doesn't match */
|
||||
crtc_state = alloc_test_crtc_state(test, 1920, 1080);
|
||||
conn_state = alloc_test_conn_state(test, 1920, 720,
|
||||
DRM_FORMAT_XRGB2101010);
|
||||
|
||||
ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
|
||||
KUNIT_EXPECT_EQ(test, ret, -EINVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_wb_atomic_check_invalid_format - Verify rejection of unsupported pixel format
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* When the framebuffer dimensions match but the pixel format is not in
|
||||
* amdgpu_dm_wb_formats[], the function should return -EINVAL.
|
||||
*/
|
||||
static void dm_test_wb_atomic_check_invalid_format(struct kunit *test)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector_state *conn_state;
|
||||
int ret;
|
||||
|
||||
/* Correct size but unsupported format */
|
||||
crtc_state = alloc_test_crtc_state(test, 1920, 1080);
|
||||
conn_state = alloc_test_conn_state(test, 1920, 1080,
|
||||
DRM_FORMAT_XRGB8888);
|
||||
|
||||
ret = amdgpu_dm_wb_encoder_atomic_check(NULL, crtc_state, conn_state);
|
||||
KUNIT_EXPECT_EQ(test, ret, -EINVAL);
|
||||
}
|
||||
|
||||
/* Tests for amdgpu_dm_wb_connector_get_modes using DRM mock */
|
||||
|
||||
static const struct drm_connector_funcs dm_wb_test_connector_funcs = {
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
};
|
||||
|
||||
/**
|
||||
* dm_test_wb_get_modes_returns_modes - Verify at least one mode is returned
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* Uses a DRM mock connector to verify that amdgpu_dm_wb_connector_get_modes()
|
||||
* populates the connector with at least one display mode.
|
||||
*/
|
||||
static void dm_test_wb_get_modes_returns_modes(struct kunit *test)
|
||||
{
|
||||
struct device *dev;
|
||||
struct drm_device *drm;
|
||||
struct drm_connector *connector;
|
||||
int count;
|
||||
|
||||
dev = drm_kunit_helper_alloc_device(test);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||
|
||||
drm = __drm_kunit_helper_alloc_drm_device(test, dev,
|
||||
sizeof(*drm), 0,
|
||||
DRIVER_MODESET | DRIVER_ATOMIC);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
|
||||
|
||||
connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, connector);
|
||||
|
||||
drmm_connector_init(drm, connector, &dm_wb_test_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VIRTUAL, NULL);
|
||||
|
||||
count = amdgpu_dm_wb_connector_get_modes(connector);
|
||||
|
||||
/* drm_add_modes_noedid should return at least one mode */
|
||||
KUNIT_EXPECT_GT(test, count, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_wb_get_modes_bounded_by_max - Verify all modes are within max resolution
|
||||
* @test: KUnit test context
|
||||
*
|
||||
* Uses a DRM mock connector to verify that all modes returned by
|
||||
* amdgpu_dm_wb_connector_get_modes() have hdisplay <= 3840 and
|
||||
* vdisplay <= 2160, matching the DWB hardware maximum.
|
||||
*/
|
||||
static void dm_test_wb_get_modes_bounded_by_max(struct kunit *test)
|
||||
{
|
||||
struct device *dev;
|
||||
struct drm_device *drm;
|
||||
struct drm_connector *connector;
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
dev = drm_kunit_helper_alloc_device(test);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
|
||||
|
||||
drm = __drm_kunit_helper_alloc_drm_device(test, dev,
|
||||
sizeof(*drm), 0,
|
||||
DRIVER_MODESET | DRIVER_ATOMIC);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
|
||||
|
||||
connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_NULL(test, connector);
|
||||
|
||||
drmm_connector_init(drm, connector, &dm_wb_test_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VIRTUAL, NULL);
|
||||
|
||||
amdgpu_dm_wb_connector_get_modes(connector);
|
||||
|
||||
/* All modes must fit within 3840x2160 */
|
||||
list_for_each_entry(mode, &connector->probed_modes, head) {
|
||||
KUNIT_EXPECT_LE(test, mode->hdisplay, 3840);
|
||||
KUNIT_EXPECT_LE(test, mode->vdisplay, 2160);
|
||||
}
|
||||
}
|
||||
|
||||
static struct kunit_case dm_wb_test_cases[] = {
|
||||
/* amdgpu_dm_wb_encoder_atomic_check */
|
||||
KUNIT_CASE(dm_test_wb_atomic_check_no_job),
|
||||
KUNIT_CASE(dm_test_wb_atomic_check_no_fb),
|
||||
KUNIT_CASE(dm_test_wb_atomic_check_valid),
|
||||
KUNIT_CASE(dm_test_wb_atomic_check_size_mismatch),
|
||||
KUNIT_CASE(dm_test_wb_atomic_check_width_mismatch),
|
||||
KUNIT_CASE(dm_test_wb_atomic_check_height_mismatch),
|
||||
KUNIT_CASE(dm_test_wb_atomic_check_invalid_format),
|
||||
/* amdgpu_dm_wb_connector_get_modes */
|
||||
KUNIT_CASE(dm_test_wb_get_modes_returns_modes),
|
||||
KUNIT_CASE(dm_test_wb_get_modes_bounded_by_max),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite dm_wb_test_suite = {
|
||||
.name = "amdgpu_dm_wb",
|
||||
.test_cases = dm_wb_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(dm_wb_test_suite);
|
||||
|
||||
MODULE_LICENSE("Dual MIT/GPL");
|
||||
MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_wb");
|
||||
Loading…
Reference in New Issue
Block a user