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:
Alex Hung
2026-04-29 21:17:43 -06:00
committed by Alex Deucher
parent 179b22085e
commit c71a6dc1cf
4 changed files with 527 additions and 3 deletions

View File

@@ -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

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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 = &marker;
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");