1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2012 Samsung Electronics Co.Ltd 4 * Authors: 5 * Eunchul Kim <chulspro.kim@samsung.com> 6 * Jinyoung Jeon <jy0.jeon@samsung.com> 7 * Sangmin Lee <lsmin.lee@samsung.com> 8 */ 9 #include <linux/kernel.h> 10 #include <linux/component.h> 11 #include <linux/platform_device.h> 12 #include <linux/mfd/syscon.h> 13 #include <linux/regmap.h> 14 #include <linux/clk.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/of.h> 17 #include <linux/spinlock.h> 18 19 #include <drm/drmP.h> 20 #include <drm/exynos_drm.h> 21 #include "regs-fimc.h" 22 #include "exynos_drm_drv.h" 23 #include "exynos_drm_ipp.h" 24 25 /* 26 * FIMC stands for Fully Interactive Mobile Camera and 27 * supports image scaler/rotator and input/output DMA operations. 28 * input DMA reads image data from the memory. 29 * output DMA writes image data to memory. 30 * FIMC supports image rotation and image effect functions. 31 */ 32 33 #define FIMC_MAX_DEVS 4 34 #define FIMC_MAX_SRC 2 35 #define FIMC_MAX_DST 32 36 #define FIMC_SHFACTOR 10 37 #define FIMC_BUF_STOP 1 38 #define FIMC_BUF_START 2 39 #define FIMC_WIDTH_ITU_709 1280 40 #define FIMC_AUTOSUSPEND_DELAY 2000 41 42 static unsigned int fimc_mask = 0xc; 43 module_param_named(fimc_devs, fimc_mask, uint, 0644); 44 MODULE_PARM_DESC(fimc_devs, "Alias mask for assigning FIMC devices to Exynos DRM"); 45 46 #define get_fimc_context(dev) platform_get_drvdata(to_platform_device(dev)) 47 48 enum { 49 FIMC_CLK_LCLK, 50 FIMC_CLK_GATE, 51 FIMC_CLK_WB_A, 52 FIMC_CLK_WB_B, 53 FIMC_CLKS_MAX 54 }; 55 56 static const char * const fimc_clock_names[] = { 57 [FIMC_CLK_LCLK] = "sclk_fimc", 58 [FIMC_CLK_GATE] = "fimc", 59 [FIMC_CLK_WB_A] = "pxl_async0", 60 [FIMC_CLK_WB_B] = "pxl_async1", 61 }; 62 63 /* 64 * A structure of scaler. 65 * 66 * @range: narrow, wide. 67 * @bypass: unused scaler path. 68 * @up_h: horizontal scale up. 69 * @up_v: vertical scale up. 70 * @hratio: horizontal ratio. 71 * @vratio: vertical ratio. 72 */ 73 struct fimc_scaler { 74 bool range; 75 bool bypass; 76 bool up_h; 77 bool up_v; 78 u32 hratio; 79 u32 vratio; 80 }; 81 82 /* 83 * A structure of fimc context. 84 * 85 * @regs_res: register resources. 86 * @regs: memory mapped io registers. 87 * @lock: locking of operations. 88 * @clocks: fimc clocks. 89 * @sc: scaler infomations. 90 * @pol: porarity of writeback. 91 * @id: fimc id. 92 * @irq: irq number. 93 */ 94 struct fimc_context { 95 struct exynos_drm_ipp ipp; 96 struct drm_device *drm_dev; 97 struct device *dev; 98 struct exynos_drm_ipp_task *task; 99 struct exynos_drm_ipp_formats *formats; 100 unsigned int num_formats; 101 102 struct resource *regs_res; 103 void __iomem *regs; 104 spinlock_t lock; 105 struct clk *clocks[FIMC_CLKS_MAX]; 106 struct fimc_scaler sc; 107 int id; 108 int irq; 109 }; 110 111 static u32 fimc_read(struct fimc_context *ctx, u32 reg) 112 { 113 return readl(ctx->regs + reg); 114 } 115 116 static void fimc_write(struct fimc_context *ctx, u32 val, u32 reg) 117 { 118 writel(val, ctx->regs + reg); 119 } 120 121 static void fimc_set_bits(struct fimc_context *ctx, u32 reg, u32 bits) 122 { 123 void __iomem *r = ctx->regs + reg; 124 125 writel(readl(r) | bits, r); 126 } 127 128 static void fimc_clear_bits(struct fimc_context *ctx, u32 reg, u32 bits) 129 { 130 void __iomem *r = ctx->regs + reg; 131 132 writel(readl(r) & ~bits, r); 133 } 134 135 static void fimc_sw_reset(struct fimc_context *ctx) 136 { 137 u32 cfg; 138 139 /* stop dma operation */ 140 cfg = fimc_read(ctx, EXYNOS_CISTATUS); 141 if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg)) 142 fimc_clear_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID); 143 144 fimc_set_bits(ctx, EXYNOS_CISRCFMT, EXYNOS_CISRCFMT_ITU601_8BIT); 145 146 /* disable image capture */ 147 fimc_clear_bits(ctx, EXYNOS_CIIMGCPT, 148 EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN); 149 150 /* s/w reset */ 151 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_SWRST); 152 153 /* s/w reset complete */ 154 fimc_clear_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_SWRST); 155 156 /* reset sequence */ 157 fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ); 158 } 159 160 static void fimc_set_type_ctrl(struct fimc_context *ctx) 161 { 162 u32 cfg; 163 164 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 165 cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK | 166 EXYNOS_CIGCTRL_SELCAM_ITU_MASK | 167 EXYNOS_CIGCTRL_SELCAM_MIPI_MASK | 168 EXYNOS_CIGCTRL_SELCAM_FIMC_MASK | 169 EXYNOS_CIGCTRL_SELWB_CAMIF_MASK | 170 EXYNOS_CIGCTRL_SELWRITEBACK_MASK); 171 172 cfg |= (EXYNOS_CIGCTRL_SELCAM_ITU_A | 173 EXYNOS_CIGCTRL_SELWRITEBACK_A | 174 EXYNOS_CIGCTRL_SELCAM_MIPI_A | 175 EXYNOS_CIGCTRL_SELCAM_FIMC_ITU); 176 177 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 178 } 179 180 static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable) 181 { 182 u32 cfg; 183 184 DRM_DEV_DEBUG_KMS(ctx->dev, "enable[%d]\n", enable); 185 186 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 187 if (enable) 188 cfg |= EXYNOS_CIGCTRL_CAM_JPEG; 189 else 190 cfg &= ~EXYNOS_CIGCTRL_CAM_JPEG; 191 192 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 193 } 194 195 static void fimc_mask_irq(struct fimc_context *ctx, bool enable) 196 { 197 u32 cfg; 198 199 DRM_DEV_DEBUG_KMS(ctx->dev, "enable[%d]\n", enable); 200 201 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 202 if (enable) { 203 cfg &= ~EXYNOS_CIGCTRL_IRQ_OVFEN; 204 cfg |= EXYNOS_CIGCTRL_IRQ_ENABLE | EXYNOS_CIGCTRL_IRQ_LEVEL; 205 } else 206 cfg &= ~EXYNOS_CIGCTRL_IRQ_ENABLE; 207 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 208 } 209 210 static void fimc_clear_irq(struct fimc_context *ctx) 211 { 212 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_CLR); 213 } 214 215 static bool fimc_check_ovf(struct fimc_context *ctx) 216 { 217 u32 status, flag; 218 219 status = fimc_read(ctx, EXYNOS_CISTATUS); 220 flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB | 221 EXYNOS_CISTATUS_OVFICR; 222 223 DRM_DEV_DEBUG_KMS(ctx->dev, "flag[0x%x]\n", flag); 224 225 if (status & flag) { 226 fimc_set_bits(ctx, EXYNOS_CIWDOFST, 227 EXYNOS_CIWDOFST_CLROVFIY | EXYNOS_CIWDOFST_CLROVFICB | 228 EXYNOS_CIWDOFST_CLROVFICR); 229 230 DRM_DEV_ERROR(ctx->dev, 231 "occurred overflow at %d, status 0x%x.\n", 232 ctx->id, status); 233 return true; 234 } 235 236 return false; 237 } 238 239 static bool fimc_check_frame_end(struct fimc_context *ctx) 240 { 241 u32 cfg; 242 243 cfg = fimc_read(ctx, EXYNOS_CISTATUS); 244 245 DRM_DEV_DEBUG_KMS(ctx->dev, "cfg[0x%x]\n", cfg); 246 247 if (!(cfg & EXYNOS_CISTATUS_FRAMEEND)) 248 return false; 249 250 cfg &= ~(EXYNOS_CISTATUS_FRAMEEND); 251 fimc_write(ctx, cfg, EXYNOS_CISTATUS); 252 253 return true; 254 } 255 256 static int fimc_get_buf_id(struct fimc_context *ctx) 257 { 258 u32 cfg; 259 int frame_cnt, buf_id; 260 261 cfg = fimc_read(ctx, EXYNOS_CISTATUS2); 262 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg); 263 264 if (frame_cnt == 0) 265 frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg); 266 267 DRM_DEV_DEBUG_KMS(ctx->dev, "present[%d]before[%d]\n", 268 EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg), 269 EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg)); 270 271 if (frame_cnt == 0) { 272 DRM_DEV_ERROR(ctx->dev, "failed to get frame count.\n"); 273 return -EIO; 274 } 275 276 buf_id = frame_cnt - 1; 277 DRM_DEV_DEBUG_KMS(ctx->dev, "buf_id[%d]\n", buf_id); 278 279 return buf_id; 280 } 281 282 static void fimc_handle_lastend(struct fimc_context *ctx, bool enable) 283 { 284 u32 cfg; 285 286 DRM_DEV_DEBUG_KMS(ctx->dev, "enable[%d]\n", enable); 287 288 cfg = fimc_read(ctx, EXYNOS_CIOCTRL); 289 if (enable) 290 cfg |= EXYNOS_CIOCTRL_LASTENDEN; 291 else 292 cfg &= ~EXYNOS_CIOCTRL_LASTENDEN; 293 294 fimc_write(ctx, cfg, EXYNOS_CIOCTRL); 295 } 296 297 static void fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt) 298 { 299 u32 cfg; 300 301 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); 302 303 /* RGB */ 304 cfg = fimc_read(ctx, EXYNOS_CISCCTRL); 305 cfg &= ~EXYNOS_CISCCTRL_INRGB_FMT_RGB_MASK; 306 307 switch (fmt) { 308 case DRM_FORMAT_RGB565: 309 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB565; 310 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 311 return; 312 case DRM_FORMAT_RGB888: 313 case DRM_FORMAT_XRGB8888: 314 cfg |= EXYNOS_CISCCTRL_INRGB_FMT_RGB888; 315 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 316 return; 317 default: 318 /* bypass */ 319 break; 320 } 321 322 /* YUV */ 323 cfg = fimc_read(ctx, EXYNOS_MSCTRL); 324 cfg &= ~(EXYNOS_MSCTRL_ORDER2P_SHIFT_MASK | 325 EXYNOS_MSCTRL_C_INT_IN_2PLANE | 326 EXYNOS_MSCTRL_ORDER422_YCBYCR); 327 328 switch (fmt) { 329 case DRM_FORMAT_YUYV: 330 cfg |= EXYNOS_MSCTRL_ORDER422_YCBYCR; 331 break; 332 case DRM_FORMAT_YVYU: 333 cfg |= EXYNOS_MSCTRL_ORDER422_YCRYCB; 334 break; 335 case DRM_FORMAT_UYVY: 336 cfg |= EXYNOS_MSCTRL_ORDER422_CBYCRY; 337 break; 338 case DRM_FORMAT_VYUY: 339 case DRM_FORMAT_YUV444: 340 cfg |= EXYNOS_MSCTRL_ORDER422_CRYCBY; 341 break; 342 case DRM_FORMAT_NV21: 343 case DRM_FORMAT_NV61: 344 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CRCB | 345 EXYNOS_MSCTRL_C_INT_IN_2PLANE); 346 break; 347 case DRM_FORMAT_YUV422: 348 case DRM_FORMAT_YUV420: 349 case DRM_FORMAT_YVU420: 350 cfg |= EXYNOS_MSCTRL_C_INT_IN_3PLANE; 351 break; 352 case DRM_FORMAT_NV12: 353 case DRM_FORMAT_NV16: 354 cfg |= (EXYNOS_MSCTRL_ORDER2P_LSB_CBCR | 355 EXYNOS_MSCTRL_C_INT_IN_2PLANE); 356 break; 357 } 358 359 fimc_write(ctx, cfg, EXYNOS_MSCTRL); 360 } 361 362 static void fimc_src_set_fmt(struct fimc_context *ctx, u32 fmt, bool tiled) 363 { 364 u32 cfg; 365 366 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); 367 368 cfg = fimc_read(ctx, EXYNOS_MSCTRL); 369 cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB; 370 371 switch (fmt) { 372 case DRM_FORMAT_RGB565: 373 case DRM_FORMAT_RGB888: 374 case DRM_FORMAT_XRGB8888: 375 cfg |= EXYNOS_MSCTRL_INFORMAT_RGB; 376 break; 377 case DRM_FORMAT_YUV444: 378 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; 379 break; 380 case DRM_FORMAT_YUYV: 381 case DRM_FORMAT_YVYU: 382 case DRM_FORMAT_UYVY: 383 case DRM_FORMAT_VYUY: 384 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422_1PLANE; 385 break; 386 case DRM_FORMAT_NV16: 387 case DRM_FORMAT_NV61: 388 case DRM_FORMAT_YUV422: 389 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR422; 390 break; 391 case DRM_FORMAT_YUV420: 392 case DRM_FORMAT_YVU420: 393 case DRM_FORMAT_NV12: 394 case DRM_FORMAT_NV21: 395 cfg |= EXYNOS_MSCTRL_INFORMAT_YCBCR420; 396 break; 397 } 398 399 fimc_write(ctx, cfg, EXYNOS_MSCTRL); 400 401 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM); 402 cfg &= ~EXYNOS_CIDMAPARAM_R_MODE_MASK; 403 404 if (tiled) 405 cfg |= EXYNOS_CIDMAPARAM_R_MODE_64X32; 406 else 407 cfg |= EXYNOS_CIDMAPARAM_R_MODE_LINEAR; 408 409 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM); 410 411 fimc_src_set_fmt_order(ctx, fmt); 412 } 413 414 static void fimc_src_set_transf(struct fimc_context *ctx, unsigned int rotation) 415 { 416 unsigned int degree = rotation & DRM_MODE_ROTATE_MASK; 417 u32 cfg1, cfg2; 418 419 DRM_DEV_DEBUG_KMS(ctx->dev, "rotation[%x]\n", rotation); 420 421 cfg1 = fimc_read(ctx, EXYNOS_MSCTRL); 422 cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR | 423 EXYNOS_MSCTRL_FLIP_Y_MIRROR); 424 425 cfg2 = fimc_read(ctx, EXYNOS_CITRGFMT); 426 cfg2 &= ~EXYNOS_CITRGFMT_INROT90_CLOCKWISE; 427 428 switch (degree) { 429 case DRM_MODE_ROTATE_0: 430 if (rotation & DRM_MODE_REFLECT_X) 431 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR; 432 if (rotation & DRM_MODE_REFLECT_Y) 433 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; 434 break; 435 case DRM_MODE_ROTATE_90: 436 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE; 437 if (rotation & DRM_MODE_REFLECT_X) 438 cfg1 |= EXYNOS_MSCTRL_FLIP_X_MIRROR; 439 if (rotation & DRM_MODE_REFLECT_Y) 440 cfg1 |= EXYNOS_MSCTRL_FLIP_Y_MIRROR; 441 break; 442 case DRM_MODE_ROTATE_180: 443 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR | 444 EXYNOS_MSCTRL_FLIP_Y_MIRROR); 445 if (rotation & DRM_MODE_REFLECT_X) 446 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; 447 if (rotation & DRM_MODE_REFLECT_Y) 448 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; 449 break; 450 case DRM_MODE_ROTATE_270: 451 cfg1 |= (EXYNOS_MSCTRL_FLIP_X_MIRROR | 452 EXYNOS_MSCTRL_FLIP_Y_MIRROR); 453 cfg2 |= EXYNOS_CITRGFMT_INROT90_CLOCKWISE; 454 if (rotation & DRM_MODE_REFLECT_X) 455 cfg1 &= ~EXYNOS_MSCTRL_FLIP_X_MIRROR; 456 if (rotation & DRM_MODE_REFLECT_Y) 457 cfg1 &= ~EXYNOS_MSCTRL_FLIP_Y_MIRROR; 458 break; 459 } 460 461 fimc_write(ctx, cfg1, EXYNOS_MSCTRL); 462 fimc_write(ctx, cfg2, EXYNOS_CITRGFMT); 463 } 464 465 static void fimc_set_window(struct fimc_context *ctx, 466 struct exynos_drm_ipp_buffer *buf) 467 { 468 unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0]; 469 u32 cfg, h1, h2, v1, v2; 470 471 /* cropped image */ 472 h1 = buf->rect.x; 473 h2 = real_width - buf->rect.w - buf->rect.x; 474 v1 = buf->rect.y; 475 v2 = buf->buf.height - buf->rect.h - buf->rect.y; 476 477 DRM_DEV_DEBUG_KMS(ctx->dev, "x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n", 478 buf->rect.x, buf->rect.y, buf->rect.w, buf->rect.h, 479 real_width, buf->buf.height); 480 DRM_DEV_DEBUG_KMS(ctx->dev, "h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, 481 v2); 482 483 /* 484 * set window offset 1, 2 size 485 * check figure 43-21 in user manual 486 */ 487 cfg = fimc_read(ctx, EXYNOS_CIWDOFST); 488 cfg &= ~(EXYNOS_CIWDOFST_WINHOROFST_MASK | 489 EXYNOS_CIWDOFST_WINVEROFST_MASK); 490 cfg |= (EXYNOS_CIWDOFST_WINHOROFST(h1) | 491 EXYNOS_CIWDOFST_WINVEROFST(v1)); 492 cfg |= EXYNOS_CIWDOFST_WINOFSEN; 493 fimc_write(ctx, cfg, EXYNOS_CIWDOFST); 494 495 cfg = (EXYNOS_CIWDOFST2_WINHOROFST2(h2) | 496 EXYNOS_CIWDOFST2_WINVEROFST2(v2)); 497 fimc_write(ctx, cfg, EXYNOS_CIWDOFST2); 498 } 499 500 static void fimc_src_set_size(struct fimc_context *ctx, 501 struct exynos_drm_ipp_buffer *buf) 502 { 503 unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0]; 504 u32 cfg; 505 506 DRM_DEV_DEBUG_KMS(ctx->dev, "hsize[%d]vsize[%d]\n", real_width, 507 buf->buf.height); 508 509 /* original size */ 510 cfg = (EXYNOS_ORGISIZE_HORIZONTAL(real_width) | 511 EXYNOS_ORGISIZE_VERTICAL(buf->buf.height)); 512 513 fimc_write(ctx, cfg, EXYNOS_ORGISIZE); 514 515 DRM_DEV_DEBUG_KMS(ctx->dev, "x[%d]y[%d]w[%d]h[%d]\n", buf->rect.x, 516 buf->rect.y, buf->rect.w, buf->rect.h); 517 518 /* set input DMA image size */ 519 cfg = fimc_read(ctx, EXYNOS_CIREAL_ISIZE); 520 cfg &= ~(EXYNOS_CIREAL_ISIZE_HEIGHT_MASK | 521 EXYNOS_CIREAL_ISIZE_WIDTH_MASK); 522 cfg |= (EXYNOS_CIREAL_ISIZE_WIDTH(buf->rect.w) | 523 EXYNOS_CIREAL_ISIZE_HEIGHT(buf->rect.h)); 524 fimc_write(ctx, cfg, EXYNOS_CIREAL_ISIZE); 525 526 /* 527 * set input FIFO image size 528 * for now, we support only ITU601 8 bit mode 529 */ 530 cfg = (EXYNOS_CISRCFMT_ITU601_8BIT | 531 EXYNOS_CISRCFMT_SOURCEHSIZE(real_width) | 532 EXYNOS_CISRCFMT_SOURCEVSIZE(buf->buf.height)); 533 fimc_write(ctx, cfg, EXYNOS_CISRCFMT); 534 535 /* offset Y(RGB), Cb, Cr */ 536 cfg = (EXYNOS_CIIYOFF_HORIZONTAL(buf->rect.x) | 537 EXYNOS_CIIYOFF_VERTICAL(buf->rect.y)); 538 fimc_write(ctx, cfg, EXYNOS_CIIYOFF); 539 cfg = (EXYNOS_CIICBOFF_HORIZONTAL(buf->rect.x) | 540 EXYNOS_CIICBOFF_VERTICAL(buf->rect.y)); 541 fimc_write(ctx, cfg, EXYNOS_CIICBOFF); 542 cfg = (EXYNOS_CIICROFF_HORIZONTAL(buf->rect.x) | 543 EXYNOS_CIICROFF_VERTICAL(buf->rect.y)); 544 fimc_write(ctx, cfg, EXYNOS_CIICROFF); 545 546 fimc_set_window(ctx, buf); 547 } 548 549 static void fimc_src_set_addr(struct fimc_context *ctx, 550 struct exynos_drm_ipp_buffer *buf) 551 { 552 fimc_write(ctx, buf->dma_addr[0], EXYNOS_CIIYSA(0)); 553 fimc_write(ctx, buf->dma_addr[1], EXYNOS_CIICBSA(0)); 554 fimc_write(ctx, buf->dma_addr[2], EXYNOS_CIICRSA(0)); 555 } 556 557 static void fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt) 558 { 559 u32 cfg; 560 561 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); 562 563 /* RGB */ 564 cfg = fimc_read(ctx, EXYNOS_CISCCTRL); 565 cfg &= ~EXYNOS_CISCCTRL_OUTRGB_FMT_RGB_MASK; 566 567 switch (fmt) { 568 case DRM_FORMAT_RGB565: 569 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB565; 570 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 571 return; 572 case DRM_FORMAT_RGB888: 573 cfg |= EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888; 574 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 575 return; 576 case DRM_FORMAT_XRGB8888: 577 cfg |= (EXYNOS_CISCCTRL_OUTRGB_FMT_RGB888 | 578 EXYNOS_CISCCTRL_EXTRGB_EXTENSION); 579 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 580 break; 581 default: 582 /* bypass */ 583 break; 584 } 585 586 /* YUV */ 587 cfg = fimc_read(ctx, EXYNOS_CIOCTRL); 588 cfg &= ~(EXYNOS_CIOCTRL_ORDER2P_MASK | 589 EXYNOS_CIOCTRL_ORDER422_MASK | 590 EXYNOS_CIOCTRL_YCBCR_PLANE_MASK); 591 592 switch (fmt) { 593 case DRM_FORMAT_XRGB8888: 594 cfg |= EXYNOS_CIOCTRL_ALPHA_OUT; 595 break; 596 case DRM_FORMAT_YUYV: 597 cfg |= EXYNOS_CIOCTRL_ORDER422_YCBYCR; 598 break; 599 case DRM_FORMAT_YVYU: 600 cfg |= EXYNOS_CIOCTRL_ORDER422_YCRYCB; 601 break; 602 case DRM_FORMAT_UYVY: 603 cfg |= EXYNOS_CIOCTRL_ORDER422_CBYCRY; 604 break; 605 case DRM_FORMAT_VYUY: 606 cfg |= EXYNOS_CIOCTRL_ORDER422_CRYCBY; 607 break; 608 case DRM_FORMAT_NV21: 609 case DRM_FORMAT_NV61: 610 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CRCB; 611 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; 612 break; 613 case DRM_FORMAT_YUV422: 614 case DRM_FORMAT_YUV420: 615 case DRM_FORMAT_YVU420: 616 cfg |= EXYNOS_CIOCTRL_YCBCR_3PLANE; 617 break; 618 case DRM_FORMAT_NV12: 619 case DRM_FORMAT_NV16: 620 cfg |= EXYNOS_CIOCTRL_ORDER2P_LSB_CBCR; 621 cfg |= EXYNOS_CIOCTRL_YCBCR_2PLANE; 622 break; 623 } 624 625 fimc_write(ctx, cfg, EXYNOS_CIOCTRL); 626 } 627 628 static void fimc_dst_set_fmt(struct fimc_context *ctx, u32 fmt, bool tiled) 629 { 630 u32 cfg; 631 632 DRM_DEV_DEBUG_KMS(ctx->dev, "fmt[0x%x]\n", fmt); 633 634 cfg = fimc_read(ctx, EXYNOS_CIEXTEN); 635 636 if (fmt == DRM_FORMAT_AYUV) { 637 cfg |= EXYNOS_CIEXTEN_YUV444_OUT; 638 fimc_write(ctx, cfg, EXYNOS_CIEXTEN); 639 } else { 640 cfg &= ~EXYNOS_CIEXTEN_YUV444_OUT; 641 fimc_write(ctx, cfg, EXYNOS_CIEXTEN); 642 643 cfg = fimc_read(ctx, EXYNOS_CITRGFMT); 644 cfg &= ~EXYNOS_CITRGFMT_OUTFORMAT_MASK; 645 646 switch (fmt) { 647 case DRM_FORMAT_RGB565: 648 case DRM_FORMAT_RGB888: 649 case DRM_FORMAT_XRGB8888: 650 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_RGB; 651 break; 652 case DRM_FORMAT_YUYV: 653 case DRM_FORMAT_YVYU: 654 case DRM_FORMAT_UYVY: 655 case DRM_FORMAT_VYUY: 656 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE; 657 break; 658 case DRM_FORMAT_NV16: 659 case DRM_FORMAT_NV61: 660 case DRM_FORMAT_YUV422: 661 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR422; 662 break; 663 case DRM_FORMAT_YUV420: 664 case DRM_FORMAT_YVU420: 665 case DRM_FORMAT_NV12: 666 case DRM_FORMAT_NV21: 667 cfg |= EXYNOS_CITRGFMT_OUTFORMAT_YCBCR420; 668 break; 669 } 670 671 fimc_write(ctx, cfg, EXYNOS_CITRGFMT); 672 } 673 674 cfg = fimc_read(ctx, EXYNOS_CIDMAPARAM); 675 cfg &= ~EXYNOS_CIDMAPARAM_W_MODE_MASK; 676 677 if (tiled) 678 cfg |= EXYNOS_CIDMAPARAM_W_MODE_64X32; 679 else 680 cfg |= EXYNOS_CIDMAPARAM_W_MODE_LINEAR; 681 682 fimc_write(ctx, cfg, EXYNOS_CIDMAPARAM); 683 684 fimc_dst_set_fmt_order(ctx, fmt); 685 } 686 687 static void fimc_dst_set_transf(struct fimc_context *ctx, unsigned int rotation) 688 { 689 unsigned int degree = rotation & DRM_MODE_ROTATE_MASK; 690 u32 cfg; 691 692 DRM_DEV_DEBUG_KMS(ctx->dev, "rotation[0x%x]\n", rotation); 693 694 cfg = fimc_read(ctx, EXYNOS_CITRGFMT); 695 cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK; 696 cfg &= ~EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; 697 698 switch (degree) { 699 case DRM_MODE_ROTATE_0: 700 if (rotation & DRM_MODE_REFLECT_X) 701 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; 702 if (rotation & DRM_MODE_REFLECT_Y) 703 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 704 break; 705 case DRM_MODE_ROTATE_90: 706 cfg |= EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE; 707 if (rotation & DRM_MODE_REFLECT_X) 708 cfg |= EXYNOS_CITRGFMT_FLIP_X_MIRROR; 709 if (rotation & DRM_MODE_REFLECT_Y) 710 cfg |= EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 711 break; 712 case DRM_MODE_ROTATE_180: 713 cfg |= (EXYNOS_CITRGFMT_FLIP_X_MIRROR | 714 EXYNOS_CITRGFMT_FLIP_Y_MIRROR); 715 if (rotation & DRM_MODE_REFLECT_X) 716 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; 717 if (rotation & DRM_MODE_REFLECT_Y) 718 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 719 break; 720 case DRM_MODE_ROTATE_270: 721 cfg |= (EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE | 722 EXYNOS_CITRGFMT_FLIP_X_MIRROR | 723 EXYNOS_CITRGFMT_FLIP_Y_MIRROR); 724 if (rotation & DRM_MODE_REFLECT_X) 725 cfg &= ~EXYNOS_CITRGFMT_FLIP_X_MIRROR; 726 if (rotation & DRM_MODE_REFLECT_Y) 727 cfg &= ~EXYNOS_CITRGFMT_FLIP_Y_MIRROR; 728 break; 729 } 730 731 fimc_write(ctx, cfg, EXYNOS_CITRGFMT); 732 } 733 734 static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc, 735 struct drm_exynos_ipp_task_rect *src, 736 struct drm_exynos_ipp_task_rect *dst) 737 { 738 u32 cfg, cfg_ext, shfactor; 739 u32 pre_dst_width, pre_dst_height; 740 u32 hfactor, vfactor; 741 int ret = 0; 742 u32 src_w, src_h, dst_w, dst_h; 743 744 cfg_ext = fimc_read(ctx, EXYNOS_CITRGFMT); 745 if (cfg_ext & EXYNOS_CITRGFMT_INROT90_CLOCKWISE) { 746 src_w = src->h; 747 src_h = src->w; 748 } else { 749 src_w = src->w; 750 src_h = src->h; 751 } 752 753 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) { 754 dst_w = dst->h; 755 dst_h = dst->w; 756 } else { 757 dst_w = dst->w; 758 dst_h = dst->h; 759 } 760 761 /* fimc_ippdrv_check_property assures that dividers are not null */ 762 hfactor = fls(src_w / dst_w / 2); 763 if (hfactor > FIMC_SHFACTOR / 2) { 764 dev_err(ctx->dev, "failed to get ratio horizontal.\n"); 765 return -EINVAL; 766 } 767 768 vfactor = fls(src_h / dst_h / 2); 769 if (vfactor > FIMC_SHFACTOR / 2) { 770 dev_err(ctx->dev, "failed to get ratio vertical.\n"); 771 return -EINVAL; 772 } 773 774 pre_dst_width = src_w >> hfactor; 775 pre_dst_height = src_h >> vfactor; 776 DRM_DEV_DEBUG_KMS(ctx->dev, "pre_dst_width[%d]pre_dst_height[%d]\n", 777 pre_dst_width, pre_dst_height); 778 DRM_DEV_DEBUG_KMS(ctx->dev, "hfactor[%d]vfactor[%d]\n", hfactor, 779 vfactor); 780 781 sc->hratio = (src_w << 14) / (dst_w << hfactor); 782 sc->vratio = (src_h << 14) / (dst_h << vfactor); 783 sc->up_h = (dst_w >= src_w) ? true : false; 784 sc->up_v = (dst_h >= src_h) ? true : false; 785 DRM_DEV_DEBUG_KMS(ctx->dev, "hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n", 786 sc->hratio, sc->vratio, sc->up_h, sc->up_v); 787 788 shfactor = FIMC_SHFACTOR - (hfactor + vfactor); 789 DRM_DEV_DEBUG_KMS(ctx->dev, "shfactor[%d]\n", shfactor); 790 791 cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) | 792 EXYNOS_CISCPRERATIO_PREHORRATIO(1 << hfactor) | 793 EXYNOS_CISCPRERATIO_PREVERRATIO(1 << vfactor)); 794 fimc_write(ctx, cfg, EXYNOS_CISCPRERATIO); 795 796 cfg = (EXYNOS_CISCPREDST_PREDSTWIDTH(pre_dst_width) | 797 EXYNOS_CISCPREDST_PREDSTHEIGHT(pre_dst_height)); 798 fimc_write(ctx, cfg, EXYNOS_CISCPREDST); 799 800 return ret; 801 } 802 803 static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc) 804 { 805 u32 cfg, cfg_ext; 806 807 DRM_DEV_DEBUG_KMS(ctx->dev, "range[%d]bypass[%d]up_h[%d]up_v[%d]\n", 808 sc->range, sc->bypass, sc->up_h, sc->up_v); 809 DRM_DEV_DEBUG_KMS(ctx->dev, "hratio[%d]vratio[%d]\n", 810 sc->hratio, sc->vratio); 811 812 cfg = fimc_read(ctx, EXYNOS_CISCCTRL); 813 cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS | 814 EXYNOS_CISCCTRL_SCALEUP_H | EXYNOS_CISCCTRL_SCALEUP_V | 815 EXYNOS_CISCCTRL_MAIN_V_RATIO_MASK | 816 EXYNOS_CISCCTRL_MAIN_H_RATIO_MASK | 817 EXYNOS_CISCCTRL_CSCR2Y_WIDE | 818 EXYNOS_CISCCTRL_CSCY2R_WIDE); 819 820 if (sc->range) 821 cfg |= (EXYNOS_CISCCTRL_CSCR2Y_WIDE | 822 EXYNOS_CISCCTRL_CSCY2R_WIDE); 823 if (sc->bypass) 824 cfg |= EXYNOS_CISCCTRL_SCALERBYPASS; 825 if (sc->up_h) 826 cfg |= EXYNOS_CISCCTRL_SCALEUP_H; 827 if (sc->up_v) 828 cfg |= EXYNOS_CISCCTRL_SCALEUP_V; 829 830 cfg |= (EXYNOS_CISCCTRL_MAINHORRATIO((sc->hratio >> 6)) | 831 EXYNOS_CISCCTRL_MAINVERRATIO((sc->vratio >> 6))); 832 fimc_write(ctx, cfg, EXYNOS_CISCCTRL); 833 834 cfg_ext = fimc_read(ctx, EXYNOS_CIEXTEN); 835 cfg_ext &= ~EXYNOS_CIEXTEN_MAINHORRATIO_EXT_MASK; 836 cfg_ext &= ~EXYNOS_CIEXTEN_MAINVERRATIO_EXT_MASK; 837 cfg_ext |= (EXYNOS_CIEXTEN_MAINHORRATIO_EXT(sc->hratio) | 838 EXYNOS_CIEXTEN_MAINVERRATIO_EXT(sc->vratio)); 839 fimc_write(ctx, cfg_ext, EXYNOS_CIEXTEN); 840 } 841 842 static void fimc_dst_set_size(struct fimc_context *ctx, 843 struct exynos_drm_ipp_buffer *buf) 844 { 845 unsigned int real_width = buf->buf.pitch[0] / buf->format->cpp[0]; 846 u32 cfg, cfg_ext; 847 848 DRM_DEV_DEBUG_KMS(ctx->dev, "hsize[%d]vsize[%d]\n", real_width, 849 buf->buf.height); 850 851 /* original size */ 852 cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(real_width) | 853 EXYNOS_ORGOSIZE_VERTICAL(buf->buf.height)); 854 855 fimc_write(ctx, cfg, EXYNOS_ORGOSIZE); 856 857 DRM_DEV_DEBUG_KMS(ctx->dev, "x[%d]y[%d]w[%d]h[%d]\n", buf->rect.x, 858 buf->rect.y, 859 buf->rect.w, buf->rect.h); 860 861 /* CSC ITU */ 862 cfg = fimc_read(ctx, EXYNOS_CIGCTRL); 863 cfg &= ~EXYNOS_CIGCTRL_CSC_MASK; 864 865 if (buf->buf.width >= FIMC_WIDTH_ITU_709) 866 cfg |= EXYNOS_CIGCTRL_CSC_ITU709; 867 else 868 cfg |= EXYNOS_CIGCTRL_CSC_ITU601; 869 870 fimc_write(ctx, cfg, EXYNOS_CIGCTRL); 871 872 cfg_ext = fimc_read(ctx, EXYNOS_CITRGFMT); 873 874 /* target image size */ 875 cfg = fimc_read(ctx, EXYNOS_CITRGFMT); 876 cfg &= ~(EXYNOS_CITRGFMT_TARGETH_MASK | 877 EXYNOS_CITRGFMT_TARGETV_MASK); 878 if (cfg_ext & EXYNOS_CITRGFMT_OUTROT90_CLOCKWISE) 879 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(buf->rect.h) | 880 EXYNOS_CITRGFMT_TARGETVSIZE(buf->rect.w)); 881 else 882 cfg |= (EXYNOS_CITRGFMT_TARGETHSIZE(buf->rect.w) | 883 EXYNOS_CITRGFMT_TARGETVSIZE(buf->rect.h)); 884 fimc_write(ctx, cfg, EXYNOS_CITRGFMT); 885 886 /* target area */ 887 cfg = EXYNOS_CITAREA_TARGET_AREA(buf->rect.w * buf->rect.h); 888 fimc_write(ctx, cfg, EXYNOS_CITAREA); 889 890 /* offset Y(RGB), Cb, Cr */ 891 cfg = (EXYNOS_CIOYOFF_HORIZONTAL(buf->rect.x) | 892 EXYNOS_CIOYOFF_VERTICAL(buf->rect.y)); 893 fimc_write(ctx, cfg, EXYNOS_CIOYOFF); 894 cfg = (EXYNOS_CIOCBOFF_HORIZONTAL(buf->rect.x) | 895 EXYNOS_CIOCBOFF_VERTICAL(buf->rect.y)); 896 fimc_write(ctx, cfg, EXYNOS_CIOCBOFF); 897 cfg = (EXYNOS_CIOCROFF_HORIZONTAL(buf->rect.x) | 898 EXYNOS_CIOCROFF_VERTICAL(buf->rect.y)); 899 fimc_write(ctx, cfg, EXYNOS_CIOCROFF); 900 } 901 902 static void fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id, 903 bool enqueue) 904 { 905 unsigned long flags; 906 u32 buf_num; 907 u32 cfg; 908 909 DRM_DEV_DEBUG_KMS(ctx->dev, "buf_id[%d]enqueu[%d]\n", buf_id, enqueue); 910 911 spin_lock_irqsave(&ctx->lock, flags); 912 913 cfg = fimc_read(ctx, EXYNOS_CIFCNTSEQ); 914 915 if (enqueue) 916 cfg |= (1 << buf_id); 917 else 918 cfg &= ~(1 << buf_id); 919 920 fimc_write(ctx, cfg, EXYNOS_CIFCNTSEQ); 921 922 buf_num = hweight32(cfg); 923 924 if (enqueue && buf_num >= FIMC_BUF_START) 925 fimc_mask_irq(ctx, true); 926 else if (!enqueue && buf_num <= FIMC_BUF_STOP) 927 fimc_mask_irq(ctx, false); 928 929 spin_unlock_irqrestore(&ctx->lock, flags); 930 } 931 932 static void fimc_dst_set_addr(struct fimc_context *ctx, 933 struct exynos_drm_ipp_buffer *buf) 934 { 935 fimc_write(ctx, buf->dma_addr[0], EXYNOS_CIOYSA(0)); 936 fimc_write(ctx, buf->dma_addr[1], EXYNOS_CIOCBSA(0)); 937 fimc_write(ctx, buf->dma_addr[2], EXYNOS_CIOCRSA(0)); 938 939 fimc_dst_set_buf_seq(ctx, 0, true); 940 } 941 942 static void fimc_stop(struct fimc_context *ctx); 943 944 static irqreturn_t fimc_irq_handler(int irq, void *dev_id) 945 { 946 struct fimc_context *ctx = dev_id; 947 int buf_id; 948 949 DRM_DEV_DEBUG_KMS(ctx->dev, "fimc id[%d]\n", ctx->id); 950 951 fimc_clear_irq(ctx); 952 if (fimc_check_ovf(ctx)) 953 return IRQ_NONE; 954 955 if (!fimc_check_frame_end(ctx)) 956 return IRQ_NONE; 957 958 buf_id = fimc_get_buf_id(ctx); 959 if (buf_id < 0) 960 return IRQ_HANDLED; 961 962 DRM_DEV_DEBUG_KMS(ctx->dev, "buf_id[%d]\n", buf_id); 963 964 if (ctx->task) { 965 struct exynos_drm_ipp_task *task = ctx->task; 966 967 ctx->task = NULL; 968 pm_runtime_mark_last_busy(ctx->dev); 969 pm_runtime_put_autosuspend(ctx->dev); 970 exynos_drm_ipp_task_done(task, 0); 971 } 972 973 fimc_dst_set_buf_seq(ctx, buf_id, false); 974 fimc_stop(ctx); 975 976 return IRQ_HANDLED; 977 } 978 979 static void fimc_clear_addr(struct fimc_context *ctx) 980 { 981 int i; 982 983 for (i = 0; i < FIMC_MAX_SRC; i++) { 984 fimc_write(ctx, 0, EXYNOS_CIIYSA(i)); 985 fimc_write(ctx, 0, EXYNOS_CIICBSA(i)); 986 fimc_write(ctx, 0, EXYNOS_CIICRSA(i)); 987 } 988 989 for (i = 0; i < FIMC_MAX_DST; i++) { 990 fimc_write(ctx, 0, EXYNOS_CIOYSA(i)); 991 fimc_write(ctx, 0, EXYNOS_CIOCBSA(i)); 992 fimc_write(ctx, 0, EXYNOS_CIOCRSA(i)); 993 } 994 } 995 996 static void fimc_reset(struct fimc_context *ctx) 997 { 998 /* reset h/w block */ 999 fimc_sw_reset(ctx); 1000 1001 /* reset scaler capability */ 1002 memset(&ctx->sc, 0x0, sizeof(ctx->sc)); 1003 1004 fimc_clear_addr(ctx); 1005 } 1006 1007 static void fimc_start(struct fimc_context *ctx) 1008 { 1009 u32 cfg0, cfg1; 1010 1011 fimc_mask_irq(ctx, true); 1012 1013 /* If set true, we can save jpeg about screen */ 1014 fimc_handle_jpeg(ctx, false); 1015 fimc_set_scaler(ctx, &ctx->sc); 1016 1017 fimc_set_type_ctrl(ctx); 1018 fimc_handle_lastend(ctx, false); 1019 1020 /* setup dma */ 1021 cfg0 = fimc_read(ctx, EXYNOS_MSCTRL); 1022 cfg0 &= ~EXYNOS_MSCTRL_INPUT_MASK; 1023 cfg0 |= EXYNOS_MSCTRL_INPUT_MEMORY; 1024 fimc_write(ctx, cfg0, EXYNOS_MSCTRL); 1025 1026 /* Reset status */ 1027 fimc_write(ctx, 0x0, EXYNOS_CISTATUS); 1028 1029 cfg0 = fimc_read(ctx, EXYNOS_CIIMGCPT); 1030 cfg0 &= ~EXYNOS_CIIMGCPT_IMGCPTEN_SC; 1031 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN_SC; 1032 1033 /* Scaler */ 1034 cfg1 = fimc_read(ctx, EXYNOS_CISCCTRL); 1035 cfg1 &= ~EXYNOS_CISCCTRL_SCAN_MASK; 1036 cfg1 |= (EXYNOS_CISCCTRL_PROGRESSIVE | 1037 EXYNOS_CISCCTRL_SCALERSTART); 1038 1039 fimc_write(ctx, cfg1, EXYNOS_CISCCTRL); 1040 1041 /* Enable image capture*/ 1042 cfg0 |= EXYNOS_CIIMGCPT_IMGCPTEN; 1043 fimc_write(ctx, cfg0, EXYNOS_CIIMGCPT); 1044 1045 /* Disable frame end irq */ 1046 fimc_clear_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_END_DISABLE); 1047 1048 fimc_clear_bits(ctx, EXYNOS_CIOCTRL, EXYNOS_CIOCTRL_WEAVE_MASK); 1049 1050 fimc_set_bits(ctx, EXYNOS_MSCTRL, EXYNOS_MSCTRL_ENVID); 1051 } 1052 1053 static void fimc_stop(struct fimc_context *ctx) 1054 { 1055 u32 cfg; 1056 1057 /* Source clear */ 1058 cfg = fimc_read(ctx, EXYNOS_MSCTRL); 1059 cfg &= ~EXYNOS_MSCTRL_INPUT_MASK; 1060 cfg &= ~EXYNOS_MSCTRL_ENVID; 1061 fimc_write(ctx, cfg, EXYNOS_MSCTRL); 1062 1063 fimc_mask_irq(ctx, false); 1064 1065 /* reset sequence */ 1066 fimc_write(ctx, 0x0, EXYNOS_CIFCNTSEQ); 1067 1068 /* Scaler disable */ 1069 fimc_clear_bits(ctx, EXYNOS_CISCCTRL, EXYNOS_CISCCTRL_SCALERSTART); 1070 1071 /* Disable image capture */ 1072 fimc_clear_bits(ctx, EXYNOS_CIIMGCPT, 1073 EXYNOS_CIIMGCPT_IMGCPTEN_SC | EXYNOS_CIIMGCPT_IMGCPTEN); 1074 1075 /* Enable frame end irq */ 1076 fimc_set_bits(ctx, EXYNOS_CIGCTRL, EXYNOS_CIGCTRL_IRQ_END_DISABLE); 1077 } 1078 1079 static int fimc_commit(struct exynos_drm_ipp *ipp, 1080 struct exynos_drm_ipp_task *task) 1081 { 1082 struct fimc_context *ctx = 1083 container_of(ipp, struct fimc_context, ipp); 1084 1085 pm_runtime_get_sync(ctx->dev); 1086 ctx->task = task; 1087 1088 fimc_src_set_fmt(ctx, task->src.buf.fourcc, task->src.buf.modifier); 1089 fimc_src_set_size(ctx, &task->src); 1090 fimc_src_set_transf(ctx, DRM_MODE_ROTATE_0); 1091 fimc_src_set_addr(ctx, &task->src); 1092 fimc_dst_set_fmt(ctx, task->dst.buf.fourcc, task->dst.buf.modifier); 1093 fimc_dst_set_transf(ctx, task->transform.rotation); 1094 fimc_dst_set_size(ctx, &task->dst); 1095 fimc_dst_set_addr(ctx, &task->dst); 1096 fimc_set_prescaler(ctx, &ctx->sc, &task->src.rect, &task->dst.rect); 1097 fimc_start(ctx); 1098 1099 return 0; 1100 } 1101 1102 static void fimc_abort(struct exynos_drm_ipp *ipp, 1103 struct exynos_drm_ipp_task *task) 1104 { 1105 struct fimc_context *ctx = 1106 container_of(ipp, struct fimc_context, ipp); 1107 1108 fimc_reset(ctx); 1109 1110 if (ctx->task) { 1111 struct exynos_drm_ipp_task *task = ctx->task; 1112 1113 ctx->task = NULL; 1114 pm_runtime_mark_last_busy(ctx->dev); 1115 pm_runtime_put_autosuspend(ctx->dev); 1116 exynos_drm_ipp_task_done(task, -EIO); 1117 } 1118 } 1119 1120 static struct exynos_drm_ipp_funcs ipp_funcs = { 1121 .commit = fimc_commit, 1122 .abort = fimc_abort, 1123 }; 1124 1125 static int fimc_bind(struct device *dev, struct device *master, void *data) 1126 { 1127 struct fimc_context *ctx = dev_get_drvdata(dev); 1128 struct drm_device *drm_dev = data; 1129 struct exynos_drm_ipp *ipp = &ctx->ipp; 1130 1131 ctx->drm_dev = drm_dev; 1132 ipp->drm_dev = drm_dev; 1133 exynos_drm_register_dma(drm_dev, dev); 1134 1135 exynos_drm_ipp_register(dev, ipp, &ipp_funcs, 1136 DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE | 1137 DRM_EXYNOS_IPP_CAP_SCALE | DRM_EXYNOS_IPP_CAP_CONVERT, 1138 ctx->formats, ctx->num_formats, "fimc"); 1139 1140 dev_info(dev, "The exynos fimc has been probed successfully\n"); 1141 1142 return 0; 1143 } 1144 1145 static void fimc_unbind(struct device *dev, struct device *master, 1146 void *data) 1147 { 1148 struct fimc_context *ctx = dev_get_drvdata(dev); 1149 struct drm_device *drm_dev = data; 1150 struct exynos_drm_ipp *ipp = &ctx->ipp; 1151 1152 exynos_drm_ipp_unregister(dev, ipp); 1153 exynos_drm_unregister_dma(drm_dev, dev); 1154 } 1155 1156 static const struct component_ops fimc_component_ops = { 1157 .bind = fimc_bind, 1158 .unbind = fimc_unbind, 1159 }; 1160 1161 static void fimc_put_clocks(struct fimc_context *ctx) 1162 { 1163 int i; 1164 1165 for (i = 0; i < FIMC_CLKS_MAX; i++) { 1166 if (IS_ERR(ctx->clocks[i])) 1167 continue; 1168 clk_put(ctx->clocks[i]); 1169 ctx->clocks[i] = ERR_PTR(-EINVAL); 1170 } 1171 } 1172 1173 static int fimc_setup_clocks(struct fimc_context *ctx) 1174 { 1175 struct device *fimc_dev = ctx->dev; 1176 struct device *dev; 1177 int ret, i; 1178 1179 for (i = 0; i < FIMC_CLKS_MAX; i++) 1180 ctx->clocks[i] = ERR_PTR(-EINVAL); 1181 1182 for (i = 0; i < FIMC_CLKS_MAX; i++) { 1183 if (i == FIMC_CLK_WB_A || i == FIMC_CLK_WB_B) 1184 dev = fimc_dev->parent; 1185 else 1186 dev = fimc_dev; 1187 1188 ctx->clocks[i] = clk_get(dev, fimc_clock_names[i]); 1189 if (IS_ERR(ctx->clocks[i])) { 1190 ret = PTR_ERR(ctx->clocks[i]); 1191 dev_err(fimc_dev, "failed to get clock: %s\n", 1192 fimc_clock_names[i]); 1193 goto e_clk_free; 1194 } 1195 } 1196 1197 ret = clk_prepare_enable(ctx->clocks[FIMC_CLK_LCLK]); 1198 if (!ret) 1199 return ret; 1200 e_clk_free: 1201 fimc_put_clocks(ctx); 1202 return ret; 1203 } 1204 1205 int exynos_drm_check_fimc_device(struct device *dev) 1206 { 1207 int id = of_alias_get_id(dev->of_node, "fimc"); 1208 1209 if (id >= 0 && (BIT(id) & fimc_mask)) 1210 return 0; 1211 return -ENODEV; 1212 } 1213 1214 static const unsigned int fimc_formats[] = { 1215 DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB565, 1216 DRM_FORMAT_NV12, DRM_FORMAT_NV16, DRM_FORMAT_NV21, DRM_FORMAT_NV61, 1217 DRM_FORMAT_UYVY, DRM_FORMAT_VYUY, DRM_FORMAT_YUYV, DRM_FORMAT_YVYU, 1218 DRM_FORMAT_YUV420, DRM_FORMAT_YVU420, DRM_FORMAT_YUV422, 1219 DRM_FORMAT_YUV444, 1220 }; 1221 1222 static const unsigned int fimc_tiled_formats[] = { 1223 DRM_FORMAT_NV12, DRM_FORMAT_NV21, 1224 }; 1225 1226 static const struct drm_exynos_ipp_limit fimc_4210_limits_v1[] = { 1227 { IPP_SIZE_LIMIT(BUFFER, .h = { 16, 8192, 8 }, .v = { 16, 8192, 2 }) }, 1228 { IPP_SIZE_LIMIT(AREA, .h = { 16, 4224, 2 }, .v = { 16, 0, 2 }) }, 1229 { IPP_SIZE_LIMIT(ROTATED, .h = { 128, 1920 }, .v = { 128, 0 }) }, 1230 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 }, 1231 .v = { (1 << 16) / 64, (1 << 16) * 64 }) }, 1232 }; 1233 1234 static const struct drm_exynos_ipp_limit fimc_4210_limits_v2[] = { 1235 { IPP_SIZE_LIMIT(BUFFER, .h = { 16, 8192, 8 }, .v = { 16, 8192, 2 }) }, 1236 { IPP_SIZE_LIMIT(AREA, .h = { 16, 1920, 2 }, .v = { 16, 0, 2 }) }, 1237 { IPP_SIZE_LIMIT(ROTATED, .h = { 128, 1366 }, .v = { 128, 0 }) }, 1238 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 }, 1239 .v = { (1 << 16) / 64, (1 << 16) * 64 }) }, 1240 }; 1241 1242 static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v1[] = { 1243 { IPP_SIZE_LIMIT(BUFFER, .h = { 128, 1920, 128 }, .v = { 32, 1920, 32 }) }, 1244 { IPP_SIZE_LIMIT(AREA, .h = { 128, 1920, 2 }, .v = { 128, 0, 2 }) }, 1245 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 }, 1246 .v = { (1 << 16) / 64, (1 << 16) * 64 }) }, 1247 }; 1248 1249 static const struct drm_exynos_ipp_limit fimc_4210_limits_tiled_v2[] = { 1250 { IPP_SIZE_LIMIT(BUFFER, .h = { 128, 1920, 128 }, .v = { 32, 1920, 32 }) }, 1251 { IPP_SIZE_LIMIT(AREA, .h = { 128, 1366, 2 }, .v = { 128, 0, 2 }) }, 1252 { IPP_SCALE_LIMIT(.h = { (1 << 16) / 64, (1 << 16) * 64 }, 1253 .v = { (1 << 16) / 64, (1 << 16) * 64 }) }, 1254 }; 1255 1256 static int fimc_probe(struct platform_device *pdev) 1257 { 1258 const struct drm_exynos_ipp_limit *limits; 1259 struct exynos_drm_ipp_formats *formats; 1260 struct device *dev = &pdev->dev; 1261 struct fimc_context *ctx; 1262 struct resource *res; 1263 int ret; 1264 int i, j, num_limits, num_formats; 1265 1266 if (exynos_drm_check_fimc_device(dev) != 0) 1267 return -ENODEV; 1268 1269 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 1270 if (!ctx) 1271 return -ENOMEM; 1272 1273 ctx->dev = dev; 1274 ctx->id = of_alias_get_id(dev->of_node, "fimc"); 1275 1276 /* construct formats/limits array */ 1277 num_formats = ARRAY_SIZE(fimc_formats) + ARRAY_SIZE(fimc_tiled_formats); 1278 formats = devm_kcalloc(dev, num_formats, sizeof(*formats), 1279 GFP_KERNEL); 1280 if (!formats) 1281 return -ENOMEM; 1282 1283 /* linear formats */ 1284 if (ctx->id < 3) { 1285 limits = fimc_4210_limits_v1; 1286 num_limits = ARRAY_SIZE(fimc_4210_limits_v1); 1287 } else { 1288 limits = fimc_4210_limits_v2; 1289 num_limits = ARRAY_SIZE(fimc_4210_limits_v2); 1290 } 1291 for (i = 0; i < ARRAY_SIZE(fimc_formats); i++) { 1292 formats[i].fourcc = fimc_formats[i]; 1293 formats[i].type = DRM_EXYNOS_IPP_FORMAT_SOURCE | 1294 DRM_EXYNOS_IPP_FORMAT_DESTINATION; 1295 formats[i].limits = limits; 1296 formats[i].num_limits = num_limits; 1297 } 1298 1299 /* tiled formats */ 1300 if (ctx->id < 3) { 1301 limits = fimc_4210_limits_tiled_v1; 1302 num_limits = ARRAY_SIZE(fimc_4210_limits_tiled_v1); 1303 } else { 1304 limits = fimc_4210_limits_tiled_v2; 1305 num_limits = ARRAY_SIZE(fimc_4210_limits_tiled_v2); 1306 } 1307 for (j = i, i = 0; i < ARRAY_SIZE(fimc_tiled_formats); j++, i++) { 1308 formats[j].fourcc = fimc_tiled_formats[i]; 1309 formats[j].modifier = DRM_FORMAT_MOD_SAMSUNG_64_32_TILE; 1310 formats[j].type = DRM_EXYNOS_IPP_FORMAT_SOURCE | 1311 DRM_EXYNOS_IPP_FORMAT_DESTINATION; 1312 formats[j].limits = limits; 1313 formats[j].num_limits = num_limits; 1314 } 1315 1316 ctx->formats = formats; 1317 ctx->num_formats = num_formats; 1318 1319 /* resource memory */ 1320 ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1321 ctx->regs = devm_ioremap_resource(dev, ctx->regs_res); 1322 if (IS_ERR(ctx->regs)) 1323 return PTR_ERR(ctx->regs); 1324 1325 /* resource irq */ 1326 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1327 if (!res) { 1328 dev_err(dev, "failed to request irq resource.\n"); 1329 return -ENOENT; 1330 } 1331 1332 ret = devm_request_irq(dev, res->start, fimc_irq_handler, 1333 0, dev_name(dev), ctx); 1334 if (ret < 0) { 1335 dev_err(dev, "failed to request irq.\n"); 1336 return ret; 1337 } 1338 1339 ret = fimc_setup_clocks(ctx); 1340 if (ret < 0) 1341 return ret; 1342 1343 spin_lock_init(&ctx->lock); 1344 platform_set_drvdata(pdev, ctx); 1345 1346 pm_runtime_use_autosuspend(dev); 1347 pm_runtime_set_autosuspend_delay(dev, FIMC_AUTOSUSPEND_DELAY); 1348 pm_runtime_enable(dev); 1349 1350 ret = component_add(dev, &fimc_component_ops); 1351 if (ret) 1352 goto err_pm_dis; 1353 1354 dev_info(dev, "drm fimc registered successfully.\n"); 1355 1356 return 0; 1357 1358 err_pm_dis: 1359 pm_runtime_dont_use_autosuspend(dev); 1360 pm_runtime_disable(dev); 1361 fimc_put_clocks(ctx); 1362 1363 return ret; 1364 } 1365 1366 static int fimc_remove(struct platform_device *pdev) 1367 { 1368 struct device *dev = &pdev->dev; 1369 struct fimc_context *ctx = get_fimc_context(dev); 1370 1371 component_del(dev, &fimc_component_ops); 1372 pm_runtime_dont_use_autosuspend(dev); 1373 pm_runtime_disable(dev); 1374 1375 fimc_put_clocks(ctx); 1376 1377 return 0; 1378 } 1379 1380 #ifdef CONFIG_PM 1381 static int fimc_runtime_suspend(struct device *dev) 1382 { 1383 struct fimc_context *ctx = get_fimc_context(dev); 1384 1385 DRM_DEV_DEBUG_KMS(dev, "id[%d]\n", ctx->id); 1386 clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]); 1387 return 0; 1388 } 1389 1390 static int fimc_runtime_resume(struct device *dev) 1391 { 1392 struct fimc_context *ctx = get_fimc_context(dev); 1393 1394 DRM_DEV_DEBUG_KMS(dev, "id[%d]\n", ctx->id); 1395 return clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]); 1396 } 1397 #endif 1398 1399 static const struct dev_pm_ops fimc_pm_ops = { 1400 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1401 pm_runtime_force_resume) 1402 SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL) 1403 }; 1404 1405 static const struct of_device_id fimc_of_match[] = { 1406 { .compatible = "samsung,exynos4210-fimc" }, 1407 { .compatible = "samsung,exynos4212-fimc" }, 1408 { }, 1409 }; 1410 MODULE_DEVICE_TABLE(of, fimc_of_match); 1411 1412 struct platform_driver fimc_driver = { 1413 .probe = fimc_probe, 1414 .remove = fimc_remove, 1415 .driver = { 1416 .of_match_table = fimc_of_match, 1417 .name = "exynos-drm-fimc", 1418 .owner = THIS_MODULE, 1419 .pm = &fimc_pm_ops, 1420 }, 1421 }; 1422