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