1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Test cases for the drm_framebuffer functions 4 * 5 * Copyright (c) 2022 Maíra Canal <[email protected]> 6 */ 7 8 #include <kunit/test.h> 9 10 #include <drm/drm_device.h> 11 #include <drm/drm_drv.h> 12 #include <drm/drm_mode.h> 13 #include <drm/drm_fourcc.h> 14 #include <drm/drm_kunit_helpers.h> 15 #include <drm/drm_print.h> 16 17 #include "../drm_crtc_internal.h" 18 19 #define MIN_WIDTH 4 20 #define MAX_WIDTH 4096 21 #define MIN_HEIGHT 4 22 #define MAX_HEIGHT 4096 23 24 struct drm_framebuffer_test { 25 int buffer_created; 26 struct drm_mode_fb_cmd2 cmd; 27 const char *name; 28 }; 29 30 static const struct drm_framebuffer_test drm_framebuffer_create_cases[] = { 31 { .buffer_created = 1, .name = "ABGR8888 normal sizes", 32 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_ABGR8888, 33 .handles = { 1, 0, 0 }, .pitches = { 4 * 600, 0, 0 }, 34 } 35 }, 36 { .buffer_created = 1, .name = "ABGR8888 max sizes", 37 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 38 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 }, 39 } 40 }, 41 { .buffer_created = 1, .name = "ABGR8888 pitch greater than min required", 42 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 43 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH + 1, 0, 0 }, 44 } 45 }, 46 { .buffer_created = 0, .name = "ABGR8888 pitch less than min required", 47 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 48 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH - 1, 0, 0 }, 49 } 50 }, 51 { .buffer_created = 0, .name = "ABGR8888 Invalid width", 52 .cmd = { .width = MAX_WIDTH + 1, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 53 .handles = { 1, 0, 0 }, .pitches = { 4 * (MAX_WIDTH + 1), 0, 0 }, 54 } 55 }, 56 { .buffer_created = 0, .name = "ABGR8888 Invalid buffer handle", 57 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 58 .handles = { 0, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 }, 59 } 60 }, 61 { .buffer_created = 0, .name = "No pixel format", 62 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = 0, 63 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 }, 64 } 65 }, 66 { .buffer_created = 0, .name = "ABGR8888 Width 0", 67 .cmd = { .width = 0, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 68 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 }, 69 } 70 }, 71 { .buffer_created = 0, .name = "ABGR8888 Height 0", 72 .cmd = { .width = MAX_WIDTH, .height = 0, .pixel_format = DRM_FORMAT_ABGR8888, 73 .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 }, 74 } 75 }, 76 { .buffer_created = 0, .name = "ABGR8888 Out of bound height * pitch combination", 77 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 78 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX - 1, 0, 0 }, 79 .pitches = { 4 * MAX_WIDTH, 0, 0 }, 80 } 81 }, 82 { .buffer_created = 1, .name = "ABGR8888 Large buffer offset", 83 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 84 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, 85 .pitches = { 4 * MAX_WIDTH, 0, 0 }, 86 } 87 }, 88 { .buffer_created = 1, .name = "ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers", 89 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 90 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, 91 .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS, 92 } 93 }, 94 { .buffer_created = 1, .name = "ABGR8888 Valid buffer modifier", 95 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 96 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, 97 .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS, 98 .modifier = { AFBC_FORMAT_MOD_YTR, 0, 0 }, 99 } 100 }, 101 { .buffer_created = 0, 102 .name = "ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)", 103 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 104 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, 105 .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS, 106 .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 }, 107 } 108 }, 109 { .buffer_created = 1, .name = "ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS", 110 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 111 .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, 112 .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 }, 113 } 114 }, 115 { .buffer_created = 0, .name = "ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS", 116 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888, 117 .handles = { 1, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS, 118 .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 }, 119 } 120 }, 121 { .buffer_created = 1, .name = "NV12 Normal sizes", 122 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12, 123 .handles = { 1, 1, 0 }, .pitches = { 600, 600, 0 }, 124 } 125 }, 126 { .buffer_created = 1, .name = "NV12 Max sizes", 127 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, 128 .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, 129 } 130 }, 131 { .buffer_created = 0, .name = "NV12 Invalid pitch", 132 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, 133 .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH - 1, 0 }, 134 } 135 }, 136 { .buffer_created = 0, .name = "NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag", 137 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, 138 .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 }, 139 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, 140 } 141 }, 142 { .buffer_created = 0, .name = "NV12 different modifier per-plane", 143 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, 144 .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS, 145 .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 }, 146 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, 147 } 148 }, 149 { .buffer_created = 1, .name = "NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE", 150 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, 151 .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS, 152 .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 153 DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 }, 154 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, 155 } 156 }, 157 { .buffer_created = 0, .name = "NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS", 158 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, 159 .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 160 DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 }, 161 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, 162 } 163 }, 164 { .buffer_created = 0, .name = "NV12 Modifier for inexistent plane", 165 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, 166 .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS, 167 .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 168 DRM_FORMAT_MOD_SAMSUNG_64_32_TILE }, 169 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, 170 } 171 }, 172 { .buffer_created = 0, .name = "NV12 Handle for inexistent plane", 173 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12, 174 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, 175 .pitches = { MAX_WIDTH, MAX_WIDTH, 0 }, 176 } 177 }, 178 { .buffer_created = 1, .name = "NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS", 179 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12, 180 .handles = { 1, 1, 1 }, .pitches = { 600, 600, 600 }, 181 } 182 }, 183 { .buffer_created = 1, .name = "YVU420 DRM_MODE_FB_MODIFIERS set without modifier", 184 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420, 185 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, 186 .pitches = { 600, 300, 300 }, 187 } 188 }, 189 { .buffer_created = 1, .name = "YVU420 Normal sizes", 190 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420, 191 .handles = { 1, 1, 1 }, .pitches = { 600, 300, 300 }, 192 } 193 }, 194 { .buffer_created = 1, .name = "YVU420 Max sizes", 195 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 196 .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), 197 DIV_ROUND_UP(MAX_WIDTH, 2) }, 198 } 199 }, 200 { .buffer_created = 0, .name = "YVU420 Invalid pitch", 201 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 202 .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) - 1, 203 DIV_ROUND_UP(MAX_WIDTH, 2) }, 204 } 205 }, 206 { .buffer_created = 1, .name = "YVU420 Different pitches", 207 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 208 .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1, 209 DIV_ROUND_UP(MAX_WIDTH, 2) + 7 }, 210 } 211 }, 212 { .buffer_created = 1, .name = "YVU420 Different buffer offsets/pitches", 213 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 214 .handles = { 1, 1, 1 }, .offsets = { MAX_WIDTH, MAX_WIDTH + 215 MAX_WIDTH * MAX_HEIGHT, MAX_WIDTH + 2 * MAX_WIDTH * MAX_HEIGHT }, 216 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1, 217 DIV_ROUND_UP(MAX_WIDTH, 2) + 7 }, 218 } 219 }, 220 { .buffer_created = 0, 221 .name = "YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS", 222 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 223 .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 }, 224 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, 225 } 226 }, 227 { .buffer_created = 0, 228 .name = "YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS", 229 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 230 .handles = { 1, 1, 1 }, 231 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 }, 232 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, 233 } 234 }, 235 { .buffer_created = 0, 236 .name = "YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS", 237 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 238 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, 239 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 }, 240 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, 241 } 242 }, 243 { .buffer_created = 1, .name = "YVU420 Valid modifier", 244 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 245 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, 246 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 247 AFBC_FORMAT_MOD_SPARSE }, 248 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, 249 } 250 }, 251 { .buffer_created = 0, .name = "YVU420 Different modifiers per plane", 252 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 253 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, 254 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_YTR, 255 AFBC_FORMAT_MOD_SPARSE }, 256 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, 257 } 258 }, 259 { .buffer_created = 0, .name = "YVU420 Modifier for inexistent plane", 260 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420, 261 .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, 262 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 263 AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE }, 264 .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) }, 265 } 266 }, 267 { .buffer_created = 1, .name = "X0L2 Normal sizes", 268 .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_X0L2, 269 .handles = { 1, 0, 0 }, .pitches = { 1200, 0, 0 } 270 } 271 }, 272 { .buffer_created = 1, .name = "X0L2 Max sizes", 273 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2, 274 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH, 0, 0 } 275 } 276 }, 277 { .buffer_created = 0, .name = "X0L2 Invalid pitch", 278 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2, 279 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH - 1, 0, 0 } 280 } 281 }, 282 { .buffer_created = 1, .name = "X0L2 Pitch greater than minimum required", 283 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2, 284 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 } 285 } 286 }, 287 { .buffer_created = 0, .name = "X0L2 Handle for inexistent plane", 288 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2, 289 .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS, 290 .pitches = { 2 * MAX_WIDTH + 1, 0, 0 } 291 } 292 }, 293 { .buffer_created = 1, 294 .name = "X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set", 295 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2, 296 .handles = { 1, 0, 0 }, .offsets = { 0, 0, 3 }, 297 .pitches = { 2 * MAX_WIDTH + 1, 0, 0 } 298 } 299 }, 300 { .buffer_created = 0, .name = "X0L2 Modifier without DRM_MODE_FB_MODIFIERS set", 301 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2, 302 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }, 303 .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 }, 304 } 305 }, 306 { .buffer_created = 1, .name = "X0L2 Valid modifier", 307 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2, 308 .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }, 309 .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS, 310 } 311 }, 312 { .buffer_created = 0, .name = "X0L2 Modifier for inexistent plane", 313 .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, 314 .pixel_format = DRM_FORMAT_X0L2, .handles = { 1, 0, 0 }, 315 .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }, 316 .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 }, 317 .flags = DRM_MODE_FB_MODIFIERS, 318 } 319 }, 320 }; 321 322 /* 323 * This struct is intended to provide a way to mocked functions communicate 324 * with the outer test when it can't be achieved by using its return value. In 325 * this way, the functions that receive the mocked drm_device, for example, can 326 * grab a reference to this and actually return something to be used on some 327 * expectation. 328 */ 329 struct drm_framebuffer_test_priv { 330 struct drm_device dev; 331 bool buffer_created; 332 }; 333 334 static struct drm_framebuffer *fb_create_mock(struct drm_device *dev, 335 struct drm_file *file_priv, 336 const struct drm_mode_fb_cmd2 *mode_cmd) 337 { 338 struct drm_framebuffer_test_priv *priv = container_of(dev, typeof(*priv), dev); 339 340 priv->buffer_created = true; 341 return ERR_PTR(-EINVAL); 342 } 343 344 static struct drm_mode_config_funcs mock_config_funcs = { 345 .fb_create = fb_create_mock, 346 }; 347 348 static int drm_framebuffer_test_init(struct kunit *test) 349 { 350 struct device *parent; 351 struct drm_framebuffer_test_priv *priv; 352 struct drm_device *dev; 353 354 parent = drm_kunit_helper_alloc_device(test); 355 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); 356 357 priv = drm_kunit_helper_alloc_drm_device(test, parent, typeof(*priv), 358 dev, 0); 359 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 360 dev = &priv->dev; 361 362 dev->mode_config.min_width = MIN_WIDTH; 363 dev->mode_config.max_width = MAX_WIDTH; 364 dev->mode_config.min_height = MIN_HEIGHT; 365 dev->mode_config.max_height = MAX_HEIGHT; 366 dev->mode_config.funcs = &mock_config_funcs; 367 368 test->priv = priv; 369 return 0; 370 } 371 372 static void drm_test_framebuffer_create(struct kunit *test) 373 { 374 const struct drm_framebuffer_test *params = test->param_value; 375 struct drm_framebuffer_test_priv *priv = test->priv; 376 struct drm_device *dev = &priv->dev; 377 378 priv->buffer_created = false; 379 drm_internal_framebuffer_create(dev, ¶ms->cmd, NULL); 380 KUNIT_EXPECT_EQ(test, params->buffer_created, priv->buffer_created); 381 } 382 383 static void drm_framebuffer_test_to_desc(const struct drm_framebuffer_test *t, char *desc) 384 { 385 strcpy(desc, t->name); 386 } 387 388 KUNIT_ARRAY_PARAM(drm_framebuffer_create, drm_framebuffer_create_cases, 389 drm_framebuffer_test_to_desc); 390 391 static struct kunit_case drm_framebuffer_tests[] = { 392 KUNIT_CASE_PARAM(drm_test_framebuffer_create, drm_framebuffer_create_gen_params), 393 { } 394 }; 395 396 static struct kunit_suite drm_framebuffer_test_suite = { 397 .name = "drm_framebuffer", 398 .init = drm_framebuffer_test_init, 399 .test_cases = drm_framebuffer_tests, 400 }; 401 402 kunit_test_suite(drm_framebuffer_test_suite); 403 404 MODULE_DESCRIPTION("Test cases for the drm_framebuffer functions"); 405 MODULE_LICENSE("GPL"); 406