16b4dc080SMaxime Ripard // SPDX-License-Identifier: GPL-2.0 26b4dc080SMaxime Ripard /* 36b4dc080SMaxime Ripard * Kunit test for drm_bridge functions 46b4dc080SMaxime Ripard */ 56b4dc080SMaxime Ripard #include <drm/drm_atomic_state_helper.h> 66b4dc080SMaxime Ripard #include <drm/drm_bridge.h> 76b4dc080SMaxime Ripard #include <drm/drm_bridge_connector.h> 8*d4dfff47SMaxime Ripard #include <drm/drm_bridge_helper.h> 96b4dc080SMaxime Ripard #include <drm/drm_kunit_helpers.h> 106b4dc080SMaxime Ripard 116b4dc080SMaxime Ripard #include <kunit/test.h> 126b4dc080SMaxime Ripard 136b4dc080SMaxime Ripard struct drm_bridge_init_priv { 146b4dc080SMaxime Ripard struct drm_device drm; 156b4dc080SMaxime Ripard struct drm_plane *plane; 166b4dc080SMaxime Ripard struct drm_crtc *crtc; 176b4dc080SMaxime Ripard struct drm_encoder encoder; 186b4dc080SMaxime Ripard struct drm_bridge bridge; 196b4dc080SMaxime Ripard struct drm_connector *connector; 20*d4dfff47SMaxime Ripard unsigned int enable_count; 21*d4dfff47SMaxime Ripard unsigned int disable_count; 226b4dc080SMaxime Ripard }; 236b4dc080SMaxime Ripard 24*d4dfff47SMaxime Ripard static void drm_test_bridge_enable(struct drm_bridge *bridge) 25*d4dfff47SMaxime Ripard { 26*d4dfff47SMaxime Ripard struct drm_bridge_init_priv *priv = 27*d4dfff47SMaxime Ripard container_of(bridge, struct drm_bridge_init_priv, bridge); 28*d4dfff47SMaxime Ripard 29*d4dfff47SMaxime Ripard priv->enable_count++; 30*d4dfff47SMaxime Ripard } 31*d4dfff47SMaxime Ripard 32*d4dfff47SMaxime Ripard static void drm_test_bridge_disable(struct drm_bridge *bridge) 33*d4dfff47SMaxime Ripard { 34*d4dfff47SMaxime Ripard struct drm_bridge_init_priv *priv = 35*d4dfff47SMaxime Ripard container_of(bridge, struct drm_bridge_init_priv, bridge); 36*d4dfff47SMaxime Ripard 37*d4dfff47SMaxime Ripard priv->disable_count++; 38*d4dfff47SMaxime Ripard } 39*d4dfff47SMaxime Ripard 406b4dc080SMaxime Ripard static const struct drm_bridge_funcs drm_test_bridge_legacy_funcs = { 41*d4dfff47SMaxime Ripard .enable = drm_test_bridge_enable, 42*d4dfff47SMaxime Ripard .disable = drm_test_bridge_disable, 436b4dc080SMaxime Ripard }; 446b4dc080SMaxime Ripard 45*d4dfff47SMaxime Ripard static void drm_test_bridge_atomic_enable(struct drm_bridge *bridge, 46*d4dfff47SMaxime Ripard struct drm_atomic_state *state) 47*d4dfff47SMaxime Ripard { 48*d4dfff47SMaxime Ripard struct drm_bridge_init_priv *priv = 49*d4dfff47SMaxime Ripard container_of(bridge, struct drm_bridge_init_priv, bridge); 50*d4dfff47SMaxime Ripard 51*d4dfff47SMaxime Ripard priv->enable_count++; 52*d4dfff47SMaxime Ripard } 53*d4dfff47SMaxime Ripard 54*d4dfff47SMaxime Ripard static void drm_test_bridge_atomic_disable(struct drm_bridge *bridge, 55*d4dfff47SMaxime Ripard struct drm_atomic_state *state) 56*d4dfff47SMaxime Ripard { 57*d4dfff47SMaxime Ripard struct drm_bridge_init_priv *priv = 58*d4dfff47SMaxime Ripard container_of(bridge, struct drm_bridge_init_priv, bridge); 59*d4dfff47SMaxime Ripard 60*d4dfff47SMaxime Ripard priv->disable_count++; 61*d4dfff47SMaxime Ripard } 62*d4dfff47SMaxime Ripard 636b4dc080SMaxime Ripard static const struct drm_bridge_funcs drm_test_bridge_atomic_funcs = { 64*d4dfff47SMaxime Ripard .atomic_enable = drm_test_bridge_atomic_enable, 65*d4dfff47SMaxime Ripard .atomic_disable = drm_test_bridge_atomic_disable, 666b4dc080SMaxime Ripard .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 676b4dc080SMaxime Ripard .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 686b4dc080SMaxime Ripard .atomic_reset = drm_atomic_helper_bridge_reset, 696b4dc080SMaxime Ripard }; 706b4dc080SMaxime Ripard 716b4dc080SMaxime Ripard KUNIT_DEFINE_ACTION_WRAPPER(drm_bridge_remove_wrapper, 726b4dc080SMaxime Ripard drm_bridge_remove, 736b4dc080SMaxime Ripard struct drm_bridge *); 746b4dc080SMaxime Ripard 756b4dc080SMaxime Ripard static int drm_kunit_bridge_add(struct kunit *test, 766b4dc080SMaxime Ripard struct drm_bridge *bridge) 776b4dc080SMaxime Ripard { 786b4dc080SMaxime Ripard drm_bridge_add(bridge); 796b4dc080SMaxime Ripard 806b4dc080SMaxime Ripard return kunit_add_action_or_reset(test, 816b4dc080SMaxime Ripard drm_bridge_remove_wrapper, 826b4dc080SMaxime Ripard bridge); 836b4dc080SMaxime Ripard } 846b4dc080SMaxime Ripard 856b4dc080SMaxime Ripard static struct drm_bridge_init_priv * 866b4dc080SMaxime Ripard drm_test_bridge_init(struct kunit *test, const struct drm_bridge_funcs *funcs) 876b4dc080SMaxime Ripard { 886b4dc080SMaxime Ripard struct drm_bridge_init_priv *priv; 896b4dc080SMaxime Ripard struct drm_encoder *enc; 906b4dc080SMaxime Ripard struct drm_bridge *bridge; 916b4dc080SMaxime Ripard struct drm_device *drm; 926b4dc080SMaxime Ripard struct device *dev; 936b4dc080SMaxime Ripard int ret; 946b4dc080SMaxime Ripard 956b4dc080SMaxime Ripard dev = drm_kunit_helper_alloc_device(test); 966b4dc080SMaxime Ripard if (IS_ERR(dev)) 976b4dc080SMaxime Ripard return ERR_CAST(dev); 986b4dc080SMaxime Ripard 996b4dc080SMaxime Ripard priv = drm_kunit_helper_alloc_drm_device(test, dev, 1006b4dc080SMaxime Ripard struct drm_bridge_init_priv, drm, 1016b4dc080SMaxime Ripard DRIVER_MODESET | DRIVER_ATOMIC); 1026b4dc080SMaxime Ripard if (IS_ERR(priv)) 1036b4dc080SMaxime Ripard return ERR_CAST(priv); 1046b4dc080SMaxime Ripard 1056b4dc080SMaxime Ripard drm = &priv->drm; 1066b4dc080SMaxime Ripard priv->plane = drm_kunit_helper_create_primary_plane(test, drm, 1076b4dc080SMaxime Ripard NULL, 1086b4dc080SMaxime Ripard NULL, 1096b4dc080SMaxime Ripard NULL, 0, 1106b4dc080SMaxime Ripard NULL); 1116b4dc080SMaxime Ripard if (IS_ERR(priv->plane)) 1126b4dc080SMaxime Ripard return ERR_CAST(priv->plane); 1136b4dc080SMaxime Ripard 1146b4dc080SMaxime Ripard priv->crtc = drm_kunit_helper_create_crtc(test, drm, 1156b4dc080SMaxime Ripard priv->plane, NULL, 1166b4dc080SMaxime Ripard NULL, 1176b4dc080SMaxime Ripard NULL); 1186b4dc080SMaxime Ripard if (IS_ERR(priv->crtc)) 1196b4dc080SMaxime Ripard return ERR_CAST(priv->crtc); 1206b4dc080SMaxime Ripard 1216b4dc080SMaxime Ripard enc = &priv->encoder; 1226b4dc080SMaxime Ripard ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL); 1236b4dc080SMaxime Ripard if (ret) 1246b4dc080SMaxime Ripard return ERR_PTR(ret); 1256b4dc080SMaxime Ripard 1266b4dc080SMaxime Ripard enc->possible_crtcs = drm_crtc_mask(priv->crtc); 1276b4dc080SMaxime Ripard 1286b4dc080SMaxime Ripard bridge = &priv->bridge; 1296b4dc080SMaxime Ripard bridge->type = DRM_MODE_CONNECTOR_VIRTUAL; 1306b4dc080SMaxime Ripard bridge->funcs = funcs; 1316b4dc080SMaxime Ripard 1326b4dc080SMaxime Ripard ret = drm_kunit_bridge_add(test, bridge); 1336b4dc080SMaxime Ripard if (ret) 1346b4dc080SMaxime Ripard return ERR_PTR(ret); 1356b4dc080SMaxime Ripard 1366b4dc080SMaxime Ripard ret = drm_bridge_attach(enc, bridge, NULL, 0); 1376b4dc080SMaxime Ripard if (ret) 1386b4dc080SMaxime Ripard return ERR_PTR(ret); 1396b4dc080SMaxime Ripard 1406b4dc080SMaxime Ripard priv->connector = drm_bridge_connector_init(drm, enc); 1416b4dc080SMaxime Ripard if (IS_ERR(priv->connector)) 1426b4dc080SMaxime Ripard return ERR_CAST(priv->connector); 1436b4dc080SMaxime Ripard 1446b4dc080SMaxime Ripard drm_connector_attach_encoder(priv->connector, enc); 1456b4dc080SMaxime Ripard 1466b4dc080SMaxime Ripard drm_mode_config_reset(drm); 1476b4dc080SMaxime Ripard 1486b4dc080SMaxime Ripard return priv; 1496b4dc080SMaxime Ripard } 1506b4dc080SMaxime Ripard 1516b4dc080SMaxime Ripard /* 1526b4dc080SMaxime Ripard * Test that drm_bridge_get_current_state() returns the last committed 1536b4dc080SMaxime Ripard * state for an atomic bridge. 1546b4dc080SMaxime Ripard */ 1556b4dc080SMaxime Ripard static void drm_test_drm_bridge_get_current_state_atomic(struct kunit *test) 1566b4dc080SMaxime Ripard { 1576b4dc080SMaxime Ripard struct drm_modeset_acquire_ctx ctx; 1586b4dc080SMaxime Ripard struct drm_bridge_init_priv *priv; 1596b4dc080SMaxime Ripard struct drm_bridge_state *curr_bridge_state; 1606b4dc080SMaxime Ripard struct drm_bridge_state *bridge_state; 1616b4dc080SMaxime Ripard struct drm_atomic_state *state; 1626b4dc080SMaxime Ripard struct drm_bridge *bridge; 1636b4dc080SMaxime Ripard struct drm_device *drm; 1646b4dc080SMaxime Ripard int ret; 1656b4dc080SMaxime Ripard 1666b4dc080SMaxime Ripard priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs); 1676b4dc080SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 1686b4dc080SMaxime Ripard 1696b4dc080SMaxime Ripard drm_modeset_acquire_init(&ctx, 0); 1706b4dc080SMaxime Ripard 1716b4dc080SMaxime Ripard drm = &priv->drm; 1726b4dc080SMaxime Ripard state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 1736b4dc080SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 1746b4dc080SMaxime Ripard 1756b4dc080SMaxime Ripard retry_commit: 1766b4dc080SMaxime Ripard bridge = &priv->bridge; 1776b4dc080SMaxime Ripard bridge_state = drm_atomic_get_bridge_state(state, bridge); 1786b4dc080SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bridge_state); 1796b4dc080SMaxime Ripard 1806b4dc080SMaxime Ripard ret = drm_atomic_commit(state); 1816b4dc080SMaxime Ripard if (ret == -EDEADLK) { 1826b4dc080SMaxime Ripard drm_atomic_state_clear(state); 1836b4dc080SMaxime Ripard drm_modeset_backoff(&ctx); 1846b4dc080SMaxime Ripard goto retry_commit; 1856b4dc080SMaxime Ripard } 1866b4dc080SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 1876b4dc080SMaxime Ripard 1886b4dc080SMaxime Ripard drm_modeset_drop_locks(&ctx); 1896b4dc080SMaxime Ripard drm_modeset_acquire_fini(&ctx); 1906b4dc080SMaxime Ripard 1916b4dc080SMaxime Ripard drm_modeset_acquire_init(&ctx, 0); 1926b4dc080SMaxime Ripard 1936b4dc080SMaxime Ripard retry_state: 1946b4dc080SMaxime Ripard ret = drm_modeset_lock(&bridge->base.lock, &ctx); 1956b4dc080SMaxime Ripard if (ret == -EDEADLK) { 1966b4dc080SMaxime Ripard drm_modeset_backoff(&ctx); 1976b4dc080SMaxime Ripard goto retry_state; 1986b4dc080SMaxime Ripard } 1996b4dc080SMaxime Ripard 2006b4dc080SMaxime Ripard curr_bridge_state = drm_bridge_get_current_state(bridge); 2016b4dc080SMaxime Ripard KUNIT_EXPECT_PTR_EQ(test, curr_bridge_state, bridge_state); 2026b4dc080SMaxime Ripard 2036b4dc080SMaxime Ripard drm_modeset_unlock(&bridge->base.lock); 2046b4dc080SMaxime Ripard 2056b4dc080SMaxime Ripard drm_modeset_drop_locks(&ctx); 2066b4dc080SMaxime Ripard drm_modeset_acquire_fini(&ctx); 2076b4dc080SMaxime Ripard } 2086b4dc080SMaxime Ripard 2096b4dc080SMaxime Ripard /* 2106b4dc080SMaxime Ripard * Test that drm_bridge_get_current_state() returns NULL for a 2116b4dc080SMaxime Ripard * non-atomic bridge. 2126b4dc080SMaxime Ripard */ 2136b4dc080SMaxime Ripard static void drm_test_drm_bridge_get_current_state_legacy(struct kunit *test) 2146b4dc080SMaxime Ripard { 2156b4dc080SMaxime Ripard struct drm_bridge_init_priv *priv; 2166b4dc080SMaxime Ripard struct drm_bridge *bridge; 2176b4dc080SMaxime Ripard 2186b4dc080SMaxime Ripard priv = drm_test_bridge_init(test, &drm_test_bridge_legacy_funcs); 2196b4dc080SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 2206b4dc080SMaxime Ripard 2216b4dc080SMaxime Ripard /* 2226b4dc080SMaxime Ripard * NOTE: Strictly speaking, we should take the bridge->base.lock 2236b4dc080SMaxime Ripard * before calling that function. However, bridge->base is only 2246b4dc080SMaxime Ripard * initialized if the bridge is atomic, while we explicitly 2256b4dc080SMaxime Ripard * initialize one that isn't there. 2266b4dc080SMaxime Ripard * 2276b4dc080SMaxime Ripard * In order to avoid unnecessary warnings, let's skip the 2286b4dc080SMaxime Ripard * locking. The function would return NULL in all cases anyway, 2296b4dc080SMaxime Ripard * so we don't really have any concurrency to worry about. 2306b4dc080SMaxime Ripard */ 2316b4dc080SMaxime Ripard bridge = &priv->bridge; 2326b4dc080SMaxime Ripard KUNIT_EXPECT_NULL(test, drm_bridge_get_current_state(bridge)); 2336b4dc080SMaxime Ripard } 2346b4dc080SMaxime Ripard 2356b4dc080SMaxime Ripard static struct kunit_case drm_bridge_get_current_state_tests[] = { 2366b4dc080SMaxime Ripard KUNIT_CASE(drm_test_drm_bridge_get_current_state_atomic), 2376b4dc080SMaxime Ripard KUNIT_CASE(drm_test_drm_bridge_get_current_state_legacy), 2386b4dc080SMaxime Ripard { } 2396b4dc080SMaxime Ripard }; 2406b4dc080SMaxime Ripard 2416b4dc080SMaxime Ripard 2426b4dc080SMaxime Ripard static struct kunit_suite drm_bridge_get_current_state_test_suite = { 2436b4dc080SMaxime Ripard .name = "drm_test_bridge_get_current_state", 2446b4dc080SMaxime Ripard .test_cases = drm_bridge_get_current_state_tests, 2456b4dc080SMaxime Ripard }; 2466b4dc080SMaxime Ripard 247*d4dfff47SMaxime Ripard /* 248*d4dfff47SMaxime Ripard * Test that an atomic bridge is properly power-cycled when calling 249*d4dfff47SMaxime Ripard * drm_bridge_helper_reset_crtc(). 250*d4dfff47SMaxime Ripard */ 251*d4dfff47SMaxime Ripard static void drm_test_drm_bridge_helper_reset_crtc_atomic(struct kunit *test) 252*d4dfff47SMaxime Ripard { 253*d4dfff47SMaxime Ripard struct drm_modeset_acquire_ctx ctx; 254*d4dfff47SMaxime Ripard struct drm_bridge_init_priv *priv; 255*d4dfff47SMaxime Ripard struct drm_display_mode *mode; 256*d4dfff47SMaxime Ripard struct drm_bridge *bridge; 257*d4dfff47SMaxime Ripard int ret; 258*d4dfff47SMaxime Ripard 259*d4dfff47SMaxime Ripard priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs); 260*d4dfff47SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 261*d4dfff47SMaxime Ripard 262*d4dfff47SMaxime Ripard mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16); 263*d4dfff47SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode); 264*d4dfff47SMaxime Ripard 265*d4dfff47SMaxime Ripard drm_modeset_acquire_init(&ctx, 0); 266*d4dfff47SMaxime Ripard 267*d4dfff47SMaxime Ripard retry_commit: 268*d4dfff47SMaxime Ripard ret = drm_kunit_helper_enable_crtc_connector(test, 269*d4dfff47SMaxime Ripard &priv->drm, priv->crtc, 270*d4dfff47SMaxime Ripard priv->connector, 271*d4dfff47SMaxime Ripard mode, 272*d4dfff47SMaxime Ripard &ctx); 273*d4dfff47SMaxime Ripard if (ret == -EDEADLK) { 274*d4dfff47SMaxime Ripard drm_modeset_backoff(&ctx); 275*d4dfff47SMaxime Ripard goto retry_commit; 276*d4dfff47SMaxime Ripard } 277*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 278*d4dfff47SMaxime Ripard 279*d4dfff47SMaxime Ripard drm_modeset_drop_locks(&ctx); 280*d4dfff47SMaxime Ripard drm_modeset_acquire_fini(&ctx); 281*d4dfff47SMaxime Ripard 282*d4dfff47SMaxime Ripard bridge = &priv->bridge; 283*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, priv->enable_count, 1); 284*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, priv->disable_count, 0); 285*d4dfff47SMaxime Ripard 286*d4dfff47SMaxime Ripard drm_modeset_acquire_init(&ctx, 0); 287*d4dfff47SMaxime Ripard 288*d4dfff47SMaxime Ripard retry_reset: 289*d4dfff47SMaxime Ripard ret = drm_bridge_helper_reset_crtc(bridge, &ctx); 290*d4dfff47SMaxime Ripard if (ret == -EDEADLK) { 291*d4dfff47SMaxime Ripard drm_modeset_backoff(&ctx); 292*d4dfff47SMaxime Ripard goto retry_reset; 293*d4dfff47SMaxime Ripard } 294*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 295*d4dfff47SMaxime Ripard 296*d4dfff47SMaxime Ripard drm_modeset_drop_locks(&ctx); 297*d4dfff47SMaxime Ripard drm_modeset_acquire_fini(&ctx); 298*d4dfff47SMaxime Ripard 299*d4dfff47SMaxime Ripard KUNIT_EXPECT_EQ(test, priv->enable_count, 2); 300*d4dfff47SMaxime Ripard KUNIT_EXPECT_EQ(test, priv->disable_count, 1); 301*d4dfff47SMaxime Ripard } 302*d4dfff47SMaxime Ripard 303*d4dfff47SMaxime Ripard /* 304*d4dfff47SMaxime Ripard * Test that calling drm_bridge_helper_reset_crtc() on a disabled atomic 305*d4dfff47SMaxime Ripard * bridge will fail and not call the enable / disable callbacks 306*d4dfff47SMaxime Ripard */ 307*d4dfff47SMaxime Ripard static void drm_test_drm_bridge_helper_reset_crtc_atomic_disabled(struct kunit *test) 308*d4dfff47SMaxime Ripard { 309*d4dfff47SMaxime Ripard struct drm_modeset_acquire_ctx ctx; 310*d4dfff47SMaxime Ripard struct drm_bridge_init_priv *priv; 311*d4dfff47SMaxime Ripard struct drm_display_mode *mode; 312*d4dfff47SMaxime Ripard struct drm_bridge *bridge; 313*d4dfff47SMaxime Ripard int ret; 314*d4dfff47SMaxime Ripard 315*d4dfff47SMaxime Ripard priv = drm_test_bridge_init(test, &drm_test_bridge_atomic_funcs); 316*d4dfff47SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 317*d4dfff47SMaxime Ripard 318*d4dfff47SMaxime Ripard mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16); 319*d4dfff47SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode); 320*d4dfff47SMaxime Ripard 321*d4dfff47SMaxime Ripard bridge = &priv->bridge; 322*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, priv->enable_count, 0); 323*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, priv->disable_count, 0); 324*d4dfff47SMaxime Ripard 325*d4dfff47SMaxime Ripard drm_modeset_acquire_init(&ctx, 0); 326*d4dfff47SMaxime Ripard 327*d4dfff47SMaxime Ripard retry_reset: 328*d4dfff47SMaxime Ripard ret = drm_bridge_helper_reset_crtc(bridge, &ctx); 329*d4dfff47SMaxime Ripard if (ret == -EDEADLK) { 330*d4dfff47SMaxime Ripard drm_modeset_backoff(&ctx); 331*d4dfff47SMaxime Ripard goto retry_reset; 332*d4dfff47SMaxime Ripard } 333*d4dfff47SMaxime Ripard KUNIT_EXPECT_LT(test, ret, 0); 334*d4dfff47SMaxime Ripard 335*d4dfff47SMaxime Ripard drm_modeset_drop_locks(&ctx); 336*d4dfff47SMaxime Ripard drm_modeset_acquire_fini(&ctx); 337*d4dfff47SMaxime Ripard 338*d4dfff47SMaxime Ripard KUNIT_EXPECT_EQ(test, priv->enable_count, 0); 339*d4dfff47SMaxime Ripard KUNIT_EXPECT_EQ(test, priv->disable_count, 0); 340*d4dfff47SMaxime Ripard } 341*d4dfff47SMaxime Ripard 342*d4dfff47SMaxime Ripard /* 343*d4dfff47SMaxime Ripard * Test that a non-atomic bridge is properly power-cycled when calling 344*d4dfff47SMaxime Ripard * drm_bridge_helper_reset_crtc(). 345*d4dfff47SMaxime Ripard */ 346*d4dfff47SMaxime Ripard static void drm_test_drm_bridge_helper_reset_crtc_legacy(struct kunit *test) 347*d4dfff47SMaxime Ripard { 348*d4dfff47SMaxime Ripard struct drm_modeset_acquire_ctx ctx; 349*d4dfff47SMaxime Ripard struct drm_bridge_init_priv *priv; 350*d4dfff47SMaxime Ripard struct drm_display_mode *mode; 351*d4dfff47SMaxime Ripard struct drm_bridge *bridge; 352*d4dfff47SMaxime Ripard int ret; 353*d4dfff47SMaxime Ripard 354*d4dfff47SMaxime Ripard priv = drm_test_bridge_init(test, &drm_test_bridge_legacy_funcs); 355*d4dfff47SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 356*d4dfff47SMaxime Ripard 357*d4dfff47SMaxime Ripard mode = drm_kunit_display_mode_from_cea_vic(test, &priv->drm, 16); 358*d4dfff47SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mode); 359*d4dfff47SMaxime Ripard 360*d4dfff47SMaxime Ripard drm_modeset_acquire_init(&ctx, 0); 361*d4dfff47SMaxime Ripard 362*d4dfff47SMaxime Ripard retry_commit: 363*d4dfff47SMaxime Ripard ret = drm_kunit_helper_enable_crtc_connector(test, 364*d4dfff47SMaxime Ripard &priv->drm, priv->crtc, 365*d4dfff47SMaxime Ripard priv->connector, 366*d4dfff47SMaxime Ripard mode, 367*d4dfff47SMaxime Ripard &ctx); 368*d4dfff47SMaxime Ripard if (ret == -EDEADLK) { 369*d4dfff47SMaxime Ripard drm_modeset_backoff(&ctx); 370*d4dfff47SMaxime Ripard goto retry_commit; 371*d4dfff47SMaxime Ripard } 372*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 373*d4dfff47SMaxime Ripard 374*d4dfff47SMaxime Ripard drm_modeset_drop_locks(&ctx); 375*d4dfff47SMaxime Ripard drm_modeset_acquire_fini(&ctx); 376*d4dfff47SMaxime Ripard 377*d4dfff47SMaxime Ripard bridge = &priv->bridge; 378*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, priv->enable_count, 1); 379*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, priv->disable_count, 0); 380*d4dfff47SMaxime Ripard 381*d4dfff47SMaxime Ripard drm_modeset_acquire_init(&ctx, 0); 382*d4dfff47SMaxime Ripard 383*d4dfff47SMaxime Ripard retry_reset: 384*d4dfff47SMaxime Ripard ret = drm_bridge_helper_reset_crtc(bridge, &ctx); 385*d4dfff47SMaxime Ripard if (ret == -EDEADLK) { 386*d4dfff47SMaxime Ripard drm_modeset_backoff(&ctx); 387*d4dfff47SMaxime Ripard goto retry_reset; 388*d4dfff47SMaxime Ripard } 389*d4dfff47SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 390*d4dfff47SMaxime Ripard 391*d4dfff47SMaxime Ripard drm_modeset_drop_locks(&ctx); 392*d4dfff47SMaxime Ripard drm_modeset_acquire_fini(&ctx); 393*d4dfff47SMaxime Ripard 394*d4dfff47SMaxime Ripard KUNIT_EXPECT_EQ(test, priv->enable_count, 2); 395*d4dfff47SMaxime Ripard KUNIT_EXPECT_EQ(test, priv->disable_count, 1); 396*d4dfff47SMaxime Ripard } 397*d4dfff47SMaxime Ripard 398*d4dfff47SMaxime Ripard static struct kunit_case drm_bridge_helper_reset_crtc_tests[] = { 399*d4dfff47SMaxime Ripard KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_atomic), 400*d4dfff47SMaxime Ripard KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_atomic_disabled), 401*d4dfff47SMaxime Ripard KUNIT_CASE(drm_test_drm_bridge_helper_reset_crtc_legacy), 402*d4dfff47SMaxime Ripard { } 403*d4dfff47SMaxime Ripard }; 404*d4dfff47SMaxime Ripard 405*d4dfff47SMaxime Ripard static struct kunit_suite drm_bridge_helper_reset_crtc_test_suite = { 406*d4dfff47SMaxime Ripard .name = "drm_test_bridge_helper_reset_crtc", 407*d4dfff47SMaxime Ripard .test_cases = drm_bridge_helper_reset_crtc_tests, 408*d4dfff47SMaxime Ripard }; 409*d4dfff47SMaxime Ripard 410*d4dfff47SMaxime Ripard kunit_test_suites( 411*d4dfff47SMaxime Ripard &drm_bridge_get_current_state_test_suite, 412*d4dfff47SMaxime Ripard &drm_bridge_helper_reset_crtc_test_suite, 413*d4dfff47SMaxime Ripard ); 4146b4dc080SMaxime Ripard 4156b4dc080SMaxime Ripard MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>"); 4166b4dc080SMaxime Ripard MODULE_DESCRIPTION("Kunit test for drm_bridge functions"); 4176b4dc080SMaxime Ripard MODULE_LICENSE("GPL"); 418