1 /* 2 * Copyright (C) 2017 Samsung Electronics Co.Ltd 3 * Authors: 4 * Marek Szyprowski <m.szyprowski@samsung.com> 5 * 6 * Exynos DRM Image Post Processing (IPP) related functions 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included in 16 * all copies or substantial portions of the Software. 17 */ 18 19 #include <linux/uaccess.h> 20 21 #include <drm/drm_blend.h> 22 #include <drm/drm_file.h> 23 #include <drm/drm_fourcc.h> 24 #include <drm/drm_mode.h> 25 #include <drm/exynos_drm.h> 26 27 #include "exynos_drm_drv.h" 28 #include "exynos_drm_gem.h" 29 #include "exynos_drm_ipp.h" 30 31 static int num_ipp; 32 static LIST_HEAD(ipp_list); 33 34 /** 35 * exynos_drm_ipp_register - Register a new picture processor hardware module 36 * @dev: DRM device 37 * @ipp: ipp module to init 38 * @funcs: callbacks for the new ipp object 39 * @caps: bitmask of ipp capabilities (%DRM_EXYNOS_IPP_CAP_*) 40 * @formats: array of supported formats 41 * @num_formats: size of the supported formats array 42 * @name: name (for debugging purposes) 43 * 44 * Initializes a ipp module. 45 * 46 * Returns: 47 * Zero on success, error code on failure. 48 */ 49 int exynos_drm_ipp_register(struct device *dev, struct exynos_drm_ipp *ipp, 50 const struct exynos_drm_ipp_funcs *funcs, unsigned int caps, 51 const struct exynos_drm_ipp_formats *formats, 52 unsigned int num_formats, const char *name) 53 { 54 WARN_ON(!ipp); 55 WARN_ON(!funcs); 56 WARN_ON(!formats); 57 WARN_ON(!num_formats); 58 59 spin_lock_init(&ipp->lock); 60 INIT_LIST_HEAD(&ipp->todo_list); 61 init_waitqueue_head(&ipp->done_wq); 62 ipp->dev = dev; 63 ipp->funcs = funcs; 64 ipp->capabilities = caps; 65 ipp->name = name; 66 ipp->formats = formats; 67 ipp->num_formats = num_formats; 68 69 /* ipp_list modification is serialized by component framework */ 70 list_add_tail(&ipp->head, &ipp_list); 71 ipp->id = num_ipp++; 72 73 DRM_DEV_DEBUG_DRIVER(dev, "Registered ipp %d\n", ipp->id); 74 75 return 0; 76 } 77 78 /** 79 * exynos_drm_ipp_unregister - Unregister the picture processor module 80 * @dev: DRM device 81 * @ipp: ipp module 82 */ 83 void exynos_drm_ipp_unregister(struct device *dev, 84 struct exynos_drm_ipp *ipp) 85 { 86 WARN_ON(ipp->task); 87 WARN_ON(!list_empty(&ipp->todo_list)); 88 list_del(&ipp->head); 89 } 90 91 /** 92 * exynos_drm_ipp_get_res_ioctl - enumerate all ipp modules 93 * @dev: DRM device 94 * @data: ioctl data 95 * @file_priv: DRM file info 96 * 97 * Construct a list of ipp ids. 98 * 99 * Called by the user via ioctl. 100 * 101 * Returns: 102 * Zero on success, negative errno on failure. 103 */ 104 int exynos_drm_ipp_get_res_ioctl(struct drm_device *dev, void *data, 105 struct drm_file *file_priv) 106 { 107 struct drm_exynos_ioctl_ipp_get_res *resp = data; 108 struct exynos_drm_ipp *ipp; 109 uint32_t __user *ipp_ptr = (uint32_t __user *) 110 (unsigned long)resp->ipp_id_ptr; 111 unsigned int count = num_ipp, copied = 0; 112 113 /* 114 * This ioctl is called twice, once to determine how much space is 115 * needed, and the 2nd time to fill it. 116 */ 117 if (count && resp->count_ipps >= count) { 118 list_for_each_entry(ipp, &ipp_list, head) { 119 if (put_user(ipp->id, ipp_ptr + copied)) 120 return -EFAULT; 121 copied++; 122 } 123 } 124 resp->count_ipps = count; 125 126 return 0; 127 } 128 129 static inline struct exynos_drm_ipp *__ipp_get(uint32_t id) 130 { 131 struct exynos_drm_ipp *ipp; 132 133 list_for_each_entry(ipp, &ipp_list, head) 134 if (ipp->id == id) 135 return ipp; 136 return NULL; 137 } 138 139 /** 140 * exynos_drm_ipp_get_caps_ioctl - get ipp module capabilities and formats 141 * @dev: DRM device 142 * @data: ioctl data 143 * @file_priv: DRM file info 144 * 145 * Construct a structure describing ipp module capabilities. 146 * 147 * Called by the user via ioctl. 148 * 149 * Returns: 150 * Zero on success, negative errno on failure. 151 */ 152 int exynos_drm_ipp_get_caps_ioctl(struct drm_device *dev, void *data, 153 struct drm_file *file_priv) 154 { 155 struct drm_exynos_ioctl_ipp_get_caps *resp = data; 156 void __user *ptr = (void __user *)(unsigned long)resp->formats_ptr; 157 struct exynos_drm_ipp *ipp; 158 int i; 159 160 ipp = __ipp_get(resp->ipp_id); 161 if (!ipp) 162 return -ENOENT; 163 164 resp->ipp_id = ipp->id; 165 resp->capabilities = ipp->capabilities; 166 167 /* 168 * This ioctl is called twice, once to determine how much space is 169 * needed, and the 2nd time to fill it. 170 */ 171 if (resp->formats_count >= ipp->num_formats) { 172 for (i = 0; i < ipp->num_formats; i++) { 173 struct drm_exynos_ipp_format tmp = { 174 .fourcc = ipp->formats[i].fourcc, 175 .type = ipp->formats[i].type, 176 .modifier = ipp->formats[i].modifier, 177 }; 178 179 if (copy_to_user(ptr, &tmp, sizeof(tmp))) 180 return -EFAULT; 181 ptr += sizeof(tmp); 182 } 183 } 184 resp->formats_count = ipp->num_formats; 185 186 return 0; 187 } 188 189 static inline const struct exynos_drm_ipp_formats *__ipp_format_get( 190 struct exynos_drm_ipp *ipp, uint32_t fourcc, 191 uint64_t mod, unsigned int type) 192 { 193 int i; 194 195 for (i = 0; i < ipp->num_formats; i++) { 196 if ((ipp->formats[i].type & type) && 197 ipp->formats[i].fourcc == fourcc && 198 ipp->formats[i].modifier == mod) 199 return &ipp->formats[i]; 200 } 201 return NULL; 202 } 203 204 /** 205 * exynos_drm_ipp_get_limits_ioctl - get ipp module limits 206 * @dev: DRM device 207 * @data: ioctl data 208 * @file_priv: DRM file info 209 * 210 * Construct a structure describing ipp module limitations for provided 211 * picture format. 212 * 213 * Called by the user via ioctl. 214 * 215 * Returns: 216 * Zero on success, negative errno on failure. 217 */ 218 int exynos_drm_ipp_get_limits_ioctl(struct drm_device *dev, void *data, 219 struct drm_file *file_priv) 220 { 221 struct drm_exynos_ioctl_ipp_get_limits *resp = data; 222 void __user *ptr = (void __user *)(unsigned long)resp->limits_ptr; 223 const struct exynos_drm_ipp_formats *format; 224 struct exynos_drm_ipp *ipp; 225 226 if (resp->type != DRM_EXYNOS_IPP_FORMAT_SOURCE && 227 resp->type != DRM_EXYNOS_IPP_FORMAT_DESTINATION) 228 return -EINVAL; 229 230 ipp = __ipp_get(resp->ipp_id); 231 if (!ipp) 232 return -ENOENT; 233 234 format = __ipp_format_get(ipp, resp->fourcc, resp->modifier, 235 resp->type); 236 if (!format) 237 return -EINVAL; 238 239 /* 240 * This ioctl is called twice, once to determine how much space is 241 * needed, and the 2nd time to fill it. 242 */ 243 if (format->num_limits && resp->limits_count >= format->num_limits) 244 if (copy_to_user((void __user *)ptr, format->limits, 245 sizeof(*format->limits) * format->num_limits)) 246 return -EFAULT; 247 resp->limits_count = format->num_limits; 248 249 return 0; 250 } 251 252 struct drm_pending_exynos_ipp_event { 253 struct drm_pending_event base; 254 struct drm_exynos_ipp_event event; 255 }; 256 257 static inline struct exynos_drm_ipp_task * 258 exynos_drm_ipp_task_alloc(struct exynos_drm_ipp *ipp) 259 { 260 struct exynos_drm_ipp_task *task; 261 262 task = kzalloc(sizeof(*task), GFP_KERNEL); 263 if (!task) 264 return NULL; 265 266 task->dev = ipp->dev; 267 task->ipp = ipp; 268 269 /* some defaults */ 270 task->src.rect.w = task->dst.rect.w = UINT_MAX; 271 task->src.rect.h = task->dst.rect.h = UINT_MAX; 272 task->transform.rotation = DRM_MODE_ROTATE_0; 273 274 DRM_DEV_DEBUG_DRIVER(task->dev, "Allocated task %pK\n", task); 275 276 return task; 277 } 278 279 static const struct exynos_drm_param_map { 280 unsigned int id; 281 unsigned int size; 282 unsigned int offset; 283 } exynos_drm_ipp_params_maps[] = { 284 { 285 DRM_EXYNOS_IPP_TASK_BUFFER | DRM_EXYNOS_IPP_TASK_TYPE_SOURCE, 286 sizeof(struct drm_exynos_ipp_task_buffer), 287 offsetof(struct exynos_drm_ipp_task, src.buf), 288 }, { 289 DRM_EXYNOS_IPP_TASK_BUFFER | 290 DRM_EXYNOS_IPP_TASK_TYPE_DESTINATION, 291 sizeof(struct drm_exynos_ipp_task_buffer), 292 offsetof(struct exynos_drm_ipp_task, dst.buf), 293 }, { 294 DRM_EXYNOS_IPP_TASK_RECTANGLE | DRM_EXYNOS_IPP_TASK_TYPE_SOURCE, 295 sizeof(struct drm_exynos_ipp_task_rect), 296 offsetof(struct exynos_drm_ipp_task, src.rect), 297 }, { 298 DRM_EXYNOS_IPP_TASK_RECTANGLE | 299 DRM_EXYNOS_IPP_TASK_TYPE_DESTINATION, 300 sizeof(struct drm_exynos_ipp_task_rect), 301 offsetof(struct exynos_drm_ipp_task, dst.rect), 302 }, { 303 DRM_EXYNOS_IPP_TASK_TRANSFORM, 304 sizeof(struct drm_exynos_ipp_task_transform), 305 offsetof(struct exynos_drm_ipp_task, transform), 306 }, { 307 DRM_EXYNOS_IPP_TASK_ALPHA, 308 sizeof(struct drm_exynos_ipp_task_alpha), 309 offsetof(struct exynos_drm_ipp_task, alpha), 310 }, 311 }; 312 313 static int exynos_drm_ipp_task_set(struct exynos_drm_ipp_task *task, 314 struct drm_exynos_ioctl_ipp_commit *arg) 315 { 316 const struct exynos_drm_param_map *map = exynos_drm_ipp_params_maps; 317 void __user *params = (void __user *)(unsigned long)arg->params_ptr; 318 unsigned int size = arg->params_size; 319 uint32_t id; 320 int i; 321 322 while (size) { 323 if (get_user(id, (uint32_t __user *)params)) 324 return -EFAULT; 325 326 for (i = 0; i < ARRAY_SIZE(exynos_drm_ipp_params_maps); i++) 327 if (map[i].id == id) 328 break; 329 if (i == ARRAY_SIZE(exynos_drm_ipp_params_maps) || 330 map[i].size > size) 331 return -EINVAL; 332 333 if (copy_from_user((void *)task + map[i].offset, params, 334 map[i].size)) 335 return -EFAULT; 336 337 params += map[i].size; 338 size -= map[i].size; 339 } 340 341 DRM_DEV_DEBUG_DRIVER(task->dev, 342 "Got task %pK configuration from userspace\n", 343 task); 344 return 0; 345 } 346 347 static int exynos_drm_ipp_task_setup_buffer(struct exynos_drm_ipp_buffer *buf, 348 struct drm_file *filp) 349 { 350 int ret = 0; 351 int i; 352 353 /* get GEM buffers and check their size */ 354 for (i = 0; i < buf->format->num_planes; i++) { 355 unsigned int height = (i == 0) ? buf->buf.height : 356 DIV_ROUND_UP(buf->buf.height, buf->format->vsub); 357 unsigned long size = height * buf->buf.pitch[i]; 358 struct exynos_drm_gem *gem = exynos_drm_gem_get(filp, 359 buf->buf.gem_id[i]); 360 if (!gem) { 361 ret = -ENOENT; 362 goto gem_free; 363 } 364 buf->exynos_gem[i] = gem; 365 366 if (size + buf->buf.offset[i] > buf->exynos_gem[i]->size) { 367 i++; 368 ret = -EINVAL; 369 goto gem_free; 370 } 371 buf->dma_addr[i] = buf->exynos_gem[i]->dma_addr + 372 buf->buf.offset[i]; 373 } 374 375 return 0; 376 gem_free: 377 while (i--) { 378 exynos_drm_gem_put(buf->exynos_gem[i]); 379 buf->exynos_gem[i] = NULL; 380 } 381 return ret; 382 } 383 384 static void exynos_drm_ipp_task_release_buf(struct exynos_drm_ipp_buffer *buf) 385 { 386 int i; 387 388 if (!buf->exynos_gem[0]) 389 return; 390 for (i = 0; i < buf->format->num_planes; i++) 391 exynos_drm_gem_put(buf->exynos_gem[i]); 392 } 393 394 static void exynos_drm_ipp_task_free(struct exynos_drm_ipp *ipp, 395 struct exynos_drm_ipp_task *task) 396 { 397 DRM_DEV_DEBUG_DRIVER(task->dev, "Freeing task %pK\n", task); 398 399 exynos_drm_ipp_task_release_buf(&task->src); 400 exynos_drm_ipp_task_release_buf(&task->dst); 401 if (task->event) 402 drm_event_cancel_free(ipp->drm_dev, &task->event->base); 403 kfree(task); 404 } 405 406 struct drm_ipp_limit { 407 struct drm_exynos_ipp_limit_val h; 408 struct drm_exynos_ipp_limit_val v; 409 }; 410 411 enum drm_ipp_size_id { 412 IPP_LIMIT_BUFFER, IPP_LIMIT_AREA, IPP_LIMIT_ROTATED, IPP_LIMIT_MAX 413 }; 414 415 static const enum drm_exynos_ipp_limit_type limit_id_fallback[IPP_LIMIT_MAX][4] = { 416 [IPP_LIMIT_BUFFER] = { DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER }, 417 [IPP_LIMIT_AREA] = { DRM_EXYNOS_IPP_LIMIT_SIZE_AREA, 418 DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER }, 419 [IPP_LIMIT_ROTATED] = { DRM_EXYNOS_IPP_LIMIT_SIZE_ROTATED, 420 DRM_EXYNOS_IPP_LIMIT_SIZE_AREA, 421 DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER }, 422 }; 423 424 static inline void __limit_set_val(unsigned int *ptr, unsigned int val) 425 { 426 if (!*ptr) 427 *ptr = val; 428 } 429 430 static void __get_size_limit(const struct drm_exynos_ipp_limit *limits, 431 unsigned int num_limits, enum drm_ipp_size_id id, 432 struct drm_ipp_limit *res) 433 { 434 const struct drm_exynos_ipp_limit *l = limits; 435 int i = 0; 436 437 memset(res, 0, sizeof(*res)); 438 for (i = 0; limit_id_fallback[id][i]; i++) 439 for (l = limits; l - limits < num_limits; l++) { 440 if (((l->type & DRM_EXYNOS_IPP_LIMIT_TYPE_MASK) != 441 DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE) || 442 ((l->type & DRM_EXYNOS_IPP_LIMIT_SIZE_MASK) != 443 limit_id_fallback[id][i])) 444 continue; 445 __limit_set_val(&res->h.min, l->h.min); 446 __limit_set_val(&res->h.max, l->h.max); 447 __limit_set_val(&res->h.align, l->h.align); 448 __limit_set_val(&res->v.min, l->v.min); 449 __limit_set_val(&res->v.max, l->v.max); 450 __limit_set_val(&res->v.align, l->v.align); 451 } 452 } 453 454 static inline bool __align_check(unsigned int val, unsigned int align) 455 { 456 if (align && (val & (align - 1))) { 457 DRM_DEBUG_DRIVER("Value %d exceeds HW limits (align %d)\n", 458 val, align); 459 return false; 460 } 461 return true; 462 } 463 464 static inline bool __size_limit_check(unsigned int val, 465 struct drm_exynos_ipp_limit_val *l) 466 { 467 if ((l->min && val < l->min) || (l->max && val > l->max)) { 468 DRM_DEBUG_DRIVER("Value %d exceeds HW limits (min %d, max %d)\n", 469 val, l->min, l->max); 470 return false; 471 } 472 return __align_check(val, l->align); 473 } 474 475 static int exynos_drm_ipp_check_size_limits(struct exynos_drm_ipp_buffer *buf, 476 const struct drm_exynos_ipp_limit *limits, unsigned int num_limits, 477 bool rotate, bool swap) 478 { 479 enum drm_ipp_size_id id = rotate ? IPP_LIMIT_ROTATED : IPP_LIMIT_AREA; 480 struct drm_ipp_limit l; 481 struct drm_exynos_ipp_limit_val *lh = &l.h, *lv = &l.v; 482 int real_width = buf->buf.pitch[0] / buf->format->cpp[0]; 483 484 if (!limits) 485 return 0; 486 487 __get_size_limit(limits, num_limits, IPP_LIMIT_BUFFER, &l); 488 if (!__size_limit_check(real_width, &l.h) || 489 !__size_limit_check(buf->buf.height, &l.v)) 490 return -EINVAL; 491 492 if (swap) { 493 lv = &l.h; 494 lh = &l.v; 495 } 496 __get_size_limit(limits, num_limits, id, &l); 497 if (!__size_limit_check(buf->rect.w, lh) || 498 !__align_check(buf->rect.x, lh->align) || 499 !__size_limit_check(buf->rect.h, lv) || 500 !__align_check(buf->rect.y, lv->align)) 501 return -EINVAL; 502 503 return 0; 504 } 505 506 static inline bool __scale_limit_check(unsigned int src, unsigned int dst, 507 unsigned int min, unsigned int max) 508 { 509 if ((max && (dst << 16) > src * max) || 510 (min && (dst << 16) < src * min)) { 511 DRM_DEBUG_DRIVER("Scale from %d to %d exceeds HW limits (ratio min %d.%05d, max %d.%05d)\n", 512 src, dst, 513 min >> 16, 100000 * (min & 0xffff) / (1 << 16), 514 max >> 16, 100000 * (max & 0xffff) / (1 << 16)); 515 return false; 516 } 517 return true; 518 } 519 520 static int exynos_drm_ipp_check_scale_limits( 521 struct drm_exynos_ipp_task_rect *src, 522 struct drm_exynos_ipp_task_rect *dst, 523 const struct drm_exynos_ipp_limit *limits, 524 unsigned int num_limits, bool swap) 525 { 526 const struct drm_exynos_ipp_limit_val *lh, *lv; 527 int dw, dh; 528 529 for (; num_limits; limits++, num_limits--) 530 if ((limits->type & DRM_EXYNOS_IPP_LIMIT_TYPE_MASK) == 531 DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE) 532 break; 533 if (!num_limits) 534 return 0; 535 536 lh = (!swap) ? &limits->h : &limits->v; 537 lv = (!swap) ? &limits->v : &limits->h; 538 dw = (!swap) ? dst->w : dst->h; 539 dh = (!swap) ? dst->h : dst->w; 540 541 if (!__scale_limit_check(src->w, dw, lh->min, lh->max) || 542 !__scale_limit_check(src->h, dh, lv->min, lv->max)) 543 return -EINVAL; 544 545 return 0; 546 } 547 548 static int exynos_drm_ipp_check_format(struct exynos_drm_ipp_task *task, 549 struct exynos_drm_ipp_buffer *buf, 550 struct exynos_drm_ipp_buffer *src, 551 struct exynos_drm_ipp_buffer *dst, 552 bool rotate, bool swap) 553 { 554 const struct exynos_drm_ipp_formats *fmt; 555 int ret, i; 556 557 fmt = __ipp_format_get(task->ipp, buf->buf.fourcc, buf->buf.modifier, 558 buf == src ? DRM_EXYNOS_IPP_FORMAT_SOURCE : 559 DRM_EXYNOS_IPP_FORMAT_DESTINATION); 560 if (!fmt) { 561 DRM_DEV_DEBUG_DRIVER(task->dev, 562 "Task %pK: %s format not supported\n", 563 task, buf == src ? "src" : "dst"); 564 return -EINVAL; 565 } 566 567 /* basic checks */ 568 if (buf->buf.width == 0 || buf->buf.height == 0) 569 return -EINVAL; 570 571 buf->format = drm_format_info(buf->buf.fourcc); 572 for (i = 0; i < buf->format->num_planes; i++) { 573 unsigned int width = (i == 0) ? buf->buf.width : 574 DIV_ROUND_UP(buf->buf.width, buf->format->hsub); 575 576 if (buf->buf.pitch[i] == 0) 577 buf->buf.pitch[i] = width * buf->format->cpp[i]; 578 if (buf->buf.pitch[i] < width * buf->format->cpp[i]) 579 return -EINVAL; 580 if (!buf->buf.gem_id[i]) 581 return -ENOENT; 582 } 583 584 /* pitch for additional planes must match */ 585 if (buf->format->num_planes > 2 && 586 buf->buf.pitch[1] != buf->buf.pitch[2]) 587 return -EINVAL; 588 589 /* check driver limits */ 590 ret = exynos_drm_ipp_check_size_limits(buf, fmt->limits, 591 fmt->num_limits, 592 rotate, 593 buf == dst ? swap : false); 594 if (ret) 595 return ret; 596 ret = exynos_drm_ipp_check_scale_limits(&src->rect, &dst->rect, 597 fmt->limits, 598 fmt->num_limits, swap); 599 return ret; 600 } 601 602 static int exynos_drm_ipp_task_check(struct exynos_drm_ipp_task *task) 603 { 604 struct exynos_drm_ipp *ipp = task->ipp; 605 struct exynos_drm_ipp_buffer *src = &task->src, *dst = &task->dst; 606 unsigned int rotation = task->transform.rotation; 607 int ret = 0; 608 bool swap = drm_rotation_90_or_270(rotation); 609 bool rotate = (rotation != DRM_MODE_ROTATE_0); 610 bool scale = false; 611 612 DRM_DEV_DEBUG_DRIVER(task->dev, "Checking task %pK\n", task); 613 614 if (src->rect.w == UINT_MAX) 615 src->rect.w = src->buf.width; 616 if (src->rect.h == UINT_MAX) 617 src->rect.h = src->buf.height; 618 if (dst->rect.w == UINT_MAX) 619 dst->rect.w = dst->buf.width; 620 if (dst->rect.h == UINT_MAX) 621 dst->rect.h = dst->buf.height; 622 623 if (src->rect.x + src->rect.w > (src->buf.width) || 624 src->rect.y + src->rect.h > (src->buf.height) || 625 dst->rect.x + dst->rect.w > (dst->buf.width) || 626 dst->rect.y + dst->rect.h > (dst->buf.height)) { 627 DRM_DEV_DEBUG_DRIVER(task->dev, 628 "Task %pK: defined area is outside provided buffers\n", 629 task); 630 return -EINVAL; 631 } 632 633 if ((!swap && (src->rect.w != dst->rect.w || 634 src->rect.h != dst->rect.h)) || 635 (swap && (src->rect.w != dst->rect.h || 636 src->rect.h != dst->rect.w))) 637 scale = true; 638 639 if ((!(ipp->capabilities & DRM_EXYNOS_IPP_CAP_CROP) && 640 (src->rect.x || src->rect.y || dst->rect.x || dst->rect.y)) || 641 (!(ipp->capabilities & DRM_EXYNOS_IPP_CAP_ROTATE) && rotate) || 642 (!(ipp->capabilities & DRM_EXYNOS_IPP_CAP_SCALE) && scale) || 643 (!(ipp->capabilities & DRM_EXYNOS_IPP_CAP_CONVERT) && 644 src->buf.fourcc != dst->buf.fourcc)) { 645 DRM_DEV_DEBUG_DRIVER(task->dev, "Task %pK: hw capabilities exceeded\n", 646 task); 647 return -EINVAL; 648 } 649 650 ret = exynos_drm_ipp_check_format(task, src, src, dst, rotate, swap); 651 if (ret) 652 return ret; 653 654 ret = exynos_drm_ipp_check_format(task, dst, src, dst, false, swap); 655 if (ret) 656 return ret; 657 658 DRM_DEV_DEBUG_DRIVER(ipp->dev, "Task %pK: all checks done.\n", 659 task); 660 661 return ret; 662 } 663 664 static int exynos_drm_ipp_task_setup_buffers(struct exynos_drm_ipp_task *task, 665 struct drm_file *filp) 666 { 667 struct exynos_drm_ipp_buffer *src = &task->src, *dst = &task->dst; 668 int ret = 0; 669 670 DRM_DEV_DEBUG_DRIVER(task->dev, "Setting buffer for task %pK\n", 671 task); 672 673 ret = exynos_drm_ipp_task_setup_buffer(src, filp); 674 if (ret) { 675 DRM_DEV_DEBUG_DRIVER(task->dev, 676 "Task %pK: src buffer setup failed\n", 677 task); 678 return ret; 679 } 680 ret = exynos_drm_ipp_task_setup_buffer(dst, filp); 681 if (ret) { 682 DRM_DEV_DEBUG_DRIVER(task->dev, 683 "Task %pK: dst buffer setup failed\n", 684 task); 685 return ret; 686 } 687 688 DRM_DEV_DEBUG_DRIVER(task->dev, "Task %pK: buffers prepared.\n", 689 task); 690 691 return ret; 692 } 693 694 695 static int exynos_drm_ipp_event_create(struct exynos_drm_ipp_task *task, 696 struct drm_file *file_priv, uint64_t user_data) 697 { 698 struct drm_pending_exynos_ipp_event *e = NULL; 699 int ret; 700 701 e = kzalloc(sizeof(*e), GFP_KERNEL); 702 if (!e) 703 return -ENOMEM; 704 705 e->event.base.type = DRM_EXYNOS_IPP_EVENT; 706 e->event.base.length = sizeof(e->event); 707 e->event.user_data = user_data; 708 709 ret = drm_event_reserve_init(task->ipp->drm_dev, file_priv, &e->base, 710 &e->event.base); 711 if (ret) 712 goto free; 713 714 task->event = e; 715 return 0; 716 free: 717 kfree(e); 718 return ret; 719 } 720 721 static void exynos_drm_ipp_event_send(struct exynos_drm_ipp_task *task) 722 { 723 struct timespec64 now; 724 725 ktime_get_ts64(&now); 726 task->event->event.tv_sec = now.tv_sec; 727 task->event->event.tv_usec = now.tv_nsec / NSEC_PER_USEC; 728 task->event->event.sequence = atomic_inc_return(&task->ipp->sequence); 729 730 drm_send_event(task->ipp->drm_dev, &task->event->base); 731 } 732 733 static int exynos_drm_ipp_task_cleanup(struct exynos_drm_ipp_task *task) 734 { 735 int ret = task->ret; 736 737 if (ret == 0 && task->event) { 738 exynos_drm_ipp_event_send(task); 739 /* ensure event won't be canceled on task free */ 740 task->event = NULL; 741 } 742 743 exynos_drm_ipp_task_free(task->ipp, task); 744 return ret; 745 } 746 747 static void exynos_drm_ipp_cleanup_work(struct work_struct *work) 748 { 749 struct exynos_drm_ipp_task *task = container_of(work, 750 struct exynos_drm_ipp_task, cleanup_work); 751 752 exynos_drm_ipp_task_cleanup(task); 753 } 754 755 static void exynos_drm_ipp_next_task(struct exynos_drm_ipp *ipp); 756 757 /** 758 * exynos_drm_ipp_task_done - finish given task and set return code 759 * @task: ipp task to finish 760 * @ret: error code or 0 if operation has been performed successfully 761 */ 762 void exynos_drm_ipp_task_done(struct exynos_drm_ipp_task *task, int ret) 763 { 764 struct exynos_drm_ipp *ipp = task->ipp; 765 unsigned long flags; 766 767 DRM_DEV_DEBUG_DRIVER(task->dev, "ipp: %d, task %pK done: %d\n", 768 ipp->id, task, ret); 769 770 spin_lock_irqsave(&ipp->lock, flags); 771 if (ipp->task == task) 772 ipp->task = NULL; 773 task->flags |= DRM_EXYNOS_IPP_TASK_DONE; 774 task->ret = ret; 775 spin_unlock_irqrestore(&ipp->lock, flags); 776 777 exynos_drm_ipp_next_task(ipp); 778 wake_up(&ipp->done_wq); 779 780 if (task->flags & DRM_EXYNOS_IPP_TASK_ASYNC) { 781 INIT_WORK(&task->cleanup_work, exynos_drm_ipp_cleanup_work); 782 schedule_work(&task->cleanup_work); 783 } 784 } 785 786 static void exynos_drm_ipp_next_task(struct exynos_drm_ipp *ipp) 787 { 788 struct exynos_drm_ipp_task *task; 789 unsigned long flags; 790 int ret; 791 792 DRM_DEV_DEBUG_DRIVER(ipp->dev, "ipp: %d, try to run new task\n", 793 ipp->id); 794 795 spin_lock_irqsave(&ipp->lock, flags); 796 797 if (ipp->task || list_empty(&ipp->todo_list)) { 798 spin_unlock_irqrestore(&ipp->lock, flags); 799 return; 800 } 801 802 task = list_first_entry(&ipp->todo_list, struct exynos_drm_ipp_task, 803 head); 804 list_del_init(&task->head); 805 ipp->task = task; 806 807 spin_unlock_irqrestore(&ipp->lock, flags); 808 809 DRM_DEV_DEBUG_DRIVER(ipp->dev, 810 "ipp: %d, selected task %pK to run\n", ipp->id, 811 task); 812 813 ret = ipp->funcs->commit(ipp, task); 814 if (ret) 815 exynos_drm_ipp_task_done(task, ret); 816 } 817 818 static void exynos_drm_ipp_schedule_task(struct exynos_drm_ipp *ipp, 819 struct exynos_drm_ipp_task *task) 820 { 821 unsigned long flags; 822 823 spin_lock_irqsave(&ipp->lock, flags); 824 list_add(&task->head, &ipp->todo_list); 825 spin_unlock_irqrestore(&ipp->lock, flags); 826 827 exynos_drm_ipp_next_task(ipp); 828 } 829 830 static void exynos_drm_ipp_task_abort(struct exynos_drm_ipp *ipp, 831 struct exynos_drm_ipp_task *task) 832 { 833 unsigned long flags; 834 835 spin_lock_irqsave(&ipp->lock, flags); 836 if (task->flags & DRM_EXYNOS_IPP_TASK_DONE) { 837 /* already completed task */ 838 exynos_drm_ipp_task_cleanup(task); 839 } else if (ipp->task != task) { 840 /* task has not been scheduled for execution yet */ 841 list_del_init(&task->head); 842 exynos_drm_ipp_task_cleanup(task); 843 } else { 844 /* 845 * currently processed task, call abort() and perform 846 * cleanup with async worker 847 */ 848 task->flags |= DRM_EXYNOS_IPP_TASK_ASYNC; 849 spin_unlock_irqrestore(&ipp->lock, flags); 850 if (ipp->funcs->abort) 851 ipp->funcs->abort(ipp, task); 852 return; 853 } 854 spin_unlock_irqrestore(&ipp->lock, flags); 855 } 856 857 /** 858 * exynos_drm_ipp_commit_ioctl - perform image processing operation 859 * @dev: DRM device 860 * @data: ioctl data 861 * @file_priv: DRM file info 862 * 863 * Construct a ipp task from the set of properties provided from the user 864 * and try to schedule it to framebuffer processor hardware. 865 * 866 * Called by the user via ioctl. 867 * 868 * Returns: 869 * Zero on success, negative errno on failure. 870 */ 871 int exynos_drm_ipp_commit_ioctl(struct drm_device *dev, void *data, 872 struct drm_file *file_priv) 873 { 874 struct drm_exynos_ioctl_ipp_commit *arg = data; 875 struct exynos_drm_ipp *ipp; 876 struct exynos_drm_ipp_task *task; 877 int ret = 0; 878 879 if ((arg->flags & ~DRM_EXYNOS_IPP_FLAGS) || arg->reserved) 880 return -EINVAL; 881 882 /* can't test and expect an event at the same time */ 883 if ((arg->flags & DRM_EXYNOS_IPP_FLAG_TEST_ONLY) && 884 (arg->flags & DRM_EXYNOS_IPP_FLAG_EVENT)) 885 return -EINVAL; 886 887 ipp = __ipp_get(arg->ipp_id); 888 if (!ipp) 889 return -ENOENT; 890 891 task = exynos_drm_ipp_task_alloc(ipp); 892 if (!task) 893 return -ENOMEM; 894 895 ret = exynos_drm_ipp_task_set(task, arg); 896 if (ret) 897 goto free; 898 899 ret = exynos_drm_ipp_task_check(task); 900 if (ret) 901 goto free; 902 903 ret = exynos_drm_ipp_task_setup_buffers(task, file_priv); 904 if (ret || arg->flags & DRM_EXYNOS_IPP_FLAG_TEST_ONLY) 905 goto free; 906 907 if (arg->flags & DRM_EXYNOS_IPP_FLAG_EVENT) { 908 ret = exynos_drm_ipp_event_create(task, file_priv, 909 arg->user_data); 910 if (ret) 911 goto free; 912 } 913 914 /* 915 * Queue task for processing on the hardware. task object will be 916 * then freed after exynos_drm_ipp_task_done() 917 */ 918 if (arg->flags & DRM_EXYNOS_IPP_FLAG_NONBLOCK) { 919 DRM_DEV_DEBUG_DRIVER(ipp->dev, 920 "ipp: %d, nonblocking processing task %pK\n", 921 ipp->id, task); 922 923 task->flags |= DRM_EXYNOS_IPP_TASK_ASYNC; 924 exynos_drm_ipp_schedule_task(task->ipp, task); 925 ret = 0; 926 } else { 927 DRM_DEV_DEBUG_DRIVER(ipp->dev, "ipp: %d, processing task %pK\n", 928 ipp->id, task); 929 exynos_drm_ipp_schedule_task(ipp, task); 930 ret = wait_event_interruptible(ipp->done_wq, 931 task->flags & DRM_EXYNOS_IPP_TASK_DONE); 932 if (ret) 933 exynos_drm_ipp_task_abort(ipp, task); 934 else 935 ret = exynos_drm_ipp_task_cleanup(task); 936 } 937 return ret; 938 free: 939 exynos_drm_ipp_task_free(ipp, task); 940 941 return ret; 942 } 943