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