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