mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-23 16:36:56 -04:00
drm/amd/display: Add KUnit tests for amdgpu_dm_audio
Add KUnit tests for amdgpu_dm_audio.c. Tests cover: - amdgpu_dm_audio_init(): early exit when audio is disabled - amdgpu_dm_audio_fini(): early exit when audio is not enabled - fill_audio_info(): manufacturer and product ID propagation, display name copy, speaker allocation flags, CEA revision gating of audio mode copying (including the zero-mode case), and latency field propagation - amdgpu_dm_audio_component_bind()/unbind(): component ops, device, and audio_component pointer are wired up on bind and cleared on unbind - amdgpu_dm_audio_eld_notify(): callback is forwarded with the correct port and audio pointer, and the no-op guard paths for a missing component, audio_ops, or pin_eld_notify callback Assisted-by: Copilot:Claude-Opus-4.8 Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com> Signed-off-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm.h"
|
||||
#include "amdgpu_dm_audio.h"
|
||||
#include "amdgpu_dm_kunit_helpers.h"
|
||||
#include "dc.h"
|
||||
|
||||
#include <linux/component.h>
|
||||
@@ -83,7 +84,7 @@ static const struct drm_audio_component_ops amdgpu_dm_audio_component_ops = {
|
||||
.get_eld = amdgpu_dm_audio_component_get_eld,
|
||||
};
|
||||
|
||||
static int amdgpu_dm_audio_component_bind(struct device *kdev,
|
||||
STATIC_IFN_KUNIT int amdgpu_dm_audio_component_bind(struct device *kdev,
|
||||
struct device *hda_kdev, void *data)
|
||||
{
|
||||
struct drm_device *dev = dev_get_drvdata(kdev);
|
||||
@@ -96,8 +97,9 @@ static int amdgpu_dm_audio_component_bind(struct device *kdev,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_audio_component_bind);
|
||||
|
||||
static void amdgpu_dm_audio_component_unbind(struct device *kdev,
|
||||
STATIC_IFN_KUNIT void amdgpu_dm_audio_component_unbind(struct device *kdev,
|
||||
struct device *hda_kdev, void *data)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(dev_get_drvdata(kdev));
|
||||
@@ -107,6 +109,7 @@ static void amdgpu_dm_audio_component_unbind(struct device *kdev,
|
||||
acomp->dev = NULL;
|
||||
adev->dm.audio_component = NULL;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_audio_component_unbind);
|
||||
|
||||
static const struct component_ops amdgpu_dm_audio_component_bind_ops = {
|
||||
.bind = amdgpu_dm_audio_component_bind,
|
||||
@@ -144,6 +147,7 @@ int amdgpu_dm_audio_init(struct amdgpu_device *adev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_audio_init);
|
||||
|
||||
void amdgpu_dm_audio_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
@@ -162,8 +166,9 @@ void amdgpu_dm_audio_fini(struct amdgpu_device *adev)
|
||||
|
||||
adev->mode_info.audio.enabled = false;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_audio_fini);
|
||||
|
||||
static void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin)
|
||||
STATIC_IFN_KUNIT void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin)
|
||||
{
|
||||
struct drm_audio_component *acomp = adev->dm.audio_component;
|
||||
|
||||
@@ -174,6 +179,7 @@ static void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin)
|
||||
pin, -1);
|
||||
}
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_audio_eld_notify);
|
||||
|
||||
void amdgpu_dm_fill_audio_info(struct audio_info *audio_info,
|
||||
const struct drm_connector *drm_connector,
|
||||
@@ -219,6 +225,7 @@ void amdgpu_dm_fill_audio_info(struct audio_info *audio_info,
|
||||
/* TODO: For DP, video and audio latency should be calculated from DPCD caps */
|
||||
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_fill_audio_info);
|
||||
|
||||
void amdgpu_dm_commit_audio(struct drm_device *dev,
|
||||
struct drm_atomic_commit *state)
|
||||
@@ -300,3 +307,17 @@ void amdgpu_dm_commit_audio(struct drm_device *dev,
|
||||
amdgpu_dm_audio_eld_notify(adev, inst);
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
|
||||
int amdgpu_dm_audio_get_param(void)
|
||||
{
|
||||
return amdgpu_audio;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_audio_get_param);
|
||||
|
||||
void amdgpu_dm_audio_set_param(int val)
|
||||
{
|
||||
amdgpu_audio = val;
|
||||
}
|
||||
EXPORT_IF_KUNIT(amdgpu_dm_audio_set_param);
|
||||
#endif
|
||||
|
||||
@@ -41,4 +41,16 @@ void amdgpu_dm_fill_audio_info(struct audio_info *audio_info,
|
||||
const struct drm_connector *drm_connector,
|
||||
const struct dc_sink *dc_sink);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
|
||||
struct device;
|
||||
|
||||
int amdgpu_dm_audio_component_bind(struct device *kdev,
|
||||
struct device *hda_kdev, void *data);
|
||||
void amdgpu_dm_audio_component_unbind(struct device *kdev,
|
||||
struct device *hda_kdev, void *data);
|
||||
void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin);
|
||||
int amdgpu_dm_audio_get_param(void);
|
||||
void amdgpu_dm_audio_set_param(int val);
|
||||
#endif
|
||||
|
||||
#endif /* __AMDGPU_DM_AUDIO_H__ */
|
||||
|
||||
@@ -13,6 +13,7 @@ ccflags-y += -I$(src)/../../../include
|
||||
|
||||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_crc_test.o
|
||||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_hdcp_test.o
|
||||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_audio_test.o
|
||||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_color_test.o
|
||||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_colorop_test.o
|
||||
obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_backlight_test.o
|
||||
|
||||
@@ -0,0 +1,490 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
/*
|
||||
* KUnit tests for amdgpu_dm_audio.c
|
||||
*
|
||||
* Copyright 2026 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include <drm/drm_audio_component.h>
|
||||
|
||||
#include "dc.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_mode.h"
|
||||
#include "amdgpu_dm.h"
|
||||
#include "amdgpu_dm_audio.h"
|
||||
|
||||
/* Tests for amdgpu_dm_audio_init() */
|
||||
|
||||
/**
|
||||
* dm_test_audio_init_disabled - Test audio init exits when audio is disabled
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_audio_init_disabled(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
int saved_audio = amdgpu_dm_audio_get_param();
|
||||
|
||||
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
|
||||
|
||||
amdgpu_dm_audio_set_param(0);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, amdgpu_dm_audio_init(adev), 0);
|
||||
KUNIT_EXPECT_FALSE(test, adev->mode_info.audio.enabled);
|
||||
KUNIT_EXPECT_FALSE(test, adev->dm.audio_registered);
|
||||
|
||||
amdgpu_dm_audio_set_param(saved_audio);
|
||||
}
|
||||
|
||||
/* Tests for amdgpu_dm_audio_fini() */
|
||||
|
||||
/**
|
||||
* dm_test_audio_fini_without_enabled_audio - Test fini exits when audio is not enabled
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_audio_fini_without_enabled_audio(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
int saved_audio = amdgpu_dm_audio_get_param();
|
||||
|
||||
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
|
||||
|
||||
amdgpu_dm_audio_set_param(1);
|
||||
adev->mode_info.audio.enabled = false;
|
||||
adev->dm.audio_registered = true;
|
||||
|
||||
amdgpu_dm_audio_fini(adev);
|
||||
|
||||
KUNIT_EXPECT_FALSE(test, adev->mode_info.audio.enabled);
|
||||
KUNIT_EXPECT_TRUE(test, adev->dm.audio_registered);
|
||||
|
||||
amdgpu_dm_audio_set_param(saved_audio);
|
||||
}
|
||||
|
||||
/* Tests for amdgpu_dm_fill_audio_info() */
|
||||
|
||||
/**
|
||||
* dm_test_fill_audio_info_ids_name_flags - Test Fill audio info ids name flags
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_fill_audio_info_ids_name_flags(struct kunit *test)
|
||||
{
|
||||
struct audio_info *audio_info;
|
||||
struct drm_connector *connector;
|
||||
struct dc_sink *dc_sink;
|
||||
const char *name = "DM-AUDIO-PANEL";
|
||||
|
||||
audio_info = kunit_kzalloc(test, sizeof(*audio_info), GFP_KERNEL);
|
||||
connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
|
||||
dc_sink = kunit_kzalloc(test, sizeof(*dc_sink), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, audio_info);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc_sink);
|
||||
|
||||
dc_sink->edid_caps.manufacturer_id = 0x1234;
|
||||
dc_sink->edid_caps.product_id = 0xABCD;
|
||||
dc_sink->edid_caps.speaker_flags = 0x5;
|
||||
strscpy(dc_sink->edid_caps.display_name, name,
|
||||
AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
|
||||
|
||||
connector->display_info.cea_rev = 1;
|
||||
|
||||
amdgpu_dm_fill_audio_info(audio_info, connector, dc_sink);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, audio_info->manufacture_id, 0x1234U);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->product_id, 0xABCDU);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->flags.all, 0x5U);
|
||||
KUNIT_EXPECT_STREQ(test, audio_info->display_name, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_fill_audio_info_cea_lt_3_skips_modes - Test Fill audio info cea lt 3 skips modes
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_fill_audio_info_cea_lt_3_skips_modes(struct kunit *test)
|
||||
{
|
||||
struct audio_info *audio_info;
|
||||
struct drm_connector *connector;
|
||||
struct dc_sink *dc_sink;
|
||||
|
||||
audio_info = kunit_kzalloc(test, sizeof(*audio_info), GFP_KERNEL);
|
||||
connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
|
||||
dc_sink = kunit_kzalloc(test, sizeof(*dc_sink), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, audio_info);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc_sink);
|
||||
|
||||
connector->display_info.cea_rev = 2;
|
||||
dc_sink->edid_caps.audio_mode_count = 2;
|
||||
dc_sink->edid_caps.audio_modes[0].format_code = 1;
|
||||
dc_sink->edid_caps.audio_modes[0].channel_count = 2;
|
||||
dc_sink->edid_caps.audio_modes[0].sample_rate = 0x07;
|
||||
dc_sink->edid_caps.audio_modes[0].sample_size = 16;
|
||||
|
||||
amdgpu_dm_fill_audio_info(audio_info, connector, dc_sink);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, audio_info->mode_count, 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_fill_audio_info_cea_ge_3_copies_modes - Test Fill audio info cea ge 3 copies modes
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_fill_audio_info_cea_ge_3_copies_modes(struct kunit *test)
|
||||
{
|
||||
struct audio_info *audio_info;
|
||||
struct drm_connector *connector;
|
||||
struct dc_sink *dc_sink;
|
||||
|
||||
audio_info = kunit_kzalloc(test, sizeof(*audio_info), GFP_KERNEL);
|
||||
connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
|
||||
dc_sink = kunit_kzalloc(test, sizeof(*dc_sink), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, audio_info);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc_sink);
|
||||
|
||||
connector->display_info.cea_rev = 3;
|
||||
dc_sink->edid_caps.audio_mode_count = 2;
|
||||
|
||||
dc_sink->edid_caps.audio_modes[0].format_code = 1;
|
||||
dc_sink->edid_caps.audio_modes[0].channel_count = 2;
|
||||
dc_sink->edid_caps.audio_modes[0].sample_rate = 0x07;
|
||||
dc_sink->edid_caps.audio_modes[0].sample_size = 16;
|
||||
|
||||
dc_sink->edid_caps.audio_modes[1].format_code = 11;
|
||||
dc_sink->edid_caps.audio_modes[1].channel_count = 6;
|
||||
dc_sink->edid_caps.audio_modes[1].sample_rate = 0x1F;
|
||||
dc_sink->edid_caps.audio_modes[1].sample_size = 24;
|
||||
|
||||
amdgpu_dm_fill_audio_info(audio_info, connector, dc_sink);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, audio_info->mode_count, 2U);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, (int)audio_info->modes[0].format_code, 1);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->modes[0].channel_count, 2);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->modes[0].sample_rates.all, 0x07U);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->modes[0].sample_size, 16);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, (int)audio_info->modes[1].format_code, 11);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->modes[1].channel_count, 6);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->modes[1].sample_rates.all, 0x1FU);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->modes[1].sample_size, 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_fill_audio_info_latency_present - Test Fill audio info latency present
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_fill_audio_info_latency_present(struct kunit *test)
|
||||
{
|
||||
struct audio_info *audio_info;
|
||||
struct drm_connector *connector;
|
||||
struct dc_sink *dc_sink;
|
||||
|
||||
audio_info = kunit_kzalloc(test, sizeof(*audio_info), GFP_KERNEL);
|
||||
connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
|
||||
dc_sink = kunit_kzalloc(test, sizeof(*dc_sink), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, audio_info);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc_sink);
|
||||
|
||||
connector->display_info.cea_rev = 3;
|
||||
connector->latency_present[0] = true;
|
||||
connector->video_latency[0] = 11;
|
||||
connector->audio_latency[0] = 22;
|
||||
|
||||
amdgpu_dm_fill_audio_info(audio_info, connector, dc_sink);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, audio_info->video_latency, 11U);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->audio_latency, 22U);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_fill_audio_info_latency_absent_keeps_zero - Test Fill audio info latency absent keeps zero
|
||||
* @test: The KUnit test context
|
||||
*/
|
||||
static void dm_test_fill_audio_info_latency_absent_keeps_zero(struct kunit *test)
|
||||
{
|
||||
struct audio_info *audio_info;
|
||||
struct drm_connector *connector;
|
||||
struct dc_sink *dc_sink;
|
||||
|
||||
audio_info = kunit_kzalloc(test, sizeof(*audio_info), GFP_KERNEL);
|
||||
connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
|
||||
dc_sink = kunit_kzalloc(test, sizeof(*dc_sink), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, audio_info);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc_sink);
|
||||
|
||||
connector->display_info.cea_rev = 3;
|
||||
connector->latency_present[0] = false;
|
||||
connector->video_latency[0] = 99;
|
||||
connector->audio_latency[0] = 88;
|
||||
|
||||
amdgpu_dm_fill_audio_info(audio_info, connector, dc_sink);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, audio_info->video_latency, 0U);
|
||||
KUNIT_EXPECT_EQ(test, audio_info->audio_latency, 0U);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_fill_audio_info_cea_ge_3_zero_modes - Test cea >= 3 with zero modes
|
||||
* @test: The KUnit test context
|
||||
*
|
||||
* When cea_rev >= 3 but the sink reports no audio modes, mode_count must be
|
||||
* copied as 0 and no mode entries should be populated.
|
||||
*/
|
||||
static void dm_test_fill_audio_info_cea_ge_3_zero_modes(struct kunit *test)
|
||||
{
|
||||
struct audio_info *audio_info;
|
||||
struct drm_connector *connector;
|
||||
struct dc_sink *dc_sink;
|
||||
|
||||
audio_info = kunit_kzalloc(test, sizeof(*audio_info), GFP_KERNEL);
|
||||
connector = kunit_kzalloc(test, sizeof(*connector), GFP_KERNEL);
|
||||
dc_sink = kunit_kzalloc(test, sizeof(*dc_sink), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, audio_info);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, connector);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dc_sink);
|
||||
|
||||
connector->display_info.cea_rev = 3;
|
||||
dc_sink->edid_caps.audio_mode_count = 0;
|
||||
|
||||
amdgpu_dm_fill_audio_info(audio_info, connector, dc_sink);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, audio_info->mode_count, 0U);
|
||||
KUNIT_EXPECT_EQ(test, (int)audio_info->modes[0].format_code, 0);
|
||||
}
|
||||
|
||||
/* Tests for amdgpu_dm_audio_component_bind()/unbind() */
|
||||
|
||||
/**
|
||||
* dm_test_audio_component_bind_sets_fields - Test bind wires up audio component
|
||||
* @test: The KUnit test context
|
||||
*
|
||||
* Binding must publish the DRM audio component ops, record the kernel device,
|
||||
* and store the component pointer in the display manager.
|
||||
*/
|
||||
static void dm_test_audio_component_bind_sets_fields(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct device *kdev;
|
||||
struct drm_audio_component *acomp;
|
||||
int ret;
|
||||
|
||||
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
|
||||
kdev = kunit_kzalloc(test, sizeof(*kdev), GFP_KERNEL);
|
||||
acomp = kunit_kzalloc(test, sizeof(*acomp), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, kdev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acomp);
|
||||
|
||||
dev_set_drvdata(kdev, &adev->ddev);
|
||||
|
||||
ret = amdgpu_dm_audio_component_bind(kdev, NULL, acomp);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, ret, 0);
|
||||
KUNIT_EXPECT_NOT_NULL(test, acomp->ops);
|
||||
KUNIT_EXPECT_PTR_EQ(test, acomp->dev, kdev);
|
||||
KUNIT_EXPECT_PTR_EQ(test, adev->dm.audio_component, acomp);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_audio_component_unbind_clears_fields - Test unbind tears down component
|
||||
* @test: The KUnit test context
|
||||
*
|
||||
* Unbinding must clear the component ops, the kernel device, and the display
|
||||
* manager's stored component pointer.
|
||||
*/
|
||||
static void dm_test_audio_component_unbind_clears_fields(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct device *kdev;
|
||||
struct drm_audio_component *acomp;
|
||||
|
||||
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
|
||||
kdev = kunit_kzalloc(test, sizeof(*kdev), GFP_KERNEL);
|
||||
acomp = kunit_kzalloc(test, sizeof(*acomp), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, kdev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acomp);
|
||||
|
||||
dev_set_drvdata(kdev, &adev->ddev);
|
||||
|
||||
/* Pretend a prior bind already happened. */
|
||||
acomp->dev = kdev;
|
||||
adev->dm.audio_component = acomp;
|
||||
|
||||
amdgpu_dm_audio_component_unbind(kdev, NULL, acomp);
|
||||
|
||||
KUNIT_EXPECT_NULL(test, acomp->ops);
|
||||
KUNIT_EXPECT_NULL(test, acomp->dev);
|
||||
KUNIT_EXPECT_NULL(test, adev->dm.audio_component);
|
||||
}
|
||||
|
||||
/* Tests for amdgpu_dm_audio_eld_notify() */
|
||||
|
||||
static int dm_test_eld_notify_count;
|
||||
static int dm_test_eld_notify_port;
|
||||
static void *dm_test_eld_notify_ptr;
|
||||
|
||||
static void dm_test_pin_eld_notify(void *audio_ptr, int port, int pipe)
|
||||
{
|
||||
dm_test_eld_notify_count++;
|
||||
dm_test_eld_notify_port = port;
|
||||
dm_test_eld_notify_ptr = audio_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_eld_notify_invokes_callback - Test ELD notify forwards to hda driver
|
||||
* @test: The KUnit test context
|
||||
*
|
||||
* When a component with a pin_eld_notify callback is registered, the notify
|
||||
* helper must invoke it with the audio pointer and the requested pin.
|
||||
*/
|
||||
static void dm_test_eld_notify_invokes_callback(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct drm_audio_component *acomp;
|
||||
struct drm_audio_component_audio_ops *audio_ops;
|
||||
int marker = 0;
|
||||
|
||||
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
|
||||
acomp = kunit_kzalloc(test, sizeof(*acomp), GFP_KERNEL);
|
||||
audio_ops = kunit_kzalloc(test, sizeof(*audio_ops), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acomp);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, audio_ops);
|
||||
|
||||
audio_ops->audio_ptr = ▮
|
||||
audio_ops->pin_eld_notify = dm_test_pin_eld_notify;
|
||||
acomp->audio_ops = audio_ops;
|
||||
adev->dm.audio_component = acomp;
|
||||
|
||||
dm_test_eld_notify_count = 0;
|
||||
dm_test_eld_notify_port = -100;
|
||||
dm_test_eld_notify_ptr = NULL;
|
||||
|
||||
amdgpu_dm_audio_eld_notify(adev, 7);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 1);
|
||||
KUNIT_EXPECT_EQ(test, dm_test_eld_notify_port, 7);
|
||||
KUNIT_EXPECT_PTR_EQ(test, dm_test_eld_notify_ptr, (void *)&marker);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_eld_notify_no_component - Test ELD notify is a no-op without component
|
||||
* @test: The KUnit test context
|
||||
*
|
||||
* With no registered audio component, the notify helper must return without
|
||||
* invoking any callback.
|
||||
*/
|
||||
static void dm_test_eld_notify_no_component(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
|
||||
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
|
||||
|
||||
adev->dm.audio_component = NULL;
|
||||
|
||||
dm_test_eld_notify_count = 0;
|
||||
|
||||
amdgpu_dm_audio_eld_notify(adev, 3);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_eld_notify_null_audio_ops - Test ELD notify is a no-op without audio_ops
|
||||
* @test: The KUnit test context
|
||||
*
|
||||
* A component without audio_ops must not trigger any callback.
|
||||
*/
|
||||
static void dm_test_eld_notify_null_audio_ops(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct drm_audio_component *acomp;
|
||||
|
||||
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
|
||||
acomp = kunit_kzalloc(test, sizeof(*acomp), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acomp);
|
||||
|
||||
acomp->audio_ops = NULL;
|
||||
adev->dm.audio_component = acomp;
|
||||
|
||||
dm_test_eld_notify_count = 0;
|
||||
|
||||
amdgpu_dm_audio_eld_notify(adev, 3);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_test_eld_notify_null_callback - Test ELD notify is a no-op without callback
|
||||
* @test: The KUnit test context
|
||||
*
|
||||
* audio_ops present but with a NULL pin_eld_notify must not crash or call
|
||||
* anything.
|
||||
*/
|
||||
static void dm_test_eld_notify_null_callback(struct kunit *test)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct drm_audio_component *acomp;
|
||||
struct drm_audio_component_audio_ops *audio_ops;
|
||||
|
||||
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
|
||||
acomp = kunit_kzalloc(test, sizeof(*acomp), GFP_KERNEL);
|
||||
audio_ops = kunit_kzalloc(test, sizeof(*audio_ops), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acomp);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, audio_ops);
|
||||
|
||||
audio_ops->pin_eld_notify = NULL;
|
||||
acomp->audio_ops = audio_ops;
|
||||
adev->dm.audio_component = acomp;
|
||||
|
||||
dm_test_eld_notify_count = 0;
|
||||
|
||||
amdgpu_dm_audio_eld_notify(adev, 3);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 0);
|
||||
}
|
||||
|
||||
static struct kunit_case dm_audio_test_cases[] = {
|
||||
/* amdgpu_dm_audio_init */
|
||||
KUNIT_CASE(dm_test_audio_init_disabled),
|
||||
/* amdgpu_dm_audio_fini */
|
||||
KUNIT_CASE(dm_test_audio_fini_without_enabled_audio),
|
||||
/* amdgpu_dm_fill_audio_info */
|
||||
KUNIT_CASE(dm_test_fill_audio_info_ids_name_flags),
|
||||
KUNIT_CASE(dm_test_fill_audio_info_cea_lt_3_skips_modes),
|
||||
KUNIT_CASE(dm_test_fill_audio_info_cea_ge_3_copies_modes),
|
||||
KUNIT_CASE(dm_test_fill_audio_info_cea_ge_3_zero_modes),
|
||||
KUNIT_CASE(dm_test_fill_audio_info_latency_present),
|
||||
KUNIT_CASE(dm_test_fill_audio_info_latency_absent_keeps_zero),
|
||||
/* amdgpu_dm_audio_component_bind/unbind */
|
||||
KUNIT_CASE(dm_test_audio_component_bind_sets_fields),
|
||||
KUNIT_CASE(dm_test_audio_component_unbind_clears_fields),
|
||||
/* amdgpu_dm_audio_eld_notify */
|
||||
KUNIT_CASE(dm_test_eld_notify_invokes_callback),
|
||||
KUNIT_CASE(dm_test_eld_notify_no_component),
|
||||
KUNIT_CASE(dm_test_eld_notify_null_audio_ops),
|
||||
KUNIT_CASE(dm_test_eld_notify_null_callback),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite dm_audio_test_suite = {
|
||||
.name = "amdgpu_dm_audio",
|
||||
.test_cases = dm_audio_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(dm_audio_test_suite);
|
||||
|
||||
MODULE_LICENSE("Dual MIT/GPL");
|
||||
MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_audio");
|
||||
MODULE_AUTHOR("AMD");
|
||||
Reference in New Issue
Block a user