1 /* 2 * Copyright (C) 2011 Samsung Electronics Co.Ltd 3 * Authors: 4 * Seung-Woo Kim <sw0312.kim@samsung.com> 5 * Inki Dae <inki.dae@samsung.com> 6 * Joonyoung Shim <jy0922.shim@samsung.com> 7 * 8 * Based on drivers/media/video/s5p-tv/mixer_reg.c 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the 12 * Free Software Foundation; either version 2 of the License, or (at your 13 * option) any later version. 14 * 15 */ 16 17 #include <drm/drmP.h> 18 19 #include "regs-mixer.h" 20 #include "regs-vp.h" 21 22 #include <linux/kernel.h> 23 #include <linux/spinlock.h> 24 #include <linux/wait.h> 25 #include <linux/i2c.h> 26 #include <linux/platform_device.h> 27 #include <linux/interrupt.h> 28 #include <linux/irq.h> 29 #include <linux/delay.h> 30 #include <linux/pm_runtime.h> 31 #include <linux/clk.h> 32 #include <linux/regulator/consumer.h> 33 #include <linux/of.h> 34 #include <linux/component.h> 35 36 #include <drm/exynos_drm.h> 37 38 #include "exynos_drm_drv.h" 39 #include "exynos_drm_crtc.h" 40 #include "exynos_drm_plane.h" 41 #include "exynos_drm_iommu.h" 42 #include "exynos_mixer.h" 43 44 #define MIXER_WIN_NR 3 45 #define MIXER_DEFAULT_WIN 0 46 47 struct mixer_resources { 48 int irq; 49 void __iomem *mixer_regs; 50 void __iomem *vp_regs; 51 spinlock_t reg_slock; 52 struct clk *mixer; 53 struct clk *vp; 54 struct clk *hdmi; 55 struct clk *sclk_mixer; 56 struct clk *sclk_hdmi; 57 struct clk *mout_mixer; 58 }; 59 60 enum mixer_version_id { 61 MXR_VER_0_0_0_16, 62 MXR_VER_16_0_33_0, 63 MXR_VER_128_0_0_184, 64 }; 65 66 struct mixer_context { 67 struct platform_device *pdev; 68 struct device *dev; 69 struct drm_device *drm_dev; 70 struct exynos_drm_crtc *crtc; 71 struct exynos_drm_plane planes[MIXER_WIN_NR]; 72 int pipe; 73 bool interlace; 74 bool powered; 75 bool vp_enabled; 76 bool has_sclk; 77 u32 int_en; 78 79 struct mutex mixer_mutex; 80 struct mixer_resources mixer_res; 81 enum mixer_version_id mxr_ver; 82 wait_queue_head_t wait_vsync_queue; 83 atomic_t wait_vsync_event; 84 }; 85 86 struct mixer_drv_data { 87 enum mixer_version_id version; 88 bool is_vp_enabled; 89 bool has_sclk; 90 }; 91 92 static const u8 filter_y_horiz_tap8[] = { 93 0, -1, -1, -1, -1, -1, -1, -1, 94 -1, -1, -1, -1, -1, 0, 0, 0, 95 0, 2, 4, 5, 6, 6, 6, 6, 96 6, 5, 5, 4, 3, 2, 1, 1, 97 0, -6, -12, -16, -18, -20, -21, -20, 98 -20, -18, -16, -13, -10, -8, -5, -2, 99 127, 126, 125, 121, 114, 107, 99, 89, 100 79, 68, 57, 46, 35, 25, 16, 8, 101 }; 102 103 static const u8 filter_y_vert_tap4[] = { 104 0, -3, -6, -8, -8, -8, -8, -7, 105 -6, -5, -4, -3, -2, -1, -1, 0, 106 127, 126, 124, 118, 111, 102, 92, 81, 107 70, 59, 48, 37, 27, 19, 11, 5, 108 0, 5, 11, 19, 27, 37, 48, 59, 109 70, 81, 92, 102, 111, 118, 124, 126, 110 0, 0, -1, -1, -2, -3, -4, -5, 111 -6, -7, -8, -8, -8, -8, -6, -3, 112 }; 113 114 static const u8 filter_cr_horiz_tap4[] = { 115 0, -3, -6, -8, -8, -8, -8, -7, 116 -6, -5, -4, -3, -2, -1, -1, 0, 117 127, 126, 124, 118, 111, 102, 92, 81, 118 70, 59, 48, 37, 27, 19, 11, 5, 119 }; 120 121 static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id) 122 { 123 return readl(res->vp_regs + reg_id); 124 } 125 126 static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id, 127 u32 val) 128 { 129 writel(val, res->vp_regs + reg_id); 130 } 131 132 static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id, 133 u32 val, u32 mask) 134 { 135 u32 old = vp_reg_read(res, reg_id); 136 137 val = (val & mask) | (old & ~mask); 138 writel(val, res->vp_regs + reg_id); 139 } 140 141 static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id) 142 { 143 return readl(res->mixer_regs + reg_id); 144 } 145 146 static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id, 147 u32 val) 148 { 149 writel(val, res->mixer_regs + reg_id); 150 } 151 152 static inline void mixer_reg_writemask(struct mixer_resources *res, 153 u32 reg_id, u32 val, u32 mask) 154 { 155 u32 old = mixer_reg_read(res, reg_id); 156 157 val = (val & mask) | (old & ~mask); 158 writel(val, res->mixer_regs + reg_id); 159 } 160 161 static void mixer_regs_dump(struct mixer_context *ctx) 162 { 163 #define DUMPREG(reg_id) \ 164 do { \ 165 DRM_DEBUG_KMS(#reg_id " = %08x\n", \ 166 (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \ 167 } while (0) 168 169 DUMPREG(MXR_STATUS); 170 DUMPREG(MXR_CFG); 171 DUMPREG(MXR_INT_EN); 172 DUMPREG(MXR_INT_STATUS); 173 174 DUMPREG(MXR_LAYER_CFG); 175 DUMPREG(MXR_VIDEO_CFG); 176 177 DUMPREG(MXR_GRAPHIC0_CFG); 178 DUMPREG(MXR_GRAPHIC0_BASE); 179 DUMPREG(MXR_GRAPHIC0_SPAN); 180 DUMPREG(MXR_GRAPHIC0_WH); 181 DUMPREG(MXR_GRAPHIC0_SXY); 182 DUMPREG(MXR_GRAPHIC0_DXY); 183 184 DUMPREG(MXR_GRAPHIC1_CFG); 185 DUMPREG(MXR_GRAPHIC1_BASE); 186 DUMPREG(MXR_GRAPHIC1_SPAN); 187 DUMPREG(MXR_GRAPHIC1_WH); 188 DUMPREG(MXR_GRAPHIC1_SXY); 189 DUMPREG(MXR_GRAPHIC1_DXY); 190 #undef DUMPREG 191 } 192 193 static void vp_regs_dump(struct mixer_context *ctx) 194 { 195 #define DUMPREG(reg_id) \ 196 do { \ 197 DRM_DEBUG_KMS(#reg_id " = %08x\n", \ 198 (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \ 199 } while (0) 200 201 DUMPREG(VP_ENABLE); 202 DUMPREG(VP_SRESET); 203 DUMPREG(VP_SHADOW_UPDATE); 204 DUMPREG(VP_FIELD_ID); 205 DUMPREG(VP_MODE); 206 DUMPREG(VP_IMG_SIZE_Y); 207 DUMPREG(VP_IMG_SIZE_C); 208 DUMPREG(VP_PER_RATE_CTRL); 209 DUMPREG(VP_TOP_Y_PTR); 210 DUMPREG(VP_BOT_Y_PTR); 211 DUMPREG(VP_TOP_C_PTR); 212 DUMPREG(VP_BOT_C_PTR); 213 DUMPREG(VP_ENDIAN_MODE); 214 DUMPREG(VP_SRC_H_POSITION); 215 DUMPREG(VP_SRC_V_POSITION); 216 DUMPREG(VP_SRC_WIDTH); 217 DUMPREG(VP_SRC_HEIGHT); 218 DUMPREG(VP_DST_H_POSITION); 219 DUMPREG(VP_DST_V_POSITION); 220 DUMPREG(VP_DST_WIDTH); 221 DUMPREG(VP_DST_HEIGHT); 222 DUMPREG(VP_H_RATIO); 223 DUMPREG(VP_V_RATIO); 224 225 #undef DUMPREG 226 } 227 228 static inline void vp_filter_set(struct mixer_resources *res, 229 int reg_id, const u8 *data, unsigned int size) 230 { 231 /* assure 4-byte align */ 232 BUG_ON(size & 3); 233 for (; size; size -= 4, reg_id += 4, data += 4) { 234 u32 val = (data[0] << 24) | (data[1] << 16) | 235 (data[2] << 8) | data[3]; 236 vp_reg_write(res, reg_id, val); 237 } 238 } 239 240 static void vp_default_filter(struct mixer_resources *res) 241 { 242 vp_filter_set(res, VP_POLY8_Y0_LL, 243 filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8)); 244 vp_filter_set(res, VP_POLY4_Y0_LL, 245 filter_y_vert_tap4, sizeof(filter_y_vert_tap4)); 246 vp_filter_set(res, VP_POLY4_C0_LL, 247 filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4)); 248 } 249 250 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) 251 { 252 struct mixer_resources *res = &ctx->mixer_res; 253 254 /* block update on vsync */ 255 mixer_reg_writemask(res, MXR_STATUS, enable ? 256 MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); 257 258 if (ctx->vp_enabled) 259 vp_reg_write(res, VP_SHADOW_UPDATE, enable ? 260 VP_SHADOW_UPDATE_ENABLE : 0); 261 } 262 263 static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height) 264 { 265 struct mixer_resources *res = &ctx->mixer_res; 266 u32 val; 267 268 /* choosing between interlace and progressive mode */ 269 val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE : 270 MXR_CFG_SCAN_PROGRESSIVE); 271 272 if (ctx->mxr_ver != MXR_VER_128_0_0_184) { 273 /* choosing between proper HD and SD mode */ 274 if (height <= 480) 275 val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD; 276 else if (height <= 576) 277 val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD; 278 else if (height <= 720) 279 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; 280 else if (height <= 1080) 281 val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD; 282 else 283 val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; 284 } 285 286 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK); 287 } 288 289 static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) 290 { 291 struct mixer_resources *res = &ctx->mixer_res; 292 u32 val; 293 294 if (height == 480) { 295 val = MXR_CFG_RGB601_0_255; 296 } else if (height == 576) { 297 val = MXR_CFG_RGB601_0_255; 298 } else if (height == 720) { 299 val = MXR_CFG_RGB709_16_235; 300 mixer_reg_write(res, MXR_CM_COEFF_Y, 301 (1 << 30) | (94 << 20) | (314 << 10) | 302 (32 << 0)); 303 mixer_reg_write(res, MXR_CM_COEFF_CB, 304 (972 << 20) | (851 << 10) | (225 << 0)); 305 mixer_reg_write(res, MXR_CM_COEFF_CR, 306 (225 << 20) | (820 << 10) | (1004 << 0)); 307 } else if (height == 1080) { 308 val = MXR_CFG_RGB709_16_235; 309 mixer_reg_write(res, MXR_CM_COEFF_Y, 310 (1 << 30) | (94 << 20) | (314 << 10) | 311 (32 << 0)); 312 mixer_reg_write(res, MXR_CM_COEFF_CB, 313 (972 << 20) | (851 << 10) | (225 << 0)); 314 mixer_reg_write(res, MXR_CM_COEFF_CR, 315 (225 << 20) | (820 << 10) | (1004 << 0)); 316 } else { 317 val = MXR_CFG_RGB709_16_235; 318 mixer_reg_write(res, MXR_CM_COEFF_Y, 319 (1 << 30) | (94 << 20) | (314 << 10) | 320 (32 << 0)); 321 mixer_reg_write(res, MXR_CM_COEFF_CB, 322 (972 << 20) | (851 << 10) | (225 << 0)); 323 mixer_reg_write(res, MXR_CM_COEFF_CR, 324 (225 << 20) | (820 << 10) | (1004 << 0)); 325 } 326 327 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); 328 } 329 330 static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable) 331 { 332 struct mixer_resources *res = &ctx->mixer_res; 333 u32 val = enable ? ~0 : 0; 334 335 switch (win) { 336 case 0: 337 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); 338 break; 339 case 1: 340 mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); 341 break; 342 case 2: 343 if (ctx->vp_enabled) { 344 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); 345 mixer_reg_writemask(res, MXR_CFG, val, 346 MXR_CFG_VP_ENABLE); 347 348 /* control blending of graphic layer 0 */ 349 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val, 350 MXR_GRP_CFG_BLEND_PRE_MUL | 351 MXR_GRP_CFG_PIXEL_BLEND_EN); 352 } 353 break; 354 } 355 } 356 357 static void mixer_run(struct mixer_context *ctx) 358 { 359 struct mixer_resources *res = &ctx->mixer_res; 360 361 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN); 362 363 mixer_regs_dump(ctx); 364 } 365 366 static void mixer_stop(struct mixer_context *ctx) 367 { 368 struct mixer_resources *res = &ctx->mixer_res; 369 int timeout = 20; 370 371 mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN); 372 373 while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) && 374 --timeout) 375 usleep_range(10000, 12000); 376 377 mixer_regs_dump(ctx); 378 } 379 380 static void vp_video_buffer(struct mixer_context *ctx, int win) 381 { 382 struct mixer_resources *res = &ctx->mixer_res; 383 unsigned long flags; 384 struct exynos_drm_plane *plane; 385 unsigned int buf_num = 1; 386 dma_addr_t luma_addr[2], chroma_addr[2]; 387 bool tiled_mode = false; 388 bool crcb_mode = false; 389 u32 val; 390 391 plane = &ctx->planes[win]; 392 393 switch (plane->pixel_format) { 394 case DRM_FORMAT_NV12: 395 crcb_mode = false; 396 buf_num = 2; 397 break; 398 /* TODO: single buffer format NV12, NV21 */ 399 default: 400 /* ignore pixel format at disable time */ 401 if (!plane->dma_addr[0]) 402 break; 403 404 DRM_ERROR("pixel format for vp is wrong [%d].\n", 405 plane->pixel_format); 406 return; 407 } 408 409 if (buf_num == 2) { 410 luma_addr[0] = plane->dma_addr[0]; 411 chroma_addr[0] = plane->dma_addr[1]; 412 } else { 413 luma_addr[0] = plane->dma_addr[0]; 414 chroma_addr[0] = plane->dma_addr[0] 415 + (plane->pitch * plane->fb_height); 416 } 417 418 if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) { 419 ctx->interlace = true; 420 if (tiled_mode) { 421 luma_addr[1] = luma_addr[0] + 0x40; 422 chroma_addr[1] = chroma_addr[0] + 0x40; 423 } else { 424 luma_addr[1] = luma_addr[0] + plane->pitch; 425 chroma_addr[1] = chroma_addr[0] + plane->pitch; 426 } 427 } else { 428 ctx->interlace = false; 429 luma_addr[1] = 0; 430 chroma_addr[1] = 0; 431 } 432 433 spin_lock_irqsave(&res->reg_slock, flags); 434 mixer_vsync_set_update(ctx, false); 435 436 /* interlace or progressive scan mode */ 437 val = (ctx->interlace ? ~0 : 0); 438 vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP); 439 440 /* setup format */ 441 val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12); 442 val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR); 443 vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); 444 445 /* setting size of input image */ 446 vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(plane->pitch) | 447 VP_IMG_VSIZE(plane->fb_height)); 448 /* chroma height has to reduced by 2 to avoid chroma distorions */ 449 vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(plane->pitch) | 450 VP_IMG_VSIZE(plane->fb_height / 2)); 451 452 vp_reg_write(res, VP_SRC_WIDTH, plane->src_width); 453 vp_reg_write(res, VP_SRC_HEIGHT, plane->src_height); 454 vp_reg_write(res, VP_SRC_H_POSITION, 455 VP_SRC_H_POSITION_VAL(plane->src_x)); 456 vp_reg_write(res, VP_SRC_V_POSITION, plane->src_y); 457 458 vp_reg_write(res, VP_DST_WIDTH, plane->crtc_width); 459 vp_reg_write(res, VP_DST_H_POSITION, plane->crtc_x); 460 if (ctx->interlace) { 461 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height / 2); 462 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y / 2); 463 } else { 464 vp_reg_write(res, VP_DST_HEIGHT, plane->crtc_height); 465 vp_reg_write(res, VP_DST_V_POSITION, plane->crtc_y); 466 } 467 468 vp_reg_write(res, VP_H_RATIO, plane->h_ratio); 469 vp_reg_write(res, VP_V_RATIO, plane->v_ratio); 470 471 vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE); 472 473 /* set buffer address to vp */ 474 vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]); 475 vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]); 476 vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); 477 vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]); 478 479 mixer_cfg_scan(ctx, plane->mode_height); 480 mixer_cfg_rgb_fmt(ctx, plane->mode_height); 481 mixer_cfg_layer(ctx, win, true); 482 mixer_run(ctx); 483 484 mixer_vsync_set_update(ctx, true); 485 spin_unlock_irqrestore(&res->reg_slock, flags); 486 487 vp_regs_dump(ctx); 488 } 489 490 static void mixer_layer_update(struct mixer_context *ctx) 491 { 492 struct mixer_resources *res = &ctx->mixer_res; 493 494 mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); 495 } 496 497 static int mixer_setup_scale(const struct exynos_drm_plane *plane, 498 unsigned int *x_ratio, unsigned int *y_ratio) 499 { 500 if (plane->crtc_width != plane->src_width) { 501 if (plane->crtc_width == 2 * plane->src_width) 502 *x_ratio = 1; 503 else 504 goto fail; 505 } 506 507 if (plane->crtc_height != plane->src_height) { 508 if (plane->crtc_height == 2 * plane->src_height) 509 *y_ratio = 1; 510 else 511 goto fail; 512 } 513 514 return 0; 515 516 fail: 517 DRM_DEBUG_KMS("only 2x width/height scaling of plane supported\n"); 518 return -ENOTSUPP; 519 } 520 521 static void mixer_graph_buffer(struct mixer_context *ctx, int win) 522 { 523 struct mixer_resources *res = &ctx->mixer_res; 524 unsigned long flags; 525 struct exynos_drm_plane *plane; 526 unsigned int x_ratio = 0, y_ratio = 0; 527 unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; 528 dma_addr_t dma_addr; 529 unsigned int fmt; 530 u32 val; 531 532 plane = &ctx->planes[win]; 533 534 #define RGB565 4 535 #define ARGB1555 5 536 #define ARGB4444 6 537 #define ARGB8888 7 538 539 switch (plane->bpp) { 540 case 16: 541 fmt = ARGB4444; 542 break; 543 case 32: 544 fmt = ARGB8888; 545 break; 546 default: 547 fmt = ARGB8888; 548 } 549 550 /* check if mixer supports requested scaling setup */ 551 if (mixer_setup_scale(plane, &x_ratio, &y_ratio)) 552 return; 553 554 dst_x_offset = plane->crtc_x; 555 dst_y_offset = plane->crtc_y; 556 557 /* converting dma address base and source offset */ 558 dma_addr = plane->dma_addr[0] 559 + (plane->src_x * plane->bpp >> 3) 560 + (plane->src_y * plane->pitch); 561 src_x_offset = 0; 562 src_y_offset = 0; 563 564 if (plane->scan_flag & DRM_MODE_FLAG_INTERLACE) 565 ctx->interlace = true; 566 else 567 ctx->interlace = false; 568 569 spin_lock_irqsave(&res->reg_slock, flags); 570 mixer_vsync_set_update(ctx, false); 571 572 /* setup format */ 573 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win), 574 MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK); 575 576 /* setup geometry */ 577 mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), 578 plane->pitch / (plane->bpp >> 3)); 579 580 /* setup display size */ 581 if (ctx->mxr_ver == MXR_VER_128_0_0_184 && 582 win == MIXER_DEFAULT_WIN) { 583 val = MXR_MXR_RES_HEIGHT(plane->mode_height); 584 val |= MXR_MXR_RES_WIDTH(plane->mode_width); 585 mixer_reg_write(res, MXR_RESOLUTION, val); 586 } 587 588 val = MXR_GRP_WH_WIDTH(plane->src_width); 589 val |= MXR_GRP_WH_HEIGHT(plane->src_height); 590 val |= MXR_GRP_WH_H_SCALE(x_ratio); 591 val |= MXR_GRP_WH_V_SCALE(y_ratio); 592 mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); 593 594 /* setup offsets in source image */ 595 val = MXR_GRP_SXY_SX(src_x_offset); 596 val |= MXR_GRP_SXY_SY(src_y_offset); 597 mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val); 598 599 /* setup offsets in display image */ 600 val = MXR_GRP_DXY_DX(dst_x_offset); 601 val |= MXR_GRP_DXY_DY(dst_y_offset); 602 mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val); 603 604 /* set buffer address to mixer */ 605 mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr); 606 607 mixer_cfg_scan(ctx, plane->mode_height); 608 mixer_cfg_rgb_fmt(ctx, plane->mode_height); 609 mixer_cfg_layer(ctx, win, true); 610 611 /* layer update mandatory for mixer 16.0.33.0 */ 612 if (ctx->mxr_ver == MXR_VER_16_0_33_0 || 613 ctx->mxr_ver == MXR_VER_128_0_0_184) 614 mixer_layer_update(ctx); 615 616 mixer_run(ctx); 617 618 mixer_vsync_set_update(ctx, true); 619 spin_unlock_irqrestore(&res->reg_slock, flags); 620 } 621 622 static void vp_win_reset(struct mixer_context *ctx) 623 { 624 struct mixer_resources *res = &ctx->mixer_res; 625 int tries = 100; 626 627 vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING); 628 for (tries = 100; tries; --tries) { 629 /* waiting until VP_SRESET_PROCESSING is 0 */ 630 if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) 631 break; 632 usleep_range(10000, 12000); 633 } 634 WARN(tries == 0, "failed to reset Video Processor\n"); 635 } 636 637 static void mixer_win_reset(struct mixer_context *ctx) 638 { 639 struct mixer_resources *res = &ctx->mixer_res; 640 unsigned long flags; 641 u32 val; /* value stored to register */ 642 643 spin_lock_irqsave(&res->reg_slock, flags); 644 mixer_vsync_set_update(ctx, false); 645 646 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK); 647 648 /* set output in RGB888 mode */ 649 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK); 650 651 /* 16 beat burst in DMA */ 652 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST, 653 MXR_STATUS_BURST_MASK); 654 655 /* setting default layer priority: layer1 > layer0 > video 656 * because typical usage scenario would be 657 * layer1 - OSD 658 * layer0 - framebuffer 659 * video - video overlay 660 */ 661 val = MXR_LAYER_CFG_GRP1_VAL(3); 662 val |= MXR_LAYER_CFG_GRP0_VAL(2); 663 if (ctx->vp_enabled) 664 val |= MXR_LAYER_CFG_VP_VAL(1); 665 mixer_reg_write(res, MXR_LAYER_CFG, val); 666 667 /* setting background color */ 668 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); 669 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); 670 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); 671 672 /* setting graphical layers */ 673 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */ 674 val |= MXR_GRP_CFG_WIN_BLEND_EN; 675 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */ 676 677 /* Don't blend layer 0 onto the mixer background */ 678 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val); 679 680 /* Blend layer 1 into layer 0 */ 681 val |= MXR_GRP_CFG_BLEND_PRE_MUL; 682 val |= MXR_GRP_CFG_PIXEL_BLEND_EN; 683 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val); 684 685 /* setting video layers */ 686 val = MXR_GRP_CFG_ALPHA_VAL(0); 687 mixer_reg_write(res, MXR_VIDEO_CFG, val); 688 689 if (ctx->vp_enabled) { 690 /* configuration of Video Processor Registers */ 691 vp_win_reset(ctx); 692 vp_default_filter(res); 693 } 694 695 /* disable all layers */ 696 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE); 697 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE); 698 if (ctx->vp_enabled) 699 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE); 700 701 mixer_vsync_set_update(ctx, true); 702 spin_unlock_irqrestore(&res->reg_slock, flags); 703 } 704 705 static irqreturn_t mixer_irq_handler(int irq, void *arg) 706 { 707 struct mixer_context *ctx = arg; 708 struct mixer_resources *res = &ctx->mixer_res; 709 u32 val, base, shadow; 710 711 spin_lock(&res->reg_slock); 712 713 /* read interrupt status for handling and clearing flags for VSYNC */ 714 val = mixer_reg_read(res, MXR_INT_STATUS); 715 716 /* handling VSYNC */ 717 if (val & MXR_INT_STATUS_VSYNC) { 718 /* interlace scan need to check shadow register */ 719 if (ctx->interlace) { 720 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0)); 721 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0)); 722 if (base != shadow) 723 goto out; 724 725 base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1)); 726 shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1)); 727 if (base != shadow) 728 goto out; 729 } 730 731 drm_handle_vblank(ctx->drm_dev, ctx->pipe); 732 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); 733 734 /* set wait vsync event to zero and wake up queue. */ 735 if (atomic_read(&ctx->wait_vsync_event)) { 736 atomic_set(&ctx->wait_vsync_event, 0); 737 wake_up(&ctx->wait_vsync_queue); 738 } 739 } 740 741 out: 742 /* clear interrupts */ 743 if (~val & MXR_INT_EN_VSYNC) { 744 /* vsync interrupt use different bit for read and clear */ 745 val &= ~MXR_INT_EN_VSYNC; 746 val |= MXR_INT_CLEAR_VSYNC; 747 } 748 mixer_reg_write(res, MXR_INT_STATUS, val); 749 750 spin_unlock(&res->reg_slock); 751 752 return IRQ_HANDLED; 753 } 754 755 static int mixer_resources_init(struct mixer_context *mixer_ctx) 756 { 757 struct device *dev = &mixer_ctx->pdev->dev; 758 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; 759 struct resource *res; 760 int ret; 761 762 spin_lock_init(&mixer_res->reg_slock); 763 764 mixer_res->mixer = devm_clk_get(dev, "mixer"); 765 if (IS_ERR(mixer_res->mixer)) { 766 dev_err(dev, "failed to get clock 'mixer'\n"); 767 return -ENODEV; 768 } 769 770 mixer_res->hdmi = devm_clk_get(dev, "hdmi"); 771 if (IS_ERR(mixer_res->hdmi)) { 772 dev_err(dev, "failed to get clock 'hdmi'\n"); 773 return PTR_ERR(mixer_res->hdmi); 774 } 775 776 mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); 777 if (IS_ERR(mixer_res->sclk_hdmi)) { 778 dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); 779 return -ENODEV; 780 } 781 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 0); 782 if (res == NULL) { 783 dev_err(dev, "get memory resource failed.\n"); 784 return -ENXIO; 785 } 786 787 mixer_res->mixer_regs = devm_ioremap(dev, res->start, 788 resource_size(res)); 789 if (mixer_res->mixer_regs == NULL) { 790 dev_err(dev, "register mapping failed.\n"); 791 return -ENXIO; 792 } 793 794 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_IRQ, 0); 795 if (res == NULL) { 796 dev_err(dev, "get interrupt resource failed.\n"); 797 return -ENXIO; 798 } 799 800 ret = devm_request_irq(dev, res->start, mixer_irq_handler, 801 0, "drm_mixer", mixer_ctx); 802 if (ret) { 803 dev_err(dev, "request interrupt failed.\n"); 804 return ret; 805 } 806 mixer_res->irq = res->start; 807 808 return 0; 809 } 810 811 static int vp_resources_init(struct mixer_context *mixer_ctx) 812 { 813 struct device *dev = &mixer_ctx->pdev->dev; 814 struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; 815 struct resource *res; 816 817 mixer_res->vp = devm_clk_get(dev, "vp"); 818 if (IS_ERR(mixer_res->vp)) { 819 dev_err(dev, "failed to get clock 'vp'\n"); 820 return -ENODEV; 821 } 822 823 if (mixer_ctx->has_sclk) { 824 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer"); 825 if (IS_ERR(mixer_res->sclk_mixer)) { 826 dev_err(dev, "failed to get clock 'sclk_mixer'\n"); 827 return -ENODEV; 828 } 829 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer"); 830 if (IS_ERR(mixer_res->mout_mixer)) { 831 dev_err(dev, "failed to get clock 'mout_mixer'\n"); 832 return -ENODEV; 833 } 834 835 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer) 836 clk_set_parent(mixer_res->mout_mixer, 837 mixer_res->sclk_hdmi); 838 } 839 840 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1); 841 if (res == NULL) { 842 dev_err(dev, "get memory resource failed.\n"); 843 return -ENXIO; 844 } 845 846 mixer_res->vp_regs = devm_ioremap(dev, res->start, 847 resource_size(res)); 848 if (mixer_res->vp_regs == NULL) { 849 dev_err(dev, "register mapping failed.\n"); 850 return -ENXIO; 851 } 852 853 return 0; 854 } 855 856 static int mixer_initialize(struct mixer_context *mixer_ctx, 857 struct drm_device *drm_dev) 858 { 859 int ret; 860 struct exynos_drm_private *priv; 861 priv = drm_dev->dev_private; 862 863 mixer_ctx->drm_dev = drm_dev; 864 mixer_ctx->pipe = priv->pipe++; 865 866 /* acquire resources: regs, irqs, clocks */ 867 ret = mixer_resources_init(mixer_ctx); 868 if (ret) { 869 DRM_ERROR("mixer_resources_init failed ret=%d\n", ret); 870 return ret; 871 } 872 873 if (mixer_ctx->vp_enabled) { 874 /* acquire vp resources: regs, irqs, clocks */ 875 ret = vp_resources_init(mixer_ctx); 876 if (ret) { 877 DRM_ERROR("vp_resources_init failed ret=%d\n", ret); 878 return ret; 879 } 880 } 881 882 if (!is_drm_iommu_supported(mixer_ctx->drm_dev)) 883 return 0; 884 885 return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev); 886 } 887 888 static void mixer_ctx_remove(struct mixer_context *mixer_ctx) 889 { 890 if (is_drm_iommu_supported(mixer_ctx->drm_dev)) 891 drm_iommu_detach_device(mixer_ctx->drm_dev, mixer_ctx->dev); 892 } 893 894 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) 895 { 896 struct mixer_context *mixer_ctx = crtc->ctx; 897 struct mixer_resources *res = &mixer_ctx->mixer_res; 898 899 if (!mixer_ctx->powered) { 900 mixer_ctx->int_en |= MXR_INT_EN_VSYNC; 901 return 0; 902 } 903 904 /* enable vsync interrupt */ 905 mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC, 906 MXR_INT_EN_VSYNC); 907 908 return 0; 909 } 910 911 static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) 912 { 913 struct mixer_context *mixer_ctx = crtc->ctx; 914 struct mixer_resources *res = &mixer_ctx->mixer_res; 915 916 /* disable vsync interrupt */ 917 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); 918 } 919 920 static void mixer_win_commit(struct exynos_drm_crtc *crtc, unsigned int win) 921 { 922 struct mixer_context *mixer_ctx = crtc->ctx; 923 924 DRM_DEBUG_KMS("win: %d\n", win); 925 926 mutex_lock(&mixer_ctx->mixer_mutex); 927 if (!mixer_ctx->powered) { 928 mutex_unlock(&mixer_ctx->mixer_mutex); 929 return; 930 } 931 mutex_unlock(&mixer_ctx->mixer_mutex); 932 933 if (win > 1 && mixer_ctx->vp_enabled) 934 vp_video_buffer(mixer_ctx, win); 935 else 936 mixer_graph_buffer(mixer_ctx, win); 937 938 mixer_ctx->planes[win].enabled = true; 939 } 940 941 static void mixer_win_disable(struct exynos_drm_crtc *crtc, unsigned int win) 942 { 943 struct mixer_context *mixer_ctx = crtc->ctx; 944 struct mixer_resources *res = &mixer_ctx->mixer_res; 945 unsigned long flags; 946 947 DRM_DEBUG_KMS("win: %d\n", win); 948 949 mutex_lock(&mixer_ctx->mixer_mutex); 950 if (!mixer_ctx->powered) { 951 mutex_unlock(&mixer_ctx->mixer_mutex); 952 mixer_ctx->planes[win].resume = false; 953 return; 954 } 955 mutex_unlock(&mixer_ctx->mixer_mutex); 956 957 spin_lock_irqsave(&res->reg_slock, flags); 958 mixer_vsync_set_update(mixer_ctx, false); 959 960 mixer_cfg_layer(mixer_ctx, win, false); 961 962 mixer_vsync_set_update(mixer_ctx, true); 963 spin_unlock_irqrestore(&res->reg_slock, flags); 964 965 mixer_ctx->planes[win].enabled = false; 966 } 967 968 static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc) 969 { 970 struct mixer_context *mixer_ctx = crtc->ctx; 971 int err; 972 973 mutex_lock(&mixer_ctx->mixer_mutex); 974 if (!mixer_ctx->powered) { 975 mutex_unlock(&mixer_ctx->mixer_mutex); 976 return; 977 } 978 mutex_unlock(&mixer_ctx->mixer_mutex); 979 980 err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe); 981 if (err < 0) { 982 DRM_DEBUG_KMS("failed to acquire vblank counter\n"); 983 return; 984 } 985 986 atomic_set(&mixer_ctx->wait_vsync_event, 1); 987 988 /* 989 * wait for MIXER to signal VSYNC interrupt or return after 990 * timeout which is set to 50ms (refresh rate of 20). 991 */ 992 if (!wait_event_timeout(mixer_ctx->wait_vsync_queue, 993 !atomic_read(&mixer_ctx->wait_vsync_event), 994 HZ/20)) 995 DRM_DEBUG_KMS("vblank wait timed out.\n"); 996 997 drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe); 998 } 999 1000 static void mixer_window_suspend(struct mixer_context *ctx) 1001 { 1002 struct exynos_drm_plane *plane; 1003 int i; 1004 1005 for (i = 0; i < MIXER_WIN_NR; i++) { 1006 plane = &ctx->planes[i]; 1007 plane->resume = plane->enabled; 1008 mixer_win_disable(ctx->crtc, i); 1009 } 1010 mixer_wait_for_vblank(ctx->crtc); 1011 } 1012 1013 static void mixer_window_resume(struct mixer_context *ctx) 1014 { 1015 struct exynos_drm_plane *plane; 1016 int i; 1017 1018 for (i = 0; i < MIXER_WIN_NR; i++) { 1019 plane = &ctx->planes[i]; 1020 plane->enabled = plane->resume; 1021 plane->resume = false; 1022 if (plane->enabled) 1023 mixer_win_commit(ctx->crtc, i); 1024 } 1025 } 1026 1027 static void mixer_poweron(struct mixer_context *ctx) 1028 { 1029 struct mixer_resources *res = &ctx->mixer_res; 1030 1031 mutex_lock(&ctx->mixer_mutex); 1032 if (ctx->powered) { 1033 mutex_unlock(&ctx->mixer_mutex); 1034 return; 1035 } 1036 1037 mutex_unlock(&ctx->mixer_mutex); 1038 1039 pm_runtime_get_sync(ctx->dev); 1040 1041 clk_prepare_enable(res->mixer); 1042 clk_prepare_enable(res->hdmi); 1043 if (ctx->vp_enabled) { 1044 clk_prepare_enable(res->vp); 1045 if (ctx->has_sclk) 1046 clk_prepare_enable(res->sclk_mixer); 1047 } 1048 1049 mutex_lock(&ctx->mixer_mutex); 1050 ctx->powered = true; 1051 mutex_unlock(&ctx->mixer_mutex); 1052 1053 mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); 1054 1055 mixer_reg_write(res, MXR_INT_EN, ctx->int_en); 1056 mixer_win_reset(ctx); 1057 1058 mixer_window_resume(ctx); 1059 } 1060 1061 static void mixer_poweroff(struct mixer_context *ctx) 1062 { 1063 struct mixer_resources *res = &ctx->mixer_res; 1064 1065 mutex_lock(&ctx->mixer_mutex); 1066 if (!ctx->powered) { 1067 mutex_unlock(&ctx->mixer_mutex); 1068 return; 1069 } 1070 mutex_unlock(&ctx->mixer_mutex); 1071 1072 mixer_stop(ctx); 1073 mixer_window_suspend(ctx); 1074 1075 ctx->int_en = mixer_reg_read(res, MXR_INT_EN); 1076 1077 mutex_lock(&ctx->mixer_mutex); 1078 ctx->powered = false; 1079 mutex_unlock(&ctx->mixer_mutex); 1080 1081 clk_disable_unprepare(res->hdmi); 1082 clk_disable_unprepare(res->mixer); 1083 if (ctx->vp_enabled) { 1084 clk_disable_unprepare(res->vp); 1085 if (ctx->has_sclk) 1086 clk_disable_unprepare(res->sclk_mixer); 1087 } 1088 1089 pm_runtime_put_sync(ctx->dev); 1090 } 1091 1092 static void mixer_dpms(struct exynos_drm_crtc *crtc, int mode) 1093 { 1094 switch (mode) { 1095 case DRM_MODE_DPMS_ON: 1096 mixer_poweron(crtc->ctx); 1097 break; 1098 case DRM_MODE_DPMS_STANDBY: 1099 case DRM_MODE_DPMS_SUSPEND: 1100 case DRM_MODE_DPMS_OFF: 1101 mixer_poweroff(crtc->ctx); 1102 break; 1103 default: 1104 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode); 1105 break; 1106 } 1107 } 1108 1109 /* Only valid for Mixer version 16.0.33.0 */ 1110 int mixer_check_mode(struct drm_display_mode *mode) 1111 { 1112 u32 w, h; 1113 1114 w = mode->hdisplay; 1115 h = mode->vdisplay; 1116 1117 DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n", 1118 mode->hdisplay, mode->vdisplay, mode->vrefresh, 1119 (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0); 1120 1121 if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) || 1122 (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) || 1123 (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080)) 1124 return 0; 1125 1126 return -EINVAL; 1127 } 1128 1129 static struct exynos_drm_crtc_ops mixer_crtc_ops = { 1130 .dpms = mixer_dpms, 1131 .enable_vblank = mixer_enable_vblank, 1132 .disable_vblank = mixer_disable_vblank, 1133 .wait_for_vblank = mixer_wait_for_vblank, 1134 .win_commit = mixer_win_commit, 1135 .win_disable = mixer_win_disable, 1136 }; 1137 1138 static struct mixer_drv_data exynos5420_mxr_drv_data = { 1139 .version = MXR_VER_128_0_0_184, 1140 .is_vp_enabled = 0, 1141 }; 1142 1143 static struct mixer_drv_data exynos5250_mxr_drv_data = { 1144 .version = MXR_VER_16_0_33_0, 1145 .is_vp_enabled = 0, 1146 }; 1147 1148 static struct mixer_drv_data exynos4212_mxr_drv_data = { 1149 .version = MXR_VER_0_0_0_16, 1150 .is_vp_enabled = 1, 1151 }; 1152 1153 static struct mixer_drv_data exynos4210_mxr_drv_data = { 1154 .version = MXR_VER_0_0_0_16, 1155 .is_vp_enabled = 1, 1156 .has_sclk = 1, 1157 }; 1158 1159 static struct platform_device_id mixer_driver_types[] = { 1160 { 1161 .name = "s5p-mixer", 1162 .driver_data = (unsigned long)&exynos4210_mxr_drv_data, 1163 }, { 1164 .name = "exynos5-mixer", 1165 .driver_data = (unsigned long)&exynos5250_mxr_drv_data, 1166 }, { 1167 /* end node */ 1168 } 1169 }; 1170 1171 static struct of_device_id mixer_match_types[] = { 1172 { 1173 .compatible = "samsung,exynos4210-mixer", 1174 .data = &exynos4210_mxr_drv_data, 1175 }, { 1176 .compatible = "samsung,exynos4212-mixer", 1177 .data = &exynos4212_mxr_drv_data, 1178 }, { 1179 .compatible = "samsung,exynos5-mixer", 1180 .data = &exynos5250_mxr_drv_data, 1181 }, { 1182 .compatible = "samsung,exynos5250-mixer", 1183 .data = &exynos5250_mxr_drv_data, 1184 }, { 1185 .compatible = "samsung,exynos5420-mixer", 1186 .data = &exynos5420_mxr_drv_data, 1187 }, { 1188 /* end node */ 1189 } 1190 }; 1191 MODULE_DEVICE_TABLE(of, mixer_match_types); 1192 1193 static int mixer_bind(struct device *dev, struct device *manager, void *data) 1194 { 1195 struct mixer_context *ctx = dev_get_drvdata(dev); 1196 struct drm_device *drm_dev = data; 1197 struct exynos_drm_plane *exynos_plane; 1198 enum drm_plane_type type; 1199 unsigned int zpos; 1200 int ret; 1201 1202 ret = mixer_initialize(ctx, drm_dev); 1203 if (ret) 1204 return ret; 1205 1206 for (zpos = 0; zpos < MIXER_WIN_NR; zpos++) { 1207 type = (zpos == MIXER_DEFAULT_WIN) ? DRM_PLANE_TYPE_PRIMARY : 1208 DRM_PLANE_TYPE_OVERLAY; 1209 ret = exynos_plane_init(drm_dev, &ctx->planes[zpos], 1210 1 << ctx->pipe, type, zpos); 1211 if (ret) 1212 return ret; 1213 } 1214 1215 exynos_plane = &ctx->planes[MIXER_DEFAULT_WIN]; 1216 ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base, 1217 ctx->pipe, EXYNOS_DISPLAY_TYPE_HDMI, 1218 &mixer_crtc_ops, ctx); 1219 if (IS_ERR(ctx->crtc)) { 1220 mixer_ctx_remove(ctx); 1221 ret = PTR_ERR(ctx->crtc); 1222 goto free_ctx; 1223 } 1224 1225 return 0; 1226 1227 free_ctx: 1228 devm_kfree(dev, ctx); 1229 return ret; 1230 } 1231 1232 static void mixer_unbind(struct device *dev, struct device *master, void *data) 1233 { 1234 struct mixer_context *ctx = dev_get_drvdata(dev); 1235 1236 mixer_ctx_remove(ctx); 1237 } 1238 1239 static const struct component_ops mixer_component_ops = { 1240 .bind = mixer_bind, 1241 .unbind = mixer_unbind, 1242 }; 1243 1244 static int mixer_probe(struct platform_device *pdev) 1245 { 1246 struct device *dev = &pdev->dev; 1247 struct mixer_drv_data *drv; 1248 struct mixer_context *ctx; 1249 int ret; 1250 1251 ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 1252 if (!ctx) { 1253 DRM_ERROR("failed to alloc mixer context.\n"); 1254 return -ENOMEM; 1255 } 1256 1257 mutex_init(&ctx->mixer_mutex); 1258 1259 if (dev->of_node) { 1260 const struct of_device_id *match; 1261 1262 match = of_match_node(mixer_match_types, dev->of_node); 1263 drv = (struct mixer_drv_data *)match->data; 1264 } else { 1265 drv = (struct mixer_drv_data *) 1266 platform_get_device_id(pdev)->driver_data; 1267 } 1268 1269 ctx->pdev = pdev; 1270 ctx->dev = dev; 1271 ctx->vp_enabled = drv->is_vp_enabled; 1272 ctx->has_sclk = drv->has_sclk; 1273 ctx->mxr_ver = drv->version; 1274 init_waitqueue_head(&ctx->wait_vsync_queue); 1275 atomic_set(&ctx->wait_vsync_event, 0); 1276 1277 platform_set_drvdata(pdev, ctx); 1278 1279 ret = exynos_drm_component_add(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC, 1280 EXYNOS_DISPLAY_TYPE_HDMI); 1281 if (ret) 1282 return ret; 1283 1284 ret = component_add(&pdev->dev, &mixer_component_ops); 1285 if (ret) { 1286 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC); 1287 return ret; 1288 } 1289 1290 pm_runtime_enable(dev); 1291 1292 return ret; 1293 } 1294 1295 static int mixer_remove(struct platform_device *pdev) 1296 { 1297 pm_runtime_disable(&pdev->dev); 1298 1299 component_del(&pdev->dev, &mixer_component_ops); 1300 exynos_drm_component_del(&pdev->dev, EXYNOS_DEVICE_TYPE_CRTC); 1301 1302 return 0; 1303 } 1304 1305 struct platform_driver mixer_driver = { 1306 .driver = { 1307 .name = "exynos-mixer", 1308 .owner = THIS_MODULE, 1309 .of_match_table = mixer_match_types, 1310 }, 1311 .probe = mixer_probe, 1312 .remove = mixer_remove, 1313 .id_table = mixer_driver_types, 1314 }; 1315