mirror of
https://github.com/torvalds/linux.git
synced 2026-05-13 00:28:54 +02:00
drm/tests: hdmi: check the infoframes behaviour
Verify the InfoFrames behaviour. Check that reporting InfoFrame as unsupported doesn't result in a commit error. Also check that HDR and Audio InfoFrames are not triggered if corresponding features are not enabled. Acked-by: Maxime Ripard <mripard@kernel.org> Link: https://patch.msgid.link/20260107-limit-infoframes-2-v4-1-213d0d3bd490@oss.qualcomm.com Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
This commit is contained in:
parent
f5520a1a84
commit
7436a87db9
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_drv.h>
|
||||
|
|
@ -48,6 +49,8 @@ static const struct drm_connector_helper_funcs drm_client_modeset_connector_help
|
|||
};
|
||||
|
||||
static const struct drm_connector_funcs drm_client_modeset_connector_funcs = {
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state
|
||||
};
|
||||
|
||||
static int drm_client_modeset_test_init(struct kunit *test)
|
||||
|
|
|
|||
|
|
@ -35,11 +35,16 @@ struct drm_atomic_helper_connector_hdmi_priv {
|
|||
|
||||
const void *current_edid;
|
||||
size_t current_edid_len;
|
||||
|
||||
int hdmi_update_failures;
|
||||
};
|
||||
|
||||
#define connector_to_priv(c) \
|
||||
container_of_const(c, struct drm_atomic_helper_connector_hdmi_priv, connector)
|
||||
|
||||
#define encoder_to_priv(e) \
|
||||
container_of_const(e, struct drm_atomic_helper_connector_hdmi_priv, encoder)
|
||||
|
||||
static struct drm_display_mode *find_preferred_mode(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *drm = connector->dev;
|
||||
|
|
@ -138,6 +143,22 @@ static const struct drm_connector_funcs dummy_connector_funcs = {
|
|||
.reset = dummy_hdmi_connector_reset,
|
||||
};
|
||||
|
||||
static void test_encoder_atomic_enable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_helper_connector_hdmi_priv *priv =
|
||||
encoder_to_priv(encoder);
|
||||
int ret;
|
||||
|
||||
ret = drm_atomic_helper_connector_hdmi_update_infoframes(&priv->connector, state);
|
||||
if (ret)
|
||||
priv->hdmi_update_failures++;
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs test_encoder_helper_funcs = {
|
||||
.atomic_enable = test_encoder_atomic_enable,
|
||||
};
|
||||
|
||||
static
|
||||
struct drm_atomic_helper_connector_hdmi_priv *
|
||||
__connector_hdmi_init(struct kunit *test,
|
||||
|
|
@ -2323,10 +2344,616 @@ static struct kunit_suite drm_atomic_helper_connector_hdmi_mode_valid_test_suite
|
|||
.test_cases = drm_atomic_helper_connector_hdmi_mode_valid_tests,
|
||||
};
|
||||
|
||||
/*
|
||||
* Test that the default behaviour works without errors. We expect that
|
||||
* infoframe-related hooks are called and there are no errors raised.
|
||||
*/
|
||||
static void drm_test_check_infoframes(struct kunit *test)
|
||||
{
|
||||
struct drm_atomic_helper_connector_hdmi_priv *priv;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_display_mode *preferred;
|
||||
struct drm_connector *conn;
|
||||
struct drm_device *drm;
|
||||
struct drm_crtc *crtc;
|
||||
int old_hdmi_update_failures;
|
||||
int ret;
|
||||
|
||||
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
|
||||
BIT(HDMI_COLORSPACE_RGB),
|
||||
8,
|
||||
&dummy_connector_hdmi_funcs,
|
||||
test_edid_hdmi_1080p_rgb_max_200mhz);
|
||||
KUNIT_ASSERT_NOT_NULL(test, priv);
|
||||
|
||||
drm = &priv->drm;
|
||||
crtc = priv->crtc;
|
||||
conn = &priv->connector;
|
||||
|
||||
preferred = find_preferred_mode(conn);
|
||||
KUNIT_ASSERT_NOT_NULL(test, preferred);
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
retry_conn_enable:
|
||||
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
|
||||
crtc, conn,
|
||||
preferred,
|
||||
&ctx);
|
||||
if (ret == -EDEADLK) {
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_enable;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
|
||||
|
||||
retry_crtc_state:
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (PTR_ERR(crtc_state) == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state;
|
||||
}
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
|
||||
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
old_hdmi_update_failures = priv->hdmi_update_failures;
|
||||
|
||||
ret = drm_atomic_check_only(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_GE(test, old_hdmi_update_failures, priv->hdmi_update_failures);
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
}
|
||||
|
||||
static int reject_avi_infoframe_write_infoframe(struct drm_connector *connector,
|
||||
enum hdmi_infoframe_type type,
|
||||
const u8 *buffer, size_t len)
|
||||
{
|
||||
if (type == HDMI_INFOFRAME_TYPE_AVI)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_connector_hdmi_funcs reject_avi_infoframe_hdmi_funcs = {
|
||||
.write_infoframe = reject_avi_infoframe_write_infoframe,
|
||||
};
|
||||
|
||||
/*
|
||||
* Test that the rejection of AVI InfoFrame results in the failure of
|
||||
* drm_atomic_helper_connector_hdmi_update_infoframes().
|
||||
*/
|
||||
static void drm_test_check_reject_avi_infoframe(struct kunit *test)
|
||||
{
|
||||
struct drm_atomic_helper_connector_hdmi_priv *priv;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_display_mode *preferred;
|
||||
struct drm_connector *conn;
|
||||
struct drm_device *drm;
|
||||
struct drm_crtc *crtc;
|
||||
int old_hdmi_update_failures;
|
||||
int ret;
|
||||
|
||||
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
|
||||
BIT(HDMI_COLORSPACE_RGB),
|
||||
8,
|
||||
&reject_avi_infoframe_hdmi_funcs,
|
||||
test_edid_hdmi_1080p_rgb_max_200mhz);
|
||||
KUNIT_ASSERT_NOT_NULL(test, priv);
|
||||
|
||||
drm = &priv->drm;
|
||||
crtc = priv->crtc;
|
||||
conn = &priv->connector;
|
||||
|
||||
preferred = find_preferred_mode(conn);
|
||||
KUNIT_ASSERT_NOT_NULL(test, preferred);
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
retry_conn_enable:
|
||||
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
|
||||
crtc, conn,
|
||||
preferred,
|
||||
&ctx);
|
||||
if (ret == -EDEADLK) {
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_enable;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs);
|
||||
|
||||
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
|
||||
|
||||
retry_crtc_state:
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (PTR_ERR(crtc_state) == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state;
|
||||
}
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
|
||||
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
old_hdmi_update_failures = priv->hdmi_update_failures;
|
||||
|
||||
ret = drm_atomic_check_only(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_NE(test, old_hdmi_update_failures, priv->hdmi_update_failures);
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
}
|
||||
|
||||
static int reject_hdr_infoframe_write_infoframe(struct drm_connector *connector,
|
||||
enum hdmi_infoframe_type type,
|
||||
const u8 *buffer, size_t len)
|
||||
{
|
||||
if (type == HDMI_INFOFRAME_TYPE_DRM)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_connector_hdmi_funcs reject_hdr_infoframe_hdmi_funcs = {
|
||||
.write_infoframe = reject_hdr_infoframe_write_infoframe,
|
||||
};
|
||||
|
||||
/*
|
||||
* Test that the HDR InfoFrame isn't programmed in
|
||||
* drm_atomic_helper_connector_hdmi_update_infoframes() if the max_bpc is 8.
|
||||
*/
|
||||
static void drm_test_check_reject_hdr_infoframe_bpc_8(struct kunit *test)
|
||||
{
|
||||
struct drm_atomic_helper_connector_hdmi_priv *priv;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_connector_state *new_conn_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_display_mode *preferred;
|
||||
struct drm_connector *conn;
|
||||
struct drm_device *drm;
|
||||
struct drm_crtc *crtc;
|
||||
int old_hdmi_update_failures;
|
||||
int ret;
|
||||
|
||||
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
|
||||
BIT(HDMI_COLORSPACE_RGB),
|
||||
8,
|
||||
&reject_hdr_infoframe_hdmi_funcs,
|
||||
test_edid_hdmi_1080p_rgb_max_200mhz_hdr);
|
||||
KUNIT_ASSERT_NOT_NULL(test, priv);
|
||||
|
||||
drm = &priv->drm;
|
||||
crtc = priv->crtc;
|
||||
conn = &priv->connector;
|
||||
|
||||
preferred = find_preferred_mode(conn);
|
||||
KUNIT_ASSERT_NOT_NULL(test, preferred);
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
retry_conn_enable:
|
||||
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
|
||||
crtc, conn,
|
||||
preferred,
|
||||
&ctx);
|
||||
if (ret == -EDEADLK) {
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_enable;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs);
|
||||
|
||||
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
|
||||
|
||||
retry_conn_state:
|
||||
new_conn_state = drm_atomic_get_connector_state(state, conn);
|
||||
if (PTR_ERR(new_conn_state) == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_state;
|
||||
}
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (PTR_ERR(crtc_state) == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_state;
|
||||
}
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
|
||||
|
||||
/* Verify that there is no HDR property, so "userspace" can't set it. */
|
||||
for (int i = 0; i < conn->base.properties->count; i++)
|
||||
KUNIT_ASSERT_PTR_NE(test,
|
||||
drm->mode_config.hdr_output_metadata_property,
|
||||
conn->base.properties->properties[i]);
|
||||
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
old_hdmi_update_failures = priv->hdmi_update_failures;
|
||||
|
||||
ret = drm_atomic_check_only(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, old_hdmi_update_failures, priv->hdmi_update_failures);
|
||||
|
||||
new_conn_state = conn->state;
|
||||
KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.output_bpc, 8);
|
||||
KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.infoframes.hdr_drm.set, false);
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that the rejection of HDR InfoFrame results in the failure of
|
||||
* drm_atomic_helper_connector_hdmi_update_infoframes() in the high bpc is
|
||||
* supported.
|
||||
*/
|
||||
static void drm_test_check_reject_hdr_infoframe_bpc_10(struct kunit *test)
|
||||
{
|
||||
struct drm_atomic_helper_connector_hdmi_priv *priv;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_connector_state *new_conn_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_display_mode *preferred;
|
||||
struct drm_connector *conn;
|
||||
struct drm_device *drm;
|
||||
struct drm_crtc *crtc;
|
||||
int old_hdmi_update_failures;
|
||||
struct hdr_output_metadata hdr_data;
|
||||
struct drm_property_blob *hdr_blob;
|
||||
bool replaced;
|
||||
int ret;
|
||||
|
||||
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
|
||||
BIT(HDMI_COLORSPACE_RGB),
|
||||
10,
|
||||
&reject_hdr_infoframe_hdmi_funcs,
|
||||
test_edid_hdmi_1080p_rgb_max_200mhz_hdr);
|
||||
KUNIT_ASSERT_NOT_NULL(test, priv);
|
||||
|
||||
drm = &priv->drm;
|
||||
crtc = priv->crtc;
|
||||
conn = &priv->connector;
|
||||
|
||||
preferred = find_preferred_mode(conn);
|
||||
KUNIT_ASSERT_NOT_NULL(test, preferred);
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
retry_conn_enable:
|
||||
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
|
||||
crtc, conn,
|
||||
preferred,
|
||||
&ctx);
|
||||
if (ret == -EDEADLK) {
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_enable;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs);
|
||||
|
||||
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
|
||||
|
||||
retry_conn_state:
|
||||
new_conn_state = drm_atomic_get_connector_state(state, conn);
|
||||
if (PTR_ERR(new_conn_state) == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_state;
|
||||
}
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (PTR_ERR(crtc_state) == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_state;
|
||||
}
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
|
||||
|
||||
hdr_data.metadata_type = HDMI_STATIC_METADATA_TYPE1;
|
||||
hdr_data.hdmi_metadata_type1.eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
|
||||
hdr_data.hdmi_metadata_type1.metadata_type = HDMI_STATIC_METADATA_TYPE1;
|
||||
|
||||
hdr_blob = drm_property_create_blob(drm, sizeof(hdr_data), &hdr_data);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hdr_blob);
|
||||
|
||||
ret = drm_property_replace_blob_from_id(drm,
|
||||
&new_conn_state->hdr_output_metadata,
|
||||
hdr_blob->base.id,
|
||||
sizeof(struct hdr_output_metadata), -1,
|
||||
&replaced);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
KUNIT_ASSERT_EQ(test, replaced, true);
|
||||
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
old_hdmi_update_failures = priv->hdmi_update_failures;
|
||||
|
||||
ret = drm_atomic_check_only(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_LE(test, old_hdmi_update_failures, priv->hdmi_update_failures);
|
||||
|
||||
new_conn_state = conn->state;
|
||||
KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.output_bpc, 10);
|
||||
KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.infoframes.hdr_drm.set, true);
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
}
|
||||
|
||||
static int reject_audio_infoframe_write_infoframe(struct drm_connector *connector,
|
||||
enum hdmi_infoframe_type type,
|
||||
const u8 *buffer, size_t len)
|
||||
{
|
||||
if (type == HDMI_INFOFRAME_TYPE_AUDIO)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_connector_hdmi_funcs reject_audio_infoframe_hdmi_funcs = {
|
||||
.write_infoframe = reject_audio_infoframe_write_infoframe,
|
||||
};
|
||||
|
||||
/*
|
||||
* Test that Audio InfoFrame is only programmed if we call a corresponding API,
|
||||
* thus the drivers can safely assume that they won't get Audio InfoFrames if
|
||||
* they don't call it.
|
||||
*/
|
||||
static void drm_test_check_reject_audio_infoframe(struct kunit *test)
|
||||
{
|
||||
struct drm_atomic_helper_connector_hdmi_priv *priv;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_display_mode *preferred;
|
||||
struct drm_connector *conn;
|
||||
struct drm_device *drm;
|
||||
struct drm_crtc *crtc;
|
||||
int old_hdmi_update_failures;
|
||||
struct hdmi_audio_infoframe cea;
|
||||
int ret;
|
||||
|
||||
priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
|
||||
BIT(HDMI_COLORSPACE_RGB),
|
||||
8,
|
||||
&reject_audio_infoframe_hdmi_funcs,
|
||||
test_edid_hdmi_1080p_rgb_max_200mhz);
|
||||
KUNIT_ASSERT_NOT_NULL(test, priv);
|
||||
|
||||
drm = &priv->drm;
|
||||
crtc = priv->crtc;
|
||||
conn = &priv->connector;
|
||||
|
||||
preferred = find_preferred_mode(conn);
|
||||
KUNIT_ASSERT_NOT_NULL(test, preferred);
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
retry_conn_enable:
|
||||
ret = drm_kunit_helper_enable_crtc_connector(test, drm,
|
||||
crtc, conn,
|
||||
preferred,
|
||||
&ctx);
|
||||
if (ret == -EDEADLK) {
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_conn_enable;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs);
|
||||
|
||||
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
|
||||
|
||||
retry_crtc_state:
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (PTR_ERR(crtc_state) == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state;
|
||||
}
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
|
||||
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
old_hdmi_update_failures = priv->hdmi_update_failures;
|
||||
|
||||
ret = drm_atomic_check_only(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, old_hdmi_update_failures, priv->hdmi_update_failures);
|
||||
|
||||
/*
|
||||
* So, it works without Audio InfoFrame, let's fail with it in place,
|
||||
* checking that writing the infofraem actually gets triggered.
|
||||
*/
|
||||
|
||||
hdmi_audio_infoframe_init(&cea);
|
||||
cea.channels = 2;
|
||||
cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
|
||||
cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
|
||||
cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
|
||||
|
||||
ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(conn, &cea);
|
||||
KUNIT_ASSERT_EQ(test, ret, -EOPNOTSUPP);
|
||||
|
||||
state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
|
||||
|
||||
retry_crtc_state_2:
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (PTR_ERR(crtc_state) == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state_2;
|
||||
}
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
|
||||
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
old_hdmi_update_failures = priv->hdmi_update_failures;
|
||||
|
||||
ret = drm_atomic_check_only(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state_2;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_atomic_state_clear(state);
|
||||
ret = drm_modeset_backoff(&ctx);
|
||||
if (!ret)
|
||||
goto retry_crtc_state_2;
|
||||
}
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
KUNIT_EXPECT_LE(test, old_hdmi_update_failures, priv->hdmi_update_failures);
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
}
|
||||
|
||||
|
||||
static struct kunit_case drm_atomic_helper_connector_hdmi_infoframes_tests[] = {
|
||||
KUNIT_CASE(drm_test_check_infoframes),
|
||||
KUNIT_CASE(drm_test_check_reject_avi_infoframe),
|
||||
KUNIT_CASE(drm_test_check_reject_hdr_infoframe_bpc_8),
|
||||
KUNIT_CASE(drm_test_check_reject_hdr_infoframe_bpc_10),
|
||||
KUNIT_CASE(drm_test_check_reject_audio_infoframe),
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct kunit_suite drm_atomic_helper_connector_hdmi_infoframes_test_suite = {
|
||||
.name = "drm_atomic_helper_connector_hdmi_infoframes",
|
||||
.test_cases = drm_atomic_helper_connector_hdmi_infoframes_tests,
|
||||
};
|
||||
|
||||
kunit_test_suites(
|
||||
&drm_atomic_helper_connector_hdmi_check_test_suite,
|
||||
&drm_atomic_helper_connector_hdmi_reset_test_suite,
|
||||
&drm_atomic_helper_connector_hdmi_mode_valid_test_suite,
|
||||
&drm_atomic_helper_connector_hdmi_infoframes_test_suite,
|
||||
);
|
||||
|
||||
MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
|
||||
|
|
|
|||
|
|
@ -293,6 +293,125 @@ static const unsigned char test_edid_hdmi_1080p_rgb_max_200mhz[] = {
|
|||
0x00, 0x00, 0x00, 0xfc
|
||||
};
|
||||
|
||||
/*
|
||||
* edid-decode (hex):
|
||||
*
|
||||
* 00 ff ff ff ff ff ff 00 31 d8 2a 00 00 00 00 00
|
||||
* 00 21 01 03 81 a0 5a 78 02 00 00 00 00 00 00 00
|
||||
* 00 00 00 20 00 00 01 01 01 01 01 01 01 01 01 01
|
||||
* 01 01 01 01 01 01 02 3a 80 18 71 38 2d 40 58 2c
|
||||
* 45 00 40 84 63 00 00 1e 00 00 00 fc 00 54 65 73
|
||||
* 74 20 45 44 49 44 0a 20 20 20 00 00 00 fd 00 32
|
||||
* 46 1e 46 0f 00 0a 20 20 20 20 20 20 00 00 00 10
|
||||
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 92
|
||||
*
|
||||
* 02 03 1c 81 e3 05 c0 20 41 10 e2 00 4a 67 03 0c
|
||||
* 00 12 34 00 28 e6 06 05 01 52 52 51 00 00 00 00
|
||||
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4e
|
||||
*
|
||||
* ----------------
|
||||
*
|
||||
* Block 0, Base EDID:
|
||||
* EDID Structure Version & Revision: 1.3
|
||||
* Vendor & Product Identification:
|
||||
* Manufacturer: LNX
|
||||
* Model: 42
|
||||
* Made in: 2023
|
||||
* Basic Display Parameters & Features:
|
||||
* Digital display
|
||||
* DFP 1.x compatible TMDS
|
||||
* Maximum image size: 160 cm x 90 cm
|
||||
* Gamma: 2.20
|
||||
* Monochrome or grayscale display
|
||||
* First detailed timing is the preferred timing
|
||||
* Color Characteristics:
|
||||
* Red : 0.0000, 0.0000
|
||||
* Green: 0.0000, 0.0000
|
||||
* Blue : 0.0000, 0.0000
|
||||
* White: 0.0000, 0.0000
|
||||
* Established Timings I & II:
|
||||
* DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz
|
||||
* Standard Timings: none
|
||||
* Detailed Timing Descriptors:
|
||||
* DTD 1: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (1600 mm x 900 mm)
|
||||
* Hfront 88 Hsync 44 Hback 148 Hpol P
|
||||
* Vfront 4 Vsync 5 Vback 36 Vpol P
|
||||
* Display Product Name: 'Test EDID'
|
||||
* Display Range Limits:
|
||||
* Monitor ranges (GTF): 50-70 Hz V, 30-70 kHz H, max dotclock 150 MHz
|
||||
* Dummy Descriptor:
|
||||
* Extension blocks: 1
|
||||
* Checksum: 0x92
|
||||
*
|
||||
* ----------------
|
||||
*
|
||||
* Block 1, CTA-861 Extension Block:
|
||||
* Revision: 3
|
||||
* Underscans IT Video Formats by default
|
||||
* Native detailed modes: 1
|
||||
* Colorimetry Data Block:
|
||||
* BT2020YCC
|
||||
* BT2020RGB
|
||||
* sRGB
|
||||
* Video Data Block:
|
||||
* VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz
|
||||
* Video Capability Data Block:
|
||||
* YCbCr quantization: No Data
|
||||
* RGB quantization: Selectable (via AVI Q)
|
||||
* PT scan behavior: No Data
|
||||
* IT scan behavior: Always Underscanned
|
||||
* CE scan behavior: Always Underscanned
|
||||
* Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
|
||||
* Source physical address: 1.2.3.4
|
||||
* Maximum TMDS clock: 200 MHz
|
||||
* HDR Static Metadata Data Block:
|
||||
* Electro optical transfer functions:
|
||||
* Traditional gamma - SDR luminance range
|
||||
* SMPTE ST2084
|
||||
* Supported static metadata descriptors:
|
||||
* Static metadata type 1
|
||||
* Desired content max luminance: 82 (295.365 cd/m^2)
|
||||
* Desired content max frame-average luminance: 82 (295.365 cd/m^2)
|
||||
* Desired content min luminance: 81 (0.298 cd/m^2)
|
||||
* Checksum: 0x4e Unused space in Extension Block: 99 bytes
|
||||
*
|
||||
* ----------------
|
||||
*
|
||||
* edid-decode 1.31.0-5387
|
||||
* edid-decode SHA: 5508bc4301ac 2025-08-25 08:14:22
|
||||
*
|
||||
* EDID conformity: PASS
|
||||
*/
|
||||
static const unsigned char test_edid_hdmi_1080p_rgb_max_200mhz_hdr[] = {
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xd8, 0x2a, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x03, 0x81, 0xa0, 0x5a, 0x78,
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
|
||||
0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
|
||||
0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e,
|
||||
0x00, 0x00, 0x00, 0xfc, 0x00, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x44,
|
||||
0x49, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
|
||||
0x46, 0x1e, 0x46, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x92, 0x02, 0x03, 0x1c, 0x81,
|
||||
0xe3, 0x05, 0xc0, 0x20, 0x41, 0x10, 0xe2, 0x00, 0x4a, 0x67, 0x03, 0x0c,
|
||||
0x00, 0x12, 0x34, 0x78, 0x28, 0xe6, 0x06, 0x05, 0x01, 0x52, 0x52, 0x51,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xd6,
|
||||
};
|
||||
|
||||
/*
|
||||
* edid-decode (hex):
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user