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