1 /* 2 * Copyright (C) 2012 Samsung Electronics Co.Ltd 3 * Authors: 4 * YoungJun Cho <yj44.cho@samsung.com> 5 * Eunchul Kim <chulspro.kim@samsung.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundationr 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/err.h> 14 #include <linux/interrupt.h> 15 #include <linux/io.h> 16 #include <linux/platform_device.h> 17 #include <linux/clk.h> 18 #include <linux/pm_runtime.h> 19 20 #include <drm/drmP.h> 21 #include <drm/exynos_drm.h> 22 #include "regs-rotator.h" 23 #include "exynos_drm.h" 24 #include "exynos_drm_drv.h" 25 #include "exynos_drm_ipp.h" 26 27 /* 28 * Rotator supports image crop/rotator and input/output DMA operations. 29 * input DMA reads image data from the memory. 30 * output DMA writes image data to memory. 31 * 32 * M2M operation : supports crop/scale/rotation/csc so on. 33 * Memory ----> Rotator H/W ----> Memory. 34 */ 35 36 /* 37 * TODO 38 * 1. check suspend/resume api if needed. 39 * 2. need to check use case platform_device_id. 40 * 3. check src/dst size with, height. 41 * 4. need to add supported list in prop_list. 42 */ 43 44 #define get_rot_context(dev) platform_get_drvdata(to_platform_device(dev)) 45 #define get_ctx_from_ippdrv(ippdrv) container_of(ippdrv,\ 46 struct rot_context, ippdrv); 47 #define rot_read(offset) readl(rot->regs + (offset)) 48 #define rot_write(cfg, offset) writel(cfg, rot->regs + (offset)) 49 50 enum rot_irq_status { 51 ROT_IRQ_STATUS_COMPLETE = 8, 52 ROT_IRQ_STATUS_ILLEGAL = 9, 53 }; 54 55 /* 56 * A structure of limitation. 57 * 58 * @min_w: minimum width. 59 * @min_h: minimum height. 60 * @max_w: maximum width. 61 * @max_h: maximum height. 62 * @align: align size. 63 */ 64 struct rot_limit { 65 u32 min_w; 66 u32 min_h; 67 u32 max_w; 68 u32 max_h; 69 u32 align; 70 }; 71 72 /* 73 * A structure of limitation table. 74 * 75 * @ycbcr420_2p: case of YUV. 76 * @rgb888: case of RGB. 77 */ 78 struct rot_limit_table { 79 struct rot_limit ycbcr420_2p; 80 struct rot_limit rgb888; 81 }; 82 83 /* 84 * A structure of rotator context. 85 * @ippdrv: prepare initialization using ippdrv. 86 * @regs_res: register resources. 87 * @regs: memory mapped io registers. 88 * @clock: rotator gate clock. 89 * @limit_tbl: limitation of rotator. 90 * @irq: irq number. 91 * @cur_buf_id: current operation buffer id. 92 * @suspended: suspended state. 93 */ 94 struct rot_context { 95 struct exynos_drm_ippdrv ippdrv; 96 struct resource *regs_res; 97 void __iomem *regs; 98 struct clk *clock; 99 struct rot_limit_table *limit_tbl; 100 int irq; 101 int cur_buf_id[EXYNOS_DRM_OPS_MAX]; 102 bool suspended; 103 }; 104 105 static void rotator_reg_set_irq(struct rot_context *rot, bool enable) 106 { 107 u32 val = rot_read(ROT_CONFIG); 108 109 if (enable == true) 110 val |= ROT_CONFIG_IRQ; 111 else 112 val &= ~ROT_CONFIG_IRQ; 113 114 rot_write(val, ROT_CONFIG); 115 } 116 117 static u32 rotator_reg_get_fmt(struct rot_context *rot) 118 { 119 u32 val = rot_read(ROT_CONTROL); 120 121 val &= ROT_CONTROL_FMT_MASK; 122 123 return val; 124 } 125 126 static enum rot_irq_status rotator_reg_get_irq_status(struct rot_context *rot) 127 { 128 u32 val = rot_read(ROT_STATUS); 129 130 val = ROT_STATUS_IRQ(val); 131 132 if (val == ROT_STATUS_IRQ_VAL_COMPLETE) 133 return ROT_IRQ_STATUS_COMPLETE; 134 135 return ROT_IRQ_STATUS_ILLEGAL; 136 } 137 138 static irqreturn_t rotator_irq_handler(int irq, void *arg) 139 { 140 struct rot_context *rot = arg; 141 struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv; 142 struct drm_exynos_ipp_cmd_node *c_node = ippdrv->c_node; 143 struct drm_exynos_ipp_event_work *event_work = c_node->event_work; 144 enum rot_irq_status irq_status; 145 u32 val; 146 147 /* Get execution result */ 148 irq_status = rotator_reg_get_irq_status(rot); 149 150 /* clear status */ 151 val = rot_read(ROT_STATUS); 152 val |= ROT_STATUS_IRQ_PENDING((u32)irq_status); 153 rot_write(val, ROT_STATUS); 154 155 if (irq_status == ROT_IRQ_STATUS_COMPLETE) { 156 event_work->ippdrv = ippdrv; 157 event_work->buf_id[EXYNOS_DRM_OPS_DST] = 158 rot->cur_buf_id[EXYNOS_DRM_OPS_DST]; 159 queue_work(ippdrv->event_workq, 160 (struct work_struct *)event_work); 161 } else { 162 DRM_ERROR("the SFR is set illegally\n"); 163 } 164 165 return IRQ_HANDLED; 166 } 167 168 static void rotator_align_size(struct rot_context *rot, u32 fmt, u32 *hsize, 169 u32 *vsize) 170 { 171 struct rot_limit_table *limit_tbl = rot->limit_tbl; 172 struct rot_limit *limit; 173 u32 mask, val; 174 175 /* Get size limit */ 176 if (fmt == ROT_CONTROL_FMT_RGB888) 177 limit = &limit_tbl->rgb888; 178 else 179 limit = &limit_tbl->ycbcr420_2p; 180 181 /* Get mask for rounding to nearest aligned val */ 182 mask = ~((1 << limit->align) - 1); 183 184 /* Set aligned width */ 185 val = ROT_ALIGN(*hsize, limit->align, mask); 186 if (val < limit->min_w) 187 *hsize = ROT_MIN(limit->min_w, mask); 188 else if (val > limit->max_w) 189 *hsize = ROT_MAX(limit->max_w, mask); 190 else 191 *hsize = val; 192 193 /* Set aligned height */ 194 val = ROT_ALIGN(*vsize, limit->align, mask); 195 if (val < limit->min_h) 196 *vsize = ROT_MIN(limit->min_h, mask); 197 else if (val > limit->max_h) 198 *vsize = ROT_MAX(limit->max_h, mask); 199 else 200 *vsize = val; 201 } 202 203 static int rotator_src_set_fmt(struct device *dev, u32 fmt) 204 { 205 struct rot_context *rot = dev_get_drvdata(dev); 206 u32 val; 207 208 val = rot_read(ROT_CONTROL); 209 val &= ~ROT_CONTROL_FMT_MASK; 210 211 switch (fmt) { 212 case DRM_FORMAT_NV12: 213 val |= ROT_CONTROL_FMT_YCBCR420_2P; 214 break; 215 case DRM_FORMAT_XRGB8888: 216 val |= ROT_CONTROL_FMT_RGB888; 217 break; 218 default: 219 DRM_ERROR("invalid image format\n"); 220 return -EINVAL; 221 } 222 223 rot_write(val, ROT_CONTROL); 224 225 return 0; 226 } 227 228 static inline bool rotator_check_reg_fmt(u32 fmt) 229 { 230 if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) || 231 (fmt == ROT_CONTROL_FMT_RGB888)) 232 return true; 233 234 return false; 235 } 236 237 static int rotator_src_set_size(struct device *dev, int swap, 238 struct drm_exynos_pos *pos, 239 struct drm_exynos_sz *sz) 240 { 241 struct rot_context *rot = dev_get_drvdata(dev); 242 u32 fmt, hsize, vsize; 243 u32 val; 244 245 /* Get format */ 246 fmt = rotator_reg_get_fmt(rot); 247 if (!rotator_check_reg_fmt(fmt)) { 248 DRM_ERROR("invalid format.\n"); 249 return -EINVAL; 250 } 251 252 /* Align buffer size */ 253 hsize = sz->hsize; 254 vsize = sz->vsize; 255 rotator_align_size(rot, fmt, &hsize, &vsize); 256 257 /* Set buffer size configuration */ 258 val = ROT_SET_BUF_SIZE_H(vsize) | ROT_SET_BUF_SIZE_W(hsize); 259 rot_write(val, ROT_SRC_BUF_SIZE); 260 261 /* Set crop image position configuration */ 262 val = ROT_CROP_POS_Y(pos->y) | ROT_CROP_POS_X(pos->x); 263 rot_write(val, ROT_SRC_CROP_POS); 264 val = ROT_SRC_CROP_SIZE_H(pos->h) | ROT_SRC_CROP_SIZE_W(pos->w); 265 rot_write(val, ROT_SRC_CROP_SIZE); 266 267 return 0; 268 } 269 270 static int rotator_src_set_addr(struct device *dev, 271 struct drm_exynos_ipp_buf_info *buf_info, 272 u32 buf_id, enum drm_exynos_ipp_buf_type buf_type) 273 { 274 struct rot_context *rot = dev_get_drvdata(dev); 275 dma_addr_t addr[EXYNOS_DRM_PLANAR_MAX]; 276 u32 val, fmt, hsize, vsize; 277 int i; 278 279 /* Set current buf_id */ 280 rot->cur_buf_id[EXYNOS_DRM_OPS_SRC] = buf_id; 281 282 switch (buf_type) { 283 case IPP_BUF_ENQUEUE: 284 /* Set address configuration */ 285 for_each_ipp_planar(i) 286 addr[i] = buf_info->base[i]; 287 288 /* Get format */ 289 fmt = rotator_reg_get_fmt(rot); 290 if (!rotator_check_reg_fmt(fmt)) { 291 DRM_ERROR("invalid format.\n"); 292 return -EINVAL; 293 } 294 295 /* Re-set cb planar for NV12 format */ 296 if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) && 297 !addr[EXYNOS_DRM_PLANAR_CB]) { 298 299 val = rot_read(ROT_SRC_BUF_SIZE); 300 hsize = ROT_GET_BUF_SIZE_W(val); 301 vsize = ROT_GET_BUF_SIZE_H(val); 302 303 /* Set cb planar */ 304 addr[EXYNOS_DRM_PLANAR_CB] = 305 addr[EXYNOS_DRM_PLANAR_Y] + hsize * vsize; 306 } 307 308 for_each_ipp_planar(i) 309 rot_write(addr[i], ROT_SRC_BUF_ADDR(i)); 310 break; 311 case IPP_BUF_DEQUEUE: 312 for_each_ipp_planar(i) 313 rot_write(0x0, ROT_SRC_BUF_ADDR(i)); 314 break; 315 default: 316 /* Nothing to do */ 317 break; 318 } 319 320 return 0; 321 } 322 323 static int rotator_dst_set_transf(struct device *dev, 324 enum drm_exynos_degree degree, 325 enum drm_exynos_flip flip, bool *swap) 326 { 327 struct rot_context *rot = dev_get_drvdata(dev); 328 u32 val; 329 330 /* Set transform configuration */ 331 val = rot_read(ROT_CONTROL); 332 val &= ~ROT_CONTROL_FLIP_MASK; 333 334 switch (flip) { 335 case EXYNOS_DRM_FLIP_VERTICAL: 336 val |= ROT_CONTROL_FLIP_VERTICAL; 337 break; 338 case EXYNOS_DRM_FLIP_HORIZONTAL: 339 val |= ROT_CONTROL_FLIP_HORIZONTAL; 340 break; 341 default: 342 /* Flip None */ 343 break; 344 } 345 346 val &= ~ROT_CONTROL_ROT_MASK; 347 348 switch (degree) { 349 case EXYNOS_DRM_DEGREE_90: 350 val |= ROT_CONTROL_ROT_90; 351 break; 352 case EXYNOS_DRM_DEGREE_180: 353 val |= ROT_CONTROL_ROT_180; 354 break; 355 case EXYNOS_DRM_DEGREE_270: 356 val |= ROT_CONTROL_ROT_270; 357 break; 358 default: 359 /* Rotation 0 Degree */ 360 break; 361 } 362 363 rot_write(val, ROT_CONTROL); 364 365 /* Check degree for setting buffer size swap */ 366 if ((degree == EXYNOS_DRM_DEGREE_90) || 367 (degree == EXYNOS_DRM_DEGREE_270)) 368 *swap = true; 369 else 370 *swap = false; 371 372 return 0; 373 } 374 375 static int rotator_dst_set_size(struct device *dev, int swap, 376 struct drm_exynos_pos *pos, 377 struct drm_exynos_sz *sz) 378 { 379 struct rot_context *rot = dev_get_drvdata(dev); 380 u32 val, fmt, hsize, vsize; 381 382 /* Get format */ 383 fmt = rotator_reg_get_fmt(rot); 384 if (!rotator_check_reg_fmt(fmt)) { 385 DRM_ERROR("invalid format.\n"); 386 return -EINVAL; 387 } 388 389 /* Align buffer size */ 390 hsize = sz->hsize; 391 vsize = sz->vsize; 392 rotator_align_size(rot, fmt, &hsize, &vsize); 393 394 /* Set buffer size configuration */ 395 val = ROT_SET_BUF_SIZE_H(vsize) | ROT_SET_BUF_SIZE_W(hsize); 396 rot_write(val, ROT_DST_BUF_SIZE); 397 398 /* Set crop image position configuration */ 399 val = ROT_CROP_POS_Y(pos->y) | ROT_CROP_POS_X(pos->x); 400 rot_write(val, ROT_DST_CROP_POS); 401 402 return 0; 403 } 404 405 static int rotator_dst_set_addr(struct device *dev, 406 struct drm_exynos_ipp_buf_info *buf_info, 407 u32 buf_id, enum drm_exynos_ipp_buf_type buf_type) 408 { 409 struct rot_context *rot = dev_get_drvdata(dev); 410 dma_addr_t addr[EXYNOS_DRM_PLANAR_MAX]; 411 u32 val, fmt, hsize, vsize; 412 int i; 413 414 /* Set current buf_id */ 415 rot->cur_buf_id[EXYNOS_DRM_OPS_DST] = buf_id; 416 417 switch (buf_type) { 418 case IPP_BUF_ENQUEUE: 419 /* Set address configuration */ 420 for_each_ipp_planar(i) 421 addr[i] = buf_info->base[i]; 422 423 /* Get format */ 424 fmt = rotator_reg_get_fmt(rot); 425 if (!rotator_check_reg_fmt(fmt)) { 426 DRM_ERROR("invalid format.\n"); 427 return -EINVAL; 428 } 429 430 /* Re-set cb planar for NV12 format */ 431 if ((fmt == ROT_CONTROL_FMT_YCBCR420_2P) && 432 !addr[EXYNOS_DRM_PLANAR_CB]) { 433 /* Get buf size */ 434 val = rot_read(ROT_DST_BUF_SIZE); 435 436 hsize = ROT_GET_BUF_SIZE_W(val); 437 vsize = ROT_GET_BUF_SIZE_H(val); 438 439 /* Set cb planar */ 440 addr[EXYNOS_DRM_PLANAR_CB] = 441 addr[EXYNOS_DRM_PLANAR_Y] + hsize * vsize; 442 } 443 444 for_each_ipp_planar(i) 445 rot_write(addr[i], ROT_DST_BUF_ADDR(i)); 446 break; 447 case IPP_BUF_DEQUEUE: 448 for_each_ipp_planar(i) 449 rot_write(0x0, ROT_DST_BUF_ADDR(i)); 450 break; 451 default: 452 /* Nothing to do */ 453 break; 454 } 455 456 return 0; 457 } 458 459 static struct exynos_drm_ipp_ops rot_src_ops = { 460 .set_fmt = rotator_src_set_fmt, 461 .set_size = rotator_src_set_size, 462 .set_addr = rotator_src_set_addr, 463 }; 464 465 static struct exynos_drm_ipp_ops rot_dst_ops = { 466 .set_transf = rotator_dst_set_transf, 467 .set_size = rotator_dst_set_size, 468 .set_addr = rotator_dst_set_addr, 469 }; 470 471 static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv) 472 { 473 struct drm_exynos_ipp_prop_list *prop_list = &ippdrv->prop_list; 474 475 prop_list->version = 1; 476 prop_list->flip = (1 << EXYNOS_DRM_FLIP_VERTICAL) | 477 (1 << EXYNOS_DRM_FLIP_HORIZONTAL); 478 prop_list->degree = (1 << EXYNOS_DRM_DEGREE_0) | 479 (1 << EXYNOS_DRM_DEGREE_90) | 480 (1 << EXYNOS_DRM_DEGREE_180) | 481 (1 << EXYNOS_DRM_DEGREE_270); 482 prop_list->csc = 0; 483 prop_list->crop = 0; 484 prop_list->scale = 0; 485 486 return 0; 487 } 488 489 static inline bool rotator_check_drm_fmt(u32 fmt) 490 { 491 switch (fmt) { 492 case DRM_FORMAT_XRGB8888: 493 case DRM_FORMAT_NV12: 494 return true; 495 default: 496 DRM_DEBUG_KMS("not support format\n"); 497 return false; 498 } 499 } 500 501 static inline bool rotator_check_drm_flip(enum drm_exynos_flip flip) 502 { 503 switch (flip) { 504 case EXYNOS_DRM_FLIP_NONE: 505 case EXYNOS_DRM_FLIP_VERTICAL: 506 case EXYNOS_DRM_FLIP_HORIZONTAL: 507 case EXYNOS_DRM_FLIP_BOTH: 508 return true; 509 default: 510 DRM_DEBUG_KMS("invalid flip\n"); 511 return false; 512 } 513 } 514 515 static int rotator_ippdrv_check_property(struct device *dev, 516 struct drm_exynos_ipp_property *property) 517 { 518 struct drm_exynos_ipp_config *src_config = 519 &property->config[EXYNOS_DRM_OPS_SRC]; 520 struct drm_exynos_ipp_config *dst_config = 521 &property->config[EXYNOS_DRM_OPS_DST]; 522 struct drm_exynos_pos *src_pos = &src_config->pos; 523 struct drm_exynos_pos *dst_pos = &dst_config->pos; 524 struct drm_exynos_sz *src_sz = &src_config->sz; 525 struct drm_exynos_sz *dst_sz = &dst_config->sz; 526 bool swap = false; 527 528 /* Check format configuration */ 529 if (src_config->fmt != dst_config->fmt) { 530 DRM_DEBUG_KMS("not support csc feature\n"); 531 return -EINVAL; 532 } 533 534 if (!rotator_check_drm_fmt(dst_config->fmt)) { 535 DRM_DEBUG_KMS("invalid format\n"); 536 return -EINVAL; 537 } 538 539 /* Check transform configuration */ 540 if (src_config->degree != EXYNOS_DRM_DEGREE_0) { 541 DRM_DEBUG_KMS("not support source-side rotation\n"); 542 return -EINVAL; 543 } 544 545 switch (dst_config->degree) { 546 case EXYNOS_DRM_DEGREE_90: 547 case EXYNOS_DRM_DEGREE_270: 548 swap = true; 549 case EXYNOS_DRM_DEGREE_0: 550 case EXYNOS_DRM_DEGREE_180: 551 /* No problem */ 552 break; 553 default: 554 DRM_DEBUG_KMS("invalid degree\n"); 555 return -EINVAL; 556 } 557 558 if (src_config->flip != EXYNOS_DRM_FLIP_NONE) { 559 DRM_DEBUG_KMS("not support source-side flip\n"); 560 return -EINVAL; 561 } 562 563 if (!rotator_check_drm_flip(dst_config->flip)) { 564 DRM_DEBUG_KMS("invalid flip\n"); 565 return -EINVAL; 566 } 567 568 /* Check size configuration */ 569 if ((src_pos->x + src_pos->w > src_sz->hsize) || 570 (src_pos->y + src_pos->h > src_sz->vsize)) { 571 DRM_DEBUG_KMS("out of source buffer bound\n"); 572 return -EINVAL; 573 } 574 575 if (swap) { 576 if ((dst_pos->x + dst_pos->h > dst_sz->vsize) || 577 (dst_pos->y + dst_pos->w > dst_sz->hsize)) { 578 DRM_DEBUG_KMS("out of destination buffer bound\n"); 579 return -EINVAL; 580 } 581 582 if ((src_pos->w != dst_pos->h) || (src_pos->h != dst_pos->w)) { 583 DRM_DEBUG_KMS("not support scale feature\n"); 584 return -EINVAL; 585 } 586 } else { 587 if ((dst_pos->x + dst_pos->w > dst_sz->hsize) || 588 (dst_pos->y + dst_pos->h > dst_sz->vsize)) { 589 DRM_DEBUG_KMS("out of destination buffer bound\n"); 590 return -EINVAL; 591 } 592 593 if ((src_pos->w != dst_pos->w) || (src_pos->h != dst_pos->h)) { 594 DRM_DEBUG_KMS("not support scale feature\n"); 595 return -EINVAL; 596 } 597 } 598 599 return 0; 600 } 601 602 static int rotator_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd) 603 { 604 struct rot_context *rot = dev_get_drvdata(dev); 605 u32 val; 606 607 if (rot->suspended) { 608 DRM_ERROR("suspended state\n"); 609 return -EPERM; 610 } 611 612 if (cmd != IPP_CMD_M2M) { 613 DRM_ERROR("not support cmd: %d\n", cmd); 614 return -EINVAL; 615 } 616 617 /* Set interrupt enable */ 618 rotator_reg_set_irq(rot, true); 619 620 val = rot_read(ROT_CONTROL); 621 val |= ROT_CONTROL_START; 622 623 rot_write(val, ROT_CONTROL); 624 625 return 0; 626 } 627 628 static struct rot_limit_table rot_limit_tbl_4210 = { 629 .ycbcr420_2p = { 630 .min_w = 32, 631 .min_h = 32, 632 .max_w = SZ_64K, 633 .max_h = SZ_64K, 634 .align = 3, 635 }, 636 .rgb888 = { 637 .min_w = 8, 638 .min_h = 8, 639 .max_w = SZ_16K, 640 .max_h = SZ_16K, 641 .align = 2, 642 }, 643 }; 644 645 static struct rot_limit_table rot_limit_tbl_4x12 = { 646 .ycbcr420_2p = { 647 .min_w = 32, 648 .min_h = 32, 649 .max_w = SZ_32K, 650 .max_h = SZ_32K, 651 .align = 3, 652 }, 653 .rgb888 = { 654 .min_w = 8, 655 .min_h = 8, 656 .max_w = SZ_8K, 657 .max_h = SZ_8K, 658 .align = 2, 659 }, 660 }; 661 662 static struct rot_limit_table rot_limit_tbl_5250 = { 663 .ycbcr420_2p = { 664 .min_w = 32, 665 .min_h = 32, 666 .max_w = SZ_32K, 667 .max_h = SZ_32K, 668 .align = 3, 669 }, 670 .rgb888 = { 671 .min_w = 8, 672 .min_h = 8, 673 .max_w = SZ_8K, 674 .max_h = SZ_8K, 675 .align = 1, 676 }, 677 }; 678 679 static const struct of_device_id exynos_rotator_match[] = { 680 { 681 .compatible = "samsung,exynos4210-rotator", 682 .data = &rot_limit_tbl_4210, 683 }, 684 { 685 .compatible = "samsung,exynos4212-rotator", 686 .data = &rot_limit_tbl_4x12, 687 }, 688 { 689 .compatible = "samsung,exynos5250-rotator", 690 .data = &rot_limit_tbl_5250, 691 }, 692 {}, 693 }; 694 MODULE_DEVICE_TABLE(of, exynos_rotator_match); 695 696 static int rotator_probe(struct platform_device *pdev) 697 { 698 struct device *dev = &pdev->dev; 699 struct rot_context *rot; 700 struct exynos_drm_ippdrv *ippdrv; 701 const struct of_device_id *match; 702 int ret; 703 704 if (!dev->of_node) { 705 dev_err(dev, "cannot find of_node.\n"); 706 return -ENODEV; 707 } 708 709 rot = devm_kzalloc(dev, sizeof(*rot), GFP_KERNEL); 710 if (!rot) 711 return -ENOMEM; 712 713 match = of_match_node(exynos_rotator_match, dev->of_node); 714 if (!match) { 715 dev_err(dev, "failed to match node\n"); 716 return -ENODEV; 717 } 718 rot->limit_tbl = (struct rot_limit_table *)match->data; 719 720 rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 721 rot->regs = devm_ioremap_resource(dev, rot->regs_res); 722 if (IS_ERR(rot->regs)) 723 return PTR_ERR(rot->regs); 724 725 rot->irq = platform_get_irq(pdev, 0); 726 if (rot->irq < 0) { 727 dev_err(dev, "failed to get irq\n"); 728 return rot->irq; 729 } 730 731 ret = devm_request_threaded_irq(dev, rot->irq, NULL, 732 rotator_irq_handler, IRQF_ONESHOT, "drm_rotator", rot); 733 if (ret < 0) { 734 dev_err(dev, "failed to request irq\n"); 735 return ret; 736 } 737 738 rot->clock = devm_clk_get(dev, "rotator"); 739 if (IS_ERR(rot->clock)) { 740 dev_err(dev, "failed to get clock\n"); 741 return PTR_ERR(rot->clock); 742 } 743 744 pm_runtime_enable(dev); 745 746 ippdrv = &rot->ippdrv; 747 ippdrv->dev = dev; 748 ippdrv->ops[EXYNOS_DRM_OPS_SRC] = &rot_src_ops; 749 ippdrv->ops[EXYNOS_DRM_OPS_DST] = &rot_dst_ops; 750 ippdrv->check_property = rotator_ippdrv_check_property; 751 ippdrv->start = rotator_ippdrv_start; 752 ret = rotator_init_prop_list(ippdrv); 753 if (ret < 0) { 754 dev_err(dev, "failed to init property list.\n"); 755 goto err_ippdrv_register; 756 } 757 758 DRM_DEBUG_KMS("ippdrv[0x%x]\n", (int)ippdrv); 759 760 platform_set_drvdata(pdev, rot); 761 762 ret = exynos_drm_ippdrv_register(ippdrv); 763 if (ret < 0) { 764 dev_err(dev, "failed to register drm rotator device\n"); 765 goto err_ippdrv_register; 766 } 767 768 dev_info(dev, "The exynos rotator is probed successfully\n"); 769 770 return 0; 771 772 err_ippdrv_register: 773 pm_runtime_disable(dev); 774 return ret; 775 } 776 777 static int rotator_remove(struct platform_device *pdev) 778 { 779 struct device *dev = &pdev->dev; 780 struct rot_context *rot = dev_get_drvdata(dev); 781 struct exynos_drm_ippdrv *ippdrv = &rot->ippdrv; 782 783 exynos_drm_ippdrv_unregister(ippdrv); 784 785 pm_runtime_disable(dev); 786 787 return 0; 788 } 789 790 static int rotator_clk_crtl(struct rot_context *rot, bool enable) 791 { 792 if (enable) { 793 clk_enable(rot->clock); 794 rot->suspended = false; 795 } else { 796 clk_disable(rot->clock); 797 rot->suspended = true; 798 } 799 800 return 0; 801 } 802 803 804 #ifdef CONFIG_PM_SLEEP 805 static int rotator_suspend(struct device *dev) 806 { 807 struct rot_context *rot = dev_get_drvdata(dev); 808 809 if (pm_runtime_suspended(dev)) 810 return 0; 811 812 return rotator_clk_crtl(rot, false); 813 } 814 815 static int rotator_resume(struct device *dev) 816 { 817 struct rot_context *rot = dev_get_drvdata(dev); 818 819 if (!pm_runtime_suspended(dev)) 820 return rotator_clk_crtl(rot, true); 821 822 return 0; 823 } 824 #endif 825 826 #ifdef CONFIG_PM_RUNTIME 827 static int rotator_runtime_suspend(struct device *dev) 828 { 829 struct rot_context *rot = dev_get_drvdata(dev); 830 831 return rotator_clk_crtl(rot, false); 832 } 833 834 static int rotator_runtime_resume(struct device *dev) 835 { 836 struct rot_context *rot = dev_get_drvdata(dev); 837 838 return rotator_clk_crtl(rot, true); 839 } 840 #endif 841 842 static const struct dev_pm_ops rotator_pm_ops = { 843 SET_SYSTEM_SLEEP_PM_OPS(rotator_suspend, rotator_resume) 844 SET_RUNTIME_PM_OPS(rotator_runtime_suspend, rotator_runtime_resume, 845 NULL) 846 }; 847 848 struct platform_driver rotator_driver = { 849 .probe = rotator_probe, 850 .remove = rotator_remove, 851 .driver = { 852 .name = "exynos-rot", 853 .owner = THIS_MODULE, 854 .pm = &rotator_pm_ops, 855 .of_match_table = exynos_rotator_match, 856 }, 857 }; 858