Allow drivers to attach the max bpc property before allocating connector state, as needed by the upcoming non-HDMI bridge connector support. Only update the current state when one exists.
Initialize max_requested_bpc and max_bpc from the attached property default when creating connector state. Use drm_object_property_get_default_value() rather than the range maximum so that state creation and subsequent resets restore the value chosen when attaching the property. Cover deferred allocation, existing state and restoration of a default that differs from the range maximum in the connector KUnit tests. Assisted-by: LLM Signed-off-by: Xilin Wu <[email protected]> --- drivers/gpu/drm/drm_atomic_state_helper.c | 8 +++++ drivers/gpu/drm/drm_connector.c | 6 ++-- drivers/gpu/drm/tests/drm_connector_test.c | 53 ++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index a2ef272e9f27..8352b5a9097a 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -494,7 +494,15 @@ void __drm_atomic_helper_connector_state_init(struct drm_connector_state *conn_state, struct drm_connector *connector) { + u64 val; + conn_state->connector = connector; + if (connector->max_bpc_property && + !drm_object_property_get_default_value(&connector->base, + connector->max_bpc_property, &val)) { + conn_state->max_requested_bpc = val; + conn_state->max_bpc = val; + } } EXPORT_SYMBOL(__drm_atomic_helper_connector_state_init); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 8b4baed060f3..34c30469f405 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2886,8 +2886,10 @@ int drm_connector_attach_max_bpc_property(struct drm_connector *connector, } drm_object_attach_property(&connector->base, prop, max); - connector->state->max_requested_bpc = max; - connector->state->max_bpc = max; + if (connector->state) { + connector->state->max_requested_bpc = max; + connector->state->max_bpc = max; + } return 0; } diff --git a/drivers/gpu/drm/tests/drm_connector_test.c b/drivers/gpu/drm/tests/drm_connector_test.c index beb1d50a6646..1174607441b9 100644 --- a/drivers/gpu/drm/tests/drm_connector_test.c +++ b/drivers/gpu/drm/tests/drm_connector_test.c @@ -12,6 +12,7 @@ #include <drm/drm_file.h> #include <drm/drm_kunit_helpers.h> #include <drm/drm_modes.h> +#include <drm/drm_property.h> #include <drm/display/drm_hdmi_helper.h> @@ -187,7 +188,59 @@ KUNIT_ARRAY_PARAM(drm_connector_init_type_valid, drm_connector_init_type_valid_tests, drm_connector_init_type_desc); +/* The attached default need not equal the upper end of the property range. */ +static void drm_test_connector_max_bpc_default(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + struct drm_connector *connector = &priv->connector; + struct drm_property *prop; + int ret; + + ret = drmm_connector_init(&priv->drm, connector, &dummy_funcs, + DRM_MODE_CONNECTOR_DisplayPort, NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + + prop = drm_property_create_range(&priv->drm, 0, "max bpc", 6, 12); + KUNIT_ASSERT_NOT_NULL(test, prop); + connector->max_bpc_property = prop; + ret = drm_connector_attach_max_bpc_property(connector, 6, 10); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_NULL(test, connector->state); + + drm_mode_config_reset(&priv->drm); + KUNIT_ASSERT_NOT_NULL(test, connector->state); + KUNIT_EXPECT_EQ(test, connector->state->max_requested_bpc, 10); + KUNIT_EXPECT_EQ(test, connector->state->max_bpc, 10); + + connector->state->max_requested_bpc = 8; + connector->state->max_bpc = 8; + drm_mode_config_reset(&priv->drm); + KUNIT_ASSERT_NOT_NULL(test, connector->state); + KUNIT_EXPECT_EQ(test, connector->state->max_requested_bpc, 10); + KUNIT_EXPECT_EQ(test, connector->state->max_bpc, 10); +} + +static void drm_test_connector_max_bpc_existing_state(struct kunit *test) +{ + struct drm_connector_init_priv *priv = test->priv; + struct drm_connector *connector = &priv->connector; + int ret; + + ret = drmm_connector_init(&priv->drm, connector, &dummy_funcs, + DRM_MODE_CONNECTOR_DisplayPort, NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + drm_mode_config_reset(&priv->drm); + KUNIT_ASSERT_NOT_NULL(test, connector->state); + + ret = drm_connector_attach_max_bpc_property(connector, 6, 10); + KUNIT_ASSERT_EQ(test, ret, 0); + KUNIT_EXPECT_EQ(test, connector->state->max_requested_bpc, 10); + KUNIT_EXPECT_EQ(test, connector->state->max_bpc, 10); +} + static struct kunit_case drmm_connector_init_tests[] = { + KUNIT_CASE(drm_test_connector_max_bpc_default), + KUNIT_CASE(drm_test_connector_max_bpc_existing_state), KUNIT_CASE(drm_test_drmm_connector_init), KUNIT_CASE(drm_test_drmm_connector_init_null_ddc), KUNIT_CASE_PARAM(drm_test_drmm_connector_init_type_valid, -- 2.56.0
