1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License version 2 and 5 * only version 2 as published by the Free Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 * 02110-1301, USA. 16 */ 17 18#include <linux/module.h> 19#include <linux/kernel.h> 20#include <linux/sched.h> 21#include <linux/time.h> 22#include <linux/init.h> 23#include <linux/interrupt.h> 24#include <linux/spinlock.h> 25#include <linux/hrtimer.h> 26#include <linux/clk.h> 27#include <mach/hardware.h> 28#include <linux/io.h> 29#include <linux/debugfs.h> 30#include <linux/fb.h> 31#include <msm_mdp.h> 32#include <linux/file.h> 33#include "android_pmem.h" 34#include <linux/major.h> 35#include <asm/system.h> 36#include <asm/mach-types.h> 37#include <linux/semaphore.h> 38#include <linux/uaccess.h> 39#include <linux/mutex.h> 40 41#include "mdp.h" 42#include "msm_fb.h" 43#include "mdp4.h" 44 45 46struct mdp4_overlay_ctrl { 47 struct mdp4_overlay_pipe plist[MDP4_MAX_OVERLAY_PIPE]; 48 struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE]; 49} mdp4_overlay_db; 50 51static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db; 52 53 54void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc) 55{ 56 uint32 dma2_cfg_reg; 57 58 dma2_cfg_reg = DMA_DITHER_EN; 59 60 if (mfd->fb_imgType == MDP_BGR_565) 61 dma2_cfg_reg |= DMA_PACK_PATTERN_BGR; 62 else 63 dma2_cfg_reg |= DMA_PACK_PATTERN_RGB; 64 65 66 if (mfd->panel_info.bpp == 18) { 67 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */ 68 DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; 69 } else if (mfd->panel_info.bpp == 16) { 70 dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */ 71 DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS; 72 } else { 73 dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */ 74 DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS; 75 } 76 77 if (lcdc) 78 dma2_cfg_reg |= DMA_PACK_ALIGN_MSB; 79 80 /* dma2 config register */ 81 MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg); 82 83} 84 85void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe) 86{ 87 88 /* dma_p source */ 89 MDP_OUTP(MDP_BASE + 0x90004, 90 (pipe->src_height << 16 | pipe->src_width)); 91 MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr); 92 MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride); 93 94 /* dma_p dest */ 95 MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x)); 96} 97 98#define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000 99#define MDP4_VG_PHASE_STEP_SHIFT 29 100 101static int mdp4_leading_0(uint32 num) 102{ 103 uint32 bit = 0x80000000; 104 int i; 105 106 for (i = 0; i < 32; i++) { 107 if (bit & num) 108 return i; 109 bit >>= 1; 110 } 111 112 return i; 113} 114 115static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst) 116{ 117 uint32 val; 118 int n; 119 120 n = mdp4_leading_0(src); 121 if (n > f_num) 122 n = f_num; 123 val = src << n; /* maximum to reduce lose of resolution */ 124 val /= dst; 125 if (n < f_num) { 126 n = f_num - n; 127 val <<= n; 128 } 129 130 return val; 131} 132 133static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe) 134{ 135 136 pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT; 137 pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT; 138 139 if (pipe->dst_h && pipe->src_h != pipe->dst_h) { 140 if (pipe->dst_h >= pipe->src_h * 8) /* too much */ 141 return; 142 pipe->op_mode |= MDP4_OP_SCALEY_EN; 143 144 if (pipe->pipe_type == OVERLAY_TYPE_VG) { 145 if (pipe->dst_h <= (pipe->src_h / 4)) 146 pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE; 147 else 148 pipe->op_mode |= MDP4_OP_SCALEY_FIR; 149 } 150 151 pipe->phasey_step = mdp4_scale_phase_step(29, 152 pipe->src_h, pipe->dst_h); 153 } 154 155 if (pipe->dst_w && pipe->src_w != pipe->dst_w) { 156 if (pipe->dst_w >= pipe->src_w * 8) /* too much */ 157 return; 158 pipe->op_mode |= MDP4_OP_SCALEX_EN; 159 160 if (pipe->pipe_type == OVERLAY_TYPE_VG) { 161 if (pipe->dst_w <= (pipe->src_w / 4)) 162 pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE; 163 else 164 pipe->op_mode |= MDP4_OP_SCALEY_FIR; 165 } 166 167 pipe->phasex_step = mdp4_scale_phase_step(29, 168 pipe->src_w, pipe->dst_w); 169 } 170} 171 172void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe) 173{ 174 char *rgb_base; 175 uint32 src_size, src_xy, dst_size, dst_xy; 176 uint32 format, pattern; 177 178 rgb_base = MDP_BASE + MDP4_RGB_BASE; 179 rgb_base += (MDP4_RGB_OFF * pipe->pipe_num); 180 181 src_size = ((pipe->src_h << 16) | pipe->src_w); 182 src_xy = ((pipe->src_y << 16) | pipe->src_x); 183 dst_size = ((pipe->dst_h << 16) | pipe->dst_w); 184 dst_xy = ((pipe->dst_y << 16) | pipe->dst_x); 185 186 format = mdp4_overlay_format(pipe); 187 pattern = mdp4_overlay_unpack_pattern(pipe); 188 189 pipe->op_mode |= MDP4_OP_IGC_LUT_EN; 190 191 mdp4_scale_setup(pipe); 192 193 outpdw(rgb_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */ 194 outpdw(rgb_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */ 195 outpdw(rgb_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */ 196 outpdw(rgb_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */ 197 198 outpdw(rgb_base + 0x0010, pipe->srcp0_addr); 199 outpdw(rgb_base + 0x0040, pipe->srcp0_ystride); 200 201 outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */ 202 outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */ 203 outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */ 204 outpdw(rgb_base + 0x005c, pipe->phasex_step); 205 outpdw(rgb_base + 0x0060, pipe->phasey_step); 206 207 /* 16 bytes-burst x 3 req <= 48 bytes */ 208 outpdw(rgb_base + 0x1004, 0xc2); /* MDP_RGB_FETCH_CFG */ 209} 210 211void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe) 212{ 213 char *vg_base; 214 uint32 frame_size, src_size, src_xy, dst_size, dst_xy; 215 uint32 format, pattern; 216 217 vg_base = MDP_BASE + MDP4_VIDEO_BASE; 218 vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num); 219 220 frame_size = ((pipe->src_height << 16) | pipe->src_width); 221 src_size = ((pipe->src_h << 16) | pipe->src_w); 222 src_xy = ((pipe->src_y << 16) | pipe->src_x); 223 dst_size = ((pipe->dst_h << 16) | pipe->dst_w); 224 dst_xy = ((pipe->dst_y << 16) | pipe->dst_x); 225 226 format = mdp4_overlay_format(pipe); 227 pattern = mdp4_overlay_unpack_pattern(pipe); 228 229 pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR | 230 MDP4_OP_IGC_LUT_EN); 231 232 mdp4_scale_setup(pipe); 233 234 outpdw(vg_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */ 235 outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */ 236 outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */ 237 outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */ 238 outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */ 239 240 /* luma component plane */ 241 outpdw(vg_base + 0x0010, pipe->srcp0_addr); 242 243 /* chroma component plane */ 244 outpdw(vg_base + 0x0014, pipe->srcp1_addr); 245 246 outpdw(vg_base + 0x0040, 247 pipe->srcp1_ystride << 16 | pipe->srcp0_ystride); 248 249 outpdw(vg_base + 0x0050, format); /* MDP_RGB_SRC_FORMAT */ 250 outpdw(vg_base + 0x0054, pattern); /* MDP_RGB_SRC_UNPACK_PATTERN */ 251 outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */ 252 outpdw(vg_base + 0x005c, pipe->phasex_step); 253 outpdw(vg_base + 0x0060, pipe->phasey_step); 254 255 if (pipe->op_mode & MDP4_OP_DITHER_EN) { 256 outpdw(vg_base + 0x0068, 257 pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit); 258 } 259 260 /* 16 bytes-burst x 3 req <= 48 bytes */ 261 outpdw(vg_base + 0x1004, 0xc2); /* MDP_VG_FETCH_CFG */ 262} 263 264int mdp4_overlay_format2type(uint32 format) 265{ 266 switch (format) { 267 case MDP_RGB_565: 268 case MDP_RGB_888: 269 case MDP_BGR_565: 270 case MDP_ARGB_8888: 271 case MDP_RGBA_8888: 272 case MDP_BGRA_8888: 273 return OVERLAY_TYPE_RGB; 274 case MDP_YCRYCB_H2V1: 275 case MDP_Y_CRCB_H2V1: 276 case MDP_Y_CBCR_H2V1: 277 case MDP_Y_CRCB_H2V2: 278 case MDP_Y_CBCR_H2V2: 279 case MDP_Y_CBCR_H2V2_TILE: 280 case MDP_Y_CRCB_H2V2_TILE: 281 return OVERLAY_TYPE_VG; 282 default: 283 return -ERANGE; 284 } 285 286} 287 288#define C3_ALPHA 3 /* alpha */ 289#define C2_R_Cr 2 /* R/Cr */ 290#define C1_B_Cb 1 /* B/Cb */ 291#define C0_G_Y 0 /* G/luma */ 292 293int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe) 294{ 295 switch (pipe->src_format) { 296 case MDP_RGB_565: 297 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; 298 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; 299 pipe->a_bit = 0; 300 pipe->r_bit = 1; /* R, 5 bits */ 301 pipe->b_bit = 1; /* B, 5 bits */ 302 pipe->g_bit = 2; /* G, 6 bits */ 303 pipe->alpha_enable = 0; 304 pipe->unpack_tight = 1; 305 pipe->unpack_align_msb = 0; 306 pipe->unpack_count = 2; 307 pipe->element2 = C2_R_Cr; /* R */ 308 pipe->element1 = C0_G_Y; /* G */ 309 pipe->element0 = C1_B_Cb; /* B */ 310 pipe->bpp = 2; /* 2 bpp */ 311 break; 312 case MDP_RGB_888: 313 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; 314 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; 315 pipe->a_bit = 0; 316 pipe->r_bit = 3; /* R, 8 bits */ 317 pipe->b_bit = 3; /* B, 8 bits */ 318 pipe->g_bit = 3; /* G, 8 bits */ 319 pipe->alpha_enable = 0; 320 pipe->unpack_tight = 1; 321 pipe->unpack_align_msb = 0; 322 pipe->unpack_count = 2; 323 pipe->element2 = C2_R_Cr; /* R */ 324 pipe->element1 = C0_G_Y; /* G */ 325 pipe->element0 = C1_B_Cb; /* B */ 326 pipe->bpp = 3; /* 3 bpp */ 327 break; 328 case MDP_BGR_565: 329 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; 330 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; 331 pipe->a_bit = 0; 332 pipe->r_bit = 1; /* R, 5 bits */ 333 pipe->b_bit = 1; /* B, 5 bits */ 334 pipe->g_bit = 2; /* G, 6 bits */ 335 pipe->alpha_enable = 0; 336 pipe->unpack_tight = 1; 337 pipe->unpack_align_msb = 0; 338 pipe->unpack_count = 2; 339 pipe->element2 = C1_B_Cb; /* B */ 340 pipe->element1 = C0_G_Y; /* G */ 341 pipe->element0 = C2_R_Cr; /* R */ 342 pipe->bpp = 2; /* 2 bpp */ 343 break; 344 case MDP_ARGB_8888: 345 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; 346 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; 347 pipe->a_bit = 3; /* alpha, 4 bits */ 348 pipe->r_bit = 3; /* R, 8 bits */ 349 pipe->b_bit = 3; /* B, 8 bits */ 350 pipe->g_bit = 3; /* G, 8 bits */ 351 pipe->alpha_enable = 1; 352 pipe->unpack_tight = 1; 353 pipe->unpack_align_msb = 0; 354 pipe->unpack_count = 3; 355 pipe->element3 = C3_ALPHA; /* alpha */ 356 pipe->element2 = C2_R_Cr; /* R */ 357 pipe->element1 = C0_G_Y; /* G */ 358 pipe->element0 = C1_B_Cb; /* B */ 359 pipe->bpp = 4; /* 4 bpp */ 360 break; 361 case MDP_RGBA_8888: 362 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; 363 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; 364 pipe->a_bit = 3; /* alpha, 4 bits */ 365 pipe->r_bit = 3; /* R, 8 bits */ 366 pipe->b_bit = 3; /* B, 8 bits */ 367 pipe->g_bit = 3; /* G, 8 bits */ 368 pipe->alpha_enable = 1; 369 pipe->unpack_tight = 1; 370 pipe->unpack_align_msb = 0; 371 pipe->unpack_count = 3; 372 pipe->element3 = C2_R_Cr; /* R */ 373 pipe->element2 = C0_G_Y; /* G */ 374 pipe->element1 = C1_B_Cb; /* B */ 375 pipe->element0 = C3_ALPHA; /* alpha */ 376 pipe->bpp = 4; /* 4 bpp */ 377 break; 378 case MDP_BGRA_8888: 379 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; 380 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; 381 pipe->a_bit = 3; /* alpha, 4 bits */ 382 pipe->r_bit = 3; /* R, 8 bits */ 383 pipe->b_bit = 3; /* B, 8 bits */ 384 pipe->g_bit = 3; /* G, 8 bits */ 385 pipe->alpha_enable = 1; 386 pipe->unpack_tight = 1; 387 pipe->unpack_align_msb = 0; 388 pipe->unpack_count = 3; 389 pipe->element3 = C1_B_Cb; /* B */ 390 pipe->element2 = C0_G_Y; /* G */ 391 pipe->element1 = C2_R_Cr; /* R */ 392 pipe->element0 = C3_ALPHA; /* alpha */ 393 pipe->bpp = 4; /* 4 bpp */ 394 break; 395 case MDP_YCRYCB_H2V1: 396 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; 397 pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; 398 pipe->a_bit = 0; /* alpha, 4 bits */ 399 pipe->r_bit = 3; /* R, 8 bits */ 400 pipe->b_bit = 3; /* B, 8 bits */ 401 pipe->g_bit = 3; /* G, 8 bits */ 402 pipe->alpha_enable = 0; 403 pipe->unpack_tight = 1; 404 pipe->unpack_align_msb = 0; 405 pipe->unpack_count = 3; 406 pipe->element3 = C0_G_Y; /* G */ 407 pipe->element2 = C2_R_Cr; /* R */ 408 pipe->element1 = C0_G_Y; /* G */ 409 pipe->element0 = C1_B_Cb; /* B */ 410 pipe->bpp = 2; /* 2 bpp */ 411 pipe->chroma_sample = MDP4_CHROMA_H2V1; 412 break; 413 case MDP_Y_CRCB_H2V1: 414 case MDP_Y_CBCR_H2V1: 415 case MDP_Y_CRCB_H2V2: 416 case MDP_Y_CBCR_H2V2: 417 pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; 418 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR; 419 pipe->a_bit = 0; 420 pipe->r_bit = 3; /* R, 8 bits */ 421 pipe->b_bit = 3; /* B, 8 bits */ 422 pipe->g_bit = 3; /* G, 8 bits */ 423 pipe->alpha_enable = 0; 424 pipe->unpack_tight = 1; 425 pipe->unpack_align_msb = 0; 426 pipe->unpack_count = 1; /* 2 */ 427 pipe->element3 = C0_G_Y; /* not used */ 428 pipe->element2 = C0_G_Y; /* not used */ 429 if (pipe->src_format == MDP_Y_CRCB_H2V1) { 430 pipe->element1 = C2_R_Cr; /* R */ 431 pipe->element0 = C1_B_Cb; /* B */ 432 pipe->chroma_sample = MDP4_CHROMA_H2V1; 433 } else if (pipe->src_format == MDP_Y_CBCR_H2V1) { 434 pipe->element1 = C1_B_Cb; /* B */ 435 pipe->element0 = C2_R_Cr; /* R */ 436 pipe->chroma_sample = MDP4_CHROMA_H2V1; 437 } else if (pipe->src_format == MDP_Y_CRCB_H2V2) { 438 pipe->element1 = C2_R_Cr; /* R */ 439 pipe->element0 = C1_B_Cb; /* B */ 440 pipe->chroma_sample = MDP4_CHROMA_420; 441 } else if (pipe->src_format == MDP_Y_CBCR_H2V2) { 442 pipe->element1 = C1_B_Cb; /* B */ 443 pipe->element0 = C2_R_Cr; /* R */ 444 pipe->chroma_sample = MDP4_CHROMA_420; 445 } 446 pipe->bpp = 2; /* 2 bpp */ 447 break; 448 case MDP_Y_CBCR_H2V2_TILE: 449 case MDP_Y_CRCB_H2V2_TILE: 450 pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE; 451 pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR; 452 pipe->a_bit = 0; 453 pipe->r_bit = 3; /* R, 8 bits */ 454 pipe->b_bit = 3; /* B, 8 bits */ 455 pipe->g_bit = 3; /* G, 8 bits */ 456 pipe->alpha_enable = 0; 457 pipe->unpack_tight = 1; 458 pipe->unpack_align_msb = 0; 459 pipe->unpack_count = 1; /* 2 */ 460 pipe->element3 = C0_G_Y; /* not used */ 461 pipe->element2 = C0_G_Y; /* not used */ 462 if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) { 463 pipe->element1 = C2_R_Cr; /* R */ 464 pipe->element0 = C1_B_Cb; /* B */ 465 pipe->chroma_sample = MDP4_CHROMA_420; 466 } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) { 467 pipe->element1 = C1_B_Cb; /* B */ 468 pipe->element0 = C2_R_Cr; /* R */ 469 pipe->chroma_sample = MDP4_CHROMA_420; 470 } 471 pipe->bpp = 2; /* 2 bpp */ 472 break; 473 default: 474 /* not likely */ 475 return -ERANGE; 476 } 477 478 return 0; 479} 480 481/* 482 * color_key_convert: output with 12 bits color key 483 */ 484static uint32 color_key_convert(int start, int num, uint32 color) 485{ 486 487 uint32 data; 488 489 data = (color >> start) & ((1 << num) - 1); 490 491 if (num == 5) 492 data = (data << 7) + (data << 2) + (data >> 3); 493 else if (num == 6) 494 data = (data << 6) + data; 495 else /* 8 bits */ 496 data = (data << 4) + (data >> 4); 497 498 return data; 499 500} 501 502void transp_color_key(int format, uint32 transp, 503 uint32 *c0, uint32 *c1, uint32 *c2) 504{ 505 int b_start, g_start, r_start; 506 int b_num, g_num, r_num; 507 508 switch (format) { 509 case MDP_RGB_565: 510 b_start = 0; 511 g_start = 5; 512 r_start = 11; 513 r_num = 5; 514 g_num = 6; 515 b_num = 5; 516 break; 517 case MDP_RGB_888: 518 case MDP_XRGB_8888: 519 case MDP_ARGB_8888: 520 b_start = 0; 521 g_start = 8; 522 r_start = 16; 523 r_num = 8; 524 g_num = 8; 525 b_num = 8; 526 break; 527 case MDP_BGR_565: 528 b_start = 11; 529 g_start = 5; 530 r_start = 0; 531 r_num = 5; 532 g_num = 6; 533 b_num = 5; 534 break; 535 case MDP_Y_CBCR_H2V2: 536 case MDP_Y_CBCR_H2V1: 537 b_start = 8; 538 g_start = 16; 539 r_start = 0; 540 r_num = 8; 541 g_num = 8; 542 b_num = 8; 543 break; 544 case MDP_Y_CRCB_H2V2: 545 case MDP_Y_CRCB_H2V1: 546 b_start = 0; 547 g_start = 16; 548 r_start = 8; 549 r_num = 8; 550 g_num = 8; 551 b_num = 8; 552 break; 553 default: 554 b_start = 0; 555 g_start = 8; 556 r_start = 16; 557 r_num = 8; 558 g_num = 8; 559 b_num = 8; 560 break; 561 } 562 563 *c0 = color_key_convert(g_start, g_num, transp); 564 *c1 = color_key_convert(b_start, b_num, transp); 565 *c2 = color_key_convert(r_start, r_num, transp); 566} 567 568uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe) 569{ 570 uint32 format; 571 572 format = 0; 573 574 if (pipe->solid_fill) 575 format |= MDP4_FORMAT_SOLID_FILL; 576 577 if (pipe->unpack_align_msb) 578 format |= MDP4_FORMAT_UNPACK_ALIGN_MSB; 579 580 if (pipe->unpack_tight) 581 format |= MDP4_FORMAT_UNPACK_TIGHT; 582 583 if (pipe->alpha_enable) 584 format |= MDP4_FORMAT_ALPHA_ENABLE; 585 586 format |= (pipe->unpack_count << 13); 587 format |= ((pipe->bpp - 1) << 9); 588 format |= (pipe->a_bit << 6); 589 format |= (pipe->r_bit << 4); 590 format |= (pipe->b_bit << 2); 591 format |= pipe->g_bit; 592 593 format |= (pipe->frame_format << 29); 594 595 if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) { 596 /* video/graphic */ 597 format |= (pipe->fetch_plane << 19); 598 format |= (pipe->chroma_site << 28); 599 format |= (pipe->chroma_sample << 26); 600 } 601 602 return format; 603} 604 605uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe) 606{ 607 return (pipe->element3 << 24) | (pipe->element2 << 16) | 608 (pipe->element1 << 8) | pipe->element0; 609} 610 611void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe) 612{ 613 uint32 data; 614 char *overlay_base; 615 616 if (pipe->mixer_num == MDP4_MIXER1) 617 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ 618 else 619 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ 620 621 /* MDP_OVERLAYPROC_CFG */ 622 outpdw(overlay_base + 0x0004, 0x01); /* directout */ 623 data = pipe->src_height; 624 data <<= 16; 625 data |= pipe->src_width; 626 outpdw(overlay_base + 0x0008, data); /* ROI, height + width */ 627 outpdw(overlay_base + 0x000c, pipe->srcp0_addr); 628 outpdw(overlay_base + 0x0010, pipe->srcp0_ystride); 629 outpdw(overlay_base + 0x0014, 0x4); /* GC_LUT_EN, 888 */ 630} 631 632int mdp4_overlay_active(int mixer) 633{ 634 uint32 data, mask, i; 635 int p1, p2; 636 637 data = inpdw(MDP_BASE + 0x10100); 638 p1 = 0; 639 p2 = 0; 640 for (i = 0; i < 8; i++) { 641 mask = data & 0x0f; 642 if (mask) { 643 if (mask <= 4) 644 p1++; 645 else 646 p2++; 647 } 648 data >>= 4; 649 } 650 651 if (mixer) 652 return p2; 653 else 654 return p1; 655} 656 657void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe) 658{ 659 uint32 data, mask, snum, stage, mixer; 660 661 stage = pipe->mixer_stage; 662 mixer = pipe->mixer_num; 663 664 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */ 665 data = inpdw(MDP_BASE + 0x10100); 666 667 if (mixer == MDP4_MIXER1) 668 stage += 8; 669 670 if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */ 671 snum = 0; 672 snum += (4 * pipe->pipe_num); 673 } else { 674 snum = 8; 675 snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */ 676 } 677 678 mask = 0x0f; 679 mask <<= snum; 680 stage <<= snum; 681 data &= ~mask; /* clear old bits */ 682 683 data |= stage; 684 685 outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */ 686 687 data = inpdw(MDP_BASE + 0x10100); 688 689 ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */ 690} 691 692void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe) 693{ 694 uint32 data, mask, snum, stage, mixer; 695 696 stage = pipe->mixer_stage; 697 mixer = pipe->mixer_num; 698 699 if (pipe != ctrl->stage[mixer][stage]) /* not runing */ 700 return; 701 702 /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */ 703 data = inpdw(MDP_BASE + 0x10100); 704 705 if (mixer == MDP4_MIXER1) 706 stage += 8; 707 708 if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */ 709 snum = 0; 710 snum += (4 * pipe->pipe_num); 711 } else { 712 snum = 8; 713 snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */ 714 } 715 716 mask = 0x0f; 717 mask <<= snum; 718 data &= ~mask; /* clear old bits */ 719 720 outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */ 721 722 data = inpdw(MDP_BASE + 0x10100); 723 724 ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */ 725} 726 727void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe) 728{ 729 unsigned char *overlay_base; 730 uint32 c0, c1, c2, blend_op; 731 int off; 732 733 if (pipe->mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */ 734 overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ 735 else 736 overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ 737 738 /* stage 0 to stage 2 */ 739 off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0); 740 741 blend_op = 0; 742 if (pipe->alpha_enable) /* ARGB */ 743 blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL | 744 MDP4_BLEND_BG_ALPHA_FG_PIXEL; 745 else 746 blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST | 747 MDP4_BLEND_FG_ALPHA_FG_CONST); 748 749 750 if (pipe->alpha_enable == 0) { /* not ARGB */ 751 if (pipe->is_fg) { 752 outpdw(overlay_base + off + 0x108, pipe->alpha); 753 outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha); 754 } else { 755 outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha); 756 outpdw(overlay_base + off + 0x10c, pipe->alpha); 757 } 758 } 759 760 if (pipe->transp != MDP_TRANSP_NOP) { 761 transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2); 762 if (pipe->is_fg) { 763 blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */ 764 /* lower limit */ 765 if (c0 > 0x10) 766 c0 -= 0x10; 767 if (c1 > 0x10) 768 c1 -= 0x10; 769 if (c2 > 0x10) 770 c2 -= 0x10; 771 outpdw(overlay_base + off + 0x110, 772 (c1 << 16 | c0));/* low */ 773 outpdw(overlay_base + off + 0x114, c2);/* low */ 774 /* upper limit */ 775 if ((c0 + 0x20) < 0x0fff) 776 c0 += 0x20; 777 else 778 c0 = 0x0fff; 779 if ((c1 + 0x20) < 0x0fff) 780 c1 += 0x20; 781 else 782 c1 = 0x0fff; 783 if ((c2 + 0x20) < 0x0fff) 784 c2 += 0x20; 785 else 786 c2 = 0x0fff; 787 outpdw(overlay_base + off + 0x118, 788 (c1 << 16 | c0));/* high */ 789 outpdw(overlay_base + off + 0x11c, c2);/* high */ 790 } else { 791 blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */ 792 /* lower limit */ 793 if (c0 > 0x10) 794 c0 -= 0x10; 795 if (c1 > 0x10) 796 c1 -= 0x10; 797 if (c2 > 0x10) 798 c2 -= 0x10; 799 outpdw(overlay_base + 0x180, 800 (c1 << 16 | c0));/* low */ 801 outpdw(overlay_base + 0x184, c2);/* low */ 802 /* upper limit */ 803 if ((c0 + 0x20) < 0x0fff) 804 c0 += 0x20; 805 else 806 c0 = 0x0fff; 807 if ((c1 + 0x20) < 0x0fff) 808 c1 += 0x20; 809 else 810 c1 = 0x0fff; 811 if ((c2 + 0x20) < 0x0fff) 812 c2 += 0x20; 813 else 814 c2 = 0x0fff; 815 outpdw(overlay_base + 0x188, 816 (c1 << 16 | c0));/* high */ 817 outpdw(overlay_base + 0x18c, c2);/* high */ 818 } 819 } 820 outpdw(overlay_base + off + 0x104, blend_op); 821} 822 823void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all) 824{ 825 uint32 bits = 0; 826 827 if (pipe->mixer_num == MDP4_MIXER1) 828 bits |= 0x02; 829 else 830 bits |= 0x01; 831 832 if (all) { 833 if (pipe->pipe_type == OVERLAY_TYPE_RGB) { 834 if (pipe->pipe_num == OVERLAY_PIPE_RGB2) 835 bits |= 0x20; 836 else 837 bits |= 0x10; 838 } else { 839 if (pipe->pipe_num == OVERLAY_PIPE_VG2) 840 bits |= 0x08; 841 else 842 bits |= 0x04; 843 } 844 } 845 846 outpdw(MDP_BASE + 0x18000, bits); /* MDP_OVERLAY_REG_FLUSH */ 847 848 while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */ 849 ; 850} 851 852struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx) 853{ 854 struct mdp4_overlay_pipe *pipe; 855 856 if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE) 857 return NULL; 858 859 pipe = &ctrl->plist[ndx - 1]; /* ndx start from 1 */ 860 861 if (pipe->pipe_ndx == 0) 862 return NULL; 863 864 return pipe; 865} 866 867struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void) 868{ 869 int i; 870 struct mdp4_overlay_pipe *pipe; 871 872 pipe = &ctrl->plist[0]; 873 for (i = 0; i < MDP4_MAX_OVERLAY_PIPE; i++) { 874 if (pipe->pipe_ndx == 0) { 875 pipe->pipe_ndx = i + 1; /* start from 1 */ 876 init_completion(&pipe->comp); 877 printk(KERN_INFO "mdp4_overlay_pipe_alloc: pipe=%p ndx=%d\n", 878 pipe, pipe->pipe_ndx); 879 return pipe; 880 } 881 pipe++; 882 } 883 884 return NULL; 885} 886 887 888void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe) 889{ 890 printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%p ndx=%d\n", 891 pipe, pipe->pipe_ndx); 892 memset(pipe, 0, sizeof(*pipe)); 893} 894 895static int get_pipe_num(int ptype, int stage) 896{ 897 if (ptype == OVERLAY_TYPE_RGB) { 898 if (stage == MDP4_MIXER_STAGE_BASE) 899 return OVERLAY_PIPE_RGB1; 900 else 901 return OVERLAY_PIPE_RGB2; 902 } else { 903 if (stage == MDP4_MIXER_STAGE0) 904 return OVERLAY_PIPE_VG1; 905 else 906 return OVERLAY_PIPE_VG2; 907 } 908} 909 910int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer) 911{ 912 struct mdp4_overlay_pipe *pipe; 913 914 pipe = ctrl->stage[mixer][z_order]; 915 916 if (pipe == NULL) 917 return 0; 918 919 if (pipe->pipe_ndx == id) /* same req, recycle */ 920 return 0; 921 922 return -EPERM; 923} 924 925static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer, 926 struct mdp4_overlay_pipe **ppipe) 927{ 928 struct mdp4_overlay_pipe *pipe; 929 int ret, ptype; 930 931 if (mixer >= MDP4_MAX_MIXER) { 932 printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n"); 933 return -ERANGE; 934 } 935 936 if (req->z_order < 0 || req->z_order > 2) { 937 printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n", 938 req->z_order); 939 return -ERANGE; 940 } 941 942 if (req->src_rect.h == 0 || req->src_rect.w == 0) { 943 printk(KERN_ERR "mpd_overlay_req2pipe: src img of zero size!\n"); 944 return -EINVAL; 945 } 946 947 ret = mdp4_overlay_req_check(req->id, req->z_order, mixer); 948 if (ret < 0) 949 return ret; 950 951 ptype = mdp4_overlay_format2type(req->src.format); 952 if (ptype < 0) 953 return ptype; 954 955 if (req->id == MSMFB_NEW_REQUEST) /* new request */ 956 pipe = mdp4_overlay_pipe_alloc(); 957 else 958 pipe = mdp4_overlay_ndx2pipe(req->id); 959 960 if (pipe == NULL) 961 return -ENOMEM; 962 963 pipe->src_format = req->src.format; 964 ret = mdp4_overlay_format2pipe(pipe); 965 966 if (ret < 0) 967 return ret; 968 969 /* 970 * base layer == 1, reserved for frame buffer 971 * zorder 0 == stage 0 == 2 972 * zorder 1 == stage 1 == 3 973 * zorder 2 == stage 2 == 4 974 */ 975 if (req->id == MSMFB_NEW_REQUEST) { /* new request */ 976 pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0; 977 pipe->pipe_type = ptype; 978 pipe->pipe_num = get_pipe_num(ptype, pipe->mixer_stage); 979 printk(KERN_INFO "mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n", 980 req->z_order, pipe->pipe_num); 981 } 982 983 pipe->src_width = req->src.width & 0x07ff; /* source img width */ 984 pipe->src_height = req->src.height & 0x07ff; /* source img height */ 985 pipe->src_h = req->src_rect.h & 0x07ff; 986 pipe->src_w = req->src_rect.w & 0x07ff; 987 pipe->src_y = req->src_rect.y & 0x07ff; 988 pipe->src_x = req->src_rect.x & 0x07ff; 989 pipe->dst_h = req->dst_rect.h & 0x07ff; 990 pipe->dst_w = req->dst_rect.w & 0x07ff; 991 pipe->dst_y = req->dst_rect.y & 0x07ff; 992 pipe->dst_x = req->dst_rect.x & 0x07ff; 993 994 if (req->flags & MDP_FLIP_LR) 995 pipe->op_mode |= MDP4_OP_FLIP_LR; 996 997 if (req->flags & MDP_FLIP_UD) 998 pipe->op_mode |= MDP4_OP_FLIP_UD; 999 1000 if (req->flags & MDP_DITHER) 1001 pipe->op_mode |= MDP4_OP_DITHER_EN; 1002 1003 if (req->flags & MDP_DEINTERLACE) 1004 pipe->op_mode |= MDP4_OP_DEINT_ODD_REF; 1005 1006 pipe->is_fg = req->is_fg;/* control alpha and color key */ 1007 1008 pipe->alpha = req->alpha & 0x0ff; 1009 1010 pipe->transp = req->transp_mask; 1011 1012 *ppipe = pipe; 1013 1014 return 0; 1015} 1016 1017int get_img(struct msmfb_data *img, struct fb_info *info, 1018 unsigned long *start, unsigned long *len, struct file **pp_file) 1019{ 1020 int put_needed, ret = 0; 1021 struct file *file; 1022#ifdef CONFIG_ANDROID_PMEM 1023 unsigned long vstart; 1024#endif 1025 1026#ifdef CONFIG_ANDROID_PMEM 1027 if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file)) 1028 return 0; 1029#endif 1030 file = fget_light(img->memory_id, &put_needed); 1031 if (file == NULL) 1032 return -1; 1033 1034 if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) { 1035 *start = info->fix.smem_start; 1036 *len = info->fix.smem_len; 1037 *pp_file = file; 1038 } else { 1039 ret = -1; 1040 fput_light(file, put_needed); 1041 } 1042 return ret; 1043} 1044int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req) 1045{ 1046 struct mdp4_overlay_pipe *pipe; 1047 1048 pipe = mdp4_overlay_ndx2pipe(req->id); 1049 if (pipe == NULL) 1050 return -ENODEV; 1051 1052 *req = pipe->req_data; 1053 1054 return 0; 1055} 1056 1057int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req) 1058{ 1059 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; 1060 int ret, mixer; 1061 struct mdp4_overlay_pipe *pipe; 1062 int lcdc; 1063 1064 if (mfd == NULL) 1065 return -ENODEV; 1066 1067 if (req->src.format == MDP_FB_FORMAT) 1068 req->src.format = mfd->fb_imgType; 1069 1070 if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) 1071 return -EINTR; 1072 1073 mixer = info->node; /* minor number of char device */ 1074 1075 ret = mdp4_overlay_req2pipe(req, mixer, &pipe); 1076 if (ret < 0) { 1077 mutex_unlock(&mfd->dma->ov_mutex); 1078 return ret; 1079 } 1080 1081 lcdc = inpdw(MDP_BASE + 0xc0000); 1082 1083 if (lcdc == 0) { /* mddi */ 1084 /* MDP cmd block enable */ 1085 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); 1086 } 1087 1088 /* return id back to user */ 1089 req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */ 1090 pipe->req_data = *req; /* keep original req */ 1091 1092 mutex_unlock(&mfd->dma->ov_mutex); 1093 1094 return 0; 1095} 1096 1097int mdp4_overlay_unset(struct fb_info *info, int ndx) 1098{ 1099 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; 1100 struct mdp4_overlay_pipe *pipe; 1101 int lcdc; 1102 1103 if (mfd == NULL) 1104 return -ENODEV; 1105 1106 if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) 1107 return -EINTR; 1108 1109 pipe = mdp4_overlay_ndx2pipe(ndx); 1110 1111 if (pipe == NULL) { 1112 mutex_unlock(&mfd->dma->ov_mutex); 1113 return -ENODEV; 1114 } 1115 1116 lcdc = inpdw(MDP_BASE + 0xc0000); 1117 1118 mdp4_mixer_stage_down(pipe); 1119 1120 if (lcdc == 0) { /* mddi */ 1121 /* MDP cmd block disable */ 1122 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); 1123 } 1124 1125 if (lcdc) /* LCDC mode */ 1126 mdp4_overlay_reg_flush(pipe, 0); 1127 1128 mdp4_overlay_pipe_free(pipe); 1129 1130 if (lcdc == 0) { /* mddi */ 1131 mdp4_mddi_overlay_restore(); 1132 } 1133 1134 mutex_unlock(&mfd->dma->ov_mutex); 1135 1136 return 0; 1137} 1138 1139struct tile_desc { 1140 uint32 width; /* tile's width */ 1141 uint32 height; /* tile's height */ 1142 uint32 row_tile_w; /* tiles per row's width */ 1143 uint32 row_tile_h; /* tiles per row's height */ 1144}; 1145 1146void tile_samsung(struct tile_desc *tp) 1147{ 1148 /* 1149 * each row of samsung tile consists of two tiles in height 1150 * and two tiles in width which means width should align to 1151 * 64 x 2 bytes and height should align to 32 x 2 bytes. 1152 * video decoder generate two tiles in width and one tile 1153 * in height which ends up height align to 32 X 1 bytes. 1154 */ 1155 tp->width = 64; /* 64 bytes */ 1156 tp->row_tile_w = 2; /* 2 tiles per row's width */ 1157 tp->height = 32; /* 32 bytes */ 1158 tp->row_tile_h = 1; /* 1 tiles per row's height */ 1159} 1160 1161uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp) 1162{ 1163 uint32 tile_w, tile_h; 1164 uint32 row_num_w, row_num_h; 1165 1166 1167 tile_w = tp->width * tp->row_tile_w; 1168 tile_h = tp->height * tp->row_tile_h; 1169 1170 row_num_w = (pipe->src_width + tile_w - 1) / tile_w; 1171 row_num_h = (pipe->src_height + tile_h - 1) / tile_h; 1172 1173 return row_num_w * row_num_h * tile_w * tile_h; 1174} 1175 1176int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req, 1177 struct file **pp_src_file) 1178{ 1179 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; 1180 struct msmfb_data *img; 1181 struct mdp4_overlay_pipe *pipe; 1182 ulong start, addr; 1183 ulong len = 0; 1184 struct file *p_src_file = 0; 1185 int lcdc; 1186 1187 if (mfd == NULL) 1188 return -ENODEV; 1189 1190 pipe = mdp4_overlay_ndx2pipe(req->id); 1191 if (pipe == NULL) 1192 return -ENODEV; 1193 1194 if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) 1195 return -EINTR; 1196 1197 img = &req->data; 1198 get_img(img, info, &start, &len, &p_src_file); 1199 if (len == 0) { 1200 mutex_unlock(&mfd->dma->ov_mutex); 1201 printk(KERN_ERR "mdp_overlay_play: could not retrieve" 1202 " image from memory\n"); 1203 return -1; 1204 } 1205 *pp_src_file = p_src_file; 1206 1207 addr = start + img->offset; 1208 pipe->srcp0_addr = addr; 1209 pipe->srcp0_ystride = pipe->src_width * pipe->bpp; 1210 1211 if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) { 1212 if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) { 1213 struct tile_desc tile; 1214 1215 tile_samsung(&tile); 1216 pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile); 1217 } else 1218 pipe->srcp1_addr = addr + 1219 pipe->src_width * pipe->src_height; 1220 1221 pipe->srcp0_ystride = pipe->src_width; 1222 pipe->srcp1_ystride = pipe->src_width; 1223 } 1224 1225 lcdc = inpdw(MDP_BASE + 0xc0000); 1226 lcdc &= 0x01; /* LCDC mode */ 1227 1228 if (pipe->pipe_type == OVERLAY_TYPE_VG) 1229 mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */ 1230 else 1231 mdp4_overlay_rgb_setup(pipe); /* rgb pipe */ 1232 1233 mdp4_mixer_blend_setup(pipe); 1234 mdp4_mixer_stage_up(pipe); 1235 1236 if (lcdc) { /* LCDC mode */ 1237 mdp4_overlay_reg_flush(pipe, 1); 1238 } 1239 1240 if (lcdc) { /* LCDC mode */ 1241 if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */ 1242 mutex_unlock(&mfd->dma->ov_mutex); 1243 return 0; 1244 } 1245 } 1246 1247 if (lcdc == 0) { /* MDDI mode */ 1248#ifdef MDP4_NONBLOCKING 1249 if (mfd->panel_power_on) 1250#else 1251 if (!mfd->dma->busy && mfd->panel_power_on) 1252#endif 1253 mdp4_mddi_overlay_kickoff(mfd, pipe); 1254 } 1255 1256 mutex_unlock(&mfd->dma->ov_mutex); 1257 1258 return 0; 1259} 1260