1/* drivers/video/msm/src/drv/mdp/mdp_ppp.c 2 * 3 * Copyright (C) 2007 Google Incorporated 4 * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. 5 * 6 * This software is licensed under the terms of the GNU General Public 7 * License version 2, as published by the Free Software Foundation, and 8 * may be copied, distributed, and modified under those terms. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 */ 15 16#include <linux/module.h> 17#include <linux/kernel.h> 18#include <linux/sched.h> 19#include <linux/time.h> 20#include <linux/init.h> 21#include <linux/interrupt.h> 22#include <linux/fb.h> 23#include <msm_mdp.h> 24#include <linux/file.h> 25#include <linux/major.h> 26 27#include "linux/proc_fs.h" 28 29#include <mach/hardware.h> 30#include <linux/io.h> 31 32#include <asm/system.h> 33#include <asm/mach-types.h> 34#include <linux/semaphore.h> 35 36#include "mdp.h" 37#include "msm_fb.h" 38 39#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \ 40 (((x) < MDP_IMGTYPE2_START) || \ 41 ((x) >= MDP_IMGTYPE_LIMIT2))) 42 43static uint32_t bytes_per_pixel[] = { 44 [MDP_RGB_565] = 2, 45 [MDP_RGB_888] = 3, 46 [MDP_XRGB_8888] = 4, 47 [MDP_ARGB_8888] = 4, 48 [MDP_RGBA_8888] = 4, 49 [MDP_BGRA_8888] = 4, 50 [MDP_Y_CBCR_H2V1] = 1, 51 [MDP_Y_CBCR_H2V2] = 1, 52 [MDP_Y_CRCB_H2V1] = 1, 53 [MDP_Y_CRCB_H2V2] = 1, 54 [MDP_YCRYCB_H2V1] = 2, 55 [MDP_BGR_565] = 2 56}; 57 58extern uint32 mdp_plv[]; 59extern struct semaphore mdp_ppp_mutex; 60 61uint32_t mdp_get_bytes_per_pixel(uint32_t format) 62{ 63 uint32_t bpp = 0; 64 if (format < ARRAY_SIZE(bytes_per_pixel)) 65 bpp = bytes_per_pixel[format]; 66 67 BUG_ON(!bpp); 68 return bpp; 69} 70 71static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel, 72 uint16 *matrix_and_bias_vector, 73 uint32 *clamp_vector, 74 uint32 *look_up_table) 75{ 76 uint8 input_C2, input_C0, input_C1; 77 uint32 output; 78 int32 comp_C2, comp_C1, comp_C0, temp; 79 int32 temp1, temp2, temp3; 80 int32 matrix[9]; 81 int32 bias_vector[3]; 82 int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit; 83 int32 i; 84 uint32 _is_lookup_table_enabled; 85 86 input_C2 = (input_pixel >> 16) & 0xFF; 87 input_C1 = (input_pixel >> 8) & 0xFF; 88 input_C0 = (input_pixel >> 0) & 0xFF; 89 90 comp_C0 = input_C0; 91 comp_C1 = input_C1; 92 comp_C2 = input_C2; 93 94 for (i = 0; i < 9; i++) 95 matrix[i] = 96 ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20; 97 98 bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF); 99 bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF); 100 bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF); 101 102 Y_low_limit = (int32) clamp_vector[0]; 103 Y_high_limit = (int32) clamp_vector[1]; 104 C_low_limit = (int32) clamp_vector[2]; 105 C_high_limit = (int32) clamp_vector[3]; 106 107 if (look_up_table == 0) /* check for NULL point */ 108 _is_lookup_table_enabled = 0; 109 else 110 _is_lookup_table_enabled = 1; 111 112 if (_is_lookup_table_enabled == 1) { 113 comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF; 114 comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF; 115 comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF; 116 } 117 /* 118 * Color Conversion 119 * reorder input colors 120 */ 121 temp = comp_C2; 122 comp_C2 = comp_C1; 123 comp_C1 = comp_C0; 124 comp_C0 = temp; 125 126 /* matrix multiplication */ 127 temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2]; 128 temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5]; 129 temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8]; 130 131 comp_C0 = temp1 + 0x100; 132 comp_C1 = temp2 + 0x100; 133 comp_C2 = temp3 + 0x100; 134 135 /* take interger part */ 136 comp_C0 >>= 9; 137 comp_C1 >>= 9; 138 comp_C2 >>= 9; 139 140 /* post bias (+) */ 141 comp_C0 += bias_vector[0]; 142 comp_C1 += bias_vector[1]; 143 comp_C2 += bias_vector[2]; 144 145 /* limit pixel to 8-bit */ 146 if (comp_C0 < 0) 147 comp_C0 = 0; 148 149 if (comp_C0 > 255) 150 comp_C0 = 255; 151 152 if (comp_C1 < 0) 153 comp_C1 = 0; 154 155 if (comp_C1 > 255) 156 comp_C1 = 255; 157 158 if (comp_C2 < 0) 159 comp_C2 = 0; 160 161 if (comp_C2 > 255) 162 comp_C2 = 255; 163 164 /* clamp */ 165 if (comp_C0 < Y_low_limit) 166 comp_C0 = Y_low_limit; 167 168 if (comp_C0 > Y_high_limit) 169 comp_C0 = Y_high_limit; 170 171 if (comp_C1 < C_low_limit) 172 comp_C1 = C_low_limit; 173 174 if (comp_C1 > C_high_limit) 175 comp_C1 = C_high_limit; 176 177 if (comp_C2 < C_low_limit) 178 comp_C2 = C_low_limit; 179 180 if (comp_C2 > C_high_limit) 181 comp_C2 = C_high_limit; 182 183 output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0; 184 return output; 185} 186 187uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel, 188 uint16 *matrix_and_bias_vector, 189 uint32 *clamp_vector, uint32 *look_up_table) 190{ 191 uint8 input_C2, input_C0, input_C1; 192 uint32 output; 193 int32 comp_C2, comp_C1, comp_C0, temp; 194 int32 temp1, temp2, temp3; 195 int32 matrix[9]; 196 int32 bias_vector[3]; 197 int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit; 198 int32 i; 199 uint32 _is_lookup_table_enabled; 200 201 input_C2 = (input_pixel >> 16) & 0xFF; 202 input_C1 = (input_pixel >> 8) & 0xFF; 203 input_C0 = (input_pixel >> 0) & 0xFF; 204 205 comp_C0 = input_C0; 206 comp_C1 = input_C1; 207 comp_C2 = input_C2; 208 209 for (i = 0; i < 9; i++) 210 matrix[i] = 211 ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20; 212 213 bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF); 214 bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF); 215 bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF); 216 217 Y_low_limit = (int32) clamp_vector[0]; 218 Y_high_limit = (int32) clamp_vector[1]; 219 C_low_limit = (int32) clamp_vector[2]; 220 C_high_limit = (int32) clamp_vector[3]; 221 222 if (look_up_table == 0) /* check for NULL point */ 223 _is_lookup_table_enabled = 0; 224 else 225 _is_lookup_table_enabled = 1; 226 227 /* clamp */ 228 if (comp_C0 < Y_low_limit) 229 comp_C0 = Y_low_limit; 230 231 if (comp_C0 > Y_high_limit) 232 comp_C0 = Y_high_limit; 233 234 if (comp_C1 < C_low_limit) 235 comp_C1 = C_low_limit; 236 237 if (comp_C1 > C_high_limit) 238 comp_C1 = C_high_limit; 239 240 if (comp_C2 < C_low_limit) 241 comp_C2 = C_low_limit; 242 243 if (comp_C2 > C_high_limit) 244 comp_C2 = C_high_limit; 245 246 /* 247 * Color Conversion 248 * pre bias (-) 249 */ 250 comp_C0 -= bias_vector[0]; 251 comp_C1 -= bias_vector[1]; 252 comp_C2 -= bias_vector[2]; 253 254 /* matrix multiplication */ 255 temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2]; 256 temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5]; 257 temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8]; 258 259 comp_C0 = temp1 + 0x100; 260 comp_C1 = temp2 + 0x100; 261 comp_C2 = temp3 + 0x100; 262 263 /* take interger part */ 264 comp_C0 >>= 9; 265 comp_C1 >>= 9; 266 comp_C2 >>= 9; 267 268 /* reorder output colors */ 269 temp = comp_C0; 270 comp_C0 = comp_C1; 271 comp_C1 = comp_C2; 272 comp_C2 = temp; 273 274 /* limit pixel to 8-bit */ 275 if (comp_C0 < 0) 276 comp_C0 = 0; 277 278 if (comp_C0 > 255) 279 comp_C0 = 255; 280 281 if (comp_C1 < 0) 282 comp_C1 = 0; 283 284 if (comp_C1 > 255) 285 comp_C1 = 255; 286 287 if (comp_C2 < 0) 288 comp_C2 = 0; 289 290 if (comp_C2 > 255) 291 comp_C2 = 255; 292 293 /* Look-up table */ 294 if (_is_lookup_table_enabled == 1) { 295 comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF; 296 comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF; 297 comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF; 298 } 299 300 output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0; 301 return output; 302} 303 304static uint32 mdp_calc_tpval(MDPIMG *mdpImg) 305{ 306 uint32 tpVal; 307 uint8 plane_tp; 308 309 tpVal = 0; 310 if ((mdpImg->imgType == MDP_RGB_565) 311 || (mdpImg->imgType == MDP_BGR_565)) { 312 /* 313 * transparent color conversion into 24 bpp 314 * 315 * C2R_8BIT 316 * left shift the entire bit and or it with the upper most bits 317 */ 318 plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11); 319 tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16; 320 321 /* C1B_8BIT */ 322 plane_tp = (uint8) (mdpImg->tpVal & 0x1F); 323 tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8; 324 325 /* C0G_8BIT */ 326 plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5); 327 tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4)); 328 } else { 329 /* 24bit RGB to RBG conversion */ 330 331 tpVal = (mdpImg->tpVal & 0xFF00) >> 8; 332 tpVal |= (mdpImg->tpVal & 0xFF) << 8; 333 tpVal |= (mdpImg->tpVal & 0xFF0000); 334 } 335 336 return tpVal; 337} 338 339static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf) 340{ 341 uint8 *dest1; 342 343 dest1 = NULL; 344 switch (iBuf->ibuf_type) { 345 case MDP_Y_CBCR_H2V2: 346 case MDP_Y_CRCB_H2V2: 347 case MDP_Y_CBCR_H2V1: 348 case MDP_Y_CRCB_H2V1: 349 dest1 = (uint8 *) iBuf->buf; 350 dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp; 351 break; 352 353 default: 354 break; 355 } 356 357 return dest1; 358} 359 360static void mdp_ppp_setbg(MDPIBUF *iBuf) 361{ 362 uint8 *bg0_addr; 363 uint8 *bg1_addr; 364 uint32 bg0_ystride, bg1_ystride; 365 uint32 ppp_src_cfg_reg, unpack_pattern; 366 int v_slice, h_slice; 367 368 v_slice = h_slice = 1; 369 bg0_addr = (uint8 *) iBuf->buf; 370 bg1_addr = mdp_get_chroma_addr(iBuf); 371 372 bg0_ystride = iBuf->ibuf_width * iBuf->bpp; 373 bg1_ystride = iBuf->ibuf_width * iBuf->bpp; 374 375 switch (iBuf->ibuf_type) { 376 case MDP_BGR_565: 377 case MDP_RGB_565: 378 /* 888 = 3bytes 379 * RGB = 3Components 380 * RGB interleaved 381 */ 382 ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS | 383 PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | 384 PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | 385 PPP_SRC_UNPACK_ALIGN_LSB | 386 PPP_SRC_FETCH_PLANES_INTERLVD; 387 388 if (iBuf->ibuf_type == MDP_RGB_565) 389 unpack_pattern = 390 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); 391 else 392 unpack_pattern = 393 MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); 394 break; 395 396 case MDP_RGB_888: 397 /* 398 * 888 = 3bytes 399 * RGB = 3Components 400 * RGB interleaved 401 */ 402 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | 403 PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | 404 PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | 405 PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD; 406 407 unpack_pattern = 408 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); 409 break; 410 411 case MDP_BGRA_8888: 412 case MDP_RGBA_8888: 413 case MDP_ARGB_8888: 414 case MDP_XRGB_8888: 415 /* 416 * 8888 = 4bytes 417 * ARGB = 4Components 418 * ARGB interleaved 419 */ 420 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | 421 PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN | 422 PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS | 423 PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB | 424 PPP_SRC_FETCH_PLANES_INTERLVD; 425 426 if (iBuf->ibuf_type == MDP_BGRA_8888) 427 unpack_pattern = 428 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 429 8); 430 else if (iBuf->ibuf_type == MDP_RGBA_8888) 431 unpack_pattern = 432 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 433 8); 434 else 435 unpack_pattern = 436 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 437 8); 438 break; 439 440 case MDP_Y_CBCR_H2V2: 441 case MDP_Y_CRCB_H2V2: 442 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | 443 PPP_SRC_C0G_8BITS | 444 PPP_SRC_C1B_8BITS | 445 PPP_SRC_C3A_8BITS | 446 PPP_SRC_BPP_INTERLVD_2BYTES | 447 PPP_SRC_INTERLVD_2COMPONENTS | 448 PPP_SRC_UNPACK_TIGHT | 449 PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; 450 451 if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) 452 unpack_pattern = 453 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); 454 else 455 unpack_pattern = 456 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); 457 v_slice = h_slice = 2; 458 break; 459 460 case MDP_YCRYCB_H2V1: 461 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | 462 PPP_SRC_C0G_8BITS | 463 PPP_SRC_C1B_8BITS | 464 PPP_SRC_C3A_8BITS | 465 PPP_SRC_BPP_INTERLVD_2BYTES | 466 PPP_SRC_INTERLVD_4COMPONENTS | 467 PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB; 468 469 unpack_pattern = 470 MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); 471 h_slice = 2; 472 break; 473 474 case MDP_Y_CBCR_H2V1: 475 case MDP_Y_CRCB_H2V1: 476 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | 477 PPP_SRC_C0G_8BITS | 478 PPP_SRC_C1B_8BITS | 479 PPP_SRC_C3A_8BITS | 480 PPP_SRC_BPP_INTERLVD_2BYTES | 481 PPP_SRC_INTERLVD_2COMPONENTS | 482 PPP_SRC_UNPACK_TIGHT | 483 PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; 484 485 if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) 486 unpack_pattern = 487 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); 488 else 489 unpack_pattern = 490 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); 491 h_slice = 2; 492 break; 493 494 default: 495 return; 496 } 497 498 /* starting input address adjustment */ 499 mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice, 500 iBuf->roi.lcd_x, iBuf->roi.lcd_y, 501 iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp, 502 iBuf, 1); 503 504 /* 505 * 0x01c0: background plane 0 addr 506 * 0x01c4: background plane 1 addr 507 * 0x01c8: background plane 2 addr 508 * 0x01cc: bg y stride for plane 0 and 1 509 * 0x01d0: bg y stride for plane 2 510 * 0x01d4: bg src PPP config 511 * 0x01d8: unpack pattern 512 */ 513 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr); 514 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr); 515 516 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc, 517 (bg1_ystride << 16) | bg0_ystride); 518 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg); 519 520 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern); 521} 522 523#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \ 524 (img == MDP_Y_CBCR_H2V2) | \ 525 (img == MDP_Y_CRCB_H2V1) | \ 526 (img == MDP_Y_CBCR_H2V1)) 527 528#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp) 529 530#define Y_TO_CRCB_RATIO(format) \ 531 ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\ 532 (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1) 533 534static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp, 535 uint32_t *len0, uint32_t *len1) 536{ 537 *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp); 538 if (IS_PSEUDOPLNR(img->format)) 539 *len1 = *len0/Y_TO_CRCB_RATIO(img->format); 540 else 541 *len1 = 0; 542} 543 544static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp, 545 struct file *p_src_file, struct file *p_dst_file) 546{ 547#ifdef CONFIG_ANDROID_PMEM 548 uint32_t src0_len, src1_len, dst0_len, dst1_len; 549 550 /* flush src images to memory before dma to mdp */ 551 get_len(&req->src, &req->src_rect, src_bpp, 552 &src0_len, &src1_len); 553 554 flush_pmem_file(p_src_file, 555 req->src.offset, src0_len); 556 557 if (IS_PSEUDOPLNR(req->src.format)) 558 flush_pmem_file(p_src_file, 559 req->src.offset + src0_len, src1_len); 560 561 get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len); 562 flush_pmem_file(p_dst_file, req->dst.offset, dst0_len); 563 564 if (IS_PSEUDOPLNR(req->dst.format)) 565 flush_pmem_file(p_dst_file, 566 req->dst.offset + dst0_len, dst1_len); 567#endif 568} 569 570static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf, 571struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file) 572{ 573 uint8 *src0, *src1; 574 uint8 *dest0, *dest1; 575 uint16 inpBpp; 576 uint32 dest0_ystride; 577 uint32 src_width; 578 uint32 src_height; 579 uint32 src0_ystride; 580 uint32 dst_roi_width; 581 uint32 dst_roi_height; 582 uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg; 583 uint32 alpha, tpVal; 584 uint32 packPattern; 585 uint32 dst_packPattern; 586 boolean inputRGB, outputRGB, pseudoplanr_output; 587 int sv_slice, sh_slice; 588 int dv_slice, dh_slice; 589 boolean perPixelAlpha = FALSE; 590 boolean ppp_lookUp_enable = FALSE; 591 592 sv_slice = sh_slice = dv_slice = dh_slice = 1; 593 alpha = tpVal = 0; 594 src_width = iBuf->mdpImg.width; 595 src_height = iBuf->roi.y + iBuf->roi.height; 596 src1 = NULL; 597 dest1 = NULL; 598 599 inputRGB = outputRGB = TRUE; 600 pseudoplanr_output = FALSE; 601 ppp_operation_reg = 0; 602 ppp_dst_cfg_reg = 0; 603 ppp_src_cfg_reg = 0; 604 605 /* Wait for the pipe to clear */ 606 do { } while (mdp_ppp_pipe_wait() <= 0); 607 608 /* 609 * destination config 610 */ 611 switch (iBuf->ibuf_type) { 612 case MDP_RGB_888: 613 dst_packPattern = 614 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); 615 ppp_dst_cfg_reg = 616 PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT | 617 PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT | 618 PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI | 619 PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD; 620 break; 621 622 case MDP_XRGB_8888: 623 case MDP_ARGB_8888: 624 case MDP_RGBA_8888: 625 if (iBuf->ibuf_type == MDP_BGRA_8888) 626 dst_packPattern = 627 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 628 8); 629 else if (iBuf->ibuf_type == MDP_RGBA_8888) 630 dst_packPattern = 631 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 632 8); 633 else 634 dst_packPattern = 635 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 636 8); 637 638 ppp_dst_cfg_reg = PPP_DST_C0G_8BIT | 639 PPP_DST_C1B_8BIT | 640 PPP_DST_C2R_8BIT | 641 PPP_DST_C3A_8BIT | 642 PPP_DST_C3ALPHA_EN | 643 PPP_DST_PACKET_CNT_INTERLVD_4ELEM | 644 PPP_DST_PACK_TIGHT | 645 PPP_DST_PACK_ALIGN_LSB | 646 PPP_DST_OUT_SEL_AXI | 647 PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD; 648 break; 649 650 case MDP_Y_CBCR_H2V2: 651 case MDP_Y_CRCB_H2V2: 652 if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2) 653 dst_packPattern = 654 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); 655 else 656 dst_packPattern = 657 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); 658 659 ppp_dst_cfg_reg = PPP_DST_C2R_8BIT | 660 PPP_DST_C0G_8BIT | 661 PPP_DST_C1B_8BIT | 662 PPP_DST_C3A_8BIT | 663 PPP_DST_PACKET_CNT_INTERLVD_2ELEM | 664 PPP_DST_PACK_TIGHT | 665 PPP_DST_PACK_ALIGN_LSB | 666 PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES; 667 668 ppp_operation_reg |= PPP_OP_DST_CHROMA_420; 669 outputRGB = FALSE; 670 pseudoplanr_output = TRUE; 671 /* 672 * vertically (y direction) and horizontally (x direction) 673 * sample reduction by 2 674 */ 675 676 /* 677 * H2V2(YUV420) Cosite 678 * 679 * Y Y Y Y 680 * CbCr CbCr 681 * Y Y Y Y 682 * Y Y Y Y 683 * CbCr CbCr 684 * Y Y Y Y 685 */ 686 dv_slice = dh_slice = 2; 687 688 /* (x,y) and (width,height) must be even numbern */ 689 iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; 690 iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; 691 iBuf->roi.x = (iBuf->roi.x / 2) * 2; 692 iBuf->roi.width = (iBuf->roi.width / 2) * 2; 693 694 iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2; 695 iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2; 696 iBuf->roi.y = (iBuf->roi.y / 2) * 2; 697 iBuf->roi.height = (iBuf->roi.height / 2) * 2; 698 break; 699 700 case MDP_YCRYCB_H2V1: 701 dst_packPattern = 702 MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); 703 ppp_dst_cfg_reg = 704 PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | 705 PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | 706 PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | 707 PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES | 708 PPP_DST_PLANE_INTERLVD; 709 710 ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1; 711 outputRGB = FALSE; 712 /* 713 * horizontally (x direction) sample reduction by 2 714 * 715 * H2V1(YUV422) Cosite 716 * 717 * YCbCr Y YCbCr Y 718 * YCbCr Y YCbCr Y 719 * YCbCr Y YCbCr Y 720 * YCbCr Y YCbCr Y 721 */ 722 dh_slice = 2; 723 724 /* 725 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the 726 * preloaded gamma setting of 2.2 when the content is 727 * non-linear ppp_lookUp_enable = TRUE; 728 */ 729 730 /* x and width must be even number */ 731 iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; 732 iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; 733 iBuf->roi.x = (iBuf->roi.x / 2) * 2; 734 iBuf->roi.width = (iBuf->roi.width / 2) * 2; 735 break; 736 737 case MDP_Y_CBCR_H2V1: 738 case MDP_Y_CRCB_H2V1: 739 if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) 740 dst_packPattern = 741 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); 742 else 743 dst_packPattern = 744 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); 745 746 ppp_dst_cfg_reg = PPP_DST_C2R_8BIT | 747 PPP_DST_C0G_8BIT | 748 PPP_DST_C1B_8BIT | 749 PPP_DST_C3A_8BIT | 750 PPP_DST_PACKET_CNT_INTERLVD_2ELEM | 751 PPP_DST_PACK_TIGHT | 752 PPP_DST_PACK_ALIGN_LSB | 753 PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES; 754 755 ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1; 756 outputRGB = FALSE; 757 pseudoplanr_output = TRUE; 758 /* horizontally (x direction) sample reduction by 2 */ 759 dh_slice = 2; 760 761 /* x and width must be even number */ 762 iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; 763 iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; 764 iBuf->roi.x = (iBuf->roi.x / 2) * 2; 765 iBuf->roi.width = (iBuf->roi.width / 2) * 2; 766 break; 767 768 case MDP_BGR_565: 769 case MDP_RGB_565: 770 default: 771 if (iBuf->ibuf_type == MDP_RGB_565) 772 dst_packPattern = 773 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); 774 else 775 dst_packPattern = 776 MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); 777 778 ppp_dst_cfg_reg = PPP_DST_C0G_6BIT | 779 PPP_DST_C1B_5BIT | 780 PPP_DST_C2R_5BIT | 781 PPP_DST_PACKET_CNT_INTERLVD_3ELEM | 782 PPP_DST_PACK_TIGHT | 783 PPP_DST_PACK_ALIGN_LSB | 784 PPP_DST_OUT_SEL_AXI | 785 PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD; 786 break; 787 } 788 789 /* source config */ 790 switch (iBuf->mdpImg.imgType) { 791 case MDP_RGB_888: 792 inpBpp = 3; 793 /* 794 * 565 = 2bytes 795 * RGB = 3Components 796 * RGB interleaved 797 */ 798 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | 799 PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | 800 PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | 801 PPP_SRC_UNPACK_ALIGN_LSB | 802 PPP_SRC_FETCH_PLANES_INTERLVD; 803 804 packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); 805 806 ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | 807 PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; 808 break; 809 810 case MDP_BGRA_8888: 811 case MDP_RGBA_8888: 812 case MDP_ARGB_8888: 813 perPixelAlpha = TRUE; 814 case MDP_XRGB_8888: 815 inpBpp = 4; 816 /* 817 * 8888 = 4bytes 818 * ARGB = 4Components 819 * ARGB interleaved 820 */ 821 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | 822 PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | 823 PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES | 824 PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT | 825 PPP_SRC_UNPACK_ALIGN_LSB | 826 PPP_SRC_FETCH_PLANES_INTERLVD; 827 828 if (iBuf->mdpImg.imgType == MDP_BGRA_8888) 829 packPattern = 830 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 831 8); 832 else if (iBuf->mdpImg.imgType == MDP_RGBA_8888) 833 packPattern = 834 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 835 8); 836 else 837 packPattern = 838 MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 839 8); 840 841 ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | 842 PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; 843 break; 844 845 case MDP_Y_CBCR_H2V2: 846 case MDP_Y_CRCB_H2V2: 847 inpBpp = 1; 848 src1 = (uint8 *) iBuf->mdpImg.cbcr_addr; 849 850 /* 851 * CbCr = 2bytes 852 * CbCr = 2Components 853 * Y+CbCr 854 */ 855 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | 856 PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | 857 PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT | 858 PPP_SRC_UNPACK_ALIGN_LSB | 859 PPP_SRC_FETCH_PLANES_PSEUDOPLNR; 860 861 if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2) 862 packPattern = 863 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); 864 else 865 packPattern = 866 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); 867 868 ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR | 869 PPP_OP_SRC_CHROMA_420 | 870 PPP_OP_SRC_CHROMA_COSITE | 871 PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE; 872 873 inputRGB = FALSE; 874 sh_slice = sv_slice = 2; 875 break; 876 877 case MDP_YCRYCB_H2V1: 878 inpBpp = 2; 879 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | 880 PPP_SRC_C0G_8BITS | 881 PPP_SRC_C1B_8BITS | 882 PPP_SRC_C3A_8BITS | 883 PPP_SRC_BPP_INTERLVD_2BYTES | 884 PPP_SRC_INTERLVD_4COMPONENTS | 885 PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB; 886 887 packPattern = 888 MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); 889 890 ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 | 891 PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE; 892 893 /* 894 * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the 895 * preloaded inverse gamma setting of 2.2 since they're 896 * symetric when the content is non-linear 897 * ppp_lookUp_enable = TRUE; 898 */ 899 900 /* x and width must be even number */ 901 iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; 902 iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; 903 iBuf->roi.x = (iBuf->roi.x / 2) * 2; 904 iBuf->roi.width = (iBuf->roi.width / 2) * 2; 905 906 inputRGB = FALSE; 907 sh_slice = 2; 908 break; 909 910 case MDP_Y_CBCR_H2V1: 911 case MDP_Y_CRCB_H2V1: 912 inpBpp = 1; 913 src1 = (uint8 *) iBuf->mdpImg.cbcr_addr; 914 915 ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | 916 PPP_SRC_C0G_8BITS | 917 PPP_SRC_C1B_8BITS | 918 PPP_SRC_C3A_8BITS | 919 PPP_SRC_BPP_INTERLVD_2BYTES | 920 PPP_SRC_INTERLVD_2COMPONENTS | 921 PPP_SRC_UNPACK_TIGHT | 922 PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; 923 924 if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1) 925 packPattern = 926 MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); 927 else 928 packPattern = 929 MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); 930 931 ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 | 932 PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE; 933 inputRGB = FALSE; 934 sh_slice = 2; 935 break; 936 937 case MDP_BGR_565: 938 case MDP_RGB_565: 939 default: 940 inpBpp = 2; 941 /* 942 * 565 = 2bytes 943 * RGB = 3Components 944 * RGB interleaved 945 */ 946 ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS | 947 PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | 948 PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | 949 PPP_SRC_UNPACK_ALIGN_LSB | 950 PPP_SRC_FETCH_PLANES_INTERLVD; 951 952 if (iBuf->mdpImg.imgType == MDP_RGB_565) 953 packPattern = 954 MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); 955 else 956 packPattern = 957 MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); 958 959 ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | 960 PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; 961 break; 962 963 } 964 965 if (pseudoplanr_output) 966 ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN; 967 968 /* YCbCr to RGB color conversion flag */ 969 if ((!inputRGB) && (outputRGB)) { 970 ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB | 971 PPP_OP_CONVERT_ON; 972 973 /* 974 * primary/secondary is sort of misleading term...but 975 * in mdp2.2/3.0 we only use primary matrix (forward/rev) 976 * in mdp3.1 we use set1(prim) and set2(secd) 977 */ 978#ifdef CONFIG_FB_MSM_MDP31 979 ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY | 980 PPP_OP_DST_RGB; 981 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0); 982#endif 983 984 if (ppp_lookUp_enable) { 985 ppp_operation_reg |= PPP_OP_LUT_C0_ON | 986 PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON; 987 } 988 } 989 /* RGB to YCbCr color conversion flag */ 990 if ((inputRGB) && (!outputRGB)) { 991 ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR | 992 PPP_OP_CONVERT_ON; 993 994#ifdef CONFIG_FB_MSM_MDP31 995 ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY | 996 PPP_OP_DST_YCBCR; 997 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e); 998#endif 999 1000 if (ppp_lookUp_enable) { 1001 ppp_operation_reg |= PPP_OP_LUT_C0_ON | 1002 PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON; 1003 } 1004 } 1005 /* YCbCr to YCbCr color conversion flag */ 1006 if ((!inputRGB) && (!outputRGB)) { 1007 if ((ppp_lookUp_enable) && 1008 (iBuf->mdpImg.imgType != iBuf->ibuf_type)) { 1009 ppp_operation_reg |= PPP_OP_LUT_C0_ON; 1010 } 1011 } 1012 1013 ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0; 1014 ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0; 1015 1016 if (req->flags & MDP_DEINTERLACE) 1017 ppp_operation_reg |= PPP_OP_DEINT_EN; 1018 1019 /* Dither at DMA side only since iBuf format is RGB888 */ 1020 if (iBuf->mdpImg.mdpOp & MDPOP_DITHER) 1021 ppp_operation_reg |= PPP_OP_DITHER_EN; 1022 1023 if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) { 1024 ppp_operation_reg |= PPP_OP_ROT_ON; 1025 1026 if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { 1027 ppp_operation_reg |= PPP_OP_ROT_90; 1028 } 1029 if (iBuf->mdpImg.mdpOp & MDPOP_LR) { 1030 ppp_operation_reg |= PPP_OP_FLIP_LR; 1031 } 1032 if (iBuf->mdpImg.mdpOp & MDPOP_UD) { 1033 ppp_operation_reg |= PPP_OP_FLIP_UD; 1034 } 1035 } 1036 1037 src0_ystride = src_width * inpBpp; 1038 dest0_ystride = iBuf->ibuf_width * iBuf->bpp; 1039 1040 /* no need to care about rotation since it's the real-XY. */ 1041 dst_roi_width = iBuf->roi.dst_width; 1042 dst_roi_height = iBuf->roi.dst_height; 1043 1044 src0 = (uint8 *) iBuf->mdpImg.bmy_addr; 1045 dest0 = (uint8 *) iBuf->buf; 1046 1047 /* Jumping from Y-Plane to Chroma Plane */ 1048 dest1 = mdp_get_chroma_addr(iBuf); 1049 1050 /* first pixel addr calculation */ 1051 mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x, 1052 iBuf->roi.y, src_width, src_height, inpBpp, iBuf, 1053 0); 1054 mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice, 1055 iBuf->roi.lcd_x, iBuf->roi.lcd_y, 1056 iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp, 1057 iBuf, 2); 1058 1059 /* set scale operation */ 1060 mdp_set_scale(iBuf, dst_roi_width, dst_roi_height, 1061 inputRGB, outputRGB, &ppp_operation_reg); 1062 1063 /* 1064 * setting background source for blending 1065 */ 1066 mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha, 1067 &ppp_operation_reg); 1068 1069 if (ppp_operation_reg & PPP_OP_BLEND_ON) { 1070 mdp_ppp_setbg(iBuf); 1071 1072 if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) { 1073 ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1; 1074 1075 if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) { 1076 tpVal = mdp_conv_matx_rgb2yuv(tpVal, 1077 (uint16 *) & 1078 mdp_ccs_rgb2yuv, 1079 &mdp_plv[0], NULL); 1080 } 1081 } 1082 } 1083 1084 /* 1085 * 0x0004: enable dbg bus 1086 * 0x0100: "don't care" Edge Condit until scaling is on 1087 * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit 1088 * 0x0108: src pixel size 1089 * 0x010c: component plane 0 starting address 1090 * 0x011c: component plane 0 ystride 1091 * 0x0124: PPP source config register 1092 * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR) 1093 */ 1094 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 | 1095 iBuf->roi.width)); 1096 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */ 1097 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */ 1098 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c, 1099 (src0_ystride << 16 | src0_ystride)); 1100 1101 /* setup for rgb 565 */ 1102 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg); 1103 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern); 1104 /* 1105 * 0x0138: PPP destination operation register 1106 * 0x014c: constant_alpha|transparent_color 1107 * 0x0150: PPP destination config register 1108 * 0x0154: PPP packing pattern 1109 */ 1110 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg); 1111 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal); 1112 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg); 1113 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern); 1114 1115 /* 1116 * 0x0164: ROI height and width 1117 * 0x0168: Component Plane 0 starting addr 1118 * 0x016c: Component Plane 1 starting addr 1119 * 0x0178: Component Plane 1/0 y stride 1120 */ 1121 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164, 1122 (dst_roi_height << 16 | dst_roi_width)); 1123 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0); 1124 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1); 1125 MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178, 1126 (dest0_ystride << 16 | dest0_ystride)); 1127 1128 flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file); 1129#ifdef CONFIG_MDP_PPP_ASYNC_OP 1130 mdp_ppp_process_curr_djob(); 1131#else 1132 mdp_pipe_kickoff(MDP_PPP_TERM, mfd); 1133#endif 1134} 1135 1136static int mdp_ppp_verify_req(struct mdp_blit_req *req) 1137{ 1138 u32 src_width, src_height, dst_width, dst_height; 1139 1140 if (req == NULL) 1141 return -1; 1142 1143 if (MDP_IS_IMGTYPE_BAD(req->src.format) || 1144 MDP_IS_IMGTYPE_BAD(req->dst.format)) 1145 return -1; 1146 1147 if ((req->src.width == 0) || (req->src.height == 0) || 1148 (req->src_rect.w == 0) || (req->src_rect.h == 0) || 1149 (req->dst.width == 0) || (req->dst.height == 0) || 1150 (req->dst_rect.w == 0) || (req->dst_rect.h == 0)) 1151 1152 return -1; 1153 1154 if (((req->src_rect.x + req->src_rect.w) > req->src.width) || 1155 ((req->src_rect.y + req->src_rect.h) > req->src.height)) 1156 return -1; 1157 1158 if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) || 1159 ((req->dst_rect.y + req->dst_rect.h) > req->dst.height)) 1160 return -1; 1161 1162 /* 1163 * scaling range check 1164 */ 1165 src_width = req->src_rect.w; 1166 src_height = req->src_rect.h; 1167 1168 if (req->flags & MDP_ROT_90) { 1169 dst_width = req->dst_rect.h; 1170 dst_height = req->dst_rect.w; 1171 } else { 1172 dst_width = req->dst_rect.w; 1173 dst_height = req->dst_rect.h; 1174 } 1175 1176 switch (req->dst.format) { 1177 case MDP_Y_CRCB_H2V2: 1178 case MDP_Y_CBCR_H2V2: 1179 src_width = (src_width / 2) * 2; 1180 src_height = (src_height / 2) * 2; 1181 dst_width = (src_width / 2) * 2; 1182 dst_height = (src_height / 2) * 2; 1183 break; 1184 1185 case MDP_Y_CRCB_H2V1: 1186 case MDP_Y_CBCR_H2V1: 1187 case MDP_YCRYCB_H2V1: 1188 src_width = (src_width / 2) * 2; 1189 dst_width = (src_width / 2) * 2; 1190 break; 1191 1192 default: 1193 break; 1194 } 1195 1196 if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width > 1197 MDP_MAX_X_SCALE_FACTOR) 1198 || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width < 1199 MDP_MIN_X_SCALE_FACTOR)) 1200 return -1; 1201 1202 if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height > 1203 MDP_MAX_Y_SCALE_FACTOR) 1204 || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height < 1205 MDP_MIN_Y_SCALE_FACTOR)) 1206 return -1; 1207 1208 return 0; 1209} 1210 1211/** 1212 * get_gem_img() - retrieve drm obj's start address and size 1213 * @img: contains drm file descriptor and gem handle 1214 * @start: repository of starting address of drm obj allocated memory 1215 * @len: repository of size of drm obj alloacted memory 1216 * 1217 **/ 1218int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len) 1219{ 1220 panic("waaaaaaaah"); 1221 //return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len); 1222} 1223 1224int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start, 1225 unsigned long *len, struct file **pp_file) 1226{ 1227 int put_needed, ret = 0; 1228 struct file *file; 1229 unsigned long vstart; 1230#ifdef CONFIG_ANDROID_PMEM 1231 if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file)) 1232 return 0; 1233#endif 1234 file = fget_light(img->memory_id, &put_needed); 1235 if (file == NULL) 1236 return -1; 1237 1238 if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) { 1239 *start = info->fix.smem_start; 1240 *len = info->fix.smem_len; 1241 *pp_file = file; 1242 } else { 1243 ret = -1; 1244 fput_light(file, put_needed); 1245 } 1246 return ret; 1247} 1248 1249int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, 1250 struct file **pp_src_file, struct file **pp_dst_file) 1251{ 1252 unsigned long src_start, dst_start; 1253 unsigned long src_len = 0; 1254 unsigned long dst_len = 0; 1255 MDPIBUF iBuf; 1256 u32 dst_width, dst_height; 1257 struct file *p_src_file = 0 , *p_dst_file = 0; 1258 struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; 1259 1260 if (req->dst.format == MDP_FB_FORMAT) 1261 req->dst.format = mfd->fb_imgType; 1262 if (req->src.format == MDP_FB_FORMAT) 1263 req->src.format = mfd->fb_imgType; 1264 1265 if (req->flags & MDP_BLIT_SRC_GEM) { 1266 if (get_gem_img(&req->src, &src_start, &src_len) < 0) 1267 return -1; 1268 } else { 1269 get_img(&req->src, info, &src_start, &src_len, &p_src_file); 1270 } 1271 if (src_len == 0) { 1272 printk(KERN_ERR "mdp_ppp: could not retrieve image from " 1273 "memory\n"); 1274 return -1; 1275 } 1276 1277 if (req->flags & MDP_BLIT_DST_GEM) { 1278 if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0) 1279 return -1; 1280 } else { 1281 get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file); 1282 } 1283 if (dst_len == 0) { 1284 printk(KERN_ERR "mdp_ppp: could not retrieve image from " 1285 "memory\n"); 1286 return -1; 1287 } 1288 *pp_src_file = p_src_file; 1289 *pp_dst_file = p_dst_file; 1290 if (mdp_ppp_verify_req(req)) { 1291 printk(KERN_ERR "mdp_ppp: invalid image!\n"); 1292 return -1; 1293 } 1294 1295 iBuf.ibuf_width = req->dst.width; 1296 iBuf.ibuf_height = req->dst.height; 1297 iBuf.bpp = bytes_per_pixel[req->dst.format]; 1298 1299 iBuf.ibuf_type = req->dst.format; 1300 iBuf.buf = (uint8 *) dst_start; 1301 iBuf.buf += req->dst.offset; 1302 1303 iBuf.roi.lcd_x = req->dst_rect.x; 1304 iBuf.roi.lcd_y = req->dst_rect.y; 1305 iBuf.roi.dst_width = req->dst_rect.w; 1306 iBuf.roi.dst_height = req->dst_rect.h; 1307 1308 iBuf.roi.x = req->src_rect.x; 1309 iBuf.roi.width = req->src_rect.w; 1310 iBuf.roi.y = req->src_rect.y; 1311 iBuf.roi.height = req->src_rect.h; 1312 1313 iBuf.mdpImg.width = req->src.width; 1314 iBuf.mdpImg.imgType = req->src.format; 1315 1316 iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset); 1317 iBuf.mdpImg.cbcr_addr = 1318 (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr + 1319 req->src.width * req->src.height); 1320 1321 iBuf.mdpImg.mdpOp = MDPOP_NOP; 1322 1323 /* blending check */ 1324 if (req->transp_mask != MDP_TRANSP_NOP) { 1325 iBuf.mdpImg.mdpOp |= MDPOP_TRANSP; 1326 iBuf.mdpImg.tpVal = req->transp_mask; 1327 iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg); 1328 } 1329 1330 req->alpha &= 0xff; 1331 if (req->alpha < MDP_ALPHA_NOP) { 1332 iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB; 1333 iBuf.mdpImg.alpha = req->alpha; 1334 } 1335 1336 /* rotation check */ 1337 if (req->flags & MDP_FLIP_LR) 1338 iBuf.mdpImg.mdpOp |= MDPOP_LR; 1339 if (req->flags & MDP_FLIP_UD) 1340 iBuf.mdpImg.mdpOp |= MDPOP_UD; 1341 if (req->flags & MDP_ROT_90) 1342 iBuf.mdpImg.mdpOp |= MDPOP_ROT90; 1343 if (req->flags & MDP_DITHER) 1344 iBuf.mdpImg.mdpOp |= MDPOP_DITHER; 1345 1346 if (req->flags & MDP_BLEND_FG_PREMULT) { 1347#ifdef CONFIG_FB_MSM_MDP31 1348 iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA; 1349#else 1350 return -EINVAL; 1351#endif 1352 } 1353 1354 if (req->flags & MDP_DEINTERLACE) { 1355#ifdef CONFIG_FB_MSM_MDP31 1356 if ((req->src.format != MDP_Y_CBCR_H2V2) && 1357 (req->src.format != MDP_Y_CRCB_H2V2)) 1358#endif 1359 return -EINVAL; 1360 } 1361 1362 /* scale check */ 1363 if (req->flags & MDP_ROT_90) { 1364 dst_width = req->dst_rect.h; 1365 dst_height = req->dst_rect.w; 1366 } else { 1367 dst_width = req->dst_rect.w; 1368 dst_height = req->dst_rect.h; 1369 } 1370 1371 if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height)) 1372 iBuf.mdpImg.mdpOp |= MDPOP_ASCALE; 1373 1374 if (req->flags & MDP_BLUR) { 1375#ifdef CONFIG_FB_MSM_MDP31 1376 if (req->flags & MDP_SHARPENING) 1377 printk(KERN_WARNING 1378 "mdp: MDP_SHARPENING is set with MDP_BLUR!\n"); 1379 req->flags |= MDP_SHARPENING; 1380 req->sharpening_strength = -127; 1381#else 1382 iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR; 1383 1384#endif 1385 } 1386 1387 if (req->flags & MDP_SHARPENING) { 1388#ifdef CONFIG_FB_MSM_MDP31 1389 if ((req->sharpening_strength > 127) || 1390 (req->sharpening_strength < -127)) { 1391 printk(KERN_ERR 1392 "%s: sharpening strength out of range\n", 1393 __func__); 1394 return -EINVAL; 1395 } 1396 1397 iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING; 1398 iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff; 1399#else 1400 return -EINVAL; 1401#endif 1402 } 1403 1404 down(&mdp_ppp_mutex); 1405 /* MDP cmd block enable */ 1406 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); 1407 1408#ifdef CONFIG_FB_MSM_MDP31 1409 mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); 1410#else 1411 if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) || 1412 (req->src.format == MDP_ARGB_8888) || 1413 (req->src.format == MDP_BGRA_8888) || 1414 (req->src.format == MDP_RGBA_8888)) && 1415 (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) { 1416 int dst_h, src_w, i; 1417 1418 src_w = req->src_rect.w; 1419 dst_h = iBuf.roi.dst_height; 1420 1421 for (i = 0; i < (req->dst_rect.h / 16); i++) { 1422 /* this tile size */ 1423 iBuf.roi.dst_height = 16; 1424 iBuf.roi.width = 1425 (16 * req->src_rect.w) / req->dst_rect.h; 1426 1427 /* if it's out of scale range... */ 1428 if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / 1429 iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) 1430 iBuf.roi.width = 1431 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / 1432 MDP_MAX_X_SCALE_FACTOR; 1433 else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / 1434 iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) 1435 iBuf.roi.width = 1436 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / 1437 MDP_MIN_X_SCALE_FACTOR; 1438 1439 mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); 1440 1441 /* next tile location */ 1442 iBuf.roi.lcd_y += 16; 1443 iBuf.roi.x += iBuf.roi.width; 1444 1445 /* this is for a remainder update */ 1446 dst_h -= 16; 1447 src_w -= iBuf.roi.width; 1448 } 1449 1450 if ((dst_h < 0) || (src_w < 0)) 1451 printk 1452 ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n", 1453 __LINE__); 1454 1455 /* remainder update */ 1456 if ((dst_h > 0) && (src_w > 0)) { 1457 u32 tmp_v; 1458 1459 iBuf.roi.dst_height = dst_h; 1460 iBuf.roi.width = src_w; 1461 1462 if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / 1463 iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) { 1464 tmp_v = 1465 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / 1466 MDP_MAX_X_SCALE_FACTOR + 1467 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) % 1468 MDP_MAX_X_SCALE_FACTOR ? 1 : 0; 1469 1470 /* move x location as roi width gets bigger */ 1471 iBuf.roi.x -= tmp_v - iBuf.roi.width; 1472 iBuf.roi.width = tmp_v; 1473 } else 1474 if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / 1475 iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) { 1476 tmp_v = 1477 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / 1478 MDP_MIN_X_SCALE_FACTOR + 1479 (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) % 1480 MDP_MIN_X_SCALE_FACTOR ? 1 : 0; 1481 1482 /* 1483 * we don't move x location for continuity of 1484 * source image 1485 */ 1486 iBuf.roi.width = tmp_v; 1487 } 1488 1489 mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); 1490 } 1491 } else { 1492 mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); 1493 } 1494#endif 1495 1496 /* MDP cmd block disable */ 1497 mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); 1498 up(&mdp_ppp_mutex); 1499 1500 return 0; 1501} 1502