xref: /linux/drivers/gpu/drm/tests/drm_bridge_test.c (revision b08494a8f7416e5f09907318c5460ad6f6e2a548)
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