From: Fangzhi Zuo <jerry.zuo@amd.com>
To: <amd-gfx@lists.freedesktop.org>
Cc: Harry Wentland <harry.wentland@amd.com>,
Leo Li <sunpeng.li@amd.com>,
Aurabindo Pillai <aurabindo.pillai@amd.com>,
Roman Li <roman.li@amd.com>, Wayne Lin <wayne.lin@amd.com>,
Tom Chung <chiahsuan.chung@amd.com>,
"Fangzhi Zuo" <jerry.zuo@amd.com>,
Dan Wheeler <daniel.wheeler@amd.com>, Ray Wu <Ray.Wu@amd.com>,
Ivan Lipski <ivan.lipski@amd.com>, Alex Hung <alex.hung@amd.com>,
James Lin <PingLei.Lin@amd.com>,
Chenyu Chen <Chen-Yu.Chen@amd.com>,
Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Subject: [PATCH 19/49] drm/amd/display: add KUnit tests for audio commit path
Date: Thu, 23 Jul 2026 16:13:27 -0400 [thread overview]
Message-ID: <20260723201908.373300-20-jerry.zuo@amd.com> (raw)
In-Reply-To: <20260723201908.373300-1-jerry.zuo@amd.com>
From: Alex Hung <alex.hung@amd.com>
[WHAT]
Add KUnit coverage for amdgpu_dm_commit_audio(), the remaining function
reported as untested by gcov.
The tests build hand-rolled drm_atomic_state arrays and back
dc_stream_get_status() with a fake dc->current_state to cover the
removal and addition ELD notifications along with their guard/skip
paths: writeback connector, detached connector, missing new CRTC state,
no modeset, and absent stream status.
Reviewed-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
---
.../amd/display/amdgpu_dm/amdgpu_dm_audio.c | 1 +
.../amdgpu_dm/tests/amdgpu_dm_audio_test.c | 532 ++++++++++++++++++
2 files changed, 533 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.c
index 4b10c683df8e..199f339839b2 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.c
@@ -321,6 +321,7 @@ void amdgpu_dm_commit_audio(struct drm_device *dev,
amdgpu_dm_audio_eld_notify(adev, inst);
}
}
+EXPORT_IF_KUNIT(amdgpu_dm_commit_audio);
#if IS_ENABLED(CONFIG_DRM_AMD_DC_KUNIT_TEST)
int amdgpu_dm_audio_get_param(void)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_audio_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_audio_test.c
index d30b7f644f97..040a7a9c0335 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_audio_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_audio_test.c
@@ -8,9 +8,11 @@
#include <kunit/test.h>
#include <linux/device.h>
+#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_audio_component.h>
#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
#include <drm/drm_eld.h>
#include <drm/drm_kunit_helpers.h>
#include <drm/drm_probe_helper.h>
@@ -37,6 +39,32 @@ static void dm_test_audio_connector_cleanup(void *data)
drm_connector_cleanup(data);
}
+static struct drm_atomic_commit *dm_test_audio_alloc_atomic_state(struct kunit *test,
+ unsigned int num_connector,
+ unsigned int num_crtc)
+{
+ struct drm_atomic_commit *state;
+
+ state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, state);
+
+ state->num_connector = num_connector;
+ if (num_connector) {
+ state->connectors = kunit_kcalloc(test, num_connector,
+ sizeof(*state->connectors),
+ GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, state->connectors);
+ }
+
+ if (num_crtc) {
+ state->crtcs = kunit_kcalloc(test, num_crtc, sizeof(*state->crtcs),
+ GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, state->crtcs);
+ }
+
+ return state;
+}
+
/* Tests for amdgpu_dm_audio_init() */
/**
@@ -411,6 +439,22 @@ static void dm_test_pin_eld_notify(void *audio_ptr, int port, int pipe)
dm_test_eld_notify_ptr = audio_ptr;
}
+static void dm_test_audio_setup_notify_component(struct kunit *test,
+ struct amdgpu_device *adev)
+{
+ struct drm_audio_component *acomp;
+ struct drm_audio_component_audio_ops *audio_ops;
+
+ acomp = kunit_kzalloc(test, sizeof(*acomp), GFP_KERNEL);
+ audio_ops = kunit_kzalloc(test, sizeof(*audio_ops), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, acomp);
+ KUNIT_ASSERT_NOT_NULL(test, audio_ops);
+
+ audio_ops->pin_eld_notify = dm_test_pin_eld_notify;
+ acomp->audio_ops = audio_ops;
+ adev->dm.audio_component = acomp;
+}
+
/**
* dm_test_eld_notify_invokes_callback - Test ELD notify forwards to hda driver
* @test: The KUnit test context
@@ -685,6 +729,484 @@ static void dm_test_audio_component_get_eld_no_match(struct kunit *test)
KUNIT_EXPECT_EQ(test, buf[0], 0x5a);
}
+/* Tests for amdgpu_dm_commit_audio() */
+
+/**
+ * dm_test_commit_audio_notifies_removed_connector - Test removal notification
+ * @test: The KUnit test context
+ *
+ * When a connector loses its CRTC, commit_audio should clear its audio
+ * instance and notify the audio component for the old pin.
+ */
+static void dm_test_commit_audio_notifies_removed_connector(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct drm_atomic_commit *state;
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc *crtc;
+
+ state = dm_test_audio_alloc_atomic_state(test, 1, 0);
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ old_conn_state = kunit_kzalloc(test, sizeof(*old_conn_state), GFP_KERNEL);
+ new_conn_state = kunit_kzalloc(test, sizeof(*new_conn_state), GFP_KERNEL);
+ crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ KUNIT_ASSERT_NOT_NULL(test, old_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, crtc);
+
+ mutex_init(&adev->dm.audio_lock);
+ dm_test_audio_setup_notify_component(test, adev);
+ aconnector->audio_inst = 5;
+ aconnector->base.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ old_conn_state->crtc = crtc;
+ state->connectors[0].ptr = &aconnector->base;
+ state->connectors[0].old_state = old_conn_state;
+ state->connectors[0].new_state = new_conn_state;
+
+ dm_test_eld_notify_count = 0;
+ dm_test_eld_notify_port = -1;
+
+ amdgpu_dm_commit_audio(&adev->ddev, state);
+
+ KUNIT_EXPECT_EQ(test, aconnector->audio_inst, -1);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 1);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_port, 5);
+}
+
+/**
+ * dm_test_commit_audio_notifies_added_connector - Test addition notification
+ * @test: The KUnit test context
+ *
+ * When a modeset enables a connector with a stream status, commit_audio should
+ * store the stream audio instance and notify the audio component for that pin.
+ */
+static void dm_test_commit_audio_notifies_added_connector(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct drm_atomic_commit *state;
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc *crtc;
+ struct dm_crtc_state *dm_crtc_state;
+ struct dc_stream_state *stream;
+
+ state = dm_test_audio_alloc_atomic_state(test, 1, 1);
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ old_conn_state = kunit_kzalloc(test, sizeof(*old_conn_state), GFP_KERNEL);
+ new_conn_state = kunit_kzalloc(test, sizeof(*new_conn_state), GFP_KERNEL);
+ crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+ dm_crtc_state = kunit_kzalloc(test, sizeof(*dm_crtc_state), GFP_KERNEL);
+ stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ KUNIT_ASSERT_NOT_NULL(test, old_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, crtc);
+ KUNIT_ASSERT_NOT_NULL(test, dm_crtc_state);
+ KUNIT_ASSERT_NOT_NULL(test, stream);
+
+ adev->dm.dc = kunit_kzalloc(test, sizeof(*adev->dm.dc), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, adev->dm.dc);
+ adev->dm.dc->current_state = kunit_kzalloc(test,
+ sizeof(*adev->dm.dc->current_state),
+ GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, adev->dm.dc->current_state);
+ stream->ctx = kunit_kzalloc(test, sizeof(*stream->ctx), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, stream->ctx);
+ stream->ctx->dc = adev->dm.dc;
+ adev->dm.dc->current_state->stream_count = 1;
+ adev->dm.dc->current_state->streams[0] = stream;
+ adev->dm.dc->current_state->stream_status[0].audio_inst = 8;
+
+ mutex_init(&adev->dm.audio_lock);
+ dm_test_audio_setup_notify_component(test, adev);
+ aconnector->audio_inst = -1;
+ aconnector->base.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ crtc->index = 0;
+ new_conn_state->crtc = crtc;
+ dm_crtc_state->base.crtc = crtc;
+ dm_crtc_state->base.mode_changed = true;
+ dm_crtc_state->stream = stream;
+ state->connectors[0].ptr = &aconnector->base;
+ state->connectors[0].old_state = old_conn_state;
+ state->connectors[0].new_state = new_conn_state;
+ state->crtcs[0].ptr = crtc;
+ state->crtcs[0].new_state = &dm_crtc_state->base;
+
+ dm_test_eld_notify_count = 0;
+ dm_test_eld_notify_port = -1;
+
+ amdgpu_dm_commit_audio(&adev->ddev, state);
+
+ KUNIT_EXPECT_EQ(test, aconnector->audio_inst, 8);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 2);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_port, 8);
+}
+
+/**
+ * dm_test_commit_audio_skips_writeback_removal - Test writeback removal skip
+ * @test: The KUnit test context
+ *
+ * Writeback connectors do not represent an HDA audio pin, so removal-style
+ * notifications should leave their audio instance untouched.
+ */
+static void dm_test_commit_audio_skips_writeback_removal(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct drm_atomic_commit *state;
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc *crtc;
+
+ state = dm_test_audio_alloc_atomic_state(test, 1, 0);
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ old_conn_state = kunit_kzalloc(test, sizeof(*old_conn_state), GFP_KERNEL);
+ new_conn_state = kunit_kzalloc(test, sizeof(*new_conn_state), GFP_KERNEL);
+ crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ KUNIT_ASSERT_NOT_NULL(test, old_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, crtc);
+
+ mutex_init(&adev->dm.audio_lock);
+ dm_test_audio_setup_notify_component(test, adev);
+ aconnector->audio_inst = 9;
+ aconnector->base.connector_type = DRM_MODE_CONNECTOR_WRITEBACK;
+ old_conn_state->crtc = crtc;
+ state->connectors[0].ptr = &aconnector->base;
+ state->connectors[0].old_state = old_conn_state;
+ state->connectors[0].new_state = new_conn_state;
+
+ dm_test_eld_notify_count = 0;
+
+ amdgpu_dm_commit_audio(&adev->ddev, state);
+
+ KUNIT_EXPECT_EQ(test, aconnector->audio_inst, 9);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 0);
+}
+
+/**
+ * dm_test_commit_audio_skips_without_new_crtc_state - Test missing CRTC state
+ * @test: The KUnit test context
+ *
+ * A connector still attached to the same CRTC should not notify if the atomic
+ * state does not contain a new CRTC state for that CRTC.
+ */
+static void dm_test_commit_audio_skips_without_new_crtc_state(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct drm_atomic_commit *state;
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc *crtc;
+
+ state = dm_test_audio_alloc_atomic_state(test, 1, 1);
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ old_conn_state = kunit_kzalloc(test, sizeof(*old_conn_state), GFP_KERNEL);
+ new_conn_state = kunit_kzalloc(test, sizeof(*new_conn_state), GFP_KERNEL);
+ crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ KUNIT_ASSERT_NOT_NULL(test, old_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, crtc);
+
+ mutex_init(&adev->dm.audio_lock);
+ dm_test_audio_setup_notify_component(test, adev);
+ aconnector->audio_inst = 4;
+ aconnector->base.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ crtc->index = 0;
+ old_conn_state->crtc = crtc;
+ new_conn_state->crtc = crtc;
+ state->connectors[0].ptr = &aconnector->base;
+ state->connectors[0].old_state = old_conn_state;
+ state->connectors[0].new_state = new_conn_state;
+
+ dm_test_eld_notify_count = 0;
+
+ amdgpu_dm_commit_audio(&adev->ddev, state);
+
+ KUNIT_EXPECT_EQ(test, aconnector->audio_inst, 4);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 0);
+}
+
+/**
+ * dm_test_commit_audio_skips_without_stream_status - Test missing DC status
+ * @test: The KUnit test context
+ *
+ * If the new CRTC stream is absent from the current DC state, additions should
+ * be skipped because there is no audio instance to publish.
+ */
+static void dm_test_commit_audio_skips_without_stream_status(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct drm_atomic_commit *state;
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc *crtc;
+ struct dm_crtc_state *dm_crtc_state;
+ struct dc_stream_state *stream;
+
+ state = dm_test_audio_alloc_atomic_state(test, 1, 1);
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ old_conn_state = kunit_kzalloc(test, sizeof(*old_conn_state), GFP_KERNEL);
+ new_conn_state = kunit_kzalloc(test, sizeof(*new_conn_state), GFP_KERNEL);
+ crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+ dm_crtc_state = kunit_kzalloc(test, sizeof(*dm_crtc_state), GFP_KERNEL);
+ stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ KUNIT_ASSERT_NOT_NULL(test, old_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, crtc);
+ KUNIT_ASSERT_NOT_NULL(test, dm_crtc_state);
+ KUNIT_ASSERT_NOT_NULL(test, stream);
+
+ adev->dm.dc = kunit_kzalloc(test, sizeof(*adev->dm.dc), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, adev->dm.dc);
+ adev->dm.dc->current_state = kunit_kzalloc(test,
+ sizeof(*adev->dm.dc->current_state),
+ GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, adev->dm.dc->current_state);
+ stream->ctx = kunit_kzalloc(test, sizeof(*stream->ctx), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, stream->ctx);
+ stream->ctx->dc = adev->dm.dc;
+
+ mutex_init(&adev->dm.audio_lock);
+ dm_test_audio_setup_notify_component(test, adev);
+ aconnector->audio_inst = -1;
+ aconnector->base.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ crtc->index = 0;
+ new_conn_state->crtc = crtc;
+ dm_crtc_state->base.crtc = crtc;
+ dm_crtc_state->base.mode_changed = true;
+ dm_crtc_state->stream = stream;
+ state->connectors[0].ptr = &aconnector->base;
+ state->connectors[0].old_state = old_conn_state;
+ state->connectors[0].new_state = new_conn_state;
+ state->crtcs[0].ptr = crtc;
+ state->crtcs[0].new_state = &dm_crtc_state->base;
+
+ dm_test_eld_notify_count = 0;
+
+ amdgpu_dm_commit_audio(&adev->ddev, state);
+
+ KUNIT_EXPECT_EQ(test, aconnector->audio_inst, -1);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 1);
+}
+
+/**
+ * dm_test_commit_audio_skips_detached_connector - Test detached connector skip
+ * @test: The KUnit test context
+ *
+ * A connector that remains detached across the commit should not notify or
+ * alter the stored audio instance.
+ */
+static void dm_test_commit_audio_skips_detached_connector(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct drm_atomic_commit *state;
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+
+ state = dm_test_audio_alloc_atomic_state(test, 1, 0);
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ old_conn_state = kunit_kzalloc(test, sizeof(*old_conn_state), GFP_KERNEL);
+ new_conn_state = kunit_kzalloc(test, sizeof(*new_conn_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ KUNIT_ASSERT_NOT_NULL(test, old_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
+
+ aconnector->audio_inst = 11;
+ aconnector->base.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ state->connectors[0].ptr = &aconnector->base;
+ state->connectors[0].old_state = old_conn_state;
+ state->connectors[0].new_state = new_conn_state;
+
+ dm_test_eld_notify_count = 0;
+
+ amdgpu_dm_commit_audio(&adev->ddev, state);
+
+ KUNIT_EXPECT_EQ(test, aconnector->audio_inst, 11);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 0);
+}
+
+/**
+ * dm_test_commit_audio_skips_without_modeset - Test no-modeset skip
+ * @test: The KUnit test context
+ *
+ * A connector that stays on the same CRTC should not notify if that CRTC does
+ * not need a modeset.
+ */
+static void dm_test_commit_audio_skips_without_modeset(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct drm_atomic_commit *state;
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc *crtc;
+ struct dm_crtc_state *dm_crtc_state;
+
+ state = dm_test_audio_alloc_atomic_state(test, 1, 1);
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ old_conn_state = kunit_kzalloc(test, sizeof(*old_conn_state), GFP_KERNEL);
+ new_conn_state = kunit_kzalloc(test, sizeof(*new_conn_state), GFP_KERNEL);
+ crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+ dm_crtc_state = kunit_kzalloc(test, sizeof(*dm_crtc_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ KUNIT_ASSERT_NOT_NULL(test, old_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, crtc);
+ KUNIT_ASSERT_NOT_NULL(test, dm_crtc_state);
+
+ aconnector->audio_inst = 12;
+ aconnector->base.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ crtc->index = 0;
+ old_conn_state->crtc = crtc;
+ new_conn_state->crtc = crtc;
+ dm_crtc_state->base.crtc = crtc;
+ state->connectors[0].ptr = &aconnector->base;
+ state->connectors[0].old_state = old_conn_state;
+ state->connectors[0].new_state = new_conn_state;
+ state->crtcs[0].ptr = crtc;
+ state->crtcs[0].new_state = &dm_crtc_state->base;
+
+ dm_test_eld_notify_count = 0;
+
+ amdgpu_dm_commit_audio(&adev->ddev, state);
+
+ KUNIT_EXPECT_EQ(test, aconnector->audio_inst, 12);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 0);
+}
+
+/**
+ * dm_test_commit_audio_skips_addition_without_stream - Test NULL stream skip
+ * @test: The KUnit test context
+ *
+ * A modeset still sends the removal-side ELD notification, but the addition
+ * side must skip if the new DM CRTC state has no stream.
+ */
+static void dm_test_commit_audio_skips_addition_without_stream(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct drm_atomic_commit *state;
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc *crtc;
+ struct dm_crtc_state *dm_crtc_state;
+
+ state = dm_test_audio_alloc_atomic_state(test, 1, 1);
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ old_conn_state = kunit_kzalloc(test, sizeof(*old_conn_state), GFP_KERNEL);
+ new_conn_state = kunit_kzalloc(test, sizeof(*new_conn_state), GFP_KERNEL);
+ crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+ dm_crtc_state = kunit_kzalloc(test, sizeof(*dm_crtc_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ KUNIT_ASSERT_NOT_NULL(test, old_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, crtc);
+ KUNIT_ASSERT_NOT_NULL(test, dm_crtc_state);
+
+ mutex_init(&adev->dm.audio_lock);
+ dm_test_audio_setup_notify_component(test, adev);
+ aconnector->audio_inst = 13;
+ aconnector->base.connector_type = DRM_MODE_CONNECTOR_HDMIA;
+ crtc->index = 0;
+ old_conn_state->crtc = crtc;
+ new_conn_state->crtc = crtc;
+ dm_crtc_state->base.crtc = crtc;
+ dm_crtc_state->base.mode_changed = true;
+ state->connectors[0].ptr = &aconnector->base;
+ state->connectors[0].old_state = old_conn_state;
+ state->connectors[0].new_state = new_conn_state;
+ state->crtcs[0].ptr = crtc;
+ state->crtcs[0].new_state = &dm_crtc_state->base;
+
+ dm_test_eld_notify_count = 0;
+ dm_test_eld_notify_port = -1;
+
+ amdgpu_dm_commit_audio(&adev->ddev, state);
+
+ KUNIT_EXPECT_EQ(test, aconnector->audio_inst, -1);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_count, 1);
+ KUNIT_EXPECT_EQ(test, dm_test_eld_notify_port, 13);
+}
+
+/**
+ * dm_test_commit_audio_skips_writeback_addition - Test writeback addition skip
+ * @test: The KUnit test context
+ *
+ * Even with a valid modeset and stream status, writeback connectors must not
+ * publish an HDA audio instance.
+ */
+static void dm_test_commit_audio_skips_writeback_addition(struct kunit *test)
+{
+ struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+ struct drm_atomic_commit *state;
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *old_conn_state;
+ struct drm_connector_state *new_conn_state;
+ struct drm_crtc *crtc;
+ struct dm_crtc_state *dm_crtc_state;
+ struct dc_stream_state *stream;
+
+ state = dm_test_audio_alloc_atomic_state(test, 1, 1);
+ aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+ old_conn_state = kunit_kzalloc(test, sizeof(*old_conn_state), GFP_KERNEL);
+ new_conn_state = kunit_kzalloc(test, sizeof(*new_conn_state), GFP_KERNEL);
+ crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+ dm_crtc_state = kunit_kzalloc(test, sizeof(*dm_crtc_state), GFP_KERNEL);
+ stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, aconnector);
+ KUNIT_ASSERT_NOT_NULL(test, old_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
+ KUNIT_ASSERT_NOT_NULL(test, crtc);
+ KUNIT_ASSERT_NOT_NULL(test, dm_crtc_state);
+ KUNIT_ASSERT_NOT_NULL(test, stream);
+
+ adev->dm.dc = kunit_kzalloc(test, sizeof(*adev->dm.dc), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, adev->dm.dc);
+ adev->dm.dc->current_state = kunit_kzalloc(test,
+ sizeof(*adev->dm.dc->current_state),
+ GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, adev->dm.dc->current_state);
+ stream->ctx = kunit_kzalloc(test, sizeof(*stream->ctx), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, stream->ctx);
+ stream->ctx->dc = adev->dm.dc;
+ adev->dm.dc->current_state->stream_count = 1;
+ adev->dm.dc->current_state->streams[0] = stream;
+ adev->dm.dc->current_state->stream_status[0].audio_inst = 14;
+
+ mutex_init(&adev->dm.audio_lock);
+ dm_test_audio_setup_notify_component(test, adev);
+ aconnector->audio_inst = 15;
+ aconnector->base.connector_type = DRM_MODE_CONNECTOR_WRITEBACK;
+ crtc->index = 0;
+ new_conn_state->crtc = crtc;
+ dm_crtc_state->base.crtc = crtc;
+ dm_crtc_state->base.mode_changed = true;
+ dm_crtc_state->stream = stream;
+ state->connectors[0].ptr = &aconnector->base;
+ state->connectors[0].old_state = old_conn_state;
+ state->connectors[0].new_state = new_conn_state;
+ state->crtcs[0].ptr = crtc;
+ state->crtcs[0].new_state = &dm_crtc_state->base;
+
+ dm_test_eld_notify_count = 0;
+
+ amdgpu_dm_commit_audio(&adev->ddev, state);
+
+ KUNIT_EXPECT_EQ(test, aconnector->audio_inst, 15);
+ 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),
@@ -712,6 +1234,16 @@ static struct kunit_case dm_audio_test_cases[] = {
/* amdgpu_dm_audio_component_get_eld */
KUNIT_CASE(dm_test_audio_component_get_eld_copies_matching_connector),
KUNIT_CASE(dm_test_audio_component_get_eld_no_match),
+ /* amdgpu_dm_commit_audio */
+ KUNIT_CASE(dm_test_commit_audio_notifies_removed_connector),
+ KUNIT_CASE(dm_test_commit_audio_notifies_added_connector),
+ KUNIT_CASE(dm_test_commit_audio_skips_writeback_removal),
+ KUNIT_CASE(dm_test_commit_audio_skips_without_new_crtc_state),
+ KUNIT_CASE(dm_test_commit_audio_skips_without_stream_status),
+ KUNIT_CASE(dm_test_commit_audio_skips_detached_connector),
+ KUNIT_CASE(dm_test_commit_audio_skips_without_modeset),
+ KUNIT_CASE(dm_test_commit_audio_skips_addition_without_stream),
+ KUNIT_CASE(dm_test_commit_audio_skips_writeback_addition),
{}
};
--
2.53.0
next prev parent reply other threads:[~2026-07-23 20:19 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-23 20:13 [PATCH 00/49] DC Patches July 20th, 2026 Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 01/49] drm/amd/display: share common DM KUnit helpers Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 02/49] drm/amd/display: Port DCN4+ MCIF ARB programming to new format Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 03/49] drm/amd/display: Fix force FRL rate debug setting Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 04/49] drm/amd/display: Add KUnit tests for link_lock and psp SRM helpers Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 05/49] drm/amd/display: Add KUnit tests for HDCP display helpers Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 06/49] drm/amd/display: Add KUnit tests for event_callback Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 07/49] drm/amd/display: Add KUnit tests for event_property_validate Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 08/49] drm/amd/display: Add KUnit tests for watchdog and cpirq events Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 09/49] drm/amd/display: Add KUnit tests for hdcp_destroy Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 10/49] drm/amd/display: Add AV mute wait frames to dce110_set_avmute Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 11/49] drm/amd/display: revert "convert dcn42 GPIO translation to lookup tables" Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 12/49] drm/amd/display: move scaling helper to connector Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 13/49] drm/amd/display: move stutter quirk to quirks file Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 14/49] drm/amd/display: move watermarks table to pp_smu Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 15/49] drm/amd/display: move GPU mem helpers to services Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 16/49] drm/amd/display: add FreeSync/VRR module Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 17/49] drm/amd/display: add cursor module Fangzhi Zuo
2026-08-03 12:48 ` Timur Kristóf
2026-07-23 20:13 ` [PATCH 18/49] drm/amd/display: add KUnit tests for audio component get_eld Fangzhi Zuo
2026-07-23 20:13 ` Fangzhi Zuo [this message]
2026-07-23 20:13 ` [PATCH 20/49] drm/amd/display: Use current mpc pipe in set output transfer func Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 21/49] drm/amd/display: Correct vblank_end calc for fams cmd packet Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 22/49] drm/amd/display: Add KUnit test for native backlight registration Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 23/49] drm/amd/display: Add color transfer-function tests Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 24/49] drm/amd/display: Add atomic " Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 25/49] drm/amd/display: Add CRTC and plane degamma tests Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 26/49] drm/amd/display: Add legacy plane LUT tests Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 27/49] drm/amd/display: Add truncated colorop tests Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 28/49] drm/amd/display: Add colorop LUT programming tests Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 29/49] drm/amd/display: Add KUnit tests for enable_assr Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 30/49] drm/amd/display: Add KUnit tests for update_config Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 31/49] drm/amd/display: Add KUnit tests for hdcp_create_workqueue Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 32/49] drm/amd/display: Add KUnit tests for srm_data_write and srm_data_read Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 33/49] drm/amd/display: Add KUnit tests for HDCP DDC link adapters Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 34/49] drm/amd/display: Add initialized-branch test for psp_set_srm Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 35/49] drm/amd/display: Add deeper event_property_update tests Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 36/49] drm/amd/display: adjust floating point format for gamut remap when needed Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 37/49] drm/amd/display: Reintroduce "convert dcn42 GPIO translation to lookup tables" Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 38/49] drm/amd/display: Prune per-tile Timing from Apple Studio Display Primary Tile Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 39/49] drm/amd/display: Add get replay residency function Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 40/49] drm/amd/display: Fix divide-by-zero in calculate_mcache_setting on zero viewport Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 41/49] drm/amd/display: check if dml21_add_phantom_plane() is successful Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 42/49] drm/amd/display: change dcc_rate from 1 to 2 for log use only Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 43/49] drm/amd/display: enforce UCLK pstate support in mode_support Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 44/49] drm/amd/display: add DalForceMaxDisplayClock debug option to DML2 Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 45/49] drm/amd/display: Fixes for dcn42b_soc_bb.h Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 46/49] drm/amd/display: Fix rounding errors in CalculatePrefetchSchedule Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 47/49] drm/amd/display: plumb PMO per-plane pstate methods into mode_support Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 48/49] drm/amd/display: dispatch compressed FRL cap check inside dml1_frl_cap_chk_inter Fangzhi Zuo
2026-07-23 20:13 ` [PATCH 49/49] drm/amd/display: Promote DC to 3.2.391 Fangzhi Zuo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260723201908.373300-20-jerry.zuo@amd.com \
--to=jerry.zuo@amd.com \
--cc=Chen-Yu.Chen@amd.com \
--cc=PingLei.Lin@amd.com \
--cc=Ray.Wu@amd.com \
--cc=alex.hung@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=aurabindo.pillai@amd.com \
--cc=bhawanpreet.lakha@amd.com \
--cc=chiahsuan.chung@amd.com \
--cc=daniel.wheeler@amd.com \
--cc=harry.wentland@amd.com \
--cc=ivan.lipski@amd.com \
--cc=roman.li@amd.com \
--cc=sunpeng.li@amd.com \
--cc=wayne.lin@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.