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