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