1 /* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Shengquan Yuan <shengquan.yuan (at) intel.com> 26 * Binglin Chen <binglin.chen (at) intel.com> 27 * Jason Hu <jason.hu (at) intel.com> 28 * Zeng Li <zeng.li (at) intel.com> 29 */ 30 31 /* 32 * Most of rendering codes are ported from xf86-video-i810/src/i810_overlay.c 33 */ 34 35 #include <errno.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 #include <stdio.h> 39 #include <math.h> 40 #include <va/va_backend.h> 41 #include <wsbm/wsbm_manager.h> 42 #include "psb_drv_video.h" 43 #include "psb_output.h" 44 #include "psb_overlay.h" 45 #include "psb_drv_debug.h" 46 47 #ifdef ANDROID 48 #define psb_xrandr_single_mode() 0 49 #else 50 int psb_xrandr_single_mode(); 51 #endif 52 53 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData 54 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id )) 55 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id )) 56 //#define GET_SURFACE_INFO_rotate(psb_surface) ((int) (psb_surface)->extra_info[5]) 57 58 #ifndef VA_FOURCC_I420 59 #define VA_FOURCC_I420 0x30323449 60 #endif 61 62 /********************************************************************************************** 63 * I830ResetVideo 64 * 65 * Description: Use this function to reset the overlay register back buffer to its default 66 * values. Note that this function does not actually apply these values. To do so, please 67 * write to OVADD. 68 **********************************************************************************************/ 69 static void 70 I830ResetVideo(VADriverContextP ctx, PsbPortPrivPtr pPriv) 71 { 72 INIT_DRIVER_DATA; 73 I830OverlayRegPtr overlayA = (I830OverlayRegPtr)(pPriv->regmap[0]); 74 I830OverlayRegPtr overlayC = (I830OverlayRegPtr)(pPriv->regmap[1]); 75 76 memset(overlayA, 0, sizeof(*overlayA)); 77 memset(overlayC, 0, sizeof(*overlayC)); 78 79 overlayA->OCLRC0 = (pPriv->contrast.Value << 18) | (pPriv->brightness.Value & 0xff); 80 overlayA->OCLRC1 = pPriv->saturation.Value; 81 82 overlayC->OCLRC0 = (pPriv->contrast.Value << 18) | (pPriv->brightness.Value & 0xff); 83 overlayC->OCLRC1 = pPriv->saturation.Value; 84 85 #if USE_DCLRK 86 /* case bit depth 16 */ 87 overlayA->DCLRKV = pPriv->colorKey; 88 overlayA->DCLRKM |= DEST_KEY_ENABLE; 89 overlayA->DCLRKM &= ~CONST_ALPHA_ENABLE; 90 91 overlayC->DCLRKV = pPriv->colorKey; 92 overlayC->DCLRKM |= DEST_KEY_ENABLE; 93 overlayC->DCLRKM &= ~CONST_ALPHA_ENABLE; 94 #else 95 overlayA->DCLRKM &= ~DEST_KEY_ENABLE; 96 overlayC->DCLRKM &= ~DEST_KEY_ENABLE; 97 #endif 98 overlayA->DWINSZ = 0x00000000; 99 overlayA->OCONFIG = CC_OUT_8BIT; 100 101 overlayC->DWINSZ = 0x00000000; 102 overlayC->OCONFIG = CC_OUT_8BIT; 103 } 104 105 static uint32_t I830BoundGammaElt(uint32_t elt, uint32_t eltPrev) 106 { 107 elt &= 0xff; 108 eltPrev &= 0xff; 109 if (elt < eltPrev) 110 elt = eltPrev; 111 else if ((elt - eltPrev) > 0x7e) 112 elt = eltPrev + 0x7e; 113 return elt; 114 } 115 116 static uint32_t I830BoundGamma(uint32_t gamma, uint32_t gammaPrev) 117 { 118 return (I830BoundGammaElt(gamma >> 24, gammaPrev >> 24) << 24 | 119 I830BoundGammaElt(gamma >> 16, gammaPrev >> 16) << 16 | 120 I830BoundGammaElt(gamma >> 8, gammaPrev >> 8) << 8 | 121 I830BoundGammaElt(gamma , gammaPrev)); 122 } 123 124 static void 125 I830UpdateGamma(VADriverContextP ctx, PsbPortPrivPtr pPriv) 126 { 127 #ifndef BAYTRAIL 128 INIT_DRIVER_DATA; 129 uint32_t gamma0 = pPriv->gamma0; 130 uint32_t gamma1 = pPriv->gamma1; 131 uint32_t gamma2 = pPriv->gamma2; 132 uint32_t gamma3 = pPriv->gamma3; 133 uint32_t gamma4 = pPriv->gamma4; 134 uint32_t gamma5 = pPriv->gamma5; 135 struct drm_psb_register_rw_arg regs; 136 137 gamma1 = I830BoundGamma(gamma1, gamma0); 138 gamma2 = I830BoundGamma(gamma2, gamma1); 139 gamma3 = I830BoundGamma(gamma3, gamma2); 140 gamma4 = I830BoundGamma(gamma4, gamma3); 141 gamma5 = I830BoundGamma(gamma5, gamma4); 142 143 memset(®s, 0, sizeof(regs)); 144 if (pPriv->is_mfld) 145 regs.overlay_write_mask |= OV_REGRWBITS_OGAM_ALL | OVC_REGRWBITS_OGAM_ALL; 146 else 147 regs.overlay_write_mask |= OV_REGRWBITS_OGAM_ALL; 148 regs.overlay.OGAMC0 = gamma0; 149 regs.overlay.OGAMC1 = gamma1; 150 regs.overlay.OGAMC2 = gamma2; 151 regs.overlay.OGAMC3 = gamma3; 152 regs.overlay.OGAMC4 = gamma4; 153 regs.overlay.OGAMC5 = gamma5; 154 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 155 #endif 156 } 157 158 static void I830StopVideo(VADriverContextP ctx) 159 { 160 #ifndef BAYTRAIL 161 INIT_DRIVER_DATA; 162 PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv); 163 I830OverlayRegPtr overlayA, overlayC; 164 struct drm_psb_register_rw_arg regs; 165 166 if (!pPriv->overlayA_enabled && !pPriv->overlayC_enabled) { 167 drv_debug_msg(VIDEO_DEBUG_GENERAL, "I830StopVideo : no overlay has been enabled, do nothing.\n"); 168 return; 169 } 170 171 overlayA = (I830OverlayRegPtr)(pPriv->regmap[0]); 172 overlayC = (I830OverlayRegPtr)(pPriv->regmap[1]); 173 #if 0 174 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 175 #endif 176 memset(®s, 0, sizeof(regs)); 177 if (pPriv->subpicture_enabled) { 178 regs.subpicture_disable_mask = pPriv->subpicture_enable_mask; 179 pPriv->subpicture_enabled = 0; 180 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 181 } 182 183 memset(®s, 0, sizeof(regs)); 184 185 if (pPriv->is_mfld && psb_xrandr_single_mode() == 0) { 186 if (pPriv->overlayC_enabled) { 187 regs.overlay_read_mask = OVC_REGRWBITS_OVADD; 188 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 189 190 overlayC->DWINSZ = 0x00000000; 191 overlayC->OCMD &= ~OVERLAY_ENABLE; 192 regs.overlay_read_mask = 0; 193 regs.overlay_write_mask = OVC_REGRWBITS_OVADD; 194 regs.overlay.b_wait_vblank = 1; 195 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 196 197 memset(®s, 0, sizeof(regs)); 198 pPriv->overlayC_enabled = 0; 199 } 200 if (pPriv->overlayA_enabled) { 201 regs.overlay_read_mask = OV_REGRWBITS_OVADD; 202 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 203 204 overlayA->DWINSZ = 0x00000000; 205 overlayA->OCMD &= ~OVERLAY_ENABLE; 206 regs.overlay_read_mask = 0; 207 regs.overlay_write_mask = OV_REGRWBITS_OVADD; 208 regs.overlay.b_wait_vblank = 1; 209 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 210 pPriv->overlayA_enabled = 0; 211 } 212 } else { 213 regs.overlay_read_mask = OV_REGRWBITS_OVADD; 214 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 215 216 overlayA->DWINSZ = 0x00000000; 217 overlayA->OCMD &= ~OVERLAY_ENABLE; 218 regs.overlay_read_mask = 0; 219 regs.overlay_write_mask = OV_REGRWBITS_OVADD; 220 regs.overlay.b_wait_vblank = 1; 221 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 222 pPriv->overlayA_enabled = 0; 223 } 224 #endif 225 } 226 227 #if 0 228 static void I830SwitchPipe(VADriverContextP ctx , int overlayId, int pipeId) 229 { 230 INIT_DRIVER_DATA; 231 PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv); 232 I830OverlayRegPtr overlay = (I830OverlayRegPtr)(pPriv->regmap[overlayId]); 233 struct drm_psb_register_rw_arg regs; 234 uint32_t overlay_mask; 235 236 if ((overlayId == OVERLAY_A) && pPriv->overlayA_enabled) 237 overlay_mask = OV_REGRWBITS_OVADD; 238 else if ((overlayId == OVERLAY_C) && pPriv->overlayC_enabled) 239 overlay_mask = OVC_REGRWBITS_OVADD; 240 else 241 return; /*No overlay enabled, do nothing.*/ 242 243 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Overlay %d switch to pipe %d\n", overlayId, pipeId); 244 memset(®s, 0, sizeof(regs)); 245 memset(overlay, 0, sizeof(*overlay)); 246 overlay->OCLRC0 = (pPriv->contrast.Value << 18) | (pPriv->brightness.Value & 0xff); 247 overlay->OCLRC1 = pPriv->saturation.Value; 248 249 /* case bit depth 16 */ 250 overlay->DCLRKV = pPriv->colorKey; 251 overlay->DCLRKM |= DEST_KEY_ENABLE; 252 overlay->DCLRKM &= ~CONST_ALPHA_ENABLE; 253 overlay->DWINSZ = 0x00000000; 254 overlay->OCONFIG = CC_OUT_8BIT; 255 256 regs.overlay_read_mask = overlay_mask; 257 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 258 259 switch (pipeId) { 260 case PIPEA: 261 overlay->OCONFIG |= OVERLAY_C_PIPE_A; 262 break; 263 case PIPEB: 264 overlay->OCONFIG |= OVERLAY_C_PIPE_B; 265 break; 266 case PIPEC: 267 overlay->OCONFIG |= OVERLAY_C_PIPE_C; 268 break; 269 } 270 regs.overlay_read_mask = 0; 271 regs.overlay_write_mask = overlay_mask; 272 regs.overlay.b_wait_vblank = 1; 273 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 274 } 275 #endif 276 277 static int 278 i830_swidth(unsigned int offset, unsigned int width, unsigned int mask, int shift) 279 { 280 int swidth = ((offset + width + mask) >> shift) - (offset >> shift); 281 swidth <<= 1; 282 swidth -= 1; 283 return swidth << 2; 284 } 285 286 static Bool 287 SetCoeffRegs(double *coeff, int mantSize, coeffPtr pCoeff, int pos) 288 { 289 int maxVal, icoeff, res; 290 int sign; 291 double c; 292 293 sign = 0; 294 maxVal = 1 << mantSize; 295 c = *coeff; 296 if (c < 0.0) { 297 sign = 1; 298 c = -c; 299 } 300 301 res = 12 - mantSize; 302 if ((icoeff = (int)(c * 4 * maxVal + 0.5)) < maxVal) { 303 pCoeff[pos].exponent = 3; 304 pCoeff[pos].mantissa = icoeff << res; 305 *coeff = (double)icoeff / (double)(4 * maxVal); 306 } else if ((icoeff = (int)(c * 2 * maxVal + 0.5)) < maxVal) { 307 pCoeff[pos].exponent = 2; 308 pCoeff[pos].mantissa = icoeff << res; 309 *coeff = (double)icoeff / (double)(2 * maxVal); 310 } else if ((icoeff = (int)(c * maxVal + 0.5)) < maxVal) { 311 pCoeff[pos].exponent = 1; 312 pCoeff[pos].mantissa = icoeff << res; 313 *coeff = (double)icoeff / (double)(maxVal); 314 } else if ((icoeff = (int)(c * maxVal * 0.5 + 0.5)) < maxVal) { 315 pCoeff[pos].exponent = 0; 316 pCoeff[pos].mantissa = icoeff << res; 317 *coeff = (double)icoeff / (double)(maxVal / 2); 318 } else { 319 /* Coeff out of range */ 320 return FALSE; 321 } 322 323 pCoeff[pos].sign = sign; 324 if (sign) 325 *coeff = -(*coeff); 326 return TRUE; 327 } 328 329 static void 330 UpdateCoeff(int taps, double fCutoff, Bool isHoriz, Bool isY, coeffPtr pCoeff) 331 { 332 int i, j, j1, num, pos, mantSize; 333 double pi = 3.1415926535, val, sinc, window, sum; 334 double rawCoeff[MAX_TAPS * 32], coeffs[N_PHASES][MAX_TAPS]; 335 double diff; 336 int tapAdjust[MAX_TAPS], tap2Fix; 337 Bool isVertAndUV; 338 339 if (isHoriz) 340 mantSize = 7; 341 else 342 mantSize = 6; 343 344 isVertAndUV = !isHoriz && !isY; 345 num = taps * 16; 346 for (i = 0; i < num * 2; i++) { 347 val = (1.0 / fCutoff) * taps * pi * (i - num) / (2 * num); 348 if (val == 0.0) 349 sinc = 1.0; 350 else 351 sinc = sin(val) / val; 352 353 /* Hamming window */ 354 window = (0.5 - 0.5 * cos(i * pi / num)); 355 rawCoeff[i] = sinc * window; 356 } 357 358 for (i = 0; i < N_PHASES; i++) { 359 /* Normalise the coefficients. */ 360 sum = 0.0; 361 for (j = 0; j < taps; j++) { 362 pos = i + j * 32; 363 sum += rawCoeff[pos]; 364 } 365 for (j = 0; j < taps; j++) { 366 pos = i + j * 32; 367 coeffs[i][j] = rawCoeff[pos] / sum; 368 } 369 370 /* Set the register values. */ 371 for (j = 0; j < taps; j++) { 372 pos = j + i * taps; 373 if ((j == (taps - 1) / 2) && !isVertAndUV) 374 SetCoeffRegs(&coeffs[i][j], mantSize + 2, pCoeff, pos); 375 else 376 SetCoeffRegs(&coeffs[i][j], mantSize, pCoeff, pos); 377 } 378 379 tapAdjust[0] = (taps - 1) / 2; 380 for (j = 1, j1 = 1; j <= tapAdjust[0]; j++, j1++) { 381 tapAdjust[j1] = tapAdjust[0] - j; 382 tapAdjust[++j1] = tapAdjust[0] + j; 383 } 384 385 /* Adjust the coefficients. */ 386 sum = 0.0; 387 for (j = 0; j < taps; j++) 388 sum += coeffs[i][j]; 389 if (sum != 1.0) { 390 for (j1 = 0; j1 < taps; j1++) { 391 tap2Fix = tapAdjust[j1]; 392 diff = 1.0 - sum; 393 coeffs[i][tap2Fix] += diff; 394 pos = tap2Fix + i * taps; 395 if ((tap2Fix == (taps - 1) / 2) && !isVertAndUV) 396 SetCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos); 397 else 398 SetCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos); 399 400 sum = 0.0; 401 for (j = 0; j < taps; j++) 402 sum += coeffs[i][j]; 403 if (sum == 1.0) 404 break; 405 } 406 } 407 } 408 } 409 410 static void 411 i830_display_video( 412 VADriverContextP ctx, PsbPortPrivPtr pPriv, VASurfaceID __maybe_unused surface, 413 int id, short width, short height, 414 int dstPitch, int srcPitch, int __maybe_unused x1, int __maybe_unused y1, int __maybe_unused x2, int __maybe_unused y2, BoxPtr dstBox, 415 short src_w, short src_h, short drw_w, short drw_h, 416 unsigned int flags, int overlayId, int pipeId) 417 { 418 #ifndef BAYTRAIL 419 INIT_DRIVER_DATA; 420 unsigned int swidth, swidthy, swidthuv; 421 unsigned int mask, shift, offsety, offsetu; 422 int tmp; 423 uint32_t OCMD; 424 Bool scaleChanged = FALSE; 425 unsigned int offset = wsbmBOOffsetHint(pPriv->wsbo[overlayId]) & 0x0FFFFFFF; 426 I830OverlayRegPtr overlay = (I830OverlayRegPtr)(pPriv->regmap[overlayId]); 427 struct drm_psb_register_rw_arg regs; 428 int i32EnableIEP = 0; 429 int i32EnableIEPBLE = 0; 430 431 /*before enabling overlay, make sure overlay is disabled first.*/ 432 if ((overlayId == OVERLAY_A) && !pPriv->overlayA_enabled) { 433 memset(®s, 0, sizeof(regs)); 434 regs.overlay_read_mask = OV_REGRWBITS_OVADD; 435 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 436 437 overlay->OCMD &= ~OVERLAY_ENABLE; 438 regs.overlay_read_mask = 0; 439 regs.overlay_write_mask = OV_REGRWBITS_OVADD; 440 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 441 } 442 443 /* FIXME: don't know who and why add this 444 * comment it for full screen scale issue 445 * any concern contact qiang.miao (at) intel.com 446 */ 447 #if 0 448 if (drw_w >= 800) { 449 x2 = x2 / 4; 450 y2 = y2 / 4; 451 dstBox->x2 = dstBox->x2 / 4; 452 dstBox->y2 = dstBox->y2 / 4; 453 drw_w = drw_w / 4; 454 drw_h = drw_h / 4; 455 } 456 #endif 457 458 #if USE_DCLRK 459 overlay->DCLRKM &= ~CONST_ALPHA_ENABLE; 460 if (pPriv->subpicture_enabled) 461 overlay->DCLRKM &= ~DEST_KEY_ENABLE; 462 else 463 overlay->DCLRKM |= DEST_KEY_ENABLE; 464 overlay->DCLRKV = pPriv->colorKey; 465 overlay->DCLRKM |= 0xffffff; 466 #else 467 /* disable overlay destination color key didn't work, 468 * it seems z-order of overlay has been bellow display pipe. 469 */ 470 overlay->DCLRKM &= ~DEST_KEY_ENABLE; 471 #endif 472 473 #if USE_ROTATION_FUNC 474 if (((pipeId == PIPEA) && (driver_data->mipi0_rotation != VA_ROTATION_NONE)) || 475 ((pipeId == PIPEB) && (driver_data->hdmi_rotation != VA_ROTATION_NONE))) { 476 switch (pPriv->rotation) { 477 case VA_ROTATION_NONE: 478 break; 479 case VA_ROTATION_270: 480 tmp = dstBox->x1; 481 dstBox->x1 = dstBox->y1; 482 dstBox->y1 = pPriv->height_save - tmp; 483 tmp = dstBox->x2; 484 dstBox->x2 = dstBox->y2; 485 dstBox->y2 = pPriv->height_save - tmp; 486 tmp = dstBox->y1; 487 dstBox->y1 = dstBox->y2; 488 dstBox->y2 = tmp; 489 tmp = drw_w; 490 drw_w = drw_h; 491 drw_h = tmp; 492 break; 493 case VA_ROTATION_180: 494 tmp = dstBox->x1; 495 dstBox->x1 = pPriv->width_save - dstBox->x2; 496 dstBox->x2 = pPriv->width_save - tmp; 497 tmp = dstBox->y1; 498 dstBox->y1 = pPriv->height_save - dstBox->y2; 499 dstBox->y2 = pPriv->height_save - tmp; 500 break; 501 case VA_ROTATION_90: 502 tmp = dstBox->x1; 503 dstBox->x1 = pPriv->width_save - dstBox->y1; 504 dstBox->y1 = tmp; 505 tmp = dstBox->x2; 506 dstBox->x2 = pPriv->width_save - dstBox->y2; 507 dstBox->y2 = tmp; 508 tmp = dstBox->x1; 509 dstBox->x1 = dstBox->x2; 510 dstBox->x2 = tmp; 511 tmp = drw_w; 512 drw_w = drw_h; 513 drw_h = tmp; 514 break; 515 } 516 } 517 #endif 518 519 if (pPriv->oneLineMode) { 520 /* change the coordinates with panel fitting active */ 521 dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1; 522 dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1; 523 524 /* Now, alter the height, so we scale to the correct size */ 525 drw_h = ((drw_h * pPriv->scaleRatio) >> 16) + 1; 526 } 527 528 shift = 6; 529 mask = 0x3f; 530 531 if (pPriv->curBuf == 0) { 532 offsety = pPriv->YBuf0offset; 533 offsetu = pPriv->UBuf0offset; 534 } else { 535 offsety = pPriv->YBuf1offset; 536 offsetu = pPriv->UBuf1offset; 537 } 538 539 switch (id) { 540 case VA_FOURCC_NV12: 541 overlay->SWIDTH = width | ((width / 2 & 0x7ff) << 16); 542 swidthy = i830_swidth(offsety, width, mask, shift); 543 swidthuv = i830_swidth(offsetu, width / 2, mask, shift); 544 overlay->SWIDTHSW = (swidthy) | (swidthuv << 16); 545 overlay->SHEIGHT = height | ((height / 2) << 16); 546 break; 547 case VA_FOURCC_YV12: 548 case VA_FOURCC_I420: 549 overlay->SWIDTH = width | ((width / 2 & 0x7ff) << 16); 550 swidthy = i830_swidth(offsety, width, mask, shift); 551 swidthuv = i830_swidth(offsetu, width / 2, mask, shift); 552 overlay->SWIDTHSW = (swidthy) | (swidthuv << 16); 553 overlay->SHEIGHT = height | ((height / 2) << 16); 554 break; 555 case VA_FOURCC_UYVY: 556 case VA_FOURCC_YUY2: 557 default: 558 overlay->SWIDTH = width; 559 swidth = ((offsety + (width << 1) + mask) >> shift) - 560 (offsety >> shift); 561 562 swidth <<= 1; 563 swidth -= 1; 564 swidth <<= 2; 565 566 overlay->SWIDTHSW = swidth; 567 overlay->SHEIGHT = height; 568 break; 569 } 570 571 overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1; 572 573 overlay->DWINSZ = (((dstBox->y2 - dstBox->y1) << 16) | 574 (dstBox->x2 - dstBox->x1)); 575 576 /* buffer locations */ 577 overlay->OBUF_0Y = pPriv->YBuf0offset; 578 overlay->OBUF_0U = pPriv->UBuf0offset; 579 overlay->OBUF_0V = pPriv->VBuf0offset; 580 overlay->OBUF_1Y = pPriv->YBuf1offset; 581 overlay->OBUF_1U = pPriv->UBuf1offset; 582 overlay->OBUF_1V = pPriv->VBuf1offset; 583 584 /* 585 * Calculate horizontal and vertical scaling factors and polyphase 586 * coefficients. 587 */ 588 589 if (1) { 590 int xscaleInt, xscaleFract, yscaleInt, yscaleFract; 591 int xscaleIntUV, xscaleFractUV; 592 int yscaleIntUV, yscaleFractUV; 593 /* UV is half the size of Y -- YUV420 */ 594 int uvratio = 2; 595 uint32_t newval; 596 coeffRec xcoeffY[N_HORIZ_Y_TAPS * N_PHASES]; 597 coeffRec xcoeffUV[N_HORIZ_UV_TAPS * N_PHASES]; 598 int i, j, pos; 599 int deinterlace_factor; 600 601 /* 602 * Y down-scale factor as a multiple of 4096. 603 */ 604 if ((id == VA_FOURCC_NV12) && (0 != (flags & (VA_TOP_FIELD | VA_BOTTOM_FIELD)))) 605 deinterlace_factor = 2; 606 else 607 deinterlace_factor = 1; 608 609 /* deinterlace requires twice of VSCALE setting*/ 610 if (src_w == drw_w && src_h == drw_h) { 611 xscaleFract = 1 << 12; 612 yscaleFract = (1 << 12) / deinterlace_factor; 613 } else { 614 xscaleFract = ((src_w - 1) << 12) / drw_w; 615 yscaleFract = ((src_h - 1) << 12) / (deinterlace_factor * drw_h); 616 } 617 618 /* Calculate the UV scaling factor. */ 619 xscaleFractUV = xscaleFract / uvratio; 620 yscaleFractUV = yscaleFract / uvratio; 621 622 /* 623 * To keep the relative Y and UV ratios exact, round the Y scales 624 * to a multiple of the Y/UV ratio. 625 */ 626 xscaleFract = xscaleFractUV * uvratio; 627 yscaleFract = yscaleFractUV * uvratio; 628 629 /* Integer (un-multiplied) values. */ 630 xscaleInt = xscaleFract >> 12; 631 yscaleInt = yscaleFract >> 12; 632 633 xscaleIntUV = xscaleFractUV >> 12; 634 yscaleIntUV = yscaleFractUV >> 12; 635 636 /* shouldn't get here */ 637 if (xscaleInt > 7) { 638 return; 639 } 640 641 /* shouldn't get here */ 642 if (xscaleIntUV > 7) { 643 return; 644 } 645 646 if (pPriv->is_mfld) 647 newval = (xscaleInt << 15) | 648 ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20); 649 else 650 newval = (xscaleInt << 16) | 651 ((xscaleFract & 0xFFF) << 3) | ((yscaleFract & 0xFFF) << 20); 652 653 if (newval != overlay->YRGBSCALE) { 654 scaleChanged = TRUE; 655 overlay->YRGBSCALE = newval; 656 } 657 658 if (pPriv->is_mfld) 659 newval = (xscaleIntUV << 15) | ((xscaleFractUV & 0xFFF) << 3) | 660 ((yscaleFractUV & 0xFFF) << 20); 661 else 662 newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) | 663 ((yscaleFractUV & 0xFFF) << 20); 664 665 if (newval != overlay->UVSCALE) { 666 scaleChanged = TRUE; 667 overlay->UVSCALE = newval; 668 } 669 670 newval = yscaleInt << 16 | yscaleIntUV; 671 if (newval != overlay->UVSCALEV) { 672 scaleChanged = TRUE; 673 overlay->UVSCALEV = newval; 674 } 675 676 /* Recalculate coefficients if the scaling changed. */ 677 678 /* 679 * Only Horizontal coefficients so far. 680 */ 681 if (scaleChanged) { 682 double fCutoffY; 683 double fCutoffUV; 684 685 fCutoffY = xscaleFract / 4096.0; 686 fCutoffUV = xscaleFractUV / 4096.0; 687 688 /* Limit to between 1.0 and 3.0. */ 689 if (fCutoffY < MIN_CUTOFF_FREQ) 690 fCutoffY = MIN_CUTOFF_FREQ; 691 if (fCutoffY > MAX_CUTOFF_FREQ) 692 fCutoffY = MAX_CUTOFF_FREQ; 693 if (fCutoffUV < MIN_CUTOFF_FREQ) 694 fCutoffUV = MIN_CUTOFF_FREQ; 695 if (fCutoffUV > MAX_CUTOFF_FREQ) 696 fCutoffUV = MAX_CUTOFF_FREQ; 697 698 UpdateCoeff(N_HORIZ_Y_TAPS, fCutoffY, TRUE, TRUE, xcoeffY); 699 UpdateCoeff(N_HORIZ_UV_TAPS, fCutoffUV, TRUE, FALSE, xcoeffUV); 700 701 for (i = 0; i < N_PHASES; i++) { 702 for (j = 0; j < N_HORIZ_Y_TAPS; j++) { 703 pos = i * N_HORIZ_Y_TAPS + j; 704 overlay->Y_HCOEFS[pos] = (xcoeffY[pos].sign << 15 | 705 xcoeffY[pos].exponent << 12 | 706 xcoeffY[pos].mantissa); 707 } 708 } 709 for (i = 0; i < N_PHASES; i++) { 710 for (j = 0; j < N_HORIZ_UV_TAPS; j++) { 711 pos = i * N_HORIZ_UV_TAPS + j; 712 overlay->UV_HCOEFS[pos] = (xcoeffUV[pos].sign << 15 | 713 xcoeffUV[pos].exponent << 12 | 714 xcoeffUV[pos].mantissa); 715 } 716 } 717 } 718 } 719 720 OCMD = OVERLAY_ENABLE; 721 722 switch (id) { 723 case VA_FOURCC_NV12: 724 overlay->OSTRIDE = dstPitch | (dstPitch << 16); 725 OCMD &= ~SOURCE_FORMAT; 726 OCMD &= ~OV_BYTE_ORDER; 727 OCMD |= NV12;//in the spec, there are two NV12, which to use? 728 break; 729 case VA_FOURCC_YV12: 730 case VA_FOURCC_I420: 731 /* set UV vertical phase to -0.25 */ 732 /* overlay->UV_VPH = 0x30003000; */ 733 overlay->OSTRIDE = (dstPitch * 2) | (dstPitch << 16); 734 OCMD &= ~SOURCE_FORMAT; 735 OCMD &= ~OV_BYTE_ORDER; 736 OCMD |= YUV_420; 737 break; 738 case VA_FOURCC_UYVY: 739 case VA_FOURCC_YUY2: 740 overlay->OSTRIDE = dstPitch; 741 OCMD &= ~SOURCE_FORMAT; 742 OCMD |= YUV_422; 743 OCMD &= ~OV_BYTE_ORDER; 744 if (id == VA_FOURCC_UYVY) 745 OCMD |= Y_SWAP; 746 break; 747 } 748 749 if (flags & (VA_TOP_FIELD | VA_BOTTOM_FIELD)) { 750 OCMD |= BUF_TYPE_FIELD; 751 OCMD &= ~FIELD_SELECT; 752 753 if (flags & VA_BOTTOM_FIELD) { 754 OCMD |= FIELD1; 755 overlay->OBUF_0Y = pPriv->YBuf0offset - srcPitch; 756 overlay->OBUF_0U = pPriv->UBuf0offset - srcPitch; 757 overlay->OBUF_0V = pPriv->VBuf0offset - srcPitch; 758 overlay->OBUF_1Y = pPriv->YBuf1offset - srcPitch; 759 overlay->OBUF_1U = pPriv->UBuf1offset - srcPitch; 760 overlay->OBUF_1V = pPriv->VBuf1offset - srcPitch; 761 } else 762 OCMD |= FIELD0; 763 } else { 764 OCMD &= ~(FIELD_SELECT); 765 OCMD &= ~BUF_TYPE_FIELD; 766 } 767 768 OCMD &= ~(BUFFER_SELECT); 769 770 if (pPriv->curBuf == 0) 771 OCMD |= BUFFER0; 772 else 773 OCMD |= BUFFER1; 774 775 overlay->OCMD = OCMD; 776 777 memset(®s, 0, sizeof(regs)); 778 switch (overlayId) { 779 case OVERLAY_A: 780 pPriv->overlayA_enabled = 1; 781 regs.overlay_write_mask = OV_REGRWBITS_OVADD; 782 break; 783 case OVERLAY_C: 784 pPriv->overlayC_enabled = 1; 785 regs.overlay_write_mask = OVC_REGRWBITS_OVADD; 786 break; 787 } 788 789 if (pPriv->is_mfld) { 790 i32EnableIEP = 0; 791 792 i32EnableIEPBLE = 0; 793 794 if (i32EnableIEP == 0) { 795 overlay->OCONFIG = CC_OUT_8BIT; 796 overlay->OCONFIG &= OVERLAY_C_PIPE_A | (~OVERLAY_C_PIPE_MASK); 797 overlay->OCONFIG |= IEP_LITE_BYPASS; 798 regs.overlay.OVADD = offset | 1; 799 regs.overlay.IEP_ENABLED = 0; 800 regs.overlay.buffer_handle = wsbmKBufHandle(wsbmKBuf(pPriv->wsbo[overlayId])); 801 } 802 } else { 803 overlay->OCONFIG = CC_OUT_8BIT; 804 overlay->OCONFIG |= IEP_LITE_BYPASS; 805 regs.overlay.OVADD = offset | 1; 806 } 807 808 if (pPriv->is_mfld) { 809 switch (pipeId) { 810 case PIPEA: 811 overlay->OCONFIG |= OVERLAY_C_PIPE_A; 812 overlay->OCONFIG |= ZORDER_TOP; 813 break; 814 case PIPEB: 815 overlay->OCONFIG |= OVERLAY_C_PIPE_B; 816 overlay->OCONFIG |= ZORDER_TOP; 817 regs.overlay.OVADD |= 0x80; 818 break; 819 case PIPEC: 820 overlay->OCONFIG |= OVERLAY_C_PIPE_C; 821 overlay->OCONFIG |= ZORDER_TOP; 822 regs.overlay.OVADD |= 0x40; 823 break; 824 } 825 overlay->OCONFIG |= ZORDER_TOP; 826 } else 827 overlay->OCONFIG |= pipeId << 18; /* mrst */ 828 829 if (IS_CTP(driver_data) || IS_MRFL(driver_data) ) 830 regs.overlay.b_wms = 1; 831 832 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 833 834 if (pPriv->is_mfld) { 835 if (regs.overlay.IEP_ENABLED) { 836 #if 0 837 printf("regs.overlay BLE minmax 0x%x, BSSCC control 0x%x\n", 838 regs.overlay.IEP_BLE_MINMAX, regs.overlay.IEP_BSSCC_CONTROL); 839 #endif 840 *(unsigned int *)((unsigned int)&(overlay->IEP_SPACE[0]) + 0x804) = regs.overlay.IEP_BLE_MINMAX; 841 } 842 } 843 #endif 844 } 845 846 847 static void I830PutImageFlipRotateSurface( 848 VADriverContextP ctx, 849 object_surface_p obj_surface, 850 int *src_w_new, int *src_h_new, 851 int *width_new, int *height_new, 852 psb_surface_p *psb_surface_new, 853 int pipeId) 854 { 855 int src_w = *src_w_new, src_h = *src_h_new; 856 int width = *width_new, height = *height_new; 857 int tmp = 0; 858 859 psb_surface_p psb_surface = NULL; 860 INIT_DRIVER_DATA; 861 PsbPortPrivPtr pPriv; 862 863 /* local/extend display doesn't have render rotation */ 864 if (((pipeId == PIPEA) && (driver_data->local_rotation == VA_ROTATION_NONE)) || 865 ((pipeId == PIPEB) && (driver_data->extend_rotation == VA_ROTATION_NONE))) 866 return; 867 868 pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv); 869 870 if (pipeId == PIPEA) { 871 if (driver_data->local_rotation != VA_ROTATION_NONE) { 872 psb_surface = obj_surface->out_loop_surface; 873 width = obj_surface->width_r; 874 height = obj_surface->height_r; 875 if (driver_data->local_rotation != VA_ROTATION_180) { 876 tmp = src_w; 877 src_w = src_h; 878 src_h = tmp; 879 } 880 } 881 if ((driver_data->local_rotation == VA_ROTATION_NONE) || 882 (driver_data->local_rotation == VA_ROTATION_180)) { 883 pPriv->width_save = pPriv->display_width; 884 pPriv->height_save = pPriv->display_height; 885 } else { 886 pPriv->width_save = pPriv->display_height; 887 pPriv->height_save = pPriv->display_width; 888 } 889 if (driver_data->is_android == 0) 890 pPriv->rotation = driver_data->local_rotation; 891 else 892 pPriv->rotation = 0; 893 } else if (pipeId == PIPEB) { 894 if (driver_data->extend_rotation != VA_ROTATION_NONE) { 895 psb_surface = obj_surface->out_loop_surface; 896 width = obj_surface->width_r; 897 height = obj_surface->height_r; 898 if (driver_data->extend_rotation != VA_ROTATION_180) { 899 tmp = src_w; 900 src_w = src_h; 901 src_h = tmp; 902 } 903 } 904 if ((driver_data->extend_rotation == VA_ROTATION_NONE) || 905 (driver_data->extend_rotation == VA_ROTATION_180)) { 906 pPriv->width_save = pPriv->extend_display_width; 907 pPriv->height_save = pPriv->extend_display_height; 908 } else { 909 pPriv->width_save = pPriv->extend_display_height; 910 pPriv->height_save = pPriv->extend_display_width; 911 } 912 if (driver_data->is_android == 0) 913 pPriv->rotation = driver_data->extend_rotation; 914 else 915 pPriv->rotation = 0; 916 } 917 918 *src_w_new = src_w; 919 *src_h_new = src_h; 920 *width_new = width; 921 *height_new = height; 922 *psb_surface_new = psb_surface; 923 } 924 925 926 static int I830PutImageFlipRotateDebug( 927 VADriverContextP ctx, 928 VASurfaceID surface, 929 short __maybe_unused src_x, short __maybe_unused src_y, 930 short __maybe_unused src_w, short __maybe_unused src_h, 931 short __maybe_unused drw_x, short __maybe_unused drw_y, 932 short __maybe_unused drw_w, short __maybe_unused drw_h, 933 int __maybe_unused fourcc, int __maybe_unused flags, 934 int __maybe_unused overlayId, 935 int pipeId) 936 { 937 INIT_DRIVER_DATA; 938 object_surface_p obj_surface; 939 psb_surface_p psb_surface = NULL; 940 VAStatus vaStatus = VA_STATUS_SUCCESS; 941 942 obj_surface = SURFACE(surface); 943 CHECK_SURFACE(obj_surface); 944 945 if (pipeId != 0) 946 return -1; 947 948 psb_surface = obj_surface->out_loop_surface; 949 psb_buffer_p buf = &psb_surface->buf; 950 unsigned char *data, *chroma, *buffer, *header; 951 static FILE *pf = NULL; 952 int ret, i; 953 if (!psb_surface) 954 goto dump_out; 955 if (pf == NULL) 956 if ((pf = fopen("/home/dump.yuv", "w+")) == NULL) { 957 printf("Open yuv file fails\n"); 958 return -1; 959 } 960 ret = psb_buffer_map(buf, &data); 961 962 if (ret) { 963 printf("Map buffer fail\n"); 964 return -1; 965 } 966 for (i = 0; i < obj_surface->height_r; i++) { 967 fwrite(data, 1, obj_surface->width_r, pf); 968 data += psb_surface->stride; 969 } 970 971 buffer = malloc(obj_surface->height_r * obj_surface->width_r); 972 if (!buffer) { 973 printf("Alloc chroma buffer fail\n"); 974 return -1; 975 } 976 header = buffer; 977 chroma = data; 978 for (i = 0; i < obj_surface->height_r / 2; i++) { 979 int j; 980 for (j = 0; j < obj_surface->width_r / 2; j++) { 981 *buffer++ = data[j*2]; 982 } 983 data += psb_surface->stride; 984 } 985 986 data = chroma; 987 for (i = 0; i < obj_surface->height_r / 2; i++) { 988 int j; 989 for (j = 0; j < obj_surface->width_r / 2; j++) { 990 *buffer++ = data[j*2 + 1]; 991 } 992 data += psb_surface->stride; 993 } 994 995 fwrite(header, obj_surface->height_r / 2, obj_surface->width_r, pf); 996 free(header); 997 psb_buffer_unmap(buf); 998 return 0; 999 1000 dump_out: 1001 return -1; 1002 } 1003 1004 1005 /* 1006 * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h). 1007 * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h). 1008 * id is a fourcc code for the format of the video. 1009 * buf is the pointer to the source data in system memory. 1010 * width and height are the w/h of the source data. 1011 * If "sync" is TRUE, then we must be finished with *buf at the point of return 1012 * (which we always are). 1013 * clipBoxes is the clipping region in screen space. 1014 * data is a pointer to our port private. 1015 * pDraw is a Drawable, which might not be the screen in the case of 1016 * compositing. It's a new argument to the function in the 1.1 server. 1017 */ 1018 static int I830PutImage( 1019 VADriverContextP ctx, 1020 VASurfaceID surface, 1021 int src_x, int src_y, 1022 int src_w, int src_h, 1023 int drw_x, int drw_y, 1024 int drw_w, int drw_h, 1025 int fourcc, int flags, 1026 int overlayId, 1027 int pipeId) 1028 { 1029 INIT_DRIVER_DATA; 1030 int x1, x2, y1, y2; 1031 int width, height; 1032 int top, left, npixels; 1033 int pitch = 0, pitch2 = 0; 1034 unsigned int pre_add; 1035 unsigned int gtt_ofs; 1036 struct _WsbmBufferObject *drm_buf; 1037 BoxRec dstBox; 1038 PsbPortPrivPtr pPriv; 1039 object_surface_p obj_surface = SURFACE(surface); 1040 psb_surface_p psb_surface = NULL; 1041 1042 /* silent kw */ 1043 if (NULL == obj_surface) 1044 return 1; 1045 1046 pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv); 1047 1048 switch (fourcc) { 1049 case VA_FOURCC_NV12: 1050 width = obj_surface->width; 1051 height = obj_surface->height; 1052 break; 1053 default: 1054 width = obj_surface->width; 1055 height = obj_surface->height; 1056 break; 1057 } 1058 1059 /* rotate support here: more check? 1060 * and for oold also? 1061 */ 1062 psb_surface = obj_surface->psb_surface; 1063 I830PutImageFlipRotateSurface(ctx, obj_surface, 1064 &src_w, &src_h, &width, &height, 1065 &psb_surface, pipeId); 1066 1067 if (NULL == psb_surface) { 1068 /*Rotate surface may not be ready, so we have to discard this frame.*/ 1069 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Discard this frame if rotate surface hasn't be ready.\n"); 1070 1071 return 1; 1072 } 1073 width = (width <= 1920) ? width : 1920; 1074 1075 /* If dst width and height are less than 1/8th the src size, the 1076 * src/dst scale factor becomes larger than 8 and doesn't fit in 1077 * the scale register. 1078 */ 1079 if (src_w >= (drw_w * 8)) 1080 drw_w = src_w / 7; 1081 1082 if (src_h >= (drw_h * 8)) 1083 drw_h = src_h / 7; 1084 1085 /* Clip */ 1086 x1 = src_x; 1087 x2 = src_x + src_w; 1088 y1 = src_y; 1089 y2 = src_y + src_h; 1090 1091 dstBox.x1 = drw_x; 1092 dstBox.x2 = drw_x + drw_w; 1093 dstBox.y1 = drw_y; 1094 dstBox.y2 = drw_y + drw_h; 1095 1096 #if USE_CLIP_FUNC 1097 if (!i830_get_crtc(pScrn, &crtc, &dstBox)) 1098 return Success; 1099 1100 /* 1101 *Update drw_* and 'clipBoxes' according to current downscale/upscale state 1102 * Make sure the area determined by drw_* is in 'clipBoxes' 1103 */ 1104 if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 1105 h_ratio = (float)pScrn->pScreen->height / pPriv->width_save; 1106 v_ratio = (float)pScrn->pScreen->width / pPriv->height_save; 1107 } else { 1108 h_ratio = (float)pScrn->pScreen->width / pPriv->width_save; 1109 v_ratio = (float)pScrn->pScreen->height / pPriv->height_save; 1110 } 1111 1112 /* Horizontal downscale/upscale */ 1113 if ((int)h_ratio) 1114 clipBoxes->extents.x1 /= h_ratio; 1115 else if (!(int)h_ratio) 1116 clipBoxes->extents.x2 /= h_ratio; 1117 1118 /* Vertical downscale/upscale */ 1119 if ((int)v_ratio) 1120 clipBoxes->extents.y1 /= v_ratio; 1121 else if (!(int)v_ratio) 1122 clipBoxes->extents.y2 /= v_ratio; 1123 1124 drw_x /= h_ratio; 1125 drw_y /= v_ratio; 1126 drw_w /= h_ratio; 1127 drw_h /= v_ratio; 1128 1129 dstBox.x1 = drw_x; 1130 dstBox.x2 = drw_x + drw_w; 1131 dstBox.y1 = drw_y; 1132 dstBox.y2 = drw_y + drw_h; 1133 1134 /* Count in client supplied clipboxes */ 1135 clipRegion = clipBoxes; 1136 psb_perform_clip(pScrn, vaPtr->clipbox, vaPtr->num_clipbox, clipBoxes, clipRegion, pDraw); 1137 1138 if (!i830_clip_video_helper(pScrn, 1139 &crtc, 1140 &dstBox, &x1, &x2, &y1, &y2, clipRegion, 1141 width, height)) { 1142 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: Fail to clip video to any crtc!\n", __FUNCTION__); 1143 return 0; 1144 } 1145 #endif 1146 1147 switch (fourcc) { 1148 case VA_FOURCC_NV12: 1149 pitch = (width + 0x3) & ~0x3; 1150 pitch2 = psb_surface->stride; 1151 break; 1152 case VA_FOURCC_YV12: 1153 case VA_FOURCC_I420: 1154 pitch = (width + 0x3) & ~0x3; 1155 break; 1156 #if USE_DISPLAY_C_SPRITE 1157 case FOURCC_RGBA: 1158 pitch = width << 2; 1159 break; 1160 #endif 1161 case VA_FOURCC_UYVY: 1162 case VA_FOURCC_YUY2: 1163 default: 1164 pitch = width << 1; 1165 break; 1166 } 1167 1168 top = (y1) & ~1; 1169 left = (x1) & ~1; 1170 npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; 1171 1172 if (fourcc == VA_FOURCC_NV12) { 1173 pre_add = psb_surface->buf.buffer_ofs; 1174 drm_buf = psb_surface->buf.drm_buf; 1175 gtt_ofs = wsbmBOOffsetHint(drm_buf) & 0x0FFFFFFF; 1176 1177 /*skip pad bytes.*/ 1178 if (driver_data->local_rotation == VA_ROTATION_90) { 1179 left += ((src_w + 0xf) & ~0xf) - src_w; 1180 } else if (driver_data->local_rotation == VA_ROTATION_270) { 1181 top += ((src_h + 0xf) & ~0xf) - src_h; 1182 } else if (driver_data->local_rotation == VA_ROTATION_180) { 1183 left += ((src_w + 0xf) & ~0xf) - src_w; 1184 top += ((src_h + 0xf) & ~0xf) - src_h; 1185 } 1186 pPriv->YBuf0offset = pre_add + gtt_ofs + top * pitch2 + left; 1187 pPriv->YBuf1offset = pPriv->YBuf0offset; 1188 pPriv->UBuf0offset = pre_add + gtt_ofs + (pitch2 * height) + top * (pitch2 / 2) + left; 1189 pPriv->VBuf0offset = pPriv->UBuf0offset; 1190 pPriv->UBuf1offset = pPriv->UBuf0offset; 1191 pPriv->VBuf1offset = pPriv->UBuf0offset; 1192 } else { 1193 //TBD 1194 //pPriv->YBuf0offset = pPriv->videoBuf0_gtt_offset << PAGE_SHIFT; 1195 //pPriv->YBuf1offset = pPriv->videoBuf1_gtt_offset << PAGE_SHIFT; 1196 if (pPriv->rotation & (RR_Rotate_90 | RR_Rotate_270)) { 1197 pPriv->UBuf0offset = pPriv->YBuf0offset + (pitch2 * width); 1198 pPriv->VBuf0offset = pPriv->UBuf0offset + (pitch2 * width / 2); 1199 pPriv->UBuf1offset = pPriv->YBuf1offset + (pitch2 * width); 1200 pPriv->VBuf1offset = pPriv->UBuf1offset + (pitch2 * width / 2); 1201 } else { 1202 pPriv->UBuf0offset = pPriv->YBuf0offset + (pitch2 * height); 1203 pPriv->VBuf0offset = pPriv->UBuf0offset + (pitch2 * height / 2); 1204 pPriv->UBuf1offset = pPriv->YBuf1offset + (pitch2 * height); 1205 pPriv->VBuf1offset = pPriv->UBuf1offset + (pitch2 * height / 2); 1206 } 1207 } 1208 1209 #if USE_DISPLAY_C_SPRITE 1210 if (fourcc == FOURCC_RGBA \ 1211 || (fourcc == FOURCC_XVVA \ 1212 && (pPriv->rotation != RR_Rotate_0) \ 1213 && (vaPtr->dst_srf.fourcc == VA_FOURCC_RGBA))) 1214 i830_display_video_sprite(pScrn, crtc, width, height, dstPitch, 1215 &dstBox, sprite_offset); 1216 else 1217 #endif 1218 i830_display_video(ctx, pPriv, surface, fourcc, src_w, src_h, pitch2, pitch, 1219 x1, y1, x2, y2, &dstBox, src_w, src_h, 1220 drw_w, drw_h, flags, overlayId, pipeId); 1221 1222 // FIXME : do I use two buffers here really? 1223 // pPriv->curBuf = (pPriv->curBuf + 1) & 1; 1224 1225 return Success; 1226 } 1227 1228 1229 1230 static void psbPortPrivCreate(PsbPortPrivPtr pPriv) 1231 { 1232 #if 0 1233 REGION_NULL(pScreen, &pPriv->clip); 1234 #endif 1235 1236 /* coeffs defaut value */ 1237 pPriv->brightness.Value = OV_BRIGHTNESS_DEFAULT_VALUE; 1238 pPriv->brightness.Fraction = 0; 1239 1240 pPriv->contrast.Value = OV_CONTRAST_DEFAULT_VALUE; 1241 pPriv->contrast.Fraction = 0; 1242 1243 pPriv->hue.Value = OV_HUE_DEFAULT_VALUE; 1244 pPriv->hue.Fraction = 0; 1245 1246 pPriv->saturation.Value = OV_SATURATION_DEFAULT_VALUE; 1247 pPriv->saturation.Fraction = 0; 1248 pPriv->subpicture_enabled = 0; 1249 pPriv->subpicture_enable_mask = 0; 1250 pPriv->overlayA_enabled = 0; 1251 pPriv->overlayC_enabled = 0; 1252 pPriv->overlayA_pipeId = PIPEA; 1253 pPriv->overlayC_pipeId = PIPEB; 1254 1255 /* FIXME: is this right? set up to current screen size */ 1256 #if 1 1257 pPriv->width_save = 1024; 1258 pPriv->height_save = 600; 1259 #endif 1260 } 1261 1262 static void 1263 psbPortPrivDestroy(VADriverContextP ctx, PsbPortPrivPtr pPriv) 1264 { 1265 I830StopVideo(ctx); 1266 1267 wsbmBOUnmap(pPriv->wsbo[0]); 1268 wsbmBOUnreference(&pPriv->wsbo[0]); 1269 wsbmBOUnmap(pPriv->wsbo[1]); 1270 wsbmBOUnreference(&pPriv->wsbo[1]); 1271 if (pPriv->is_mfld) { 1272 if (pPriv->p_iep_lite_context) 1273 free(pPriv->p_iep_lite_context); 1274 } 1275 pPriv->p_iep_lite_context = NULL; 1276 } 1277 1278 static int 1279 psbSetupImageVideoOverlay(VADriverContextP ctx, PsbPortPrivPtr pPriv) 1280 { 1281 INIT_DRIVER_DATA; 1282 I830OverlayRegPtr overlayA = NULL; 1283 I830OverlayRegPtr overlayC = NULL; 1284 int ret; 1285 psbPortPrivCreate(pPriv); 1286 1287 1288 /* use green as color key by default for android media player */ 1289 pPriv->colorKey = driver_data->color_key/*0x0440*/; 1290 1291 /*Bypass color correction. Because these color 1292 correction can be done in pipe color correction in future.*/ 1293 pPriv->brightness.Value = 0; /*-19*/ 1294 pPriv->contrast.Value = 0x40; /*75*/ 1295 pPriv->saturation.Value = 0x80; /*146*/ 1296 1297 pPriv->gamma5 = 0xc0c0c0; 1298 pPriv->gamma4 = 0x808080; 1299 pPriv->gamma3 = 0x404040; 1300 pPriv->gamma2 = 0x202020; 1301 pPriv->gamma1 = 0x101010; 1302 pPriv->gamma0 = 0x080808; 1303 1304 pPriv->rotation = VA_ROTATION_NONE; 1305 pPriv->subpic_clear_flag = 1; 1306 #if 0 1307 /* gotta uninit this someplace */ 1308 REGION_NULL(pScreen, &pPriv->clip); 1309 #endif 1310 1311 /* With LFP's we need to detect whether we're in One Line Mode, which 1312 * essentially means a resolution greater than 1024x768, and fix up 1313 * the scaler accordingly. 1314 */ 1315 pPriv->scaleRatio = 0x10000; 1316 pPriv->oneLineMode = FALSE; 1317 1318 ret = wsbmGenBuffers(driver_data->main_pool, 2, 1319 &pPriv->wsbo[0], 64 * 1024, /* 64k alignment */ 1320 WSBM_PL_FLAG_TT); 1321 if (ret) 1322 goto out_err; 1323 1324 ret = wsbmBOData(pPriv->wsbo[0], 1325 5 * 4096, 1326 NULL, NULL, 1327 WSBM_PL_FLAG_TT); 1328 if (ret) 1329 goto out_err_bo0; 1330 1331 pPriv->regmap[0] = wsbmBOMap(pPriv->wsbo[0], WSBM_ACCESS_READ | WSBM_ACCESS_WRITE); 1332 if (!pPriv->regmap[0]) { 1333 goto out_err_bo0; 1334 } 1335 1336 ret = wsbmBOData(pPriv->wsbo[1], 1337 5 * 4096, 1338 NULL, NULL, 1339 WSBM_PL_FLAG_TT); 1340 if (ret) 1341 goto out_err_bo1; 1342 1343 pPriv->regmap[1] = wsbmBOMap(pPriv->wsbo[1], WSBM_ACCESS_READ | WSBM_ACCESS_WRITE); 1344 if (!pPriv->regmap[1]) { 1345 goto out_err_bo1; 1346 } 1347 1348 overlayA = (I830OverlayRegPtr)(pPriv->regmap[0]); 1349 overlayC = (I830OverlayRegPtr)(pPriv->regmap[1]); 1350 1351 if (pPriv->is_mfld) { 1352 driver_data->ble_black_mode.value = 1; 1353 driver_data->ble_white_mode.value = 3; 1354 driver_data->blueStretch_gain.value = 200; 1355 driver_data->skinColorCorrection_gain.value = 100; 1356 driver_data->hue.value = (5.25f * (1 << 25)); 1357 driver_data->saturation.value = (1.07f * (1 << 25)); 1358 driver_data->brightness.value = (-10.1f * (1 << 10)); 1359 driver_data->contrast.value = (0.99f * (1 << 25)); 1360 } 1361 1362 return 0; 1363 1364 out_err_bo1: 1365 wsbmBOUnreference(&pPriv->wsbo[1]); 1366 out_err_bo0: 1367 wsbmBOUnreference(&pPriv->wsbo[0]); 1368 1369 out_err: 1370 return -1; 1371 } 1372 1373 int psb_coverlay_init(VADriverContextP ctx) 1374 { 1375 #ifndef BAYTRAIL 1376 INIT_DRIVER_DATA; 1377 PsbPortPrivPtr pPriv = &driver_data->coverlay_priv; 1378 struct drm_psb_register_rw_arg regs; 1379 int ret; 1380 1381 memset(pPriv, 0, sizeof(PsbPortPrivRec)); 1382 pPriv->is_mfld = (IS_MFLD(driver_data) || IS_MRFL(driver_data)); 1383 1384 ret = psbSetupImageVideoOverlay(ctx, pPriv); 1385 if (ret != 0) { 1386 drv_debug_msg(VIDEO_DEBUG_ERROR, "psb_coverlay_init : Create overlay cmd buffer failed.\n"); 1387 return -1; 1388 } 1389 1390 if (pPriv->is_mfld && driver_data->is_android) { 1391 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Android ExtVideo: set PIPEB(HDMI)display plane on the bottom.\n"); 1392 1393 memset(®s, 0, sizeof(regs)); 1394 regs.display_read_mask = REGRWBITS_DSPBCNTR; 1395 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 1396 regs.display.dspcntr_b |= DISPPLANE_BOTTOM; 1397 regs.display_write_mask = REGRWBITS_DSPBCNTR; 1398 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 1399 } 1400 1401 I830ResetVideo(ctx, pPriv); 1402 I830UpdateGamma(ctx, pPriv); 1403 #endif 1404 return 0; 1405 } 1406 1407 int psb_coverlay_stop(VADriverContextP ctx) 1408 { 1409 I830StopVideo(ctx); 1410 return 0; 1411 } 1412 1413 int psb_coverlay_deinit(VADriverContextP ctx) 1414 { 1415 #ifndef BAYTRAIL 1416 INIT_DRIVER_DATA; 1417 PsbPortPrivPtr pPriv = &driver_data->coverlay_priv; 1418 struct drm_psb_register_rw_arg regs; 1419 1420 if (pPriv->is_mfld && driver_data->is_android) { 1421 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Android ExtVideo: set PIPEB(HDMI)display plane normal.\n"); 1422 1423 memset(®s, 0, sizeof(regs)); 1424 regs.display_read_mask = REGRWBITS_DSPBCNTR; 1425 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 1426 regs.display.dspcntr_b &= ~DISPPLANE_BOTTOM; 1427 regs.display_write_mask = REGRWBITS_DSPBCNTR; 1428 drmCommandWriteRead(driver_data->drm_fd, DRM_PSB_REGISTER_RW, ®s, sizeof(regs)); 1429 } 1430 1431 psbPortPrivDestroy(ctx, pPriv); 1432 #endif 1433 return 0; 1434 } 1435 1436 VAStatus psb_putsurface_overlay( 1437 VADriverContextP ctx, 1438 VASurfaceID surface, 1439 short srcx, 1440 short srcy, 1441 unsigned short srcw, 1442 unsigned short srch, 1443 short destx, 1444 short desty, 1445 unsigned short destw, 1446 unsigned short desth, 1447 unsigned int flags, /* de-interlacing flags */ 1448 int overlayId, 1449 int pipeId 1450 ) 1451 { 1452 INIT_DRIVER_DATA; 1453 object_surface_p obj_surface = SURFACE(surface); 1454 PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv); 1455 #if 0 1456 if ((overlayId == OVERLAY_A) && (pPriv->overlayA_pipeId != pipeId)) { 1457 pPriv->overlayA_pipeId = pipeId; 1458 I830SwitchPipe(ctx, OVERLAY_A, pipeId); 1459 drv_debug_msg(VIDEO_DEBUG_GENERAL, "OverlayA switch pipe to %d, stop overlayA first.\n", pipeId); 1460 } else if ((overlayId == OVERLAY_C) && (pPriv->overlayC_pipeId != pipeId)) { 1461 pPriv->overlayC_pipeId = pipeId; 1462 I830SwitchPipe(ctx, OVERLAY_C, pipeId); 1463 drv_debug_msg(VIDEO_DEBUG_GENERAL, "OverlayC switch pipe to %d, stop overlayC first.\n", pipeId); 1464 } 1465 #endif 1466 I830PutImage(ctx, surface, srcx, srcy, srcw, srch, 1467 destx, desty, destw, desth, 1468 VA_FOURCC_NV12, flags, overlayId, pipeId); 1469 1470 /* current surface is being displayed */ 1471 if (driver_data->cur_displaying_surface != VA_INVALID_SURFACE) 1472 driver_data->last_displaying_surface = driver_data->cur_displaying_surface; 1473 1474 if (obj_surface == NULL) { 1475 drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid surface ID: 0x%08x\n", surface); 1476 return VA_STATUS_ERROR_INVALID_SURFACE; 1477 } 1478 1479 obj_surface->display_timestamp = GetTickCount(); 1480 driver_data->cur_displaying_surface = surface; 1481 1482 return VA_STATUS_SUCCESS; 1483 } 1484