1*5164f7e7SMaxime Ripard // SPDX-License-Identifier: GPL-2.0 2*5164f7e7SMaxime Ripard /* 3*5164f7e7SMaxime Ripard * Test cases for the drm_atomic_commit helpers 4*5164f7e7SMaxime Ripard * 5*5164f7e7SMaxime Ripard * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. 6*5164f7e7SMaxime Ripard */ 7*5164f7e7SMaxime Ripard 8*5164f7e7SMaxime Ripard #include <drm/drm_atomic.h> 9*5164f7e7SMaxime Ripard #include <drm/drm_atomic_helper.h> 10*5164f7e7SMaxime Ripard #include <drm/drm_atomic_uapi.h> 11*5164f7e7SMaxime Ripard #include <drm/drm_kunit_helpers.h> 12*5164f7e7SMaxime Ripard #include <drm/drm_probe_helper.h> 13*5164f7e7SMaxime Ripard 14*5164f7e7SMaxime Ripard #define DRM_TEST_ENC_0 BIT(0) 15*5164f7e7SMaxime Ripard #define DRM_TEST_ENC_1 BIT(1) 16*5164f7e7SMaxime Ripard #define DRM_TEST_ENC_2 BIT(2) 17*5164f7e7SMaxime Ripard 18*5164f7e7SMaxime Ripard #define DRM_TEST_CONN_0 BIT(0) 19*5164f7e7SMaxime Ripard 20*5164f7e7SMaxime Ripard struct drm_clone_mode_test { 21*5164f7e7SMaxime Ripard const char *name; 22*5164f7e7SMaxime Ripard u32 encoder_mask; 23*5164f7e7SMaxime Ripard int expected_result; 24*5164f7e7SMaxime Ripard }; 25*5164f7e7SMaxime Ripard 26*5164f7e7SMaxime Ripard static const struct drm_display_mode drm_atomic_test_mode = { 27*5164f7e7SMaxime Ripard DRM_MODE("1024x768", 0, 65000, 1024, 1048, 28*5164f7e7SMaxime Ripard 1184, 1344, 0, 768, 771, 777, 806, 0, 29*5164f7e7SMaxime Ripard DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) 30*5164f7e7SMaxime Ripard }; 31*5164f7e7SMaxime Ripard 32*5164f7e7SMaxime Ripard struct drm_atomic_test_priv { 33*5164f7e7SMaxime Ripard struct drm_device drm; 34*5164f7e7SMaxime Ripard struct drm_plane *plane; 35*5164f7e7SMaxime Ripard struct drm_crtc *crtc; 36*5164f7e7SMaxime Ripard struct drm_encoder encoders[3]; 37*5164f7e7SMaxime Ripard struct drm_connector connectors[2]; 38*5164f7e7SMaxime Ripard }; 39*5164f7e7SMaxime Ripard 40*5164f7e7SMaxime Ripard static int modeset_counter; 41*5164f7e7SMaxime Ripard 42*5164f7e7SMaxime Ripard static void drm_test_encoder_mode_set(struct drm_encoder *encoder, 43*5164f7e7SMaxime Ripard struct drm_crtc_state *crtc_state, 44*5164f7e7SMaxime Ripard struct drm_connector_state *conn_state) 45*5164f7e7SMaxime Ripard { 46*5164f7e7SMaxime Ripard modeset_counter++; 47*5164f7e7SMaxime Ripard } 48*5164f7e7SMaxime Ripard 49*5164f7e7SMaxime Ripard static const struct drm_encoder_helper_funcs drm_atomic_test_encoder_funcs = { 50*5164f7e7SMaxime Ripard .atomic_mode_set = drm_test_encoder_mode_set, 51*5164f7e7SMaxime Ripard }; 52*5164f7e7SMaxime Ripard 53*5164f7e7SMaxime Ripard static const struct drm_connector_funcs dummy_connector_funcs = { 54*5164f7e7SMaxime Ripard .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 55*5164f7e7SMaxime Ripard .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 56*5164f7e7SMaxime Ripard .reset = drm_atomic_helper_connector_reset, 57*5164f7e7SMaxime Ripard }; 58*5164f7e7SMaxime Ripard 59*5164f7e7SMaxime Ripard static int drm_atomic_test_dummy_get_modes(struct drm_connector *connector) 60*5164f7e7SMaxime Ripard { 61*5164f7e7SMaxime Ripard return drm_connector_helper_get_modes_fixed(connector, 62*5164f7e7SMaxime Ripard &drm_atomic_test_mode); 63*5164f7e7SMaxime Ripard } 64*5164f7e7SMaxime Ripard 65*5164f7e7SMaxime Ripard static const struct drm_connector_helper_funcs dummy_connector_helper_funcs = { 66*5164f7e7SMaxime Ripard .get_modes = drm_atomic_test_dummy_get_modes, 67*5164f7e7SMaxime Ripard }; 68*5164f7e7SMaxime Ripard 69*5164f7e7SMaxime Ripard static struct drm_atomic_test_priv * 70*5164f7e7SMaxime Ripard drm_atomic_test_init_drm_components(struct kunit *test, bool has_connectors) 71*5164f7e7SMaxime Ripard { 72*5164f7e7SMaxime Ripard struct drm_atomic_test_priv *priv; 73*5164f7e7SMaxime Ripard struct drm_encoder *enc; 74*5164f7e7SMaxime Ripard struct drm_connector *conn; 75*5164f7e7SMaxime Ripard struct drm_device *drm; 76*5164f7e7SMaxime Ripard struct device *dev; 77*5164f7e7SMaxime Ripard int ret; 78*5164f7e7SMaxime Ripard 79*5164f7e7SMaxime Ripard dev = drm_kunit_helper_alloc_device(test); 80*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 81*5164f7e7SMaxime Ripard 82*5164f7e7SMaxime Ripard priv = drm_kunit_helper_alloc_drm_device(test, dev, 83*5164f7e7SMaxime Ripard struct drm_atomic_test_priv, 84*5164f7e7SMaxime Ripard drm, 85*5164f7e7SMaxime Ripard DRIVER_MODESET | DRIVER_ATOMIC); 86*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 87*5164f7e7SMaxime Ripard test->priv = priv; 88*5164f7e7SMaxime Ripard 89*5164f7e7SMaxime Ripard drm = &priv->drm; 90*5164f7e7SMaxime Ripard priv->plane = drm_kunit_helper_create_primary_plane(test, drm, 91*5164f7e7SMaxime Ripard NULL, 92*5164f7e7SMaxime Ripard NULL, 93*5164f7e7SMaxime Ripard NULL, 0, 94*5164f7e7SMaxime Ripard NULL); 95*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane); 96*5164f7e7SMaxime Ripard 97*5164f7e7SMaxime Ripard priv->crtc = drm_kunit_helper_create_crtc(test, drm, 98*5164f7e7SMaxime Ripard priv->plane, NULL, 99*5164f7e7SMaxime Ripard NULL, 100*5164f7e7SMaxime Ripard NULL); 101*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc); 102*5164f7e7SMaxime Ripard 103*5164f7e7SMaxime Ripard for (int i = 0; i < ARRAY_SIZE(priv->encoders); i++) { 104*5164f7e7SMaxime Ripard enc = &priv->encoders[i]; 105*5164f7e7SMaxime Ripard 106*5164f7e7SMaxime Ripard ret = drmm_encoder_init(drm, enc, NULL, 107*5164f7e7SMaxime Ripard DRM_MODE_ENCODER_DSI, NULL); 108*5164f7e7SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 109*5164f7e7SMaxime Ripard 110*5164f7e7SMaxime Ripard enc->possible_crtcs = drm_crtc_mask(priv->crtc); 111*5164f7e7SMaxime Ripard } 112*5164f7e7SMaxime Ripard 113*5164f7e7SMaxime Ripard priv->encoders[0].possible_clones = DRM_TEST_ENC_0 | DRM_TEST_ENC_1; 114*5164f7e7SMaxime Ripard priv->encoders[1].possible_clones = DRM_TEST_ENC_0 | DRM_TEST_ENC_1; 115*5164f7e7SMaxime Ripard priv->encoders[2].possible_clones = DRM_TEST_ENC_2; 116*5164f7e7SMaxime Ripard 117*5164f7e7SMaxime Ripard if (!has_connectors) 118*5164f7e7SMaxime Ripard goto done; 119*5164f7e7SMaxime Ripard 120*5164f7e7SMaxime Ripard BUILD_BUG_ON(ARRAY_SIZE(priv->connectors) > ARRAY_SIZE(priv->encoders)); 121*5164f7e7SMaxime Ripard 122*5164f7e7SMaxime Ripard for (int i = 0; i < ARRAY_SIZE(priv->connectors); i++) { 123*5164f7e7SMaxime Ripard conn = &priv->connectors[i]; 124*5164f7e7SMaxime Ripard 125*5164f7e7SMaxime Ripard ret = drmm_connector_init(drm, conn, &dummy_connector_funcs, 126*5164f7e7SMaxime Ripard DRM_MODE_CONNECTOR_DSI, NULL); 127*5164f7e7SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 128*5164f7e7SMaxime Ripard 129*5164f7e7SMaxime Ripard drm_connector_helper_add(conn, &dummy_connector_helper_funcs); 130*5164f7e7SMaxime Ripard drm_encoder_helper_add(&priv->encoders[i], 131*5164f7e7SMaxime Ripard &drm_atomic_test_encoder_funcs); 132*5164f7e7SMaxime Ripard 133*5164f7e7SMaxime Ripard drm_connector_attach_encoder(conn, &priv->encoders[i]); 134*5164f7e7SMaxime Ripard } 135*5164f7e7SMaxime Ripard 136*5164f7e7SMaxime Ripard done: 137*5164f7e7SMaxime Ripard drm_mode_config_reset(drm); 138*5164f7e7SMaxime Ripard 139*5164f7e7SMaxime Ripard return priv; 140*5164f7e7SMaxime Ripard } 141*5164f7e7SMaxime Ripard 142*5164f7e7SMaxime Ripard static int set_up_atomic_state(struct kunit *test, 143*5164f7e7SMaxime Ripard struct drm_atomic_test_priv *priv, 144*5164f7e7SMaxime Ripard struct drm_connector *connector, 145*5164f7e7SMaxime Ripard struct drm_modeset_acquire_ctx *ctx) 146*5164f7e7SMaxime Ripard { 147*5164f7e7SMaxime Ripard struct drm_device *drm = &priv->drm; 148*5164f7e7SMaxime Ripard struct drm_crtc *crtc = priv->crtc; 149*5164f7e7SMaxime Ripard struct drm_atomic_commit *state; 150*5164f7e7SMaxime Ripard struct drm_connector_state *conn_state; 151*5164f7e7SMaxime Ripard struct drm_crtc_state *crtc_state; 152*5164f7e7SMaxime Ripard int ret; 153*5164f7e7SMaxime Ripard 154*5164f7e7SMaxime Ripard state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); 155*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 156*5164f7e7SMaxime Ripard 157*5164f7e7SMaxime Ripard if (connector) { 158*5164f7e7SMaxime Ripard conn_state = drm_atomic_get_connector_state(state, connector); 159*5164f7e7SMaxime Ripard if (IS_ERR(conn_state)) 160*5164f7e7SMaxime Ripard return PTR_ERR(conn_state); 161*5164f7e7SMaxime Ripard 162*5164f7e7SMaxime Ripard ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); 163*5164f7e7SMaxime Ripard if (ret) 164*5164f7e7SMaxime Ripard return ret; 165*5164f7e7SMaxime Ripard } 166*5164f7e7SMaxime Ripard 167*5164f7e7SMaxime Ripard crtc_state = drm_atomic_get_crtc_state(state, crtc); 168*5164f7e7SMaxime Ripard if (IS_ERR(crtc_state)) 169*5164f7e7SMaxime Ripard return PTR_ERR(crtc_state); 170*5164f7e7SMaxime Ripard 171*5164f7e7SMaxime Ripard ret = drm_atomic_set_mode_for_crtc(crtc_state, &drm_atomic_test_mode); 172*5164f7e7SMaxime Ripard if (ret) 173*5164f7e7SMaxime Ripard return ret; 174*5164f7e7SMaxime Ripard 175*5164f7e7SMaxime Ripard crtc_state->enable = true; 176*5164f7e7SMaxime Ripard crtc_state->active = true; 177*5164f7e7SMaxime Ripard 178*5164f7e7SMaxime Ripard if (connector) { 179*5164f7e7SMaxime Ripard ret = drm_atomic_commit(state); 180*5164f7e7SMaxime Ripard if (ret) 181*5164f7e7SMaxime Ripard return ret; 182*5164f7e7SMaxime Ripard } else { 183*5164f7e7SMaxime Ripard // dummy connector mask 184*5164f7e7SMaxime Ripard crtc_state->connector_mask = DRM_TEST_CONN_0; 185*5164f7e7SMaxime Ripard } 186*5164f7e7SMaxime Ripard 187*5164f7e7SMaxime Ripard return 0; 188*5164f7e7SMaxime Ripard } 189*5164f7e7SMaxime Ripard 190*5164f7e7SMaxime Ripard /* 191*5164f7e7SMaxime Ripard * Test that the DRM encoder mode_set() is called when the atomic state 192*5164f7e7SMaxime Ripard * connectors are changed but the CRTC mode is not. 193*5164f7e7SMaxime Ripard */ 194*5164f7e7SMaxime Ripard static void drm_test_check_connector_changed_modeset(struct kunit *test) 195*5164f7e7SMaxime Ripard { 196*5164f7e7SMaxime Ripard struct drm_atomic_test_priv *priv; 197*5164f7e7SMaxime Ripard struct drm_modeset_acquire_ctx ctx; 198*5164f7e7SMaxime Ripard struct drm_connector *old_conn, *new_conn; 199*5164f7e7SMaxime Ripard struct drm_atomic_commit *state; 200*5164f7e7SMaxime Ripard struct drm_device *drm; 201*5164f7e7SMaxime Ripard struct drm_connector_state *new_conn_state, *old_conn_state; 202*5164f7e7SMaxime Ripard int ret, initial_modeset_count; 203*5164f7e7SMaxime Ripard 204*5164f7e7SMaxime Ripard priv = drm_atomic_test_init_drm_components(test, true); 205*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_NULL(test, priv); 206*5164f7e7SMaxime Ripard 207*5164f7e7SMaxime Ripard drm = &priv->drm; 208*5164f7e7SMaxime Ripard old_conn = &priv->connectors[0]; 209*5164f7e7SMaxime Ripard new_conn = &priv->connectors[1]; 210*5164f7e7SMaxime Ripard 211*5164f7e7SMaxime Ripard drm_modeset_acquire_init(&ctx, 0); 212*5164f7e7SMaxime Ripard 213*5164f7e7SMaxime Ripard // first modeset to enable 214*5164f7e7SMaxime Ripard retry_set_up: 215*5164f7e7SMaxime Ripard ret = set_up_atomic_state(test, priv, old_conn, &ctx); 216*5164f7e7SMaxime Ripard if (ret == -EDEADLK) { 217*5164f7e7SMaxime Ripard ret = drm_modeset_backoff(&ctx); 218*5164f7e7SMaxime Ripard if (!ret) 219*5164f7e7SMaxime Ripard goto retry_set_up; 220*5164f7e7SMaxime Ripard } 221*5164f7e7SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 222*5164f7e7SMaxime Ripard 223*5164f7e7SMaxime Ripard state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 224*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 225*5164f7e7SMaxime Ripard 226*5164f7e7SMaxime Ripard new_conn_state = drm_atomic_get_connector_state(state, new_conn); 227*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 228*5164f7e7SMaxime Ripard 229*5164f7e7SMaxime Ripard old_conn_state = drm_atomic_get_connector_state(state, old_conn); 230*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 231*5164f7e7SMaxime Ripard 232*5164f7e7SMaxime Ripard ret = drm_atomic_set_crtc_for_connector(old_conn_state, NULL); 233*5164f7e7SMaxime Ripard KUNIT_EXPECT_EQ(test, ret, 0); 234*5164f7e7SMaxime Ripard 235*5164f7e7SMaxime Ripard ret = drm_atomic_set_crtc_for_connector(new_conn_state, priv->crtc); 236*5164f7e7SMaxime Ripard KUNIT_EXPECT_EQ(test, ret, 0); 237*5164f7e7SMaxime Ripard 238*5164f7e7SMaxime Ripard initial_modeset_count = modeset_counter; 239*5164f7e7SMaxime Ripard 240*5164f7e7SMaxime Ripard // modeset_disables is called as part of the atomic commit tail 241*5164f7e7SMaxime Ripard ret = drm_atomic_commit(state); 242*5164f7e7SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 243*5164f7e7SMaxime Ripard KUNIT_ASSERT_EQ(test, modeset_counter, initial_modeset_count + 1); 244*5164f7e7SMaxime Ripard 245*5164f7e7SMaxime Ripard drm_modeset_drop_locks(&ctx); 246*5164f7e7SMaxime Ripard drm_modeset_acquire_fini(&ctx); 247*5164f7e7SMaxime Ripard } 248*5164f7e7SMaxime Ripard 249*5164f7e7SMaxime Ripard /* 250*5164f7e7SMaxime Ripard * Test that the drm_crtc_in_clone_mode() helper can detect if a given CRTC 251*5164f7e7SMaxime Ripard * state is in clone mode 252*5164f7e7SMaxime Ripard */ 253*5164f7e7SMaxime Ripard static void drm_test_check_in_clone_mode(struct kunit *test) 254*5164f7e7SMaxime Ripard { 255*5164f7e7SMaxime Ripard bool ret; 256*5164f7e7SMaxime Ripard const struct drm_clone_mode_test *param = test->param_value; 257*5164f7e7SMaxime Ripard struct drm_crtc_state *crtc_state; 258*5164f7e7SMaxime Ripard 259*5164f7e7SMaxime Ripard crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL); 260*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_NULL(test, crtc_state); 261*5164f7e7SMaxime Ripard 262*5164f7e7SMaxime Ripard crtc_state->encoder_mask = param->encoder_mask; 263*5164f7e7SMaxime Ripard 264*5164f7e7SMaxime Ripard ret = drm_crtc_in_clone_mode(crtc_state); 265*5164f7e7SMaxime Ripard 266*5164f7e7SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, param->expected_result); 267*5164f7e7SMaxime Ripard } 268*5164f7e7SMaxime Ripard 269*5164f7e7SMaxime Ripard /* 270*5164f7e7SMaxime Ripard * Test that the atomic commit path will succeed for valid clones (or non-cloned 271*5164f7e7SMaxime Ripard * states) and fail for states where the cloned encoders are not possible_clones 272*5164f7e7SMaxime Ripard * of each other. 273*5164f7e7SMaxime Ripard */ 274*5164f7e7SMaxime Ripard static void drm_test_check_valid_clones(struct kunit *test) 275*5164f7e7SMaxime Ripard { 276*5164f7e7SMaxime Ripard int ret; 277*5164f7e7SMaxime Ripard const struct drm_clone_mode_test *param = test->param_value; 278*5164f7e7SMaxime Ripard struct drm_atomic_test_priv *priv; 279*5164f7e7SMaxime Ripard struct drm_modeset_acquire_ctx ctx; 280*5164f7e7SMaxime Ripard struct drm_device *drm; 281*5164f7e7SMaxime Ripard struct drm_atomic_commit *state; 282*5164f7e7SMaxime Ripard struct drm_crtc_state *crtc_state; 283*5164f7e7SMaxime Ripard 284*5164f7e7SMaxime Ripard priv = drm_atomic_test_init_drm_components(test, false); 285*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_NULL(test, priv); 286*5164f7e7SMaxime Ripard 287*5164f7e7SMaxime Ripard drm = &priv->drm; 288*5164f7e7SMaxime Ripard 289*5164f7e7SMaxime Ripard drm_modeset_acquire_init(&ctx, 0); 290*5164f7e7SMaxime Ripard 291*5164f7e7SMaxime Ripard retry_set_up: 292*5164f7e7SMaxime Ripard ret = set_up_atomic_state(test, priv, NULL, &ctx); 293*5164f7e7SMaxime Ripard if (ret == -EDEADLK) { 294*5164f7e7SMaxime Ripard ret = drm_modeset_backoff(&ctx); 295*5164f7e7SMaxime Ripard if (!ret) 296*5164f7e7SMaxime Ripard goto retry_set_up; 297*5164f7e7SMaxime Ripard } 298*5164f7e7SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, 0); 299*5164f7e7SMaxime Ripard 300*5164f7e7SMaxime Ripard state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 301*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 302*5164f7e7SMaxime Ripard 303*5164f7e7SMaxime Ripard retry: 304*5164f7e7SMaxime Ripard crtc_state = drm_atomic_get_crtc_state(state, priv->crtc); 305*5164f7e7SMaxime Ripard if (PTR_ERR(crtc_state) == -EDEADLK) { 306*5164f7e7SMaxime Ripard drm_atomic_commit_clear(state); 307*5164f7e7SMaxime Ripard ret = drm_modeset_backoff(&ctx); 308*5164f7e7SMaxime Ripard if (!ret) 309*5164f7e7SMaxime Ripard goto retry; 310*5164f7e7SMaxime Ripard } 311*5164f7e7SMaxime Ripard KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 312*5164f7e7SMaxime Ripard 313*5164f7e7SMaxime Ripard crtc_state->encoder_mask = param->encoder_mask; 314*5164f7e7SMaxime Ripard 315*5164f7e7SMaxime Ripard // force modeset 316*5164f7e7SMaxime Ripard crtc_state->mode_changed = true; 317*5164f7e7SMaxime Ripard 318*5164f7e7SMaxime Ripard ret = drm_atomic_helper_check_modeset(drm, state); 319*5164f7e7SMaxime Ripard if (ret == -EDEADLK) { 320*5164f7e7SMaxime Ripard drm_atomic_commit_clear(state); 321*5164f7e7SMaxime Ripard ret = drm_modeset_backoff(&ctx); 322*5164f7e7SMaxime Ripard if (!ret) 323*5164f7e7SMaxime Ripard goto retry; 324*5164f7e7SMaxime Ripard } 325*5164f7e7SMaxime Ripard KUNIT_ASSERT_EQ(test, ret, param->expected_result); 326*5164f7e7SMaxime Ripard 327*5164f7e7SMaxime Ripard drm_modeset_drop_locks(&ctx); 328*5164f7e7SMaxime Ripard drm_modeset_acquire_fini(&ctx); 329*5164f7e7SMaxime Ripard } 330*5164f7e7SMaxime Ripard 331*5164f7e7SMaxime Ripard static void drm_check_in_clone_mode_desc(const struct drm_clone_mode_test *t, 332*5164f7e7SMaxime Ripard char *desc) 333*5164f7e7SMaxime Ripard { 334*5164f7e7SMaxime Ripard sprintf(desc, "%s", t->name); 335*5164f7e7SMaxime Ripard } 336*5164f7e7SMaxime Ripard 337*5164f7e7SMaxime Ripard static void drm_check_valid_clones_desc(const struct drm_clone_mode_test *t, 338*5164f7e7SMaxime Ripard char *desc) 339*5164f7e7SMaxime Ripard { 340*5164f7e7SMaxime Ripard sprintf(desc, "%s", t->name); 341*5164f7e7SMaxime Ripard } 342*5164f7e7SMaxime Ripard 343*5164f7e7SMaxime Ripard static const struct drm_clone_mode_test drm_clone_mode_tests[] = { 344*5164f7e7SMaxime Ripard { 345*5164f7e7SMaxime Ripard .name = "in_clone_mode", 346*5164f7e7SMaxime Ripard .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_1, 347*5164f7e7SMaxime Ripard .expected_result = true, 348*5164f7e7SMaxime Ripard }, 349*5164f7e7SMaxime Ripard { 350*5164f7e7SMaxime Ripard .name = "not_in_clone_mode", 351*5164f7e7SMaxime Ripard .encoder_mask = DRM_TEST_ENC_0, 352*5164f7e7SMaxime Ripard .expected_result = false, 353*5164f7e7SMaxime Ripard }, 354*5164f7e7SMaxime Ripard }; 355*5164f7e7SMaxime Ripard 356*5164f7e7SMaxime Ripard static const struct drm_clone_mode_test drm_valid_clone_mode_tests[] = { 357*5164f7e7SMaxime Ripard { 358*5164f7e7SMaxime Ripard .name = "not_in_clone_mode", 359*5164f7e7SMaxime Ripard .encoder_mask = DRM_TEST_ENC_0, 360*5164f7e7SMaxime Ripard .expected_result = 0, 361*5164f7e7SMaxime Ripard }, 362*5164f7e7SMaxime Ripard 363*5164f7e7SMaxime Ripard { 364*5164f7e7SMaxime Ripard .name = "valid_clone", 365*5164f7e7SMaxime Ripard .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_1, 366*5164f7e7SMaxime Ripard .expected_result = 0, 367*5164f7e7SMaxime Ripard }, 368*5164f7e7SMaxime Ripard { 369*5164f7e7SMaxime Ripard .name = "invalid_clone", 370*5164f7e7SMaxime Ripard .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_2, 371*5164f7e7SMaxime Ripard .expected_result = -EINVAL, 372*5164f7e7SMaxime Ripard }, 373*5164f7e7SMaxime Ripard }; 374*5164f7e7SMaxime Ripard 375*5164f7e7SMaxime Ripard KUNIT_ARRAY_PARAM(drm_check_in_clone_mode, drm_clone_mode_tests, 376*5164f7e7SMaxime Ripard drm_check_in_clone_mode_desc); 377*5164f7e7SMaxime Ripard 378*5164f7e7SMaxime Ripard KUNIT_ARRAY_PARAM(drm_check_valid_clones, drm_valid_clone_mode_tests, 379*5164f7e7SMaxime Ripard drm_check_valid_clones_desc); 380*5164f7e7SMaxime Ripard 381*5164f7e7SMaxime Ripard static struct kunit_case drm_test_check_modeset_test[] = { 382*5164f7e7SMaxime Ripard KUNIT_CASE(drm_test_check_connector_changed_modeset), 383*5164f7e7SMaxime Ripard {} 384*5164f7e7SMaxime Ripard }; 385*5164f7e7SMaxime Ripard 386*5164f7e7SMaxime Ripard static struct kunit_case drm_in_clone_mode_check_test[] = { 387*5164f7e7SMaxime Ripard KUNIT_CASE_PARAM(drm_test_check_in_clone_mode, 388*5164f7e7SMaxime Ripard drm_check_in_clone_mode_gen_params), 389*5164f7e7SMaxime Ripard KUNIT_CASE_PARAM(drm_test_check_valid_clones, 390*5164f7e7SMaxime Ripard drm_check_valid_clones_gen_params), 391*5164f7e7SMaxime Ripard {} 392*5164f7e7SMaxime Ripard }; 393*5164f7e7SMaxime Ripard 394*5164f7e7SMaxime Ripard static struct kunit_suite drm_test_check_modeset_test_suite = { 395*5164f7e7SMaxime Ripard .name = "drm_validate_modeset", 396*5164f7e7SMaxime Ripard .test_cases = drm_test_check_modeset_test, 397*5164f7e7SMaxime Ripard }; 398*5164f7e7SMaxime Ripard 399*5164f7e7SMaxime Ripard static struct kunit_suite drm_in_clone_mode_check_test_suite = { 400*5164f7e7SMaxime Ripard .name = "drm_validate_clone_mode", 401*5164f7e7SMaxime Ripard .test_cases = drm_in_clone_mode_check_test, 402*5164f7e7SMaxime Ripard }; 403*5164f7e7SMaxime Ripard 404*5164f7e7SMaxime Ripard kunit_test_suites(&drm_in_clone_mode_check_test_suite, 405*5164f7e7SMaxime Ripard &drm_test_check_modeset_test_suite); 406*5164f7e7SMaxime Ripard 407*5164f7e7SMaxime Ripard MODULE_AUTHOR("Jessica Zhang <quic_jesszhan@quicinc.com"); 408*5164f7e7SMaxime Ripard MODULE_DESCRIPTION("Test cases for the drm_atomic_helper functions"); 409*5164f7e7SMaxime Ripard MODULE_LICENSE("GPL"); 410