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

Reply via email to