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