1/* 2 * Copyright 2004-2005 The Unichrome Project [unichrome.sf.net] 3 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 4 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sub license, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26#ifdef HAVE_CONFIG_H 27#include "config.h" 28#endif 29 30#include "xf86.h" 31#include "xf86_OSproc.h" 32 33#ifdef HAVE_DRI 34#include "xf86drm.h" 35#include "via_drmclient.h" 36#include "via_drm.h" 37#endif 38#include "via_driver.h" 39 40#include <math.h> 41#include <unistd.h> 42 43/* 44 * Warning: this file contains revision checks which are CLE266-specific. 45 * There seems to be no checking present for KM400 or more recent devices. 46 * 47 * TODO: 48 * - pVia->Chipset checking, of course 49 * - move content of pVia->HWDiff into pVia->swov 50 * - merge with CLEXF40040 51 */ 52 53/* 54 * Old via_regrec code. 55 */ 56#define VIDREG_BUFFER_SIZE 100 /* Number of entries in the VidRegBuffer. */ 57#define IN_VIDEO_DISPLAY (*((unsigned long volatile *)(pVia->MapBase + V_FLAGS)) & VBI_STATUS) 58#define VIA_FIRETIMEOUT 40000 59 60enum HQV_CME_Regs { 61 HQV_SDO_CTRL1, 62 HQV_SDO_CTRL2, 63 HQV_SDO_CTRL3, 64 HQV_SDO_CTRL4 65}; 66 67/* register offsets for VT3553/VX800 */ 68static const unsigned hqv_cme_regs[] = { 69 [HQV_SDO_CTRL1] = HQV_SRC_DATA_OFFSET_CONTROL1, 70 [HQV_SDO_CTRL2] = HQV_SRC_DATA_OFFSET_CONTROL2, 71 [HQV_SDO_CTRL3] = HQV_SRC_DATA_OFFSET_CONTROL3, 72 [HQV_SDO_CTRL4] = HQV_SRC_DATA_OFFSET_CONTROL4 73}; 74 75/* register hqv offsets for new VT3409/VX855 */ 76static const unsigned hqv_cme_regs_409[] = { 77 [HQV_SDO_CTRL1] = HQV_SRC_DATA_OFFSET_CTRL1_409, 78 [HQV_SDO_CTRL2] = HQV_SRC_DATA_OFFSET_CTRL2_409, 79 [HQV_SDO_CTRL3] = HQV_SRC_DATA_OFFSET_CTRL3_409, 80 [HQV_SDO_CTRL4] = HQV_SRC_DATA_OFFSET_CTRL4_409 81}; 82 83#define HQV_CME_REG(HWDiff, name) (HWDiff)->HQVCmeRegs[name] 84 85static void 86viaWaitVideoCommandFire(VIAPtr pVia) 87{ 88/* 89 * Uncached PCI reading throughput is about 9 MB/s; so 8 bytes/loop means about 90 * 1M loops/second. We want to time out after 50 ms, which means 50000 loops. 91 */ 92 unsigned count = 50000; 93 CARD32 volatile *pdwState = 94 (CARD32 volatile *)(pVia->MapBase + V_COMPOSE_MODE); 95 96 while (--count && ((*pdwState & V1_COMMAND_FIRE) 97 || (*pdwState & V3_COMMAND_FIRE))) ; 98 if (!count) { 99 ErrorF("viaWaitVideoCommandFire: Timeout.\n"); 100 } 101} 102 103static void 104viaWaitHQVFlip(VIAPtr pVia) 105{ 106 unsigned long proReg = 0; 107 CARD32 volatile *pdwState; 108 unsigned count = 50000; 109 110 if (pVia->ChipId == PCI_CHIP_VT3259 111 && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE)) 112 proReg = PRO_HQV1_OFFSET; 113 114 pdwState = (CARD32 volatile *)(pVia->MapBase + (HQV_CONTROL + proReg)); 115 116 if (pVia->VideoEngine == VIDEO_ENGINE_CME) { 117 while (--count && (*pdwState & HQV_SUBPIC_FLIP)); 118 } else { 119 while (--count && !(*pdwState & HQV_FLIP_STATUS)) ; 120 } 121} 122 123static void 124viaWaitHQVFlipClear(VIAPtr pVia, unsigned long dwData) 125{ 126 CARD32 volatile *pdwState = 127 (CARD32 volatile *)(pVia->MapBase + HQV_CONTROL); 128 *pdwState = dwData; 129 unsigned count = 50000; 130 131 while (--count && (*pdwState & HQV_FLIP_STATUS)) { 132 VIASETREG(HQV_CONTROL, *pdwState | HQV_FLIP_STATUS); 133 } 134} 135 136static void 137viaWaitVBI(VIAPtr pVia) 138{ 139 while (IN_VIDEO_DISPLAY) ; 140} 141 142static void 143viaWaitHQVDone(VIAPtr pVia) 144{ 145 CARD32 volatile *pdwState; 146 unsigned long proReg = 0; 147 unsigned count = 50000; 148 149 if (pVia->ChipId == PCI_CHIP_VT3259 150 && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE)) 151 proReg = PRO_HQV1_OFFSET; 152 153 pdwState = (CARD32 volatile *)(pVia->MapBase + (HQV_CONTROL + proReg)); 154 if (pVia->swov.MPEG_ON) { 155 while (--count && (*pdwState & HQV_SW_FLIP)) ; 156 } 157} 158 159/* 160 * Send all data in VidRegBuffer to the hardware. 161 */ 162static void 163FlushVidRegBuffer(VIAPtr pVia) 164{ 165 unsigned int i; 166 167 viaWaitVideoCommandFire(pVia); 168 169 for (i = 0; i < pVia->VidRegCursor; i += 2) { 170 VIASETREG(pVia->VidRegBuffer[i], pVia->VidRegBuffer[i + 1]); 171 DBG_DD(ErrorF("FlushVideoRegs: [%i] %08lx %08lx\n", 172 i >> 1, pVia->VidRegBuffer[i] + 0x200, 173 pVia->VidRegBuffer[i + 1])); 174 } 175 176 /* BUG: (?) VIA never resets the cursor. 177 * My fix is commented out for now, in case they had a reason for that. /A 178 */ 179 /* pVia->VidRegCursor = 0; */ 180} 181 182/* 183 * Initialize and clear VidRegBuffer. 184 */ 185static void 186ResetVidRegBuffer(VIAPtr pVia) 187{ 188 /* BUG: (Memory leak) This allocation may need have a corresponding free somewhere... /A */ 189 if (!pVia->VidRegBuffer) 190 pVia->VidRegBuffer = 191 xnfcalloc(VIDREG_BUFFER_SIZE, sizeof(CARD32) * 2); 192 pVia->VidRegCursor = 0; 193} 194 195/* 196 * Save a video register and data in VidRegBuffer. 197 */ 198static void 199SaveVideoRegister(VIAPtr pVia, CARD32 index, CARD32 data) 200{ 201 if (pVia->VidRegCursor >= VIDREG_BUFFER_SIZE) { 202 DBG_DD(ErrorF("SaveVideoRegister: Out of video register space flushing")); 203 FlushVidRegBuffer(pVia); 204 ResetVidRegBuffer(pVia); 205 } 206 207 pVia->VidRegBuffer[pVia->VidRegCursor++] = index; 208 pVia->VidRegBuffer[pVia->VidRegCursor++] = data; 209} 210 211/* 212 * HW Difference Flag (moved here from via_hwdiff.c) 213 * 214 * These are the entries of HWDiff used in our code (currently): 215 * CLE266Ax CLE266Cx KM400 K8M800 PM800 216 * ThreeHQVBuffer FALSE TRUE TRUE TRUE TRUE 217 * HQVFetchByteUnit FALSE TRUE TRUE TRUE TRUE 218 * SupportTwoColorKey FALSE TRUE FALSE FALSE TRUE 219 * HQVInitPatch TRUE FALSE FALSE FALSE FALSE 220 * HQVDisablePatch FALSE TRUE TRUE TRUE FALSE 221 * 222 * This is now up to date with CLEXF40040. All unused entries were removed. 223 * The functions depending on this struct are untouched. 224 */ 225void 226VIAVidHWDiffInit(ScrnInfoPtr pScrn) 227{ 228 VIAPtr pVia = VIAPTR(pScrn); 229 VIAHWDiff *HWDiff = &pVia->HWDiff; 230 231 switch (pVia->Chipset) { 232 case VIA_CLE266: 233 if (CLE266_REV_IS_AX(pVia->ChipRev)) { 234 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_FALSE; 235 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_FALSE; 236 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE; 237 HWDiff->dwHQVInitPatch = VID_HWDIFF_TRUE; 238 HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE; 239 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 240 } else { 241 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 242 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 243 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE; 244 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 245 HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE; 246 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 247 } 248 HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE; 249 break; 250 case VIA_KM400: 251 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 252 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 253 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE; 254 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 255 HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE; 256 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 257 HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE; 258 break; 259 case VIA_K8M800: 260 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 261 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 262 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE; 263 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 264 HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE; 265 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 266 HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE; 267 break; 268 case VIA_PM800: 269 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 270 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 271 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE; 272 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 273 HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE; 274 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 275 HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE; 276 HWDiff->HQVCmeRegs = hqv_cme_regs; 277 break; 278 case VIA_P4M800PRO: 279 case VIA_P4M900: 280 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 281 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 282 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE; 283 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 284 HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE; 285 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 286 HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE; 287 HWDiff->HQVCmeRegs = hqv_cme_regs; 288 break; 289 case VIA_K8M890: 290 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 291 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 292 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE; 293 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 294 HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE; 295 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_TRUE; 296 HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE; 297 HWDiff->HQVCmeRegs = hqv_cme_regs; 298 break; 299 case VIA_P4M890: 300 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 301 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 302 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE; 303 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 304 HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE; 305 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 306 HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE; 307 HWDiff->HQVCmeRegs = hqv_cme_regs; 308 break; 309 case VIA_CX700: 310 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 311 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 312 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE; 313 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 314 HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE; 315 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 316 HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE; 317 HWDiff->HQVCmeRegs = hqv_cme_regs; 318 break; 319 case VIA_VX800: 320 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 321 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 322 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE; 323 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 324 HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE; 325 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 326 HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE; 327 HWDiff->HQVCmeRegs = hqv_cme_regs; 328 break; 329 case VIA_VX855: 330 case VIA_VX900: 331 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE; 332 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE; 333 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE; 334 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE; 335 HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE; 336 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE; 337 HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE; 338 HWDiff->HQVCmeRegs = hqv_cme_regs_409; 339 break; 340 default: 341 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 342 "VIAVidHWDiffInit: Unhandled ChipSet.\n"); 343 } 344} 345 346/* 347 * Old via_overlay code. 348 */ 349typedef struct _YCBCRREC 350{ 351 CARD32 dwY; 352 CARD32 dwCB; 353 CARD32 dwCR; 354} YCBCRREC; 355 356/* 357 * Verify that using V1 bit definitions on V3 358 * is not broken in OverlayGetV1V3Format(). 359 */ 360 361#if V1_COLORSPACE_SIGN != V3_COLORSPACE_SIGN 362#error "V1_COLORSPACE_SIGN != V3_COLORSPACE_SIGN" 363#endif 364#if V1_YUV422 != V3_YUV422 365#error "V1_YUV422 != V3_YUV422" 366#endif 367#if V1_SWAP_HW_HQV != V3_SWAP_HW_HQV 368#error "V1_SWAP_HW_HQV != V3_SWAP_HW_HQV" 369#endif 370#if V1_RGB15 != V3_RGB15 371#error "V1_RGB15 != V3_RGB15" 372#endif 373#if V1_RGB16 != V3_RGB16 374#error "V1_RGB16 != V3_RGB16" 375#endif 376#if V1_RGB32 != V3_RGB32 377#error "V1_RGB32 != V3_RGB32" 378#endif 379 380static BOOL 381viaOverlayGetV1V3Format(VIAPtr pVia, int vport, /* 1 or 3, as in V1 or V3 */ 382 unsigned long videoFlag, unsigned long *pVidCtl, 383 unsigned long *pHQVCtl) 384{ 385 if (videoFlag & VIDEO_HQV_INUSE) { 386 switch (pVia->swov.SrcFourCC) { 387 case FOURCC_YV12: 388 case FOURCC_I420: 389 case FOURCC_XVMC: 390 *pHQVCtl |= HQV_YUV420; 391 break; 392 case FOURCC_YUY2: 393 *pHQVCtl |= HQV_YUV422; 394 break; 395 case FOURCC_RV32: 396 *pVidCtl |= V1_RGB32; 397 *pHQVCtl |= HQV_RGB32; 398 break; 399 case FOURCC_RV15: 400 *pVidCtl |= V1_RGB15; 401 *pHQVCtl |= HQV_RGB15; 402 break; 403 case FOURCC_RV16: 404 *pVidCtl |= V1_RGB16; 405 *pHQVCtl |= HQV_RGB16; 406 break; 407 default: 408 DBG_DD(ErrorF("viaOverlayGetV1V3Format: " 409 "Invalid FOURCC format (0x%lx).\n", 410 pVia->swov.SrcFourCC)); 411 return FALSE; 412 } 413 *pVidCtl |= V1_SWAP_HW_HQV; 414 *pHQVCtl |= HQV_SRC_SW | HQV_ENABLE | HQV_SW_FLIP; 415 } else { 416 switch (pVia->swov.SrcFourCC) { 417 case FOURCC_YV12: 418 case FOURCC_I420: 419 case FOURCC_XVMC: 420 if (vport == 1) { 421 *pVidCtl |= V1_YCbCr420; 422 } else { 423 DBG_DD(ErrorF("viaOverlayGetV1V3Format: " 424 "V3 does not support planar YUV.\n")); 425 return FALSE; 426 } 427 break; 428 case FOURCC_YUY2: 429 *pVidCtl |= V1_YUV422; 430 break; 431 case FOURCC_RV32: 432 case FOURCC_RV15: 433 case FOURCC_RV16: 434 ErrorF("viaOverlayGetV1V3Format: " 435 "Can't display RGB video in this configuration.\n"); 436 return FALSE; 437 default: 438 DBG_DD(ErrorF("viaOverlayGetV1V3Format: " 439 "Invalid FOURCC format (0x%lx).\n", 440 pVia->swov.SrcFourCC)); 441 return FALSE; 442 } 443 } 444 *pVidCtl |= V1_COLORSPACE_SIGN; 445 return TRUE; 446} 447 448static unsigned long 449viaOverlayGetSrcStartAddress(VIAPtr pVia, 450 unsigned long videoFlag, 451 LPDDUPDATEOVERLAY pUpdate, 452 unsigned long srcPitch, 453 unsigned long *pHQVoffset) 454{ 455 unsigned long srcWidth = 456 (unsigned long)(pUpdate->SrcRight - pUpdate->SrcLeft); 457 unsigned long dstWidth = 458 (unsigned long)(pUpdate->DstRight - pUpdate->DstLeft); 459 unsigned long srcHeight = 460 (unsigned long)(pUpdate->SrcBottom - pUpdate->SrcTop); 461 unsigned long dstHeight = 462 (unsigned long)(pUpdate->DstBottom - pUpdate->DstTop); 463 464 unsigned long offset = 0; 465 unsigned long srcTopOffset = 0; 466 unsigned long srcLeftOffset = 0; 467 468 int n = 1; 469 470 if ((pUpdate->SrcLeft != 0) || (pUpdate->SrcTop != 0)) { 471 switch (pVia->swov.SrcFourCC) { 472 case FOURCC_RV32: 473 n = 2; 474 case FOURCC_YUY2: 475 case FOURCC_UYVY: 476 case FOURCC_RV15: 477 case FOURCC_RV16: 478 479 if (videoFlag & VIDEO_HQV_INUSE) { 480 offset = (((pUpdate->SrcTop & ~3) * srcPitch) 481 + ((pUpdate->SrcLeft << n) & ~31)); 482 483 if (srcHeight > dstHeight) 484 srcTopOffset = ((pUpdate->SrcTop & ~3) 485 * dstHeight / srcHeight) * srcPitch; 486 else 487 srcTopOffset = (pUpdate->SrcTop & ~3) * srcPitch; 488 489 if (srcWidth > dstWidth) 490 srcLeftOffset = (((pUpdate->SrcLeft << n) & ~31) 491 * dstWidth / srcWidth); 492 else 493 srcLeftOffset = (pUpdate->SrcLeft << n) & ~31; 494 *pHQVoffset = srcTopOffset + srcLeftOffset; 495 } else 496 offset = ((pUpdate->SrcTop * srcPitch) 497 + ((pUpdate->SrcLeft << n) & ~15)); 498 break; 499 500 case FOURCC_YV12: 501 case FOURCC_I420: 502 case FOURCC_XVMC: 503 504 if (videoFlag & VIDEO_HQV_INUSE) 505 offset = (((pUpdate->SrcTop & ~3) * (srcPitch << 1)) 506 + ((pUpdate->SrcLeft << 1) & ~31)); 507 else { 508 offset = ((((pUpdate->SrcTop & ~3) * srcPitch) 509 + pUpdate->SrcLeft) & ~31); 510 if (pUpdate->SrcTop > 0) 511 pVia->swov.overlayRecordV1.dwUVoffset 512 = (((((pUpdate->SrcTop & ~3) >> 1) * srcPitch) 513 + pUpdate->SrcLeft) & ~31) >> 1; 514 else 515 pVia->swov.overlayRecordV1.dwUVoffset = offset >> 1; 516 } 517 break; 518 519 default: 520 DBG_DD(ErrorF("viaGetSrcStartAddress: " 521 "Invalid FOURCC format (0x%lx).\n", 522 pVia->swov.SrcFourCC)); 523 break; 524 } 525 } else { 526 pVia->swov.overlayRecordV1.dwUVoffset = offset = 0; 527 } 528 529 return offset; 530} 531 532static YCBCRREC 533viaOverlayGetYCbCrStartAddress(unsigned long videoFlag, 534 unsigned long startAddr, unsigned long offset, 535 unsigned long UVoffset, unsigned long srcPitch, 536 unsigned long srcHeight) 537{ 538 YCBCRREC YCbCr; 539 540 if (videoFlag & VIDEO_HQV_INUSE) { 541 YCbCr.dwY = startAddr; 542 YCbCr.dwCB = startAddr + srcPitch * srcHeight; 543 YCbCr.dwCR = (startAddr + srcPitch * srcHeight 544 + srcPitch * (srcHeight >> 2)); 545 } else { 546 YCbCr.dwY = startAddr + offset; 547 YCbCr.dwCB = startAddr + srcPitch * srcHeight + UVoffset; 548 YCbCr.dwCR = (startAddr + srcPitch * srcHeight + UVoffset 549 + srcPitch * (srcHeight >> 2)); 550 } 551 return YCbCr; 552} 553 554static unsigned long 555viaOverlayHQVCalcZoomWidth(VIAPtr pVia, 556 unsigned long videoFlag, unsigned long srcWidth, 557 unsigned long dstWidth, unsigned long *pZoomCtl, 558 unsigned long *pMiniCtl, 559 unsigned long *pHQVfilterCtl, 560 unsigned long *pHQVminiCtl, 561 unsigned long *pHQVscaleCtlH, 562 unsigned long *pHQVzoomflag) 563{ 564 unsigned long tmp, sw1, d, falign, mdiv; 565 Bool zoom_ok = TRUE; 566 VIAHWDiff *hwDiff = &pVia->HWDiff; 567 568 CARD32 HQVfilter[5] = { HQV_H_FILTER_DEFAULT, HQV_H_TAP4_121, 569 HQV_H_TAP4_121, HQV_H_TAP8_12221, HQV_H_TAP8_12221 570 }; 571 /* CARD HQVmini[5] = { 0, 0xc00, 0xa00, 0x900, 0x8800 }; */ 572 573 falign = 0; 574 mdiv = 1; 575 576 if (srcWidth == dstWidth) { /* No zoom */ 577 *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT; 578 } else if (srcWidth < dstWidth) { /* Zoom in */ 579 *pZoomCtl &= 0x0000FFFF; 580 tmp = srcWidth * 0x800 / dstWidth; 581 *pZoomCtl |= ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE; 582 *pMiniCtl |= V1_X_INTERPOLY; 583 zoom_ok = !(tmp > 0x7ff); 584 585 *pHQVzoomflag = 1; 586 *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT; 587 } else { /* srcWidth > dstWidth - Zoom out */ 588 if (hwDiff->dwNewScaleCtl) { 589 if (srcWidth > (dstWidth << 3)) { 590 /*<1/8*/ 591 /*FIXME!*/ 592 if (dstWidth <= 32) { 593 dstWidth = 33; 594 } 595 if (srcWidth > (dstWidth << 5)) { 596 tmp = 1 * 0x1000 / 31; 597 } else { 598 tmp = (dstWidth * 0x1000) / srcWidth; 599 } 600 601 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH; 602 } else if (srcWidth == (dstWidth << 3)) { 603 /*1/8*/ 604 tmp = ((dstWidth - 1) * 0x1000) / srcWidth; 605 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH; 606 } else if (srcWidth > (dstWidth << 2)) { 607 /*1/4 -1/8 zoom-out*/ 608 tmp = (srcWidth * 0x1000) / dstWidth; 609 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_EIGHTH; 610 } else { 611 /*1-1/4 zoom-out*/ 612 /*setting :src/(destination+0.5)*/ 613 tmp = (srcWidth * 0x2000) / ((dstWidth << 1) + 1); 614 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_1; 615 } 616 617 /*rounding to nearest interger*/ 618 tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0; 619 *pHQVscaleCtlH |= (tmp & 0x7fff) | HQV_H_SCALE_ENABLE; 620 } else { 621 /* HQV rounding patch, instead of: 622 * //tmp = dstWidth*0x0800 / srcWidth; */ 623 tmp = dstWidth * 0x800 * 0x400 / srcWidth; 624 tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0); 625 626 *pHQVminiCtl = (tmp & 0x7ff) | HQV_H_MINIFY_ENABLE | HQV_H_MINIFY_DOWN; 627 628 *pHQVminiCtl |= HQV_HDEBLOCK_FILTER; 629 } 630 /* Scale down the picture by a factor mdiv = (1 << d) = {2, 4, 8 or 16} */ 631 632 sw1 = srcWidth; 633 for (d = 1; d < 5; d++) { 634 sw1 >>= 1; 635 if (sw1 <= dstWidth) 636 break; 637 } 638 if (d == 5) { /* Too small. */ 639 d = 4; 640 zoom_ok = FALSE; 641 } 642 mdiv = 1 << d; /* <= {2,4,8,16} */ 643 falign = ((mdiv << 1) - 1) & 0xf; /* <= {3,7,15,15} */ 644 *pMiniCtl |= V1_X_INTERPOLY; 645 *pMiniCtl |= ((d << 1) - 1) << 24; /* <= {1,3,5,7} << 24 */ 646 647 *pHQVfilterCtl |= HQVfilter[d]; 648 649 /* Scale to arbitrary size, on top of previous scaling by (1 << d). */ 650 651 if (sw1 < dstWidth) { 652 /* CLE bug 653 *pZoomCtl = sw1 * 0x0800 / dstWidth;*/ 654 *pZoomCtl = (sw1 - 2) * 0x0800 / dstWidth; 655 *pZoomCtl = ((*pZoomCtl & 0x7ff) << 16) | V1_X_ZOOM_ENABLE; 656 } 657 658 if (videoFlag & VIDEO_1_INUSE) { 659 pVia->swov.overlayRecordV1.dwFetchAlignment = falign; 660 pVia->swov.overlayRecordV1.dwminifyH = mdiv; 661 } else { 662 pVia->swov.overlayRecordV3.dwFetchAlignment = falign; 663 pVia->swov.overlayRecordV3.dwminifyH = mdiv; 664 } 665 } 666 return zoom_ok; 667} 668 669static unsigned long 670viaOverlayHQVCalcZoomHeight(VIAPtr pVia, 671 unsigned long srcHeight, unsigned long dstHeight, 672 unsigned long *pZoomCtl, unsigned long *pMiniCtl, 673 unsigned long *pHQVfilterCtl, 674 unsigned long *pHQVminiCtl, 675 unsigned long *pHQVscaleCtlV, 676 unsigned long *pHQVzoomflag) 677{ 678 unsigned long tmp, sh1, d; 679 Bool zoom_ok = TRUE; 680 VIAHWDiff *hwDiff = &pVia->HWDiff; 681 682 CARD32 HQVfilter[5] = { HQV_V_TAP4_121, HQV_V_TAP4_121, HQV_V_TAP4_121, 683 HQV_V_TAP8_12221, HQV_V_TAP8_12221 }; 684 /* CARD32 HQVmini[5] = { 0, 0x0c000000, 0x0a000000, 0x09000000, 0x08800000 }; */ 685 686 /*if (pVia->pBIOSInfo->scaleY) 687 * { 688 * dstHeight = dstHeight + 1; 689 * } */ 690 691 if (srcHeight == dstHeight) { /* No zoom */ 692 *pHQVfilterCtl |= HQV_V_TAP4_121; 693 } else if (srcHeight < dstHeight) { /* Zoom in */ 694 *pZoomCtl &= 0xFFFF0000; 695 tmp = srcHeight * 0x400 / dstHeight - 1; 696 *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE); 697 *pMiniCtl |= (V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY); 698 699 *pHQVzoomflag = 1; 700 *pHQVfilterCtl |= HQV_V_TAP4_121; 701 } else { /* srcHeight > dstHeight - Zoom out */ 702 if (hwDiff->dwNewScaleCtl) { 703 /*setting :src/(destination+0.5)*/ 704 tmp = srcHeight * 0x2000 / ((dstHeight << 1) + 1); 705 tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0; 706 if ((tmp & 0x1ffff) == 0) { 707 tmp = 0x1ffff; 708 } 709 710 *pHQVscaleCtlV = (tmp & 0x1ffff) | HQV_V_SCALE_ENABLE| HQV_V_SCALE_DOWN; 711 } else { 712 /* HQV rounding patch, instead of: 713 * //tmp = dstHeight*0x0800 / srcHeight; */ 714 tmp = dstHeight * 0x0800 * 0x400 / srcHeight; 715 tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0); 716 *pHQVminiCtl |= (((tmp & 0x7ff) << 16) | HQV_V_MINIFY_ENABLE 717 | HQV_V_MINIFY_DOWN); 718 719 /* Scale down the picture by a factor (1 << d) = {2, 4, 8 or 16} */ 720 sh1 = srcHeight; 721 for (d = 1; d < 5; d++) { 722 sh1 >>= 1; 723 if (sh1 <= dstHeight) 724 break; 725 } 726 if (d == 5) { /* Too small. */ 727 d = 4; 728 zoom_ok = FALSE; 729 } 730 731 *pMiniCtl |= ((d << 1) - 1) << 16; /* <= {1,3,5,7} << 16 */ 732 733 *pHQVfilterCtl |= HQVfilter[d]; 734 /* *pHQVminiCtl |= HQVmini[d]; */ 735 *pHQVminiCtl |= HQV_VDEBLOCK_FILTER; 736 737 /* Scale to arbitrary size, on top of previous scaling by (1 << d). */ 738 739 if (sh1 < dstHeight) { 740 tmp = sh1 * 0x0400 / dstHeight; 741 *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE); 742 *pMiniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY; 743 } 744 } 745 } 746 return zoom_ok; 747} 748 749static unsigned long 750viaOverlayGetFetch(VIAPtr pVia, unsigned long videoFlag, 751 unsigned long srcWidth, unsigned long dstWidth, 752 unsigned long oriSrcWidth, unsigned long *pHQVsrcFetch) 753{ 754 unsigned long fetch = 0; 755 int n = 2; /* 2^n bytes per pixel. */ 756 757 switch (pVia->swov.SrcFourCC) { 758 case FOURCC_YV12: 759 case FOURCC_I420: 760 case FOURCC_XVMC: 761 n = 0; /* 2^n = 1 byte per pixel (Y channel in planar YUV) */ 762 break; 763 case FOURCC_UYVY: 764 case FOURCC_YUY2: 765 case FOURCC_RV15: 766 case FOURCC_RV16: 767 n = 1; /* 2^n = 2 bytes per pixel (packed YUV) */ 768 break; 769 case FOURCC_RV32: 770 n = 2; 771 break; 772 default: 773 DBG_DD(ErrorF("viaOverlayGetFetch: " 774 "Invalid FOURCC format (0x%lx).\n", 775 pVia->swov.SrcFourCC)); 776 break; 777 } 778 779 if (videoFlag & VIDEO_HQV_INUSE) { 780 *pHQVsrcFetch = oriSrcWidth << n; 781 if (n == 0) { 782 /* Assume n == 0 <=> Planar YUV. 783 * The V1/V3 pixelformat is always packed YUV when we use HQV, 784 * so we switch from 8-bit to 16-bit pixels here. 785 */ 786 n = 1; 787 } 788 if (dstWidth >= srcWidth) 789 fetch = (ALIGN_TO(srcWidth << n, 16) >> 4) + 1; 790 else 791 fetch = (ALIGN_TO(dstWidth << n, 16) >> 4) + 1; 792 } else { 793 if (n == 0) 794 fetch = (ALIGN_TO(srcWidth, 32) >> 4); 795 else 796 fetch = (ALIGN_TO(srcWidth << n, 16) >> 4) + 1; 797 } 798 799 /* Fix planar mode problem. */ 800 if (fetch < 4) 801 fetch = 4; 802 803 return fetch; 804} 805 806/* 807 * This function uses quadratic mapping to adjust the midpoint of the scaling. 808 */ 809static float 810rangeEqualize(float inLow, float inHigh, float outLow, float outHigh, 811 float outMid, float inValue) 812{ 813 float inRange = inHigh - inLow, 814 outRange = outHigh - outLow, 815 normIn = ((inValue - inLow) / inRange) * 2. - 1., 816 delta = outMid - outRange * 0.5 - outLow; 817 return ((inValue - inLow) * outRange / inRange + outLow 818 + (1. - normIn * normIn) * delta); 819} 820 821static unsigned 822vPackFloat(float val, float hiLimit, float loLimit, float mult, int shift, 823 Bool doSign) 824{ 825 unsigned packed, mask, sign; 826 827 val = (val > hiLimit) ? hiLimit : val; 828 val = (val < loLimit) ? loLimit : val; 829 sign = (val < 0) ? 1 : 0; 830 val = (sign) ? -val : val; 831 packed = ((unsigned)(val * mult + 1.)) >> 1; 832 mask = (1 << shift) - 1; 833 return (((packed >= mask) ? mask : packed) 834 | ((doSign) ? (sign << shift) : 0)); 835 836} 837 838typedef float colorCoeff[5]; 839static colorCoeff colorCTable[] = { 840 {1.1875, 1.625, 0.875, 0.375, 2.0}, 841 {1.164, 1.596, 0.54, 0.45, 2.2} 842}; 843 844/* 845 * This function is a partial rewrite of the overlay.c file of the original VIA 846 * drivers, which was extremely nasty and difficult to follow. Coefficients for 847 * new chipset models should be added in the table above and, if needed, 848 * implemented in the model switch below. 849 */ 850static void 851viaCalculateVideoColor(VIAPtr pVia, int hue, int saturation, 852 int brightness, int contrast, Bool reset, 853 CARD32 * col1, CARD32 * col2) 854{ 855 float fA, fB1, fC1, fD, fB2, fC2, fB3, fC3; 856 float fPI, fContrast, fSaturation, fHue, fBrightness; 857 const float *mCoeff; 858 unsigned long dwA, dwB1, dwC1, dwD, dwB2, dwC2, dwB3, dwC3, dwS; 859 unsigned long dwD_Int, dwD_Dec; 860 int intD; 861 int model; 862 863 fPI = (float)(M_PI / 180.); 864 865 if (reset) { 866 saturation = 10000; 867 brightness = 5000; 868 contrast = 10000; 869 } 870 871 switch (pVia->ChipId) { 872 case PCI_CHIP_VT3205: 873 case PCI_CHIP_VT3204: 874 case PCI_CHIP_VT3259: 875 case PCI_CHIP_VT3314: 876 case PCI_CHIP_VT3336: 877 case PCI_CHIP_VT3364: 878 case PCI_CHIP_VT3324: 879 case PCI_CHIP_VT3327: 880 case PCI_CHIP_VT3353: 881 case PCI_CHIP_VT3409: 882 case PCI_CHIP_VT3410: 883 model = 0; 884 break; 885 case PCI_CHIP_CLE3122: 886 model = (CLE266_REV_IS_CX(pVia->ChipRev) ? 0 : 1); 887 break; 888 default: 889 ErrorF("Unknown Chip ID\n"); 890 model = 0; 891 } 892 893 switch (model) { 894 case 0: 895 fBrightness = rangeEqualize(0., 10000., -128., 128., -16., 896 (float)brightness); 897 fContrast = rangeEqualize(0., 20000., 0., 1.6645, 1.0, 898 (float)contrast); 899 fSaturation = rangeEqualize(0., 20000, 0., 2., 1., 900 (float)saturation); 901 break; 902 default: 903 fBrightness = rangeEqualize(0., 10000., -128., 128., -12., 904 (float)brightness); 905 fContrast = rangeEqualize(0., 20000., 0., 1.6645, 1.1, 906 (float)contrast); 907 fSaturation = rangeEqualize(0., 20000, 0., 2., 1.15, 908 (float)saturation); 909 break; 910 } 911 fHue = (float)hue; 912 913 mCoeff = colorCTable[model]; 914 915 fA = (float)(mCoeff[0] * fContrast); 916 fB1 = (float)(-mCoeff[1] * fContrast * fSaturation * sin(fHue * fPI)); 917 fC1 = (float)(mCoeff[1] * fContrast * fSaturation * cos(fHue * fPI)); 918 fD = (float)(mCoeff[0] * (fBrightness)); 919 fB2 = (float)((mCoeff[2] * sin(fHue * fPI) - mCoeff[3] * cos(fHue * fPI)) 920 * fContrast * fSaturation); 921 fC2 = (float)(-(mCoeff[2] * cos(fHue * fPI) + mCoeff[3] * sin(fHue * fPI)) 922 * fContrast * fSaturation); 923 fB3 = (float)(mCoeff[4] * fContrast * fSaturation * cos(fHue * fPI)); 924 fC3 = (float)(mCoeff[4] * fContrast * fSaturation * sin(fHue * fPI)); 925 926 switch (model) { 927 case 0: 928 dwA = vPackFloat(fA, 1.9375, 0., 32., 5, 0); 929 dwB1 = vPackFloat(fB1, 2.125, -2.125, 16., 5, 1); 930 dwC1 = vPackFloat(fC1, 2.125, -2.125, 16., 5, 1); 931 932 if (fD >= 0) { 933 intD = (int)fD; 934 if (intD > 127) 935 intD = 127; 936 dwD_Int = ((unsigned long)intD) & 0xff; 937 dwD = ((unsigned long)(fD * 16 + 1)) >> 1; 938 dwD_Dec = dwD & 0x7; 939 } else { 940 intD = (int)fD; 941 if (intD < -128) 942 intD = -128; 943 intD = intD + 256; 944 dwD_Int = ((unsigned long)intD) & 0xff; 945 fD = -fD; 946 dwD = ((unsigned long)(fD * 16 + 1)) >> 1; 947 dwD_Dec = dwD & 0x7; 948 } 949 950 dwB2 = vPackFloat(fB2, 1.875, -1.875, 16, 4, 1); 951 dwC2 = vPackFloat(fC2, 1.875, -1.875, 16, 4, 1); 952 dwB3 = vPackFloat(fB3, 3.875, -3.875, 16, 5, 1); 953 dwC3 = vPackFloat(fC3, 3.875, -3.875, 16, 5, 1); 954 *col1 = (dwA << 24) | (dwB1 << 16) | (dwC1 << 8) | dwD_Int; 955 *col2 = (dwD_Dec << 29 | dwB2 << 24) | (dwC2 << 16) | (dwB3 << 8) 956 | (dwC3); 957 break; 958 959 default: 960 dwA = vPackFloat(fA, 1.9375, -0., 32, 5, 0); 961 dwB1 = vPackFloat(fB1, 0.75, -0.75, 8., 2, 1); 962 dwC1 = vPackFloat(fC1, 2.875, 1., 16., 5, 0); 963 964 if (fD >= 127) 965 fD = 127; 966 967 if (fD <= -128) 968 fD = -128; 969 970 if (fD >= 0) { 971 dwS = 0; 972 } else { 973 dwS = 1; 974 fD = fD + 128; 975 } 976 977 dwD = ((unsigned long)(fD * 2 + 1)) >> 1; 978 if (dwD >= 0x7f) { 979 dwD = 0x7f | (dwS << 7); 980 } else { 981 dwD = (dwD & 0x7f) | (dwS << 7); 982 } 983 984 dwB2 = vPackFloat(fB2, 0., -0.875, 16., 3, 0); 985 dwC2 = vPackFloat(fC2, 0., -1.875, 16., 4, 0); 986 dwB3 = vPackFloat(fB3, 3.75, 0., 8., 4, 0); 987 dwC3 = vPackFloat(fC3, 1.25, -1.25, 8., 3, 1); 988 *col1 = (dwA << 24) | (dwB1 << 18) | (dwC1 << 9) | dwD; 989 *col2 = (dwB2 << 25) | (dwC2 << 17) | (dwB3 << 10) | (dwC3 << 2); 990 break; 991 } 992} 993 994/* 995 * 996 * 997 */ 998void 999viaSetColorSpace(VIAPtr pVia, int hue, int saturation, int brightness, 1000 int contrast, Bool reset) 1001{ 1002 CARD32 col1, col2; 1003 1004 viaCalculateVideoColor(pVia, hue, saturation, brightness, contrast, reset, 1005 &col1, &col2); 1006 switch (pVia->ChipId) { 1007 case PCI_CHIP_VT3205: 1008 case PCI_CHIP_VT3204: 1009 case PCI_CHIP_VT3314: 1010 VIASETREG(V3_ColorSpaceReg_1, col1); 1011 VIASETREG(V3_ColorSpaceReg_2, col2); 1012 DBG_DD(ErrorF("000002C4 %08lx\n", col1)); 1013 DBG_DD(ErrorF("000002C8 %08lx\n", col2)); 1014 case PCI_CHIP_VT3259: 1015 case PCI_CHIP_VT3327: 1016 case PCI_CHIP_VT3336: 1017 case PCI_CHIP_VT3324: 1018 case PCI_CHIP_VT3364: 1019 case PCI_CHIP_VT3353: 1020 case PCI_CHIP_VT3409: 1021 case PCI_CHIP_VT3410: 1022 case PCI_CHIP_CLE3122: 1023 VIASETREG(V1_ColorSpaceReg_1, col1); 1024 VIASETREG(V1_ColorSpaceReg_2, col2); 1025 DBG_DD(ErrorF("00000288 %08lx\n", col2)); 1026 DBG_DD(ErrorF("00000284 %08lx\n", col1)); 1027 break; 1028 default: 1029 DBG_DD(ErrorF("Unknown DeviceID\n")); 1030 break; 1031 } 1032} 1033 1034static unsigned long 1035ViaInitVideoStatusFlag(VIAPtr pVia) 1036{ 1037 switch (pVia->ChipId) { 1038 case PCI_CHIP_VT3205: 1039 case PCI_CHIP_VT3204: 1040 case PCI_CHIP_VT3314: 1041 return VIDEO_HQV_INUSE | SW_USE_HQV | VIDEO_3_INUSE; 1042 case PCI_CHIP_VT3259: 1043 case PCI_CHIP_VT3327: 1044 case PCI_CHIP_VT3336: 1045 case PCI_CHIP_VT3324: 1046 case PCI_CHIP_VT3364: 1047 case PCI_CHIP_VT3353: 1048 case PCI_CHIP_VT3409: 1049 case PCI_CHIP_VT3410: 1050 return (VIDEO_HQV_INUSE | SW_USE_HQV | VIDEO_1_INUSE 1051 | VIDEO_ACTIVE | VIDEO_SHOW); 1052 case PCI_CHIP_CLE3122: 1053 return VIDEO_HQV_INUSE | SW_USE_HQV | VIDEO_1_INUSE; 1054 default: 1055 DBG_DD(ErrorF("Unknown DeviceID\n")); 1056 break; 1057 } 1058 return 0; 1059} 1060 1061static unsigned long 1062ViaSetVidCtl(VIAPtr pVia, unsigned int videoFlag) 1063{ 1064 if (videoFlag & VIDEO_1_INUSE) { 1065 /*=* Modify for C1 FIFO *=*/ 1066 /* WARNING: not checking Chipset! */ 1067 if (CLE266_REV_IS_CX(pVia->ChipRev)) 1068 return V1_ENABLE | V1_EXPIRE_NUM_F; 1069 else { 1070 /* Overlay source format for V1 */ 1071 if (pVia->swov.gdwUseExtendedFIFO) 1072 return V1_ENABLE | V1_EXPIRE_NUM_A | V1_FIFO_EXTENDED; 1073 else 1074 return V1_ENABLE | V1_EXPIRE_NUM; 1075 } 1076 } else { 1077 switch (pVia->ChipId) { 1078 case PCI_CHIP_VT3205: 1079 case PCI_CHIP_VT3204: 1080 case PCI_CHIP_VT3259: 1081 case PCI_CHIP_VT3314: 1082 return V3_ENABLE | V3_EXPIRE_NUM_3205; 1083 case PCI_CHIP_VT3327: 1084 case PCI_CHIP_VT3336: 1085 case PCI_CHIP_VT3324: 1086 case PCI_CHIP_VT3364: 1087 case PCI_CHIP_VT3353: 1088 return V3_ENABLE | VIDEO_EXPIRE_NUM_VT3336; 1089 case PCI_CHIP_VT3409: 1090 case PCI_CHIP_VT3410: 1091 return V3_ENABLE | VIDEO_EXPIRE_NUM_VT3409; 1092 case PCI_CHIP_CLE3122: 1093 if (CLE266_REV_IS_CX(pVia->ChipRev)) 1094 return V3_ENABLE | V3_EXPIRE_NUM_F; 1095 else 1096 return V3_ENABLE | V3_EXPIRE_NUM; 1097 default: 1098 DBG_DD(ErrorF("Unknown DeviceID\n")); 1099 break; 1100 } 1101 } 1102 return 0; 1103} 1104 1105/* 1106 * Fill the buffer with 0x8000 (YUV2 black). 1107 */ 1108static void 1109ViaYUVFillBlack(VIAPtr pVia, void *buf, int num) 1110{ 1111 CARD16 *ptr = (CARD16 *) buf; 1112 1113 while (num-- > 0) 1114#if X_BYTE_ORDER == X_LITTLE_ENDIAN 1115 *ptr++ = 0x0080; 1116#else 1117 *ptr++ = 0x8000; 1118#endif 1119} 1120 1121/* 1122 * Add an HQV surface to an existing FOURCC surface. 1123 * numbuf: number of buffers, 1, 2 or 3 1124 * fourcc: FOURCC code of the current (already existing) surface 1125 */ 1126static long 1127AddHQVSurface(ScrnInfoPtr pScrn, unsigned int numbuf, CARD32 fourcc) 1128{ 1129 unsigned int i, width, height, pitch, fbsize, addr; 1130 BOOL isplanar; 1131 void *buf; 1132 1133 VIAPtr pVia = VIAPTR(pScrn); 1134 CARD32 AddrReg[3] = { HQV_DST_STARTADDR0, HQV_DST_STARTADDR1, 1135 HQV_DST_STARTADDR2 }; 1136 unsigned long proReg = 0; 1137 1138 if (pVia->ChipId == PCI_CHIP_VT3259 && 1139 !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE)) 1140 proReg = PRO_HQV1_OFFSET; 1141 1142 isplanar = ((fourcc == FOURCC_YV12) || (fourcc == FOURCC_I420) || 1143 (fourcc == FOURCC_XVMC)); 1144 1145 width = pVia->swov.SWDevice.gdwSWSrcWidth; 1146 height = pVia->swov.SWDevice.gdwSWSrcHeight; 1147 pitch = pVia->swov.SWDevice.dwPitch; 1148 fbsize = pitch * height * (isplanar ? 2 : 1); 1149 1150 pVia->swov.HQVMem = drm_bo_alloc(pScrn, fbsize * numbuf, 1, TTM_PL_FLAG_VRAM); 1151 if (!pVia->swov.HQVMem) 1152 return BadAlloc; 1153 addr = pVia->swov.HQVMem->offset; 1154 buf = drm_bo_map(pScrn, pVia->swov.HQVMem); 1155 1156 ViaYUVFillBlack(pVia, buf, fbsize); 1157 1158 for (i = 0; i < numbuf; i++) { 1159 pVia->swov.overlayRecordV1.dwHQVAddr[i] = addr; 1160 VIASETREG(AddrReg[i] + proReg, addr); 1161 addr += fbsize; 1162 } 1163 drm_bo_unmap(pScrn, pVia->swov.HQVMem); 1164 return Success; 1165} 1166 1167/* 1168 * Create a FOURCC surface. 1169 * doalloc: set true to actually allocate memory for the framebuffers 1170 */ 1171static long 1172CreateSurface(ScrnInfoPtr pScrn, CARD32 FourCC, CARD16 Width, 1173 CARD16 Height, BOOL doalloc) 1174{ 1175 VIAPtr pVia = VIAPTR(pScrn); 1176 unsigned long pitch, fbsize, addr; 1177 BOOL isplanar; 1178 void *buf; 1179 1180 pVia->swov.SrcFourCC = FourCC; 1181 pVia->swov.gdwVideoFlagSW = ViaInitVideoStatusFlag(pVia); 1182 1183 isplanar = FALSE; 1184 switch (FourCC) { 1185 case FOURCC_YV12: 1186 case FOURCC_I420: 1187 case FOURCC_XVMC: 1188 isplanar = TRUE; 1189 pitch = ALIGN_TO(Width, 32); 1190 fbsize = pitch * Height * 1.5; 1191 break; 1192 case FOURCC_RV32: 1193 pitch = ALIGN_TO(Width << 2, 32); 1194 fbsize = pitch * Height; 1195 break; 1196 default: 1197 pitch = ALIGN_TO(Width << 1, 32); 1198 fbsize = pitch * Height; 1199 break; 1200 } 1201 1202 if (doalloc) { 1203 pVia->swov.SWfbMem = drm_bo_alloc(pScrn, fbsize * 2, 1, TTM_PL_FLAG_VRAM); 1204 if (!pVia->swov.SWfbMem) 1205 return BadAlloc; 1206 addr = pVia->swov.SWfbMem->offset; 1207 buf = drm_bo_map(pScrn, pVia->swov.SWfbMem); 1208 1209 ViaYUVFillBlack(pVia, buf, fbsize); 1210 1211 pVia->swov.SWDevice.dwSWPhysicalAddr[0] = addr; 1212 pVia->swov.SWDevice.dwSWPhysicalAddr[1] = addr + fbsize; 1213 pVia->swov.SWDevice.lpSWOverlaySurface[0] = buf; 1214 pVia->swov.SWDevice.lpSWOverlaySurface[1] = buf + fbsize; 1215 1216 if (isplanar) { 1217 pVia->swov.SWDevice.dwSWCrPhysicalAddr[0] = 1218 pVia->swov.SWDevice.dwSWPhysicalAddr[0] + 1219 (pitch * Height); 1220 pVia->swov.SWDevice.dwSWCrPhysicalAddr[1] = 1221 pVia->swov.SWDevice.dwSWPhysicalAddr[1] + 1222 (pitch * Height); 1223 pVia->swov.SWDevice.dwSWCbPhysicalAddr[0] = 1224 pVia->swov.SWDevice.dwSWCrPhysicalAddr[0] + 1225 ((pitch >> 1) * (Height >> 1)); 1226 pVia->swov.SWDevice.dwSWCbPhysicalAddr[1] = 1227 pVia->swov.SWDevice.dwSWCrPhysicalAddr[1] + 1228 ((pitch >> 1) * (Height >> 1)); 1229 } 1230 } 1231 1232 pVia->swov.SWDevice.gdwSWSrcWidth = Width; 1233 pVia->swov.SWDevice.gdwSWSrcHeight = Height; 1234 pVia->swov.SWDevice.dwPitch = pitch; 1235 1236 pVia->swov.overlayRecordV1.dwV1OriWidth = Width; 1237 pVia->swov.overlayRecordV1.dwV1OriHeight = Height; 1238 pVia->swov.overlayRecordV1.dwV1OriPitch = pitch; 1239 1240 return Success; 1241} 1242 1243/* 1244 * 1245 */ 1246int 1247ViaSwovSurfaceCreate(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv, 1248 CARD32 FourCC, CARD16 Width, CARD16 Height) 1249{ 1250 VIAPtr pVia = VIAPTR(pScrn); 1251 unsigned long retCode = Success; 1252 int numbuf = pVia->HWDiff.dwThreeHQVBuffer ? 3 : 2; 1253 1254 DBG_DD(ErrorF("ViaSwovSurfaceCreate: FourCC =0x%08lx\n", FourCC)); 1255 1256 if ((pVia->VideoStatus & VIDEO_SWOV_SURFACE_CREATED) 1257 && (FourCC == pPriv->FourCC)) 1258 return Success; 1259 1260 pPriv->FourCC = FourCC; 1261 switch (FourCC) { 1262 case FOURCC_YUY2: 1263 case FOURCC_RV15: 1264 case FOURCC_RV16: 1265 case FOURCC_RV32: 1266 retCode = CreateSurface(pScrn, FourCC, Width, Height, TRUE); 1267 if (retCode != Success) 1268 break; 1269 if ((pVia->swov.gdwVideoFlagSW & SW_USE_HQV)) 1270 retCode = AddHQVSurface(pScrn, numbuf, FourCC); 1271 break; 1272 1273 case FOURCC_HQVSW: 1274 retCode = AddHQVSurface(pScrn, numbuf, FOURCC_YUY2); 1275 break; 1276 1277 case FOURCC_YV12: 1278 case FOURCC_I420: 1279 retCode = CreateSurface(pScrn, FourCC, Width, Height, TRUE); 1280 if (retCode == Success) 1281 retCode = AddHQVSurface(pScrn, numbuf, FourCC); 1282 break; 1283 1284 case FOURCC_XVMC: 1285 retCode = CreateSurface(pScrn, FourCC, Width, Height, FALSE); 1286 if (retCode == Success) 1287 retCode = AddHQVSurface(pScrn, numbuf, FOURCC_XVMC); 1288 break; 1289 1290 default: 1291 break; 1292 } 1293 1294 if (retCode == Success) { 1295 DBG_DD(ErrorF(" lpSWOverlaySurface[0]: %p\n", 1296 pVia->swov.SWDevice.lpSWOverlaySurface[0])); 1297 DBG_DD(ErrorF(" lpSWOverlaySurface[1]: %p\n", 1298 pVia->swov.SWDevice.lpSWOverlaySurface[1])); 1299 1300 pVia->VideoStatus |= VIDEO_SWOV_SURFACE_CREATED | VIDEO_SWOV_ON; 1301 } 1302 return retCode; 1303} 1304 1305/* 1306 * Destroy Surface 1307 */ 1308void 1309ViaSwovSurfaceDestroy(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv) 1310{ 1311 VIAPtr pVia = VIAPTR(pScrn); 1312 1313 DBG_DD(ErrorF("ViaSwovSurfaceDestroy: FourCC =0x%08lx\n", pPriv->FourCC)); 1314 1315 if (pVia->VideoStatus & VIDEO_SWOV_SURFACE_CREATED) { 1316 DBG_DD(ErrorF("ViaSwovSurfaceDestroy: VideoStatus =0x%08lx\n", 1317 pVia->VideoStatus)); 1318 1319 switch (pPriv->FourCC) { 1320 case FOURCC_YUY2: 1321 case FOURCC_RV16: 1322 case FOURCC_RV32: 1323 case FOURCC_RV15: 1324 pVia->swov.SrcFourCC = 0; 1325 1326 drm_bo_unmap(pScrn, pVia->swov.SWfbMem); 1327 drm_bo_free(pScrn, pVia->swov.SWfbMem); 1328 if ((pVia->swov.gdwVideoFlagSW & SW_USE_HQV)) { 1329 drm_bo_unmap(pScrn, pVia->swov.HQVMem); 1330 drm_bo_free(pScrn, pVia->swov.HQVMem); 1331 } 1332 pVia->swov.gdwVideoFlagSW = 0; 1333 break; 1334 1335 case FOURCC_HQVSW: 1336 drm_bo_free(pScrn, pVia->swov.HQVMem); 1337 pVia->swov.gdwVideoFlagSW = 0; 1338 break; 1339 1340 case FOURCC_YV12: 1341 case FOURCC_I420: 1342 drm_bo_unmap(pScrn, pVia->swov.SWfbMem); 1343 drm_bo_free(pScrn, pVia->swov.SWfbMem); 1344 case FOURCC_XVMC: 1345 pVia->swov.SrcFourCC = 0; 1346 1347 drm_bo_free(pScrn, pVia->swov.HQVMem); 1348 pVia->swov.gdwVideoFlagSW = 0; 1349 break; 1350 } 1351 1352 pPriv->FourCC = 0; 1353 pVia->VideoStatus &= ~VIDEO_SWOV_SURFACE_CREATED; 1354 1355 } else 1356 DBG_DD(ErrorF("ViaSwovSurfaceDestroy: No SW Surface Destroyed, " 1357 "VideoStatus =0x%08lx\n", pVia->VideoStatus)); 1358} 1359 1360static void 1361SetFIFO_V1(VIAPtr pVia, CARD8 depth, CARD8 prethreshold, CARD8 threshold) 1362{ 1363 SaveVideoRegister(pVia, V_FIFO_CONTROL, 1364 ((depth - 1) & 0x7f) | 1365 ((prethreshold & 0x7f) << 24) | 1366 ((threshold & 0x7f) << 8)); 1367} 1368 1369static void 1370SetFIFO_V3(VIAPtr pVia, CARD8 depth, CARD8 prethreshold, CARD8 threshold) 1371{ 1372 switch (pVia->ChipId) { 1373 case PCI_CHIP_VT3314: 1374 case PCI_CHIP_VT3324: 1375 case PCI_CHIP_VT3327: 1376 case PCI_CHIP_VT3353: 1377 case PCI_CHIP_VT3409: 1378 case PCI_CHIP_VT3410: 1379 SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL, 1380 (VIAGETREG(ALPHA_V3_FIFO_CONTROL) & ALPHA_FIFO_MASK) 1381 | ((depth - 1) & 0xff) | ((threshold & 0xff) << 8)); 1382 SaveVideoRegister(pVia, ALPHA_V3_PREFIFO_CONTROL, 1383 (VIAGETREG(ALPHA_V3_PREFIFO_CONTROL) 1384 & ~V3_FIFO_MASK_3314) | (prethreshold & 0xff)); 1385 break; 1386 default : 1387 SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL, 1388 (VIAGETREG(ALPHA_V3_FIFO_CONTROL) & ALPHA_FIFO_MASK) 1389 | ((depth - 1) & 0xff) | ((threshold & 0xff) << 8)); 1390 SaveVideoRegister(pVia, ALPHA_V3_PREFIFO_CONTROL, 1391 (VIAGETREG(ALPHA_V3_PREFIFO_CONTROL) & ~V3_FIFO_MASK) 1392 | (prethreshold & 0x7f)); 1393 break; 1394 } 1395} 1396 1397static void 1398SetFIFO_64or32(VIAPtr pVia) 1399{ 1400 /*=* Modify for C1 FIFO *=*/ 1401 /* WARNING: not checking Chipset! */ 1402 if (CLE266_REV_IS_CX(pVia->ChipRev)) 1403 SetFIFO_V1(pVia, 64, 56, 56); 1404 else 1405 SetFIFO_V1(pVia, 32, 29, 16); 1406} 1407 1408static void 1409SetFIFO_64or16(VIAPtr pVia) 1410{ 1411 /*=* Modify for C1 FIFO *=*/ 1412 /* WARNING: not checking Chipset! */ 1413 if (CLE266_REV_IS_CX(pVia->ChipRev)) 1414 SetFIFO_V1(pVia, 64, 56, 56); 1415 else 1416 SetFIFO_V1(pVia, 16, 12, 8); 1417} 1418 1419static void 1420SetFIFO_64or48or32(VIAPtr pVia) 1421{ 1422 /*=* Modify for C1 FIFO *=*/ 1423 /* WARNING: not checking Chipset! */ 1424 if (CLE266_REV_IS_CX(pVia->ChipRev)) 1425 SetFIFO_V1(pVia, 64, 56, 56); 1426 else { 1427 if (pVia->swov.gdwUseExtendedFIFO) 1428 SetFIFO_V1(pVia, 48, 40, 40); 1429 else 1430 SetFIFO_V1(pVia, 32, 29, 16); 1431 } 1432} 1433 1434static void 1435SetFIFO_V3_64or32or32(VIAPtr pVia) 1436{ 1437 switch (pVia->ChipId) { 1438 case PCI_CHIP_VT3327: 1439 case PCI_CHIP_VT3336: 1440 case PCI_CHIP_VT3324: 1441 case PCI_CHIP_VT3364: 1442 case PCI_CHIP_VT3353: 1443 case PCI_CHIP_VT3409: 1444 case PCI_CHIP_VT3410: 1445 SetFIFO_V3(pVia, 225, 200, 250); 1446 break; 1447 case PCI_CHIP_VT3204: 1448 SetFIFO_V3(pVia, 100, 89, 89); 1449 break; 1450 case PCI_CHIP_VT3314: 1451 SetFIFO_V3(pVia, 64, 61, 61); 1452 break; 1453 case PCI_CHIP_VT3205: 1454 case PCI_CHIP_VT3259: 1455 SetFIFO_V3(pVia, 32, 29, 29); 1456 break; 1457 case PCI_CHIP_CLE3122: 1458 if (CLE266_REV_IS_CX(pVia->ChipRev)) 1459 SetFIFO_V3(pVia, 64, 56, 56); 1460 else 1461 SetFIFO_V3(pVia, 32, 16, 16); 1462 break; 1463 default: 1464 break; 1465 } 1466} 1467 1468static void 1469SetFIFO_V3_64or32or16(VIAPtr pVia) 1470{ 1471 switch (pVia->ChipId) { 1472 case PCI_CHIP_VT3327: 1473 case PCI_CHIP_VT3336: 1474 case PCI_CHIP_VT3324: 1475 case PCI_CHIP_VT3364: 1476 case PCI_CHIP_VT3353: 1477 case PCI_CHIP_VT3409: 1478 case PCI_CHIP_VT3410: 1479 SetFIFO_V3(pVia, 225, 200, 250); 1480 break; 1481 case PCI_CHIP_VT3204: 1482 SetFIFO_V3(pVia, 100, 89, 89); 1483 break; 1484 case PCI_CHIP_VT3314: 1485 SetFIFO_V3(pVia, 64, 61, 61); 1486 break; 1487 case PCI_CHIP_VT3205: 1488 case PCI_CHIP_VT3259: 1489 SetFIFO_V3(pVia, 32, 29, 29); 1490 break; 1491 1492 case PCI_CHIP_CLE3122: 1493 if (CLE266_REV_IS_CX(pVia->ChipRev)) 1494 SetFIFO_V3(pVia, 64, 56, 56); 1495 else 1496 SetFIFO_V3(pVia, 16, 16, 8); 1497 break; 1498 1499 default: 1500 break; 1501 } 1502} 1503 1504static void 1505SetupFIFOs(VIAPtr pVia, unsigned long videoFlag, 1506 unsigned long miniCtl, unsigned long srcWidth) 1507{ 1508 if (miniCtl & V1_Y_INTERPOLY) { 1509 if (pVia->swov.SrcFourCC == FOURCC_YV12 1510 || pVia->swov.SrcFourCC == FOURCC_I420 1511 || pVia->swov.SrcFourCC == FOURCC_XVMC) { 1512 if (videoFlag & VIDEO_HQV_INUSE) { 1513 if (videoFlag & VIDEO_1_INUSE) 1514 SetFIFO_64or32(pVia); 1515 else 1516 SetFIFO_V3_64or32or16(pVia); 1517 } else { 1518 /* Minified video will be skewed without this workaround. */ 1519 if (srcWidth <= 80) { /* Fetch count <= 5 */ 1520 if (videoFlag & VIDEO_1_INUSE) 1521 SetFIFO_V1(pVia, 16, 0, 0); 1522 else 1523 SetFIFO_V3(pVia, 16, 16, 0); 1524 } else { 1525 if (videoFlag & VIDEO_1_INUSE) 1526 SetFIFO_64or16(pVia); 1527 else 1528 SetFIFO_V3_64or32or16(pVia); 1529 } 1530 } 1531 } else { 1532 if (videoFlag & VIDEO_1_INUSE) 1533 SetFIFO_64or48or32(pVia); 1534 else { 1535 /* Fix V3 bug. */ 1536 if (srcWidth <= 8) 1537 SetFIFO_V3(pVia, 1, 0, 0); 1538 else 1539 SetFIFO_V3_64or32or32(pVia); 1540 } 1541 } 1542 } else { 1543 if (pVia->swov.SrcFourCC == FOURCC_YV12 1544 || pVia->swov.SrcFourCC == FOURCC_I420 1545 || pVia->swov.SrcFourCC == FOURCC_XVMC) { 1546 if (videoFlag & VIDEO_HQV_INUSE) { 1547 if (videoFlag & VIDEO_1_INUSE) 1548 SetFIFO_64or32(pVia); 1549 else 1550 SetFIFO_V3_64or32or16(pVia); 1551 } else { 1552 /* Minified video will be skewed without this workaround. */ 1553 if (srcWidth <= 80) { /* Fetch count <= 5 */ 1554 if (videoFlag & VIDEO_1_INUSE) 1555 SetFIFO_V1(pVia, 16, 0, 0); 1556 else 1557 SetFIFO_V3(pVia, 16, 16, 0); 1558 } else { 1559 if (videoFlag & VIDEO_1_INUSE) 1560 SetFIFO_64or16(pVia); 1561 else 1562 SetFIFO_V3_64or32or16(pVia); 1563 } 1564 } 1565 } else { 1566 if (videoFlag & VIDEO_1_INUSE) 1567 SetFIFO_64or48or32(pVia); 1568 else { 1569 /* Fix V3 bug. */ 1570 if (srcWidth <= 8) 1571 SetFIFO_V3(pVia, 1, 0, 0); 1572 else 1573 SetFIFO_V3_64or32or32(pVia); 1574 } 1575 } 1576 } 1577} 1578 1579static CARD32 1580SetColorKey(VIAPtr pVia, unsigned long videoFlag, 1581 CARD32 keyLow, CARD32 keyHigh, CARD32 compose) 1582{ 1583 keyLow &= 0x00FFFFFF; 1584 if (pVia->VideoEngine == VIDEO_ENGINE_CME) 1585 keyLow |= 0x40000000; 1586 1587 if (videoFlag & VIDEO_1_INUSE) { 1588 SaveVideoRegister(pVia, V_COLOR_KEY, keyLow); 1589 SaveVideoRegister(pVia, SND_COLOR_KEY, keyLow); 1590 } else { 1591 if (pVia->HWDiff.dwSupportTwoColorKey) /*CLE_C0 */ 1592 SaveVideoRegister(pVia, V3_COLOR_KEY, keyLow); 1593 } 1594 1595 /*CLE_C0 */ 1596 compose = ((compose & ~0x0f) | SELECT_VIDEO_IF_COLOR_KEY | 1597 SELECT_VIDEO3_IF_COLOR_KEY); 1598 1599 return compose; 1600} 1601 1602static CARD32 1603SetChromaKey(VIAPtr pVia, unsigned long videoFlag, 1604 CARD32 chromaLow, CARD32 chromaHigh, 1605 CARD32 miniCtl, CARD32 compose) 1606{ 1607 chromaLow &= CHROMA_KEY_LOW; 1608 chromaHigh &= CHROMA_KEY_HIGH; 1609 1610 chromaLow |= (VIAGETREG(V_CHROMAKEY_LOW) & ~CHROMA_KEY_LOW); 1611 chromaHigh |= (VIAGETREG(V_CHROMAKEY_HIGH) & ~CHROMA_KEY_HIGH); 1612 1613 if (pVia->VideoEngine == VIDEO_ENGINE_CME) 1614 chromaLow |= 0x40000000; 1615 1616 SaveVideoRegister(pVia, V_CHROMAKEY_HIGH, chromaHigh); 1617 if (videoFlag & VIDEO_1_INUSE) { 1618 SaveVideoRegister(pVia, V_CHROMAKEY_LOW, chromaLow & ~V_CHROMAKEY_V3); 1619 /* Temporarily solve the HW interpolation error when using Chroma key */ 1620 SaveVideoRegister(pVia, V1_MINI_CONTROL, miniCtl & 0xFFFFFFF8); 1621 } else { 1622 SaveVideoRegister(pVia, V_CHROMAKEY_LOW, chromaLow | V_CHROMAKEY_V3); 1623 SaveVideoRegister(pVia, V3_MINI_CONTROL, miniCtl & 0xFFFFFFF8); 1624 } 1625 1626 /* Modified by Scottie[2001.12.5] for select video if (Color key & Chroma key) */ 1627 if (compose == SELECT_VIDEO_IF_COLOR_KEY) 1628 compose = SELECT_VIDEO_IF_COLOR_KEY | SELECT_VIDEO_IF_CHROMA_KEY; 1629 else 1630 compose = (compose & ~0x0f) | SELECT_VIDEO_IF_CHROMA_KEY; 1631 1632 return compose; 1633} 1634 1635static void 1636SetVideoStart(VIAPtr pVia, unsigned long videoFlag, 1637 unsigned int numbufs, CARD32 a1, CARD32 a2, CARD32 a3) 1638{ 1639 CARD32 V1Addr[3] = { V1_STARTADDR_0, V1_STARTADDR_1, V1_STARTADDR_2 }; 1640 CARD32 V3Addr[3] = { V3_STARTADDR_0, V3_STARTADDR_1, V3_STARTADDR_2 }; 1641 CARD32 *VideoAddr = (videoFlag & VIDEO_1_INUSE) ? V1Addr : V3Addr; 1642 1643 SaveVideoRegister(pVia, VideoAddr[0], a1); 1644 if (numbufs > 1) 1645 SaveVideoRegister(pVia, VideoAddr[1], a2); 1646 if (numbufs > 2) 1647 SaveVideoRegister(pVia, VideoAddr[2], a3); 1648} 1649 1650static void 1651SetHQVFetch(VIAPtr pVia, CARD32 srcFetch, unsigned long srcHeight) 1652{ 1653 unsigned long proReg = 0; 1654 1655 if (pVia->ChipId == PCI_CHIP_VT3259 1656 && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE)) 1657 proReg = PRO_HQV1_OFFSET; 1658 1659 if (!pVia->HWDiff.dwHQVFetchByteUnit) { /* CLE_C0 */ 1660 srcFetch >>= 3; /* fetch unit is 8 bytes */ 1661 } 1662 1663 if ((pVia->ChipId != PCI_CHIP_VT3409) && (pVia->ChipId != PCI_CHIP_VT3410)) 1664 SaveVideoRegister(pVia, HQV_SRC_FETCH_LINE + proReg, 1665 ((srcFetch - 1) << 16) | (srcHeight - 1)); 1666} 1667 1668static void 1669SetFetch(VIAPtr pVia, unsigned long videoFlag, CARD32 fetch) 1670{ 1671 fetch <<= 20; 1672 if (videoFlag & VIDEO_1_INUSE) { 1673 SaveVideoRegister(pVia, V12_QWORD_PER_LINE, fetch); 1674 } else { 1675 fetch |= VIAGETREG(V3_ALPHA_QWORD_PER_LINE) & ~V3_FETCH_COUNT; 1676 SaveVideoRegister(pVia, V3_ALPHA_QWORD_PER_LINE, fetch); 1677 } 1678} 1679 1680static void 1681SetDisplayCount(VIAPtr pVia, unsigned long videoFlag, 1682 unsigned long srcWidth, unsigned long srcHeight) 1683{ 1684 unsigned long DisplayCount; 1685 1686 /* Removed VIA's large pixelformat switch/case. 1687 * All formats (YV12, UYVY, YUY2, VIA, RGB16 and RGB32) 1688 * seem to use the same count. /A 1689 */ 1690 1691 if (videoFlag & VIDEO_HQV_INUSE) 1692 DisplayCount = srcWidth - 1; 1693 else 1694 DisplayCount = srcWidth - pVia->swov.overlayRecordV1.dwminifyH; 1695 1696 if (videoFlag & VIDEO_1_INUSE) 1697 SaveVideoRegister(pVia, V1_SOURCE_HEIGHT, 1698 (srcHeight << 16) | DisplayCount); 1699 else 1700 SaveVideoRegister(pVia, V3_SOURCE_WIDTH, DisplayCount); 1701} 1702 1703static void 1704SetMiniAndZoom(VIAPtr pVia, unsigned long videoFlag, 1705 CARD32 miniCtl, CARD32 zoomCtl) 1706{ 1707 if (videoFlag & VIDEO_1_INUSE) { 1708 SaveVideoRegister(pVia, V1_MINI_CONTROL, miniCtl); 1709 SaveVideoRegister(pVia, V1_ZOOM_CONTROL, zoomCtl); 1710 } else { 1711 SaveVideoRegister(pVia, V3_MINI_CONTROL, miniCtl); 1712 SaveVideoRegister(pVia, V3_ZOOM_CONTROL, zoomCtl); 1713 } 1714} 1715 1716static void 1717SetVideoControl(VIAPtr pVia, unsigned long videoFlag, CARD32 vidCtl) 1718{ 1719 if (videoFlag & VIDEO_1_INUSE) 1720 SaveVideoRegister(pVia, V1_CONTROL, vidCtl); 1721 else 1722 SaveVideoRegister(pVia, V3_CONTROL, vidCtl); 1723} 1724 1725static void 1726FireVideoCommand(VIAPtr pVia, unsigned long videoFlag, CARD32 compose) 1727{ 1728 if (videoFlag & VIDEO_1_INUSE) 1729 SaveVideoRegister(pVia, V_COMPOSE_MODE, compose | V1_COMMAND_FIRE); 1730 else 1731 SaveVideoRegister(pVia, V_COMPOSE_MODE, compose | V3_COMMAND_FIRE); 1732} 1733 1734static void 1735SetVideoWindow(ScrnInfoPtr pScrn, unsigned long videoFlag, 1736 LPDDUPDATEOVERLAY pUpdate) 1737{ 1738 VIAPtr pVia = VIAPTR(pScrn); 1739 CARD32 left = pUpdate->DstLeft; 1740 CARD32 top = pUpdate->DstTop; 1741 CARD32 right = pUpdate->DstRight - 1; 1742 CARD32 bottom = pUpdate->DstBottom - 1; 1743 1744 DBG_DD(ErrorF("SetVideoWindow: X (%ld,%ld) Y (%ld,%ld)\n", 1745 left, right, top, bottom)); 1746 1747 /* Modify for HW DVI limitation. 1748 * When we enable both the CRT and DVI, then change resolution. 1749 * If the resolution is smaller than the panel's physical size, 1750 * the video display in Y direction will be cut. 1751 * So, we need to adjust the Y top and bottom position. 1752 * 1753 if (videoFlag & VIDEO_1_INUSE) { 1754 if (pBIOSInfo->SetDVI && pBIOSInfo->scaleY) { 1755 top = (pUpdate->DstTop * pBIOSInfo->Panel->NativeMode->Height 1756 / pScrn->currentMode->VDisplay); 1757 bottom = (pUpdate->DstBottom * pBIOSInfo->Panel->NativeMode->Height 1758 / pScrn->currentMode->VDisplay); 1759 } 1760 }*/ 1761 1762 if (top > 2047) 1763 top = 2047; 1764 1765 if (bottom > 2047) 1766 bottom = 2047; 1767 1768 if (left > 2047) 1769 left = 2047; 1770 1771 if (right > 2047) 1772 right = 2047; 1773 1774 if (videoFlag & VIDEO_1_INUSE) { 1775 SaveVideoRegister(pVia, V1_WIN_END_Y, (right << 16) | bottom); 1776 SaveVideoRegister(pVia, V1_WIN_START_Y, (left << 16) | top); 1777 } else { 1778 SaveVideoRegister(pVia, V3_WIN_END_Y, (right << 16) | bottom); 1779 SaveVideoRegister(pVia, V3_WIN_START_Y, (left << 16) | top); 1780 } 1781} 1782 1783/* 1784 * Upd_Video() 1785 */ 1786static Bool 1787Upd_Video(xf86CrtcPtr crtc, unsigned long videoFlag, 1788 unsigned long startAddr, LPDDUPDATEOVERLAY pUpdate, 1789 unsigned long srcPitch, 1790 unsigned long oriSrcWidth, unsigned long oriSrcHeight, 1791 unsigned long deinterlaceMode, 1792 unsigned long haveColorKey, unsigned long haveChromaKey, 1793 unsigned long colorKeyLow, unsigned long colorKeyHigh, 1794 unsigned long chromaKeyLow, unsigned long chromaKeyHigh) 1795{ 1796 drmmode_crtc_private_ptr iga = crtc->driver_private; 1797 ScrnInfoPtr pScrn = crtc->scrn; 1798 VIAPtr pVia = VIAPTR(pScrn); 1799 vgaHWPtr hwp = VGAHWPTR(pScrn); 1800 VIAHWDiff *hwDiff = &pVia->HWDiff; 1801 unsigned long vidCtl = 0, compose; 1802 unsigned long srcWidth, srcHeight, dstWidth, dstHeight; 1803 unsigned long zoomCtl = 0, miniCtl = 0; 1804 unsigned long hqvCtl = 0; 1805 unsigned long hqvFilterCtl = 0, hqvMiniCtl = 0; 1806 unsigned long hqvScaleCtlH = 0, hqvScaleCtlV = 0; 1807 unsigned long haveHQVzoomH = 0, haveHQVzoomV = 0; 1808 unsigned long hqvSrcWidth = 0, hqvDstWidth = 0; 1809 unsigned long hqvSrcFetch = 0, hqvOffset = 0; 1810 unsigned long dwOffset = 0, fetch = 0, tmp = 0; 1811 unsigned long proReg = 0; 1812 int i; 1813 1814 DBG_DD(ErrorF("videoflag=%ld\n", videoFlag)); 1815 1816 if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE)) 1817 proReg = PRO_HQV1_OFFSET; 1818 1819 compose = ((VIAGETREG(V_COMPOSE_MODE) 1820 & ~(SELECT_VIDEO_IF_COLOR_KEY 1821 | V1_COMMAND_FIRE | V3_COMMAND_FIRE)) 1822 | V_COMMAND_LOAD_VBI); 1823 1824 DBG_DD(ErrorF("// Upd_Video:\n")); 1825 DBG_DD(ErrorF("Modified rSrc X (%ld,%ld) Y (%ld,%ld)\n", 1826 pUpdate->SrcLeft, pUpdate->SrcRight, 1827 pUpdate->SrcTop, pUpdate->SrcBottom)); 1828 DBG_DD(ErrorF("Modified rDest X (%ld,%ld) Y (%ld,%ld)\n", 1829 pUpdate->DstLeft, pUpdate->DstRight, 1830 pUpdate->DstTop, pUpdate->DstBottom)); 1831 1832 dstWidth = pUpdate->DstRight - pUpdate->DstLeft; 1833 /*if (pBIOSInfo->lvds && pBIOSInfo->lvds->status == XF86OutputStatusConnected && 1834 pBIOSInfo->Panel->Scale) { 1835 * FIXME: We need to determine if the panel is using V1 or V3 * 1836 float hfactor = (float)pBIOSInfo->Panel->NativeMode->Width 1837 / pScrn->currentMode->HDisplay; 1838 dstWidth *= hfactor; 1839 }*/ 1840 1841 pVia->swov.overlayRecordV1.dwWidth = dstWidth; 1842 pVia->swov.overlayRecordV1.dwHeight = dstHeight = 1843 pUpdate->DstBottom - pUpdate->DstTop; 1844 srcWidth = (unsigned long)pUpdate->SrcRight - pUpdate->SrcLeft; 1845 srcHeight = (unsigned long)pUpdate->SrcBottom - pUpdate->SrcTop; 1846 DBG_DD(ErrorF("===srcWidth= %ld \n", srcWidth)); 1847 DBG_DD(ErrorF("===srcHeight= %ld \n", srcHeight)); 1848 1849 vidCtl = ViaSetVidCtl(pVia, videoFlag); 1850 1851 if (hwDiff->dwNeedV1Prefetch) { 1852 DBG_DD(ErrorF("NEEDV1PREFETCH\n")); 1853 vidCtl |= V1_PREFETCH_ON_3336; 1854 } 1855 1856 /* 1857 * Enable video on secondary 1858 */ 1859 if ((pVia->VideoEngine == VIDEO_ENGINE_CME || 1860 pVia->Chipset == VIA_P4M800PRO) && iga->index) { 1861 /* V1_ON_SND_DISPLAY */ 1862 vidCtl |= V1_ON_SND_DISPLAY; 1863 /* SECOND_DISPLAY_COLOR_KEY_ENABLE */ 1864 compose |= SECOND_DISPLAY_COLOR_KEY_ENABLE | 0x1; 1865 } 1866 1867 viaOverlayGetV1V3Format(pVia, (videoFlag & VIDEO_1_INUSE) ? 1 : 3, 1868 videoFlag, &vidCtl, &hqvCtl); 1869 1870 if (hwDiff->dwThreeHQVBuffer) { /* CLE_C0: HQV supports triple-buffering */ 1871 hqvCtl &= ~HQV_SW_FLIP; 1872 hqvCtl |= HQV_TRIPLE_BUFF | HQV_FLIP_STATUS; 1873 } 1874 1875 /* Starting address of source and Source offset */ 1876 dwOffset = viaOverlayGetSrcStartAddress(pVia, videoFlag, pUpdate, 1877 srcPitch, &hqvOffset); 1878 DBG_DD(ErrorF("===dwOffset= 0x%lx \n", dwOffset)); 1879 1880 pVia->swov.overlayRecordV1.dwOffset = dwOffset; 1881 1882 if (pVia->swov.SrcFourCC == FOURCC_YV12 1883 || pVia->swov.SrcFourCC == FOURCC_I420 1884 || pVia->swov.SrcFourCC == FOURCC_XVMC) { 1885 1886 YCBCRREC YCbCr; 1887 1888 if (videoFlag & VIDEO_HQV_INUSE) { 1889 SetVideoStart(pVia, videoFlag, hwDiff->dwThreeHQVBuffer ? 3 : 2, 1890 pVia->swov.overlayRecordV1.dwHQVAddr[0] + dwOffset, 1891 pVia->swov.overlayRecordV1.dwHQVAddr[1] + dwOffset, 1892 pVia->swov.overlayRecordV1.dwHQVAddr[2] + dwOffset); 1893 1894 if (pVia->swov.SrcFourCC != FOURCC_XVMC) { 1895 YCbCr = viaOverlayGetYCbCrStartAddress(videoFlag, startAddr, 1896 pVia->swov.overlayRecordV1.dwOffset, 1897 pVia->swov.overlayRecordV1.dwUVoffset, 1898 srcPitch, oriSrcHeight); 1899 if (pVia->VideoEngine == VIDEO_ENGINE_CME) { 1900 SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y + proReg, 1901 YCbCr.dwY); 1902 SaveVideoRegister(pVia, HQV_SRC_STARTADDR_U + proReg, 1903 YCbCr.dwCB); 1904 } else { 1905 SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y, YCbCr.dwY); 1906 SaveVideoRegister(pVia, HQV_SRC_STARTADDR_U, YCbCr.dwCR); 1907 SaveVideoRegister(pVia, HQV_SRC_STARTADDR_V, YCbCr.dwCB); 1908 } 1909 } 1910 } else { 1911 YCbCr = viaOverlayGetYCbCrStartAddress(videoFlag, startAddr, 1912 pVia->swov.overlayRecordV1.dwOffset, 1913 pVia->swov.overlayRecordV1.dwUVoffset, 1914 srcPitch, oriSrcHeight); 1915 1916 if (videoFlag & VIDEO_1_INUSE) { 1917 SaveVideoRegister(pVia, V1_STARTADDR_0, YCbCr.dwY); 1918 SaveVideoRegister(pVia, V1_STARTADDR_CB0, YCbCr.dwCR); 1919 SaveVideoRegister(pVia, V1_STARTADDR_CR0, YCbCr.dwCB); 1920 } else 1921 DBG_DD(ErrorF("Upd_Video(): " 1922 "We do not support YV12 with V3!\n")); 1923 } 1924 } else { 1925 if (videoFlag & VIDEO_HQV_INUSE) { 1926 hqvSrcWidth = (unsigned long)pUpdate->SrcRight - pUpdate->SrcLeft; 1927 hqvDstWidth = (unsigned long)pUpdate->DstRight - pUpdate->DstLeft; 1928 1929 if (hqvSrcWidth > hqvDstWidth) 1930 dwOffset = dwOffset * hqvDstWidth / hqvSrcWidth; 1931 1932 SetVideoStart(pVia, videoFlag, hwDiff->dwThreeHQVBuffer ? 3 : 2, 1933 pVia->swov.overlayRecordV1.dwHQVAddr[0] + hqvOffset, 1934 pVia->swov.overlayRecordV1.dwHQVAddr[1] + hqvOffset, 1935 pVia->swov.overlayRecordV1.dwHQVAddr[2] + hqvOffset); 1936 1937 if (pVia->VideoEngine == VIDEO_ENGINE_CME) 1938 SaveVideoRegister(pVia, 0x1cc + proReg, dwOffset); 1939 1940 SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y + proReg, startAddr); 1941 } else { 1942 startAddr += dwOffset; 1943 SetVideoStart(pVia, videoFlag, 1, startAddr, 0, 0); 1944 } 1945 } 1946 1947 fetch = viaOverlayGetFetch(pVia, videoFlag, 1948 srcWidth, dstWidth, oriSrcWidth, &hqvSrcFetch); 1949 DBG_DD(ErrorF("===fetch= 0x%lx\n", fetch)); 1950 1951#if 0 1952 /* For DCT450 test-BOB INTERLEAVE */ 1953 if ((deinterlaceMode & DDOVER_INTERLEAVED) 1954 && (deinterlaceMode & DDOVER_BOB)) { 1955 if (videoFlag & VIDEO_HQV_INUSE) 1956 hqvCtl |= HQV_FIELD_2_FRAME | HQV_FRAME_2_FIELD | HQV_DEINTERLACE; 1957 else 1958 vidCtl |= V1_BOB_ENABLE | V1_FRAME_BASE; 1959 } else if (deinterlaceMode & DDOVER_BOB) { 1960 if (videoFlag & VIDEO_HQV_INUSE) 1961 /* The HQV source data line count should be two times of the original line count */ 1962 hqvCtl |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE; 1963 else 1964 vidCtl |= V1_BOB_ENABLE; 1965 } 1966#endif 1967 1968 if (videoFlag & VIDEO_HQV_INUSE) { 1969 if (!(deinterlaceMode & DDOVER_INTERLEAVED) 1970 && (deinterlaceMode & DDOVER_BOB)) 1971 SetHQVFetch(pVia, hqvSrcFetch, oriSrcHeight << 1); 1972 else 1973 SetHQVFetch(pVia, hqvSrcFetch, oriSrcHeight); 1974 1975 if (pVia->swov.SrcFourCC == FOURCC_YV12 1976 || pVia->swov.SrcFourCC == FOURCC_I420 1977 || pVia->swov.SrcFourCC == FOURCC_XVMC) { 1978 if (videoFlag & VIDEO_1_INUSE) 1979 SaveVideoRegister(pVia, V1_STRIDE, srcPitch << 1); 1980 else 1981 SaveVideoRegister(pVia, V3_STRIDE, srcPitch << 1); 1982 1983 if (pVia->HWDiff.dwHQVFetchByteUnit) 1984 SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg, 1985 ((srcPitch >> 1) << 16) | srcPitch | 1986 HQV_FIFO_DEPTH_1); 1987 else 1988 SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg, 1989 ((srcPitch >> 1) << 16) | srcPitch); 1990 1991 SaveVideoRegister(pVia, HQV_DST_STRIDE + proReg, (srcPitch << 1)); 1992 } else { 1993 if (videoFlag & VIDEO_1_INUSE) 1994 SaveVideoRegister(pVia, V1_STRIDE, srcPitch); 1995 else 1996 SaveVideoRegister(pVia, V3_STRIDE, srcPitch); 1997 1998 SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg, srcPitch); 1999 SaveVideoRegister(pVia, HQV_DST_STRIDE + proReg, srcPitch); 2000 } 2001 2002 } else { 2003 if (videoFlag & VIDEO_1_INUSE) 2004 SaveVideoRegister(pVia, V1_STRIDE, srcPitch | (srcPitch << 15)); 2005 else 2006 SaveVideoRegister(pVia, V3_STRIDE, srcPitch | (srcPitch << 15)); 2007 } 2008 2009 /* Set destination window */ 2010 SetVideoWindow(pScrn, videoFlag, pUpdate); 2011 2012 compose |= ALWAYS_SELECT_VIDEO; 2013 2014 /* Set up X zoom factor */ 2015 2016 pVia->swov.overlayRecordV1.dwFetchAlignment = 0; 2017 2018 if (!viaOverlayHQVCalcZoomWidth(pVia, videoFlag, srcWidth, dstWidth, 2019 &zoomCtl, &miniCtl, &hqvFilterCtl, 2020 &hqvMiniCtl, &hqvScaleCtlH, &haveHQVzoomH)) { 2021 /* Need to scale (minify) too much - can't handle it. */ 2022 SetFetch(pVia, videoFlag, fetch); 2023 FireVideoCommand(pVia, videoFlag, compose); 2024 FlushVidRegBuffer(pVia); 2025 return FALSE; 2026 } 2027 2028 SetFetch(pVia, videoFlag, fetch); 2029 2030 /* Set up Y zoom factor */ 2031 2032 /* For DCT450 test-BOB INTERLEAVE */ 2033 if ((deinterlaceMode & DDOVER_INTERLEAVED) 2034 && (deinterlaceMode & DDOVER_BOB)) { 2035 if (!(videoFlag & VIDEO_HQV_INUSE)) { 2036 srcHeight /= 2; 2037 if (videoFlag & VIDEO_1_INUSE) 2038 vidCtl |= V1_BOB_ENABLE | V1_FRAME_BASE; 2039 else 2040 vidCtl |= V3_BOB_ENABLE | V3_FRAME_BASE; 2041 } else 2042 hqvCtl |= HQV_FIELD_2_FRAME | HQV_FRAME_2_FIELD | HQV_DEINTERLACE; 2043 } else if (deinterlaceMode & DDOVER_BOB) { 2044 if (videoFlag & VIDEO_HQV_INUSE) { 2045 srcHeight <<= 1; 2046 hqvCtl |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE; 2047 } else { 2048 if (videoFlag & VIDEO_1_INUSE) 2049 vidCtl |= V1_BOB_ENABLE; 2050 else 2051 vidCtl |= V3_BOB_ENABLE; 2052 } 2053 } 2054 2055 SetDisplayCount(pVia, videoFlag, srcWidth, srcHeight); 2056 2057 if (!viaOverlayHQVCalcZoomHeight(pVia, srcHeight, dstHeight, &zoomCtl, 2058 &miniCtl, &hqvFilterCtl, &hqvMiniCtl, 2059 &hqvScaleCtlV, &haveHQVzoomV)) { 2060 /* Need to scale (minify) too much - can't handle it. */ 2061 FireVideoCommand(pVia, videoFlag, compose); 2062 FlushVidRegBuffer(pVia); 2063 return FALSE; 2064 } 2065 2066 SetupFIFOs(pVia, videoFlag, miniCtl, srcWidth); 2067 2068 if (videoFlag & VIDEO_HQV_INUSE) { 2069 miniCtl = 0; 2070 2071 if (haveHQVzoomH || haveHQVzoomV) { 2072 tmp = 0; 2073 2074 if (haveHQVzoomH) { 2075 miniCtl = V1_X_INTERPOLY; 2076 /* Disable X interpolation if the height exceeds 2077 * the maximum supported by the hardware */ 2078 if (srcHeight >= pVia->swov.maxHInterp) 2079 miniCtl &= ~V1_X_INTERPOLY; 2080 tmp = zoomCtl & 0xffff0000; 2081 } 2082 2083 if (haveHQVzoomV) { 2084 miniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY; 2085 /* Disable Y interpolation if the width exceeds 2086 * the maximum supported by the hardware */ 2087 if (srcWidth >= pVia->swov.maxWInterp) 2088 miniCtl &= ~V1_Y_INTERPOLY; 2089 tmp |= zoomCtl & 0x0000ffff; 2090 hqvFilterCtl &= 0xfffdffff; 2091 } 2092 2093 /* Temporary fix for 2D bandwidth problem. 2002/08/01 */ 2094 if (pVia->swov.gdwUseExtendedFIFO) 2095 miniCtl &= ~V1_Y_INTERPOLY; 2096 2097 SetMiniAndZoom(pVia, videoFlag, miniCtl, tmp); 2098 } else { 2099 if (srcHeight == dstHeight) 2100 hqvFilterCtl &= 0xfffdffff; 2101 SetMiniAndZoom(pVia, videoFlag, 0, 0); 2102 } 2103 if (hwDiff->dwNewScaleCtl) { 2104 SaveVideoRegister(pVia, HQV_H_SCALE_CONTROL + proReg, hqvScaleCtlH); 2105 SaveVideoRegister(pVia, HQV_V_SCALE_CONTROL + proReg, hqvScaleCtlV); 2106 } else { 2107 SaveVideoRegister(pVia, HQV_MINIFY_CONTROL + proReg, hqvMiniCtl); 2108 } 2109 SaveVideoRegister(pVia, HQV_FILTER_CONTROL + proReg, hqvFilterCtl); 2110 } else 2111 SetMiniAndZoom(pVia, videoFlag, miniCtl, zoomCtl); 2112 2113 if (haveColorKey) 2114 compose = SetColorKey(pVia, videoFlag, colorKeyLow, colorKeyHigh, 2115 compose); 2116 2117 if (haveChromaKey) 2118 compose = SetChromaKey(pVia, videoFlag, chromaKeyLow, chromaKeyHigh, 2119 miniCtl, compose); 2120 2121 if (pVia->VideoEngine == VIDEO_ENGINE_CME) { 2122 SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL1),0); 2123 SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL3),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1)); 2124 if ((pVia->Chipset == VIA_VX800) || 2125 (pVia->Chipset == VIA_VX855) || 2126 (pVia->Chipset == VIA_VX900)) { 2127 SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL2),0); 2128 SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL4),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1)); 2129 if ((pVia->Chipset == VIA_VX855) || 2130 (pVia->Chipset == VIA_VX900)) { 2131 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL1,0); 2132 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL3,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1)); 2133 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL2,0); 2134 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL4,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1)); 2135 SaveVideoRegister(pVia, HQV_BACKGROUND_DATA_OFFSET,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1)); 2136 SaveVideoRegister(pVia, HQV_EXTENDED_CONTROL,0); 2137 /*0x3e0*/ 2138 SaveVideoRegister(pVia, HQV_SUBP_HSCALE_CTRL,0); 2139 /*0x3e8*/ 2140 SaveVideoRegister(pVia, HQV_SUBP_VSCALE_CTRL,0); 2141 } 2142 2143 if (pVia->Chipset == VIA_VX900) { 2144 2145 SaveVideoRegister(pVia, HQV_SHARPNESS_DECODER_HANDSHAKE_CTRL_410, 0); 2146 } 2147 2148 // TODO Need to be tested on VX800 2149 /* 0x3B8 */ 2150 SaveVideoRegister(pVia, HQV_DEFAULT_VIDEO_COLOR, HQV_FIX_COLOR); 2151 2152 } 2153 } 2154 2155 /* Set up video control */ 2156 if (videoFlag & VIDEO_HQV_INUSE) { 2157 2158 if (!pVia->swov.SWVideo_ON) { 2159 DBG_DD(ErrorF(" First HQV\n")); 2160 2161 FlushVidRegBuffer(pVia); 2162 2163 DBG_DD(ErrorF(" Wait flips")); 2164 2165 if (hwDiff->dwHQVInitPatch) { 2166 DBG_DD(ErrorF(" Initializing HQV twice ...")); 2167 for (i = 0; i < 2; i++) { 2168 viaWaitHQVFlipClear(pVia, 2169 ((hqvCtl & ~HQV_SW_FLIP) | 2170 HQV_FLIP_STATUS) & ~HQV_ENABLE); 2171 VIASETREG(HQV_CONTROL + proReg, hqvCtl); 2172 viaWaitHQVFlip(pVia); 2173 } 2174 DBG_DD(ErrorF(" done.\n")); 2175 } else { /* CLE_C0 */ 2176 CARD32 volatile *HQVCtrl = 2177 (CARD32 volatile *)(pVia->MapBase + HQV_CONTROL + 2178 proReg); 2179 2180 /* Check that HQV is idle */ 2181 DBG_DD(ErrorF("HQV control wf - %08lx\n", *HQVCtrl)); 2182 while (!(*HQVCtrl & HQV_IDLE)) { 2183 DBG_DD(ErrorF("HQV control busy - %08lx\n", *HQVCtrl)); 2184 usleep(1); 2185 } 2186 2187 VIASETREG(HQV_CONTROL + proReg, hqvCtl & ~HQV_SW_FLIP); 2188 VIASETREG(HQV_CONTROL + proReg, hqvCtl | HQV_SW_FLIP); 2189 2190 DBG_DD(ErrorF("HQV control wf5 - %08lx\n", *HQVCtrl)); 2191 DBG_DD(ErrorF(" Wait flips5")); 2192 2193 if (pVia->VideoEngine != VIDEO_ENGINE_CME) { 2194 for (i = 0; (i < 50) && !(*HQVCtrl & HQV_FLIP_STATUS); 2195 i++) { 2196 DBG_DD(ErrorF(" HQV wait %d %08lx\n", i, *HQVCtrl)); 2197 *HQVCtrl |= HQV_SW_FLIP | HQV_FLIP_STATUS; 2198 usleep(1); 2199 } 2200 } else { 2201 viaWaitHQVFlip(pVia); 2202 } 2203 2204 DBG_DD(ErrorF(" Wait flips6")); 2205 } 2206 2207 if (videoFlag & VIDEO_1_INUSE) { 2208 VIASETREG(V1_CONTROL, vidCtl); 2209 VIASETREG(V_COMPOSE_MODE, compose | V1_COMMAND_FIRE); 2210 if (pVia->swov.gdwUseExtendedFIFO) { 2211 /* Set Display FIFO */ 2212 DBG_DD(ErrorF(" Wait flips7")); 2213 viaWaitVBI(pVia); 2214 DBG_DD(ErrorF(" Wait flips 8")); 2215 hwp->writeSeq(hwp, 0x17, 0x2F); 2216 ViaSeqMask(hwp, 0x16, 0x14, 0x1F); 2217 hwp->writeSeq(hwp, 0x18, 0x56); 2218 DBG_DD(ErrorF(" Wait flips 9")); 2219 } 2220 } else { 2221 DBG_DD(ErrorF(" Wait flips 10")); 2222 VIASETREG(V3_CONTROL, vidCtl); 2223 VIASETREG(V_COMPOSE_MODE, compose | V3_COMMAND_FIRE); 2224 } 2225 DBG_DD(ErrorF(" Done flips")); 2226 } else { 2227 DBG_DD(ErrorF(" Normal called\n")); 2228 SaveVideoRegister(pVia, HQV_CONTROL + proReg, 2229 hqvCtl | HQV_FLIP_STATUS); 2230 SetVideoControl(pVia, videoFlag, vidCtl); 2231 FireVideoCommand(pVia, videoFlag, compose); 2232 viaWaitHQVDone(pVia); 2233 FlushVidRegBuffer(pVia); 2234 } 2235 } else { 2236 SetVideoControl(pVia, videoFlag, vidCtl); 2237 FireVideoCommand(pVia, videoFlag, compose); 2238 viaWaitHQVDone(pVia); 2239 FlushVidRegBuffer(pVia); 2240 } 2241 pVia->swov.SWVideo_ON = TRUE; 2242 2243 DBG_DD(ErrorF(" Done Upd_Video")); 2244 2245 return TRUE; 2246 2247} /* Upd_Video */ 2248 2249/* 2250 * VIAVidUpdateOverlay() 2251 * Parameters: src rectangle, dst rectangle, colorkey... 2252 * Return value: unsigned long of state 2253 * Note: updates the overlay image parameter. 2254 */ 2255Bool 2256VIAVidUpdateOverlay(xf86CrtcPtr crtc, LPDDUPDATEOVERLAY pUpdate) 2257{ 2258 ScrnInfoPtr pScrn = crtc->scrn; 2259 VIAPtr pVia = VIAPTR(pScrn); 2260 OVERLAYRECORD *ovlV1 = &pVia->swov.overlayRecordV1; 2261 2262 unsigned long flags = pUpdate->dwFlags; 2263 unsigned long videoFlag = 0; 2264 unsigned long startAddr = 0; 2265 unsigned long deinterlaceMode = 0; 2266 2267 unsigned long haveColorKey = 0, haveChromaKey = 0; 2268 unsigned long colorKeyLow = 0, colorKeyHigh = 0; 2269 unsigned long chromaKeyLow = 0, chromaKeyHigh = 0; 2270 2271 unsigned long scrnWidth, scrnHeight; 2272 int dstTop, dstBottom, dstLeft, dstRight; 2273 int panDX, panDY; /* Panning delta */ 2274 2275 unsigned long proReg = 0; 2276 2277 panDX = pVia->swov.panning_x; 2278 panDY = pVia->swov.panning_y; 2279 pVia->swov.oldPanningX = pVia->swov.panning_x; 2280 pVia->swov.oldPanningY = pVia->swov.panning_y; 2281 2282 pUpdate->DstLeft -= panDX; 2283 pUpdate->DstTop -= panDY; 2284 pUpdate->DstRight -= panDX; 2285 pUpdate->DstBottom -= panDY; 2286 2287 DBG_DD(ErrorF("Raw rSrc X (%ld,%ld) Y (%ld,%ld)\n", 2288 pUpdate->SrcLeft, pUpdate->SrcRight, 2289 pUpdate->SrcTop, pUpdate->SrcBottom)); 2290 DBG_DD(ErrorF("Raw rDest X (%ld,%ld) Y (%ld,%ld)\n", 2291 pUpdate->DstLeft, pUpdate->DstRight, 2292 pUpdate->DstTop, pUpdate->DstBottom)); 2293 2294 if ((pVia->swov.SrcFourCC == FOURCC_YUY2) || 2295 (pVia->swov.SrcFourCC == FOURCC_RV15) || 2296 (pVia->swov.SrcFourCC == FOURCC_RV16) || 2297 (pVia->swov.SrcFourCC == FOURCC_RV32) || 2298 (pVia->swov.SrcFourCC == FOURCC_YV12) || 2299 (pVia->swov.SrcFourCC == FOURCC_I420) || 2300 (pVia->swov.SrcFourCC == FOURCC_XVMC)) { 2301 videoFlag = pVia->swov.gdwVideoFlagSW; 2302 } 2303 2304 if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE)) 2305 proReg = PRO_HQV1_OFFSET; 2306 2307 flags |= DDOVER_INTERLEAVED; 2308 2309 /* Disable destination color keying if the alpha window is in use. */ 2310 if (pVia->swov.gdwAlphaEnabled) 2311 flags &= ~DDOVER_KEYDEST; 2312 2313 ResetVidRegBuffer(pVia); 2314 2315 /* For SW decode HW overlay use */ 2316 startAddr = VIAGETREG(HQV_SRC_STARTADDR_Y + proReg); 2317 2318 if (flags & DDOVER_KEYDEST) { 2319 haveColorKey = 1; 2320 colorKeyLow = pUpdate->dwColorSpaceLowValue; 2321 } 2322 2323 if (flags & DDOVER_INTERLEAVED) 2324 deinterlaceMode |= DDOVER_INTERLEAVED; 2325 2326 if (flags & DDOVER_BOB) 2327 deinterlaceMode |= DDOVER_BOB; 2328 2329 if ((pVia->ChipId == PCI_CHIP_CLE3122) 2330 && (pScrn->currentMode->HDisplay > 1024)) { 2331 DBG_DD(ErrorF("UseExtendedFIFO\n")); 2332 pVia->swov.gdwUseExtendedFIFO = 1; 2333 } else 2334 pVia->swov.gdwUseExtendedFIFO = 0; 2335 2336 /* Figure out actual rSrc rectangle */ 2337 2338 dstLeft = pUpdate->DstLeft; 2339 dstTop = pUpdate->DstTop; 2340 dstRight = pUpdate->DstRight; 2341 dstBottom = pUpdate->DstBottom; 2342 2343 scrnWidth = pScrn->currentMode->HDisplay; 2344 scrnHeight = pScrn->currentMode->VDisplay; 2345 2346 if (dstLeft < 0) { 2347 pUpdate->SrcLeft = ((((-dstLeft) * ovlV1->dwV1OriWidth) + 2348 ((dstRight - dstLeft) >> 1)) 2349 / (dstRight - dstLeft)); 2350 } 2351 if (dstRight > scrnWidth) { 2352 pUpdate->SrcRight = ((((scrnWidth - dstLeft) * ovlV1->dwV1OriWidth) + 2353 ((dstRight - dstLeft) >> 1)) 2354 / (dstRight - dstLeft)); 2355 } 2356 if (dstTop < 0) { 2357 pUpdate->SrcTop = ((((-dstTop) * ovlV1->dwV1OriHeight) + 2358 ((dstBottom - dstTop) >> 1)) 2359 / (dstBottom - dstTop)); 2360 } 2361 if (dstBottom > scrnHeight) { 2362 pUpdate->SrcBottom = ((((scrnHeight - dstTop) * ovlV1->dwV1OriHeight) + 2363 ((dstBottom - dstTop) >> 1)) 2364 / (dstBottom - dstTop)); 2365 } 2366 2367 /* Save modified src & original dest rectangle parameters */ 2368 2369 if ((pVia->swov.SrcFourCC == FOURCC_YUY2) || 2370 (pVia->swov.SrcFourCC == FOURCC_RV15) || 2371 (pVia->swov.SrcFourCC == FOURCC_RV16) || 2372 (pVia->swov.SrcFourCC == FOURCC_RV32) || 2373 (pVia->swov.SrcFourCC == FOURCC_YV12) || 2374 (pVia->swov.SrcFourCC == FOURCC_I420) || 2375 (pVia->swov.SrcFourCC == FOURCC_XVMC)) { 2376 pVia->swov.SWDevice.gdwSWDstLeft = pUpdate->DstLeft + panDX; 2377 pVia->swov.SWDevice.gdwSWDstTop = pUpdate->DstTop + panDY; 2378 pVia->swov.SWDevice.gdwSWDstWidth = 2379 pUpdate->DstRight - pUpdate->DstLeft; 2380 pVia->swov.SWDevice.gdwSWDstHeight = 2381 pUpdate->DstBottom - pUpdate->DstTop; 2382 2383 pVia->swov.SWDevice.gdwSWSrcWidth = ovlV1->dwV1SrcWidth = 2384 pUpdate->SrcRight - pUpdate->SrcLeft; 2385 pVia->swov.SWDevice.gdwSWSrcHeight = ovlV1->dwV1SrcHeight = 2386 pUpdate->SrcBottom - pUpdate->SrcTop; 2387 } 2388 2389 ovlV1->dwV1SrcLeft = pUpdate->SrcLeft; 2390 ovlV1->dwV1SrcRight = pUpdate->SrcRight; 2391 ovlV1->dwV1SrcTop = pUpdate->SrcTop; 2392 ovlV1->dwV1SrcBot = pUpdate->SrcBottom; 2393 2394 /* Figure out actual rDest rectangle */ 2395 2396 pUpdate->DstLeft = (dstLeft < 0) ? 0 : dstLeft; 2397 pUpdate->DstTop = (dstTop < 0) ? 0 : dstTop; 2398 if (pUpdate->DstTop >= scrnHeight) 2399 pUpdate->DstTop = scrnHeight - 1; 2400 pUpdate->DstRight = (dstRight > scrnWidth) ? scrnWidth : dstRight; 2401 pUpdate->DstBottom = (dstBottom > scrnHeight) ? scrnHeight : dstBottom; 2402 2403 /* Update the overlay */ 2404 2405 if (!Upd_Video(crtc, videoFlag, startAddr, pUpdate, 2406 pVia->swov.SWDevice.dwPitch, ovlV1->dwV1OriWidth, 2407 ovlV1->dwV1OriHeight, deinterlaceMode, haveColorKey, 2408 haveChromaKey, colorKeyLow, colorKeyHigh, chromaKeyLow, 2409 chromaKeyHigh)) 2410 return FALSE; 2411 2412 pVia->swov.SWVideo_ON = FALSE; 2413 2414 return TRUE; 2415 2416} /* VIAVidUpdateOverlay */ 2417 2418/* 2419 * 2420 */ 2421void 2422ViaOverlayHide(ScrnInfoPtr pScrn) 2423{ 2424 VIAPtr pVia = VIAPTR(pScrn); 2425 vgaHWPtr hwp = VGAHWPTR(pScrn); 2426 CARD32 videoFlag = 0; 2427 unsigned long proReg = 0; 2428 2429 if ((pVia->swov.SrcFourCC == FOURCC_YUY2) || 2430 (pVia->swov.SrcFourCC == FOURCC_RV15) || 2431 (pVia->swov.SrcFourCC == FOURCC_RV16) || 2432 (pVia->swov.SrcFourCC == FOURCC_RV32) || 2433 (pVia->swov.SrcFourCC == FOURCC_YV12) || 2434 (pVia->swov.SrcFourCC == FOURCC_I420) || 2435 (pVia->swov.SrcFourCC == FOURCC_XVMC)) 2436 videoFlag = pVia->swov.gdwVideoFlagSW; 2437 2438 if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE)) 2439 proReg = PRO_HQV1_OFFSET; 2440 2441 ResetVidRegBuffer(pVia); 2442 2443 if (pVia->HWDiff.dwHQVDisablePatch) 2444 ViaSeqMask(hwp, 0x2E, 0x00, 0x10); 2445 2446 SaveVideoRegister(pVia, V_FIFO_CONTROL, V1_FIFO_PRETHRESHOLD12 | 2447 V1_FIFO_THRESHOLD8 | V1_FIFO_DEPTH16); 2448 SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL, 2449 ALPHA_FIFO_THRESHOLD4 | ALPHA_FIFO_DEPTH8 | 2450 V3_FIFO_THRESHOLD24 | V3_FIFO_DEPTH32); 2451 2452 if (videoFlag & VIDEO_HQV_INUSE) 2453 SaveVideoRegister(pVia, HQV_CONTROL + proReg, 2454 VIAGETREG(HQV_CONTROL + proReg) & ~HQV_ENABLE); 2455 2456 if (videoFlag & VIDEO_1_INUSE) 2457 SaveVideoRegister(pVia, V1_CONTROL, VIAGETREG(V1_CONTROL) & ~V1_ENABLE); 2458 else 2459 SaveVideoRegister(pVia, V3_CONTROL, VIAGETREG(V3_CONTROL) & ~V3_ENABLE); 2460 2461 FireVideoCommand(pVia, videoFlag, VIAGETREG(V_COMPOSE_MODE)); 2462 FlushVidRegBuffer(pVia); 2463 2464 if (pVia->HWDiff.dwHQVDisablePatch) 2465 ViaSeqMask(hwp, 0x2E, 0x10, 0x10); 2466 2467 pVia->swov.SWVideo_ON = FALSE; 2468 pVia->VideoStatus &= ~VIDEO_SWOV_ON; 2469} 2470