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