Hi Maxime, On 1/14/25 7:41 PM, Maxime Ripard wrote: > Hi, > > On Thu, Jan 09, 2025 at 12:03:40AM +0200, Cristian Ciocaltea wrote: >> Following up a fixed bug in drm_atomic_helper_connector_hdmi_check(), >> discovered while unloading a DRM module, add a couple of tests to make >> sure the helper will not exhibit any abnormal behaviour for use cases >> that involve shutting down the connector's CRTC. >> >> Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@xxxxxxxxxxxxx> >> --- >> drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c | 173 +++++++++++++++++++++ >> 1 file changed, 173 insertions(+) >> >> diff --git a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c >> index c3b693bb966f1f8b04066d19f520bfa4bf11c23d..98187ecee5d77b5f758af29f4c4bfddbd1f658fd 100644 >> --- a/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c >> +++ b/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c >> @@ -1568,6 +1568,177 @@ static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *tes >> KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); >> } >> >> +/* >> + * Test that if we deactivate connector's CRTC, we trigger a mode change >> + * on that CRTC, along with setting {connectors|active}_changed. >> + */ >> +static void drm_test_check_crtc_deactivate_mode_changed(struct kunit *test) >> +{ >> + struct drm_atomic_helper_connector_hdmi_priv *priv; >> + struct drm_modeset_acquire_ctx *ctx; >> + struct drm_connector_state *old_conn_state; >> + struct drm_connector_state *new_conn_state; >> + struct drm_crtc_state *old_crtc_state; >> + struct drm_crtc_state *new_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 ret; >> + >> + priv = drm_kunit_helper_connector_hdmi_init(test, >> + BIT(HDMI_COLORSPACE_RGB), >> + 8); >> + KUNIT_ASSERT_NOT_NULL(test, priv); >> + >> + conn = &priv->connector; >> + KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); >> + >> + ctx = drm_kunit_helper_acquire_ctx_alloc(test); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); >> + >> + preferred = find_preferred_mode(conn); >> + KUNIT_ASSERT_NOT_NULL(test, preferred); >> + >> + drm = &priv->drm; >> + crtc = priv->crtc; >> + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); >> + KUNIT_ASSERT_EQ(test, ret, 0); >> + >> + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); >> + >> + new_conn_state = drm_atomic_get_connector_state(state, conn); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); >> + >> + old_conn_state = drm_atomic_get_old_connector_state(state, conn); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); >> + >> + new_crtc_state = drm_atomic_get_crtc_state(state, crtc); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_crtc_state); >> + >> + old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_crtc_state); >> + >> + ret = drm_atomic_set_mode_for_crtc(new_crtc_state, NULL); >> + KUNIT_EXPECT_EQ(test, ret, 0); >> + KUNIT_ASSERT_NE(test, old_crtc_state->enable, new_crtc_state->enable); >> + >> + new_crtc_state->active = false; >> + KUNIT_ASSERT_NE(test, old_crtc_state->active, new_crtc_state->active); >> + >> + ret = drm_atomic_set_crtc_for_connector(new_conn_state, NULL); >> + KUNIT_ASSERT_EQ(test, ret, 0); >> + >> + KUNIT_ASSERT_PTR_NE(test, old_conn_state->crtc, new_conn_state->crtc); >> + >> + ret = drm_atomic_check_only(state); >> + KUNIT_ASSERT_EQ(test, ret, 0); >> + >> + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_crtc_state); >> + KUNIT_EXPECT_TRUE(test, new_crtc_state->mode_changed); >> + KUNIT_EXPECT_TRUE(test, new_crtc_state->connectors_changed); >> + KUNIT_EXPECT_TRUE(test, new_crtc_state->active_changed); >> +} > > This one looks good to me > >> +/* >> + * Test that if we deactivate connector's CRTC, while changing the max >> + * bpc property to a different value, will not have any effect on the >> + * output bpc property. However, we still trigger a mode change on that >> + * CRTC, along with setting {connectors|active}_changed. >> + */ >> +static void drm_test_check_crtc_deactivate_output_bpc_not_changed(struct kunit *test) >> +{ >> + struct drm_atomic_helper_connector_hdmi_priv *priv; >> + struct drm_modeset_acquire_ctx *ctx; >> + struct drm_connector_state *old_conn_state; >> + struct drm_connector_state *new_conn_state; >> + struct drm_crtc_state *old_crtc_state; >> + struct drm_crtc_state *new_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 ret; >> + >> + priv = drm_kunit_helper_connector_hdmi_init(test, >> + BIT(HDMI_COLORSPACE_RGB), >> + 10); >> + KUNIT_ASSERT_NOT_NULL(test, priv); >> + >> + conn = &priv->connector; >> + ret = set_connector_edid(test, conn, >> + test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, >> + ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); >> + KUNIT_ASSERT_GT(test, ret, 0); >> + >> + ctx = drm_kunit_helper_acquire_ctx_alloc(test); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); >> + >> + preferred = find_preferred_mode(conn); >> + KUNIT_ASSERT_NOT_NULL(test, preferred); >> + >> + drm = &priv->drm; >> + crtc = priv->crtc; >> + ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); >> + KUNIT_ASSERT_EQ(test, ret, 0); >> + >> + state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); >> + >> + new_conn_state = drm_atomic_get_connector_state(state, conn); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); >> + >> + old_conn_state = drm_atomic_get_old_connector_state(state, conn); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); >> + >> + new_conn_state->max_requested_bpc = 8; >> + >> + KUNIT_ASSERT_NE(test, >> + old_conn_state->max_requested_bpc, >> + new_conn_state->max_requested_bpc); >> + >> + new_crtc_state = drm_atomic_get_crtc_state(state, crtc); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_crtc_state); >> + >> + old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_crtc_state); >> + >> + ret = drm_atomic_set_mode_for_crtc(new_crtc_state, NULL); >> + KUNIT_EXPECT_EQ(test, ret, 0); >> + KUNIT_ASSERT_NE(test, old_crtc_state->enable, new_crtc_state->enable); >> + >> + new_crtc_state->active = false; >> + KUNIT_ASSERT_NE(test, old_crtc_state->active, new_crtc_state->active); >> + >> + ret = drm_atomic_set_crtc_for_connector(new_conn_state, NULL); >> + KUNIT_ASSERT_EQ(test, ret, 0); >> + >> + KUNIT_ASSERT_PTR_NE(test, old_conn_state->crtc, new_conn_state->crtc); >> + >> + ret = drm_atomic_check_only(state); >> + KUNIT_ASSERT_EQ(test, ret, 0); >> + >> + old_conn_state = drm_atomic_get_old_connector_state(state, conn); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); >> + >> + new_conn_state = drm_atomic_get_new_connector_state(state, conn); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); >> + >> + KUNIT_EXPECT_EQ(test, >> + old_conn_state->hdmi.output_bpc, >> + new_conn_state->hdmi.output_bpc); >> + >> + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); >> + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_crtc_state); >> + KUNIT_EXPECT_TRUE(test, new_crtc_state->mode_changed); >> + KUNIT_EXPECT_TRUE(test, new_crtc_state->connectors_changed); >> + KUNIT_EXPECT_TRUE(test, new_crtc_state->active_changed); >> +} >> + > > However, it's not clear to me why changing bpc should change anything, > or why it's worth testing? I suppose I may have gone a little too far with all this testing :-) Will drop and send v3. Thanks for reviewing, Cristian