via_xv.c revision 90b17f1b
1/* 2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sub license, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to 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 OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24 25/* 26 * I N C L U D E S 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include "xf86.h" 34#include "xf86_OSproc.h" 35 36#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 37#include "xf86Resources.h" 38#endif 39 40#include "compiler.h" 41#include "xf86Pci.h" 42#include "regionstr.h" 43#include "via_driver.h" 44 45#include "xf86xv.h" 46#include <X11/extensions/Xv.h> 47#include "dixstruct.h" 48#include "via_xvpriv.h" 49#include "fourcc.h" 50 51/* 52 * D E F I N E 53 */ 54#define OFF_DELAY 200 /* milliseconds */ 55#define FREE_DELAY 60000 56#define PARAMSIZE 1024 57#define SLICESIZE 65536 58#define OFF_TIMER 0x01 59#define FREE_TIMER 0x02 60#define TIMER_MASK (OFF_TIMER | FREE_TIMER) 61#define VIA_MAX_XVIMAGE_X 1920 62#define VIA_MAX_XVIMAGE_Y 1200 63 64#define LOW_BAND 0x0CB0 65#define MID_BAND 0x1f10 66 67#define XV_IMAGE 0 68#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 69#ifndef XvExtension 70void 71viaInitVideo(ScreenPtr pScreen) 72{ 73} 74 75void 76viaExitVideo(ScrnInfoPtr pScrn) 77{ 78} 79void 80viaSaveVideo(ScrnInfoPtr pScrn) 81{ 82} 83void 84viaRestoreVideo(ScrnInfoPtr pScrn) 85{ 86} 87void 88VIAVidAdjustFrame(ScrnInfoPtr pScrn, int x, int y) 89{ 90} 91#else 92 93static vidCopyFunc viaFastVidCpy = NULL; 94 95/* 96 * F U N C T I O N D E C L A R A T I O N 97 */ 98static unsigned viaSetupAdaptors(ScreenPtr pScreen, 99 XF86VideoAdaptorPtr ** adaptors); 100static void viaStopVideo(ScrnInfoPtr, pointer, Bool); 101static void viaQueryBestSize(ScrnInfoPtr, Bool, 102 short, short, short, short, unsigned int *, unsigned int *, pointer); 103static int viaQueryImageAttributes(ScrnInfoPtr, 104 int, unsigned short *, unsigned short *, int *, int *); 105static int viaGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer); 106static int viaSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); 107static int viaPutImage(ScrnInfoPtr, short, short, short, short, short, short, 108 short, short, int, unsigned char *, short, short, Bool, 109 RegionPtr, pointer, DrawablePtr); 110static void UVBlit(unsigned char *dest, 111 const unsigned char *uBuffer, 112 const unsigned char *vBuffer, 113 unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines); 114static void nv12Blit(unsigned char *nv12Chroma, 115 const unsigned char *uBuffer, 116 const unsigned char *vBuffer, 117 unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines); 118 119static Atom xvBrightness, xvContrast, xvColorKey, xvHue, xvSaturation, 120 xvAutoPaint; 121 122/* 123 * S T R U C T S 124 */ 125/* client libraries expect an encoding */ 126static XF86VideoEncodingRec DummyEncoding[1] = { 127 {XV_IMAGE, "XV_IMAGE", VIA_MAX_XVIMAGE_X, VIA_MAX_XVIMAGE_Y, {1, 1}}, 128}; 129 130#define NUM_FORMATS_G 9 131 132static XF86VideoFormatRec FormatsG[NUM_FORMATS_G] = { 133 {8, TrueColor}, /* Dithered */ 134 {8, PseudoColor}, /* Using .. */ 135 {8, StaticColor}, 136 {8, GrayScale}, 137 {8, StaticGray}, /* .. TexelLUT */ 138 {16, TrueColor}, 139 {24, TrueColor}, 140 {16, DirectColor}, 141 {24, DirectColor} 142}; 143 144#define NUM_ATTRIBUTES_G 6 145 146static XF86AttributeRec AttributesG[NUM_ATTRIBUTES_G] = { 147 {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, 148 {XvSettable | XvGettable, 0, 10000, "XV_BRIGHTNESS"}, 149 {XvSettable | XvGettable, 0, 20000, "XV_CONTRAST"}, 150 {XvSettable | XvGettable, 0, 20000, "XV_SATURATION"}, 151 {XvSettable | XvGettable, -180, 180, "XV_HUE"}, 152 {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"} 153}; 154 155#define NUM_IMAGES_G 7 156 157static XF86ImageRec ImagesG[NUM_IMAGES_G] = { 158 XVIMAGE_YUY2, 159 XVIMAGE_YV12, 160 XVIMAGE_I420, 161 { 162 /* 163 * Below, a dummy picture type that is used in XvPutImage only to do 164 * an overlay update. Introduced for the XvMC client lib. 165 * Defined to have a zero data size. 166 */ 167 168 FOURCC_XVMC, 169 XvYUV, 170 LSBFirst, 171 { 'V', 'I', 'A', 0x00, 172 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00, 173 0x38, 0x9B, 0x71}, 174 12, 175 XvPlanar, 176 1, 177 0, 0, 0, 0, 178 8, 8, 8, 179 1, 2, 2, 180 1, 2, 2, 181 { 'Y', 'V', 'U', 182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 184 XvTopToBottom}, 185 { /* RGB 555 */ 186 FOURCC_RV15, 187 XvRGB, 188 LSBFirst, 189 { 'R', 'V', '1', '5', 190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 191 0x00, 0x00, 0x00}, 192 16, 193 XvPacked, 194 1, 195 15, 0x7C00, 0x03E0, 0x001F, 196 0, 0, 0, 197 0, 0, 0, 198 0, 0, 0, 199 { 'R', 'V', 'B', 0, 200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 201 0, 0, 0, 0, 0, 0, 0, 0, 0}, 202 XvTopToBottom}, 203 { /* RGB 565 */ 204 FOURCC_RV16, 205 XvRGB, 206 LSBFirst, 207 { 'R', 'V', '1', '6', 208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 209 0x00, 0x00, 0x00}, 210 16, 211 XvPacked, 212 1, 213 16, 0xF800, 0x07E0, 0x001F, 214 0, 0, 0, 215 0, 0, 0, 216 0, 0, 0, 217 { 'R', 'V', 'B', 0, 218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219 0, 0, 0, 0, 0, 0, 0, 0, 0}, 220 XvTopToBottom}, 221 { /* RGB 888 */ 222 FOURCC_RV32, 223 XvRGB, 224 LSBFirst, 225 { 'R', 'V', '3', '2', 226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 227 0x00, 0x00, 0x00}, 228 32, 229 XvPacked, 230 1, 231 24, 0xff0000, 0x00ff00, 0x0000ff, 232 0, 0, 0, 233 0, 0, 0, 234 0, 0, 0, 235 { 'R', 'V', 'B', 0, 236 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237 0, 0, 0, 0, 0, 0, 0, 0, 0}, 238 XvTopToBottom} 239 240}; 241 242static char *XvAdaptorName[XV_ADAPT_NUM] = { 243 "XV_SWOV" 244}; 245 246static XF86VideoAdaptorPtr viaAdaptPtr[XV_ADAPT_NUM]; 247static XF86VideoAdaptorPtr *allAdaptors; 248static unsigned numAdaptPort[XV_ADAPT_NUM] = { 1 }; 249 250/* 251 * F U N C T I O N 252 */ 253 254/* 255 * Decide if the mode support video overlay. This depends on the bandwidth 256 * of the mode and the type of RAM available. 257 */ 258 259static Bool 260DecideOverlaySupport(xf86CrtcPtr crtc) 261{ 262 DisplayModePtr mode = &crtc->desiredMode; 263 ScrnInfoPtr pScrn = crtc->scrn; 264 VIAPtr pVia = VIAPTR(pScrn); 265 266#ifdef HAVE_DEBUG 267 if (pVia->disableXvBWCheck) 268 return TRUE; 269#endif 270 271 /* Small trick here. We keep the height in 16's of lines and width in 32's 272 * to avoid numeric overflow */ 273 274 if (pVia->ChipId != PCI_CHIP_VT3205 && 275 pVia->ChipId != PCI_CHIP_VT3204 && 276 pVia->ChipId != PCI_CHIP_VT3259 && 277 pVia->ChipId != PCI_CHIP_VT3314 && 278 pVia->ChipId != PCI_CHIP_VT3327 && 279 pVia->ChipId != PCI_CHIP_VT3336 && 280 pVia->ChipId != PCI_CHIP_VT3409 && 281 pVia->ChipId != PCI_CHIP_VT3410 && 282 pVia->ChipId != PCI_CHIP_VT3364 && 283 pVia->ChipId != PCI_CHIP_VT3324 && 284 pVia->ChipId != PCI_CHIP_VT3353) { 285 CARD32 bandwidth = (mode->HDisplay >> 4) * (mode->VDisplay >> 5) * 286 pScrn->bitsPerPixel * mode->VRefresh; 287 288 switch (pVia->MemClk) { 289 case VIA_MEM_SDR100: /* No overlay without DDR */ 290 case VIA_MEM_SDR133: 291 return FALSE; 292 case VIA_MEM_DDR200: 293 /* Basic limit for DDR200 is about this */ 294 if (bandwidth > 1800000) 295 return FALSE; 296 /* But we have constraints at higher than 800x600 */ 297 if (mode->HDisplay > 800) { 298 if (pScrn->bitsPerPixel != 8) 299 return FALSE; 300 if (mode->VDisplay > 768) 301 return FALSE; 302 if (mode->VRefresh > 60) 303 return FALSE; 304 } 305 return TRUE; 306 case 0: /* FIXME: Why does my CLE266 report 0? */ 307 case VIA_MEM_DDR266: 308 if (bandwidth > 7901250) 309 return FALSE; 310 return TRUE; 311 } 312 return FALSE; 313 314 } else { 315 unsigned width, height, refresh, dClock; 316 float mClock, memEfficiency, needBandWidth, totalBandWidth; 317 318 switch (pVia->MemClk) { 319 case VIA_MEM_SDR100: 320 mClock = 50; /*HW base on 128 bit */ 321 memEfficiency = (float)SINGLE_3205_100; 322 break; 323 case VIA_MEM_SDR133: 324 mClock = 66.5; 325 memEfficiency = (float)SINGLE_3205_100; 326 break; 327 case VIA_MEM_DDR200: 328 mClock = 100; 329 memEfficiency = (float)SINGLE_3205_100; 330 break; 331 case VIA_MEM_DDR266: 332 mClock = 133; 333 memEfficiency = (float)SINGLE_3205_133; 334 break; 335 case VIA_MEM_DDR333: 336 mClock = 166; 337 memEfficiency = (float)SINGLE_3205_133; 338 break; 339 case VIA_MEM_DDR400: 340 mClock = 200; 341 memEfficiency = (float)SINGLE_3205_133; 342 break; 343 case VIA_MEM_DDR533: 344 mClock = 266; 345 memEfficiency = (float)SINGLE_3205_133; 346 break; 347 case VIA_MEM_DDR667: 348 mClock = 333; 349 memEfficiency = (float)SINGLE_3205_133; 350 break; 351 case VIA_MEM_DDR800: 352 mClock = 400; 353 memEfficiency = (float)SINGLE_3205_133; 354 break; 355 case VIA_MEM_DDR1066: 356 mClock = 533; 357 memEfficiency = (float)SINGLE_3205_133; 358 break; 359 default: 360 ErrorF("Unknow DRAM Type!\n"); 361 mClock = 166; 362 memEfficiency = (float)SINGLE_3205_133; 363 break; 364 } 365 366 width = mode->HDisplay; 367 height = mode->VDisplay; 368 refresh = mode->VRefresh; 369 370 if (refresh==0) { 371 refresh=60; 372 ErrorF("Unable to fetch vertical refresh value, needed for bandwidth calculation.\n"); 373 } 374 375 /* 376 * Approximative, VERY conservative formula in some cases. 377 * This formula and the one below are derived analyzing the 378 * tables present in VIA's own drivers. They may reject the over- 379 * lay in some cases where VIA's driver don't. 380 */ 381 dClock = (width * height * refresh) / 680000; 382 if (dClock) { 383 needBandWidth = 384 (float)(((pScrn->bitsPerPixel >> 3) + VIDEO_BPP) * dClock); 385 totalBandWidth = (float)(mClock * 16. * memEfficiency); 386 387 DBG_DD(ErrorF(" via_xv.c : cBitsPerPel= %d : \n", 388 pScrn->bitsPerPixel)); 389 DBG_DD(ErrorF(" via_xv.c : Video_Bpp= %d : \n", VIDEO_BPP)); 390 DBG_DD(ErrorF(" via_xv.c : refresh = %d : \n", refresh)); 391 DBG_DD(ErrorF(" via_xv.c : dClock= %d : \n", dClock)); 392 DBG_DD(ErrorF(" via_xv.c : mClk= %f : \n", mClock)); 393 DBG_DD(ErrorF(" via_xv.c : memEfficiency= %f : \n", 394 memEfficiency)); 395 ErrorF(" via_xv.c : needBandwidth= %f : \n", 396 needBandWidth); 397 ErrorF(" via_xv.c : totalBandwidth= %f : \n", 398 totalBandWidth); 399 if (needBandWidth < totalBandWidth) 400 return TRUE; 401 } 402 return FALSE; 403 } 404 return FALSE; 405} 406 407static const char *viaXvErrMsg[xve_numerr] = { "No Error.", 408 "Bandwidth is insufficient. Check bios memory settings.", 409 "PCI DMA blit failed. You probably encountered a bug.", 410 "Not enough resources to complete the request. Probably out of memory.", 411 "General Error. I wish I could be more specific.", 412 "Wrong adaptor used. Try another port number." 413}; 414 415static void 416viaXvError(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv, XvError error) 417{ 418 if (error == xve_none) { 419 pPriv->xvErr = xve_none; 420 return; 421 } 422 if (error == pPriv->xvErr) { 423 return; 424 } 425 pPriv->xvErr = error; 426 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[Xv] Port %d: %s\n", 427 pPriv->xv_portnum, viaXvErrMsg[error]); 428} 429 430static void 431viaResetVideo(ScrnInfoPtr pScrn) 432{ 433 VIAPtr pVia = VIAPTR(pScrn); 434 vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200); 435 436 DBG_DD(ErrorF(" via_xv.c : viaResetVideo: \n")); 437 438 viaVidEng->video1_ctl = 0; 439 viaVidEng->video3_ctl = 0; 440 viaVidEng->compose = V1_COMMAND_FIRE; 441 viaVidEng->compose = V3_COMMAND_FIRE; 442 viaVidEng->color_key = 0x821; 443 viaVidEng->snd_color_key = 0x821; 444} 445 446void 447viaSaveVideo(ScrnInfoPtr pScrn) 448{ 449 VIAPtr pVia = VIAPTR(pScrn); 450 vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200); 451 452 DBG_DD(ErrorF(" via_xv.c : viaSaveVideo : \n")); 453 /* Save video registers */ 454 memcpy(pVia->VideoRegs, (void*)viaVidEng, sizeof(video_via_regs)); 455 456 pVia->dwV1 = ((vmmtr) viaVidEng)->video1_ctl; 457 pVia->dwV3 = ((vmmtr) viaVidEng)->video3_ctl; 458 viaVidEng->video1_ctl = 0; 459 viaVidEng->video3_ctl = 0; 460 viaVidEng->compose = V1_COMMAND_FIRE; 461 viaVidEng->compose = V3_COMMAND_FIRE; 462} 463 464void 465viaRestoreVideo(ScrnInfoPtr pScrn) 466{ 467 VIAPtr pVia = VIAPTR(pScrn); 468 vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200); 469 video_via_regs *localVidEng = pVia->VideoRegs; 470 471 DBG_DD(ErrorF(" via_xv.c : viaRestoreVideo : \n")); 472 473 /* Restore video registers */ 474 /* flush restored video engines' setting to MapBase */ 475 viaVidEng->alphawin_hvstart = localVidEng->alphawin_hvstart; 476 viaVidEng->alphawin_size = localVidEng->alphawin_size; 477 viaVidEng->alphawin_ctl = localVidEng->alphawin_ctl; 478 viaVidEng->alphafb_stride = localVidEng->alphafb_stride; 479 viaVidEng->color_key = localVidEng->color_key; 480 viaVidEng->alphafb_addr = localVidEng->alphafb_addr; 481 viaVidEng->chroma_low = localVidEng->chroma_low; 482 viaVidEng->chroma_up = localVidEng->chroma_up; 483 viaVidEng->interruptflag = localVidEng->interruptflag; 484 485 if (pVia->ChipId != PCI_CHIP_VT3314) 486 { 487 /*VT3314 only has V3*/ 488 viaVidEng->video1_ctl = localVidEng->video1_ctl; 489 viaVidEng->video1_fetch = localVidEng->video1_fetch; 490 viaVidEng->video1y_addr1 = localVidEng->video1y_addr1; 491 viaVidEng->video1_stride = localVidEng->video1_stride; 492 viaVidEng->video1_hvstart = localVidEng->video1_hvstart; 493 viaVidEng->video1_size = localVidEng->video1_size; 494 viaVidEng->video1y_addr2 = localVidEng->video1y_addr2; 495 viaVidEng->video1_zoom = localVidEng->video1_zoom; 496 viaVidEng->video1_mictl = localVidEng->video1_mictl; 497 viaVidEng->video1y_addr0 = localVidEng->video1y_addr0; 498 viaVidEng->video1_fifo = localVidEng->video1_fifo; 499 viaVidEng->video1y_addr3 = localVidEng->video1y_addr3; 500 viaVidEng->v1_source_w_h = localVidEng->v1_source_w_h; 501 viaVidEng->video1_CSC1 = localVidEng->video1_CSC1; 502 viaVidEng->video1_CSC2 = localVidEng->video1_CSC2; 503 504 /* Fix cursor garbage after suspend for VX855 and VX900 (#405) */ 505 /* 0x2E4 T Signature Data Result 1 */ 506 viaVidEng->video1u_addr1 = localVidEng->video1u_addr1; 507 /* 0x2E8 HI for Primary Display FIFO Control Signal */ 508 viaVidEng->video1u_addr2 = localVidEng->video1u_addr2; 509 /* 0x2EC HI for Primary Display FIFO Transparent color */ 510 viaVidEng->video1u_addr3 = localVidEng->video1u_addr3; 511 /* 0x2F0 HI for Primary Display Control Signal */ 512 viaVidEng->video1v_addr0 = localVidEng->video1v_addr0; 513 /* 0x2F4 HI for Primary Display Frame Buffer Starting Address */ 514 viaVidEng->video1v_addr1 = localVidEng->video1v_addr1; 515 /* 0x2F8 HI for Primary Display Horizontal and Vertical Start */ 516 viaVidEng->video1v_addr2 = localVidEng->video1v_addr2; 517 /* 0x2FC HI for Primary Display Center Offset */ 518 viaVidEng->video1v_addr3 = localVidEng->video1v_addr3; 519 } 520 viaVidEng->snd_color_key = localVidEng->snd_color_key; 521 viaVidEng->v3alpha_prefifo = localVidEng->v3alpha_prefifo; 522 viaVidEng->v3alpha_fifo = localVidEng->v3alpha_fifo; 523 viaVidEng->video3_CSC2 = localVidEng->video3_CSC2; 524 viaVidEng->video3_CSC2 = localVidEng->video3_CSC2; 525 viaVidEng->v3_source_width = localVidEng->v3_source_width; 526 viaVidEng->video3_ctl = localVidEng->video3_ctl; 527 viaVidEng->video3_addr0 = localVidEng->video3_addr0; 528 viaVidEng->video3_addr1 = localVidEng->video3_addr1; 529 viaVidEng->video3_stride = localVidEng->video3_stride; 530 viaVidEng->video3_hvstart = localVidEng->video3_hvstart; 531 viaVidEng->video3_size = localVidEng->video3_size; 532 viaVidEng->v3alpha_fetch = localVidEng->v3alpha_fetch; 533 viaVidEng->video3_zoom = localVidEng->video3_zoom; 534 viaVidEng->video3_mictl = localVidEng->video3_mictl; 535 viaVidEng->video3_CSC1 = localVidEng->video3_CSC1; 536 viaVidEng->video3_CSC2 = localVidEng->video3_CSC2; 537 viaVidEng->compose = localVidEng->compose; 538 viaVidEng->video3_ctl = pVia->dwV3; 539 540 if (pVia->ChipId != PCI_CHIP_VT3314) { 541 viaVidEng->video1_ctl = pVia->dwV1; 542 viaVidEng->compose = V1_COMMAND_FIRE; 543 } 544 viaVidEng->compose = V3_COMMAND_FIRE; 545} 546 547void 548viaExitVideo(ScrnInfoPtr pScrn) 549{ 550 VIAPtr pVia = VIAPTR(pScrn); 551 vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200); 552 XF86VideoAdaptorPtr curAdapt; 553 int i, j, numPorts; 554 555 DBG_DD(ErrorF(" via_xv.c : viaExitVideo : \n")); 556 557#ifdef HAVE_DRI 558 ViaCleanupXVMC(pScrn, viaAdaptPtr, XV_ADAPT_NUM); 559#endif 560 561 viaVidEng->video1_ctl = 0; 562 viaVidEng->video3_ctl = 0; 563 viaVidEng->compose = V1_COMMAND_FIRE; 564 viaVidEng->compose = V3_COMMAND_FIRE; 565 566 /* 567 * Free all adaptor info allocated in viaInitVideo. 568 */ 569 570 for (i = 0; i < XV_ADAPT_NUM; ++i) { 571 curAdapt = viaAdaptPtr[i]; 572 if (curAdapt) { 573 if (curAdapt->pPortPrivates) { 574 if (curAdapt->pPortPrivates->ptr) { 575 numPorts = numAdaptPort[i]; 576 for (j = 0; j < numPorts; ++j) { 577 viaStopVideo(pScrn, 578 (viaPortPrivPtr) curAdapt->pPortPrivates->ptr + j, 579 TRUE); 580 } 581 free(curAdapt->pPortPrivates->ptr); 582 } 583 free(curAdapt->pPortPrivates); 584 } 585 free(curAdapt); 586 } 587 } 588 if (allAdaptors) 589 free(allAdaptors); 590} 591 592void 593viaInitVideo(ScreenPtr pScreen) 594{ 595 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 596 XF86VideoAdaptorPtr *adaptors, *newAdaptors; 597 VIAPtr pVia = VIAPTR(pScrn); 598 int num_adaptors, num_new; 599 600 DBG_DD(ErrorF(" via_xv.c : viaInitVideo, Screen[%d]\n", pScrn->scrnIndex)); 601 602 allAdaptors = NULL; 603 newAdaptors = NULL; 604 num_new = 0; 605 606 pVia->useDmaBlit = FALSE; 607#ifdef HAVE_DRI 608 pVia->useDmaBlit = (pVia->directRenderingType == DRI_1) && 609 ((pVia->Chipset == VIA_CLE266) || 610 (pVia->Chipset == VIA_KM400) || 611 (pVia->Chipset == VIA_K8M800) || 612 (pVia->Chipset == VIA_PM800) || 613 (pVia->Chipset == VIA_VM800) || 614 (pVia->Chipset == VIA_K8M890) || 615 (pVia->Chipset == VIA_P4M900) || 616 (pVia->Chipset == VIA_CX700) || 617 (pVia->Chipset == VIA_VX800) || 618 (pVia->Chipset == VIA_VX855) || 619 (pVia->Chipset == VIA_VX900) || 620 (pVia->Chipset == VIA_P4M890)); 621 if ((pVia->drmVerMajor < 2) || 622 ((pVia->drmVerMajor == 2) && (pVia->drmVerMinor < 9))) 623 pVia->useDmaBlit = FALSE; 624#endif 625 pVia->useDmaBlit = pVia->useDmaBlit && pVia->dmaXV; 626 627 if (pVia->useDmaBlit) 628 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 629 "[Xv] Using PCI DMA for Xv image transfer.\n"); 630 631 if (!viaFastVidCpy) 632 viaFastVidCpy = viaVidCopyInit("video", pScreen); 633 634 if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400) || 635 (pVia->Chipset == VIA_K8M800) || (pVia->Chipset == VIA_PM800) || 636 (pVia->Chipset == VIA_VM800) || (pVia->Chipset == VIA_K8M890) || 637 (pVia->Chipset == VIA_P4M900) || (pVia->Chipset == VIA_CX700) || 638 (pVia->Chipset == VIA_P4M890) || (pVia->Chipset == VIA_VX800) || 639 (pVia->Chipset == VIA_VX855 || (pVia->Chipset == VIA_VX900))) { 640 num_new = viaSetupAdaptors(pScreen, &newAdaptors); 641 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); 642 } else { 643 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 644 "[Xv] Unsupported Chipset. X video functionality disabled.\n"); 645 num_adaptors = 0; 646 memset(viaAdaptPtr, 0, sizeof(viaAdaptPtr)); 647 } 648 649 DBG_DD(ErrorF(" via_xv.c : num_adaptors : %d\n", num_adaptors)); 650 if (newAdaptors) { 651 allAdaptors = malloc((num_adaptors + num_new) * 652 sizeof(XF86VideoAdaptorPtr *)); 653 if (allAdaptors) { 654 if (num_adaptors) 655 memcpy(allAdaptors, adaptors, 656 num_adaptors * sizeof(XF86VideoAdaptorPtr)); 657 memcpy(allAdaptors + num_adaptors, newAdaptors, 658 num_new * sizeof(XF86VideoAdaptorPtr)); 659 num_adaptors += num_new; 660 } 661 } 662 663 if (num_adaptors) { 664 xf86XVScreenInit(pScreen, allAdaptors, num_adaptors); 665#ifdef HAVE_DRI 666 ViaInitXVMC(pScreen); 667#endif 668 viaSetColorSpace(pVia, 0, 0, 0, 0, TRUE); 669 pVia->swov.panning_x = 0; 670 pVia->swov.panning_y = 0; 671 pVia->swov.oldPanningX = 0; 672 pVia->swov.oldPanningY = 0; 673 } 674} 675 676static unsigned 677viaSetupAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr ** adaptors) 678{ 679 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 680 int i, j, usedPorts, numPorts; 681 viaPortPrivRec *viaPortPriv; 682 DevUnion *pdevUnion; 683 684 DBG_DD(ErrorF(" via_xv.c : viaSetupAdaptors (viaSetupImageVideo): \n")); 685 686 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); 687 xvContrast = MAKE_ATOM("XV_CONTRAST"); 688 xvColorKey = MAKE_ATOM("XV_COLORKEY"); 689 xvHue = MAKE_ATOM("XV_HUE"); 690 xvSaturation = MAKE_ATOM("XV_SATURATION"); 691 xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); 692 693 *adaptors = NULL; 694 usedPorts = 0; 695 696 for (i = 0; i < XV_ADAPT_NUM; i++) { 697 if (!(viaAdaptPtr[i] = xf86XVAllocateVideoAdaptorRec(pScrn))) 698 return 0; 699 numPorts = numAdaptPort[i]; 700 701 viaPortPriv = 702 (viaPortPrivPtr) xnfcalloc(numPorts, sizeof(viaPortPrivRec)); 703 pdevUnion = (DevUnion *) xnfcalloc(numPorts, sizeof(DevUnion)); 704 705 if (i == XV_ADAPT_SWOV) { /* Overlay engine */ 706 viaAdaptPtr[i]->type = XvInputMask | XvWindowMask | XvImageMask | 707 XvVideoMask | XvStillMask; 708 viaAdaptPtr[i]->flags = 709 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 710 } else { 711 viaAdaptPtr[i]->type = XvInputMask | XvWindowMask | XvVideoMask; 712 viaAdaptPtr[i]->flags = 713 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; 714 } 715 viaAdaptPtr[i]->name = XvAdaptorName[i]; 716 viaAdaptPtr[i]->nEncodings = 1; 717 viaAdaptPtr[i]->pEncodings = DummyEncoding; 718 viaAdaptPtr[i]->nFormats = sizeof(FormatsG) / sizeof(FormatsG[0]); 719 viaAdaptPtr[i]->pFormats = FormatsG; 720 721 /* The adapter can handle 1 port simultaneously */ 722 viaAdaptPtr[i]->nPorts = numPorts; 723 viaAdaptPtr[i]->pPortPrivates = pdevUnion; 724 viaAdaptPtr[i]->pPortPrivates->ptr = (pointer) viaPortPriv; 725 viaAdaptPtr[i]->nAttributes = NUM_ATTRIBUTES_G; 726 viaAdaptPtr[i]->pAttributes = AttributesG; 727 728 viaAdaptPtr[i]->nImages = NUM_IMAGES_G; 729 viaAdaptPtr[i]->pImages = ImagesG; 730 viaAdaptPtr[i]->PutVideo = NULL; 731 viaAdaptPtr[i]->StopVideo = viaStopVideo; 732 viaAdaptPtr[i]->QueryBestSize = viaQueryBestSize; 733 viaAdaptPtr[i]->GetPortAttribute = viaGetPortAttribute; 734 viaAdaptPtr[i]->SetPortAttribute = viaSetPortAttribute; 735 viaAdaptPtr[i]->PutImage = viaPutImage; 736 viaAdaptPtr[i]->ReputImage = NULL; 737 viaAdaptPtr[i]->QueryImageAttributes = viaQueryImageAttributes; 738 for (j = 0; j < numPorts; ++j) { 739 viaPortPriv[j].dmaBounceBuffer = NULL; 740 viaPortPriv[j].dmaBounceStride = 0; 741 viaPortPriv[j].dmaBounceLines = 0; 742 viaPortPriv[j].colorKey = 0x0821; 743 viaPortPriv[j].autoPaint = TRUE; 744 viaPortPriv[j].brightness = 5000.; 745 viaPortPriv[j].saturation = 10000; 746 viaPortPriv[j].contrast = 10000; 747 viaPortPriv[j].hue = 0; 748 viaPortPriv[j].FourCC = 0; 749 viaPortPriv[j].xv_portnum = j + usedPorts; 750 viaPortPriv[j].xvErr = xve_none; 751 752#ifdef X_USE_REGION_NULL 753 REGION_NULL(pScreen, &viaPortPriv[j].clip); 754#else 755 REGION_INIT(pScreen, &viaPortPriv[j].clip, NullBox, 1); 756#endif 757 } 758 usedPorts += j; 759 760#ifdef HAVE_DRI 761 viaXvMCInitXv(pScrn, viaAdaptPtr[i]); 762#endif 763 764 } /* End of for */ 765 viaResetVideo(pScrn); 766 *adaptors = viaAdaptPtr; 767 return XV_ADAPT_NUM; 768} 769 770static void 771viaStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit) 772{ 773 VIAPtr pVia = VIAPTR(pScrn); 774 viaPortPrivPtr pPriv = (viaPortPrivPtr) data; 775 776 DBG_DD(ErrorF(" via_xv.c : viaStopVideo: exit=%d\n", exit)); 777 778 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 779 ViaOverlayHide(pScrn); 780 if (exit) { 781 ViaSwovSurfaceDestroy(pScrn, pPriv); 782 if (pPriv->dmaBounceBuffer) 783 free(pPriv->dmaBounceBuffer); 784 pPriv->dmaBounceBuffer = 0; 785 pPriv->dmaBounceStride = 0; 786 pPriv->dmaBounceLines = 0; 787 pVia->dwFrameNum = 0; 788 pPriv->old_drw_x = 0; 789 pPriv->old_drw_y = 0; 790 pPriv->old_drw_w = 0; 791 pPriv->old_drw_h = 0; 792 } 793} 794 795static int 796viaSetPortAttribute(ScrnInfoPtr pScrn, 797 Atom attribute, INT32 value, pointer data) 798{ 799 VIAPtr pVia = VIAPTR(pScrn); 800 vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200); 801 viaPortPrivPtr pPriv = (viaPortPrivPtr) data; 802 int attr, avalue; 803 804 DBG_DD(ErrorF(" via_xv.c : viaSetPortAttribute : \n")); 805 806 /* Color Key */ 807 if (attribute == xvColorKey) { 808 DBG_DD(ErrorF(" V4L Disable xvColorKey = %08lx\n", value)); 809 810 pPriv->colorKey = value; 811 /* All assume color depth is 16 */ 812 value &= 0x00FFFFFF; 813 viaVidEng->color_key = value; 814 viaVidEng->snd_color_key = value; 815 REGION_EMPTY(pScrn->pScreen, &pPriv->clip); 816 DBG_DD(ErrorF(" V4L Disable done xvColorKey = %08lx\n", value)); 817 818 } else if (attribute == xvAutoPaint) { 819 pPriv->autoPaint = value; 820 DBG_DD(ErrorF(" xvAutoPaint = %08lx\n", value)); 821 /* Color Control */ 822 } else if (attribute == xvBrightness || 823 attribute == xvContrast || 824 attribute == xvSaturation || attribute == xvHue) { 825 if (attribute == xvBrightness) { 826 DBG_DD(ErrorF(" xvBrightness = %08ld\n", value)); 827 pPriv->brightness = value; 828 } 829 if (attribute == xvContrast) { 830 DBG_DD(ErrorF(" xvContrast = %08ld\n", value)); 831 pPriv->contrast = value; 832 } 833 if (attribute == xvSaturation) { 834 DBG_DD(ErrorF(" xvSaturation = %08ld\n", value)); 835 pPriv->saturation = value; 836 } 837 if (attribute == xvHue) { 838 DBG_DD(ErrorF(" xvHue = %08ld\n", value)); 839 pPriv->hue = value; 840 } 841 viaSetColorSpace(pVia, pPriv->hue, pPriv->saturation, 842 pPriv->brightness, pPriv->contrast, FALSE); 843 } else { 844 DBG_DD(ErrorF 845 (" via_xv.c : viaSetPortAttribute : is not supported the attribute")); 846 return BadMatch; 847 } 848 849 /* attr,avalue hardware processing goes here */ 850 (void)attr; 851 (void)avalue; 852 853 return Success; 854} 855 856static int 857viaGetPortAttribute(ScrnInfoPtr pScrn, 858 Atom attribute, INT32 * value, pointer data) 859{ 860 viaPortPrivPtr pPriv = (viaPortPrivPtr) data; 861 862 DBG_DD(ErrorF(" via_xv.c : viaGetPortAttribute : port %d %ld\n", 863 pPriv->xv_portnum, attribute)); 864 865 *value = 0; 866 if (attribute == xvColorKey) { 867 *value = (INT32) pPriv->colorKey; 868 DBG_DD(ErrorF(" via_xv.c : ColorKey 0x%lx\n", pPriv->colorKey)); 869 } else if (attribute == xvAutoPaint) { 870 *value = (INT32) pPriv->autoPaint; 871 DBG_DD(ErrorF(" AutoPaint = %08ld\n", *value)); 872 /* Color Control */ 873 } else if (attribute == xvBrightness || 874 attribute == xvContrast || 875 attribute == xvSaturation || attribute == xvHue) { 876 if (attribute == xvBrightness) { 877 *value = pPriv->brightness; 878 DBG_DD(ErrorF(" xvBrightness = %08ld\n", *value)); 879 } 880 if (attribute == xvContrast) { 881 *value = pPriv->contrast; 882 DBG_DD(ErrorF(" xvContrast = %08ld\n", *value)); 883 } 884 if (attribute == xvSaturation) { 885 *value = pPriv->saturation; 886 DBG_DD(ErrorF(" xvSaturation = %08ld\n", *value)); 887 } 888 if (attribute == xvHue) { 889 *value = pPriv->hue; 890 DBG_DD(ErrorF(" xvHue = %08ld\n", *value)); 891 } 892 893 } else { 894 DBG_DD(ErrorF(" via_xv.c : viaGetPortAttribute : is not supported the attribute\n")); 895 /*return BadMatch */; 896 } 897 return Success; 898} 899 900static void 901viaQueryBestSize(ScrnInfoPtr pScrn, 902 Bool motion, 903 short vid_w, short vid_h, 904 short drw_w, short drw_h, 905 unsigned int *p_w, unsigned int *p_h, pointer data) 906{ 907 DBG_DD(ErrorF(" via_xv.c : viaQueryBestSize :\n")); 908 *p_w = drw_w; 909 *p_h = drw_h; 910 911 if (*p_w > 2048) 912 *p_w = 2048; 913} 914 915/* 916 * To do SW Flip 917 */ 918static void 919Flip(VIAPtr pVia, viaPortPrivPtr pPriv, int fourcc, 920 unsigned long DisplayBufferIndex) 921{ 922 unsigned long proReg = 0; 923 unsigned count = 50000; 924 925 if (pVia->ChipId == PCI_CHIP_VT3259 926 && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE)) 927 proReg = PRO_HQV1_OFFSET; 928 929 switch (fourcc) { 930 case FOURCC_UYVY: 931 case FOURCC_YUY2: 932 case FOURCC_RV15: 933 case FOURCC_RV16: 934 case FOURCC_RV32: 935 while ((VIAGETREG(HQV_CONTROL + proReg) & HQV_SW_FLIP) 936 && --count); 937 VIASETREG(HQV_SRC_STARTADDR_Y + proReg, 938 pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]); 939 VIASETREG(HQV_CONTROL + proReg, (VIAGETREG(HQV_CONTROL + proReg) & ~HQV_FLIP_ODD) | HQV_SW_FLIP | HQV_FLIP_STATUS); 940 break; 941 case FOURCC_YV12: 942 case FOURCC_I420: 943 default: 944 while ((VIAGETREG(HQV_CONTROL + proReg) & HQV_SW_FLIP) 945 && --count); 946 VIASETREG(HQV_SRC_STARTADDR_Y + proReg, 947 pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]); 948 if (pVia->VideoEngine == VIDEO_ENGINE_CME) { 949 VIASETREG(HQV_SRC_STARTADDR_U + proReg, 950 pVia->swov.SWDevice.dwSWCrPhysicalAddr[DisplayBufferIndex]); 951 } else { 952 VIASETREG(HQV_SRC_STARTADDR_U, 953 pVia->swov.SWDevice.dwSWCbPhysicalAddr[DisplayBufferIndex]); 954 VIASETREG(HQV_SRC_STARTADDR_V, 955 pVia->swov.SWDevice.dwSWCrPhysicalAddr[DisplayBufferIndex]); 956 } 957 VIASETREG(HQV_CONTROL + proReg, (VIAGETREG(HQV_CONTROL + proReg) & ~HQV_FLIP_ODD) | HQV_SW_FLIP | HQV_FLIP_STATUS); 958 break; 959 } 960} 961 962static void 963planar420cp(unsigned char *dst, const unsigned char *src, int dstPitch, 964 int w, int h, int i420) 965{ 966 unsigned long srcUOffset, srcVOffset; 967 968 /* 969 * Blit luma component as a fake YUY2 assembler blit. 970 */ 971 if (i420) { 972 srcVOffset = w * h + (w >> 1) * (h >> 1); 973 srcUOffset = w * h; 974 } else { 975 srcUOffset = w * h + (w >> 1) * (h >> 1); 976 srcVOffset = w * h; 977 } 978 979 (*viaFastVidCpy) (dst, src, dstPitch, w >> 1, h, 1); 980 UVBlit(dst + dstPitch * h, src + srcUOffset, 981 src + srcVOffset, w >> 1, w >> 1, dstPitch, h >> 1); 982} 983 984/* 985 * Slow and dirty. NV12 blit. 986 */ 987static void 988nv12cp(unsigned char *dst, const unsigned char *src, int dstPitch, 989 int w, int h, int i420) 990{ 991 unsigned long srcUOffset, srcVOffset; 992 993 /* 994 * Blit luma component as a fake YUY2 assembler blit. 995 */ 996 if (i420) { 997 srcVOffset = w * h + (w >> 1) * (h >> 1); 998 srcUOffset = w * h; 999 } else { 1000 srcUOffset = w * h + (w >> 1) * (h >> 1); 1001 srcVOffset = w * h; 1002 } 1003 1004 (*viaFastVidCpy) (dst, src, dstPitch, w >> 1, h, TRUE); 1005 nv12Blit(dst + dstPitch * h, src + srcUOffset, 1006 src + srcVOffset, w >> 1, w >>1, dstPitch, h >> 1); 1007} 1008 1009#ifdef HAVE_DRI 1010 1011static int 1012viaDmaBlitImage(VIAPtr pVia, 1013 viaPortPrivPtr pPort, 1014 unsigned char *src, 1015 CARD32 dst, unsigned width, unsigned height, unsigned lumaStride, int id) 1016{ 1017 Bool bounceBuffer; 1018 drm_via_dmablit_t blit; 1019 drm_via_blitsync_t *chromaSync = &blit.sync; 1020 drm_via_blitsync_t lumaSync; 1021 unsigned char *base; 1022 unsigned char *bounceBase; 1023 unsigned bounceStride; 1024 unsigned bounceLines; 1025 unsigned size; 1026 int err = 0; 1027 Bool nv12Conversion; 1028 1029 bounceBuffer = ((unsigned long)src & 15); 1030 nv12Conversion = (pVia->VideoEngine == VIDEO_ENGINE_CME && 1031 (id == FOURCC_YV12 || id == FOURCC_I420)); 1032 1033 switch (id) { 1034 case FOURCC_YUY2: 1035 case FOURCC_RV15: 1036 case FOURCC_RV16: 1037 bounceStride = ALIGN_TO(2 * width, 16); 1038 bounceLines = height; 1039 break; 1040 case FOURCC_RV32: 1041 bounceStride = ALIGN_TO(4 * width, 16); 1042 bounceLines = height; 1043 break; 1044 1045 case FOURCC_YV12: 1046 case FOURCC_I420: 1047 default: 1048 bounceStride = ALIGN_TO(width, 16); 1049 bounceLines = height; 1050 break; 1051 } 1052 1053 if (bounceBuffer || nv12Conversion) { 1054 if (!pPort->dmaBounceBuffer || 1055 pPort->dmaBounceStride != bounceStride || 1056 pPort->dmaBounceLines != bounceLines) { 1057 if (pPort->dmaBounceBuffer) { 1058 free(pPort->dmaBounceBuffer); 1059 pPort->dmaBounceBuffer = 0; 1060 } 1061 size = bounceStride * bounceLines + 16; 1062 if (id == FOURCC_YV12 || id == FOURCC_I420) 1063 size += ALIGN_TO(bounceStride >> 1, 16) * bounceLines; 1064 pPort->dmaBounceBuffer = (unsigned char *)malloc(size); 1065 pPort->dmaBounceLines = bounceLines; 1066 pPort->dmaBounceStride = bounceStride; 1067 } 1068 } 1069 1070 bounceBase = 1071 (unsigned char *)ALIGN_TO((unsigned long)(pPort->dmaBounceBuffer), 1072 16); 1073 base = (bounceBuffer) ? bounceBase : src; 1074 1075 if (bounceBuffer) { 1076 (*viaFastVidCpy) (base, src, bounceStride, bounceStride >> 1, height, 1077 1); 1078 } 1079 1080 blit.num_lines = height; 1081 blit.line_length = bounceStride; 1082 blit.fb_addr = dst; 1083 blit.fb_stride = lumaStride; 1084 blit.mem_addr = base; 1085 blit.mem_stride = bounceStride; 1086 blit.to_fb = 1; 1087#ifdef XV_DEBUG 1088 ErrorF 1089 ("Addr: 0x%lx, Offset 0x%lx\n Fb_stride: %u, Mem_stride: %u\n width: %u num_lines: %u\n", 1090 (unsigned long)blit.mem_addr, (unsigned long)blit.fb_addr, 1091 (unsigned)blit.fb_stride, (unsigned)blit.mem_stride, 1092 (unsigned)blit.line_length, (unsigned)blit.num_lines); 1093#endif 1094 while (-EAGAIN == (err = 1095 drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_DMA_BLIT, &blit, 1096 sizeof(blit)))) ; 1097 if (err < 0) 1098 return -1; 1099 1100 lumaSync = blit.sync; 1101 1102 if (id == FOURCC_YV12 || id == FOURCC_I420) { 1103 unsigned tmp = ALIGN_TO(width >> 1, 16); 1104 1105 if (nv12Conversion) { 1106 nv12Blit(bounceBase + bounceStride * height, 1107 src + bounceStride * height + tmp * (height >> 1), 1108 src + bounceStride * height, width >> 1, tmp, 1109 bounceStride, height >> 1); 1110 } else if (bounceBuffer) { 1111 (*viaFastVidCpy) (base + bounceStride * height, 1112 src + bounceStride * height, tmp, tmp >> 1, height, 1); 1113 } 1114 1115 if (nv12Conversion) { 1116 blit.num_lines = height >> 1; 1117 blit.line_length = bounceStride; 1118 blit.mem_addr = bounceBase + bounceStride * height; 1119 blit.fb_stride = lumaStride; 1120 blit.mem_stride = bounceStride; 1121 } else { 1122 blit.num_lines = height; 1123 blit.line_length = tmp; 1124 blit.mem_addr = base + bounceStride * height; 1125 blit.fb_stride = lumaStride >> 1; 1126 blit.mem_stride = tmp; 1127 } 1128 1129 blit.fb_addr = dst + lumaStride * height; 1130 blit.to_fb = 1; 1131 1132 while (-EAGAIN == (err = 1133 drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_DMA_BLIT, &blit, 1134 sizeof(blit)))); 1135 if (err < 0) 1136 return -1; 1137 } 1138 1139 while (-EAGAIN == (err = drmCommandWrite(pVia->drmmode.fd, DRM_VIA_BLIT_SYNC, 1140 chromaSync, sizeof(*chromaSync)))) ; 1141 if (err < 0) 1142 return -1; 1143 1144 return Success; 1145} 1146 1147#endif 1148 1149 1150/* 1151 * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h). 1152 * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h). 1153 * id is a fourcc code for the format of the video. 1154 * buf is the pointer to the source data in system memory. 1155 * width and height are the w/h of the source data. 1156 * If "sync" is TRUE, then we must be finished with *buf at the point of return 1157 * (which we always are). 1158 * clipBoxes is the clipping region in screen space. 1159 * data is a pointer to our port private. 1160 * pDraw is a Drawable, which might not be the screen in the case of 1161 * compositing. It's a new argument to the function in the 1.1 server. 1162 */ 1163 1164static int 1165viaPutImage(ScrnInfoPtr pScrn, 1166 short src_x, short src_y, 1167 short drw_x, short drw_y, 1168 short src_w, short src_h, 1169 short drw_w, short drw_h, 1170 int id, unsigned char *buf, 1171 short width, short height, Bool sync, RegionPtr clipBoxes, 1172 pointer data, DrawablePtr pDraw) 1173{ 1174 VIAPtr pVia = VIAPTR(pScrn); 1175 viaPortPrivPtr pPriv = (viaPortPrivPtr) data; 1176 xf86CrtcPtr crtc = NULL; 1177 unsigned long retCode; 1178 1179# ifdef XV_DEBUG 1180 ErrorF(" via_xv.c : viaPutImage : called, Screen[%d]\n", pScrn->scrnIndex); 1181 ErrorF(" via_xv.c : FourCC=0x%x width=%d height=%d sync=%d\n", id, 1182 width, height, sync); 1183 ErrorF 1184 (" via_xv.c : src_x=%d src_y=%d src_w=%d src_h=%d colorkey=0x%lx\n", 1185 src_x, src_y, src_w, src_h, pPriv->colorKey); 1186 ErrorF(" via_xv.c : drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n", drw_x, 1187 drw_y, drw_w, drw_h); 1188# endif 1189 1190 /* Find out which CRTC the surface will belong to */ 1191 crtc = window_belongs_to_crtc(pScrn, drw_x, drw_y, drw_w, drw_h); 1192 if (!crtc) { 1193 DBG_DD(ErrorF(" via_xv.c : No usable CRTC\n")); 1194 viaXvError(pScrn, pPriv, xve_adaptor); 1195 return BadAlloc; 1196 } 1197 1198 switch (pPriv->xv_adaptor) { 1199 case XV_ADAPT_SWOV: 1200 { 1201 DDUPDATEOVERLAY UpdateOverlay_Video; 1202 LPDDUPDATEOVERLAY lpUpdateOverlay = &UpdateOverlay_Video; 1203 1204 int dstPitch; 1205 unsigned long dwUseExtendedFIFO = 0; 1206 1207 DBG_DD(ErrorF(" via_xv.c : : S/W Overlay! \n")); 1208 /* Allocate video memory(CreateSurface), 1209 * add codes to judge if need to re-create surface 1210 */ 1211 if ((pPriv->old_src_w != src_w) || (pPriv->old_src_h != src_h)) { 1212 ViaSwovSurfaceDestroy(pScrn, pPriv); 1213 } 1214 1215 if (Success != (retCode = 1216 ViaSwovSurfaceCreate(pScrn, pPriv, id, width, height))) { 1217 DBG_DD(ErrorF 1218 (" : Fail to Create SW Video Surface\n")); 1219 viaXvError(pScrn, pPriv, xve_mem); 1220 return retCode; 1221 } 1222 1223 /* Copy image data from system memory to video memory 1224 * TODO: use DRM's DMA feature to accelerate data copy 1225 */ 1226 if (id != FOURCC_XVMC) { 1227 dstPitch = pVia->swov.SWDevice.dwPitch; 1228 1229 if (pVia->useDmaBlit) { 1230#ifdef HAVE_DRI 1231 if (viaDmaBlitImage(pVia, pPriv, buf, 1232 (CARD32) pVia->swov.SWDevice.dwSWPhysicalAddr[pVia->dwFrameNum & 1], 1233 width, height, dstPitch, id)) { 1234 viaXvError(pScrn, pPriv, xve_dmablit); 1235 return BadAccess; 1236 } 1237#endif 1238 } else { 1239 switch (id) { 1240 case FOURCC_I420: 1241 if (pVia->VideoEngine == VIDEO_ENGINE_CME) { 1242 nv12cp(pVia->swov.SWDevice. 1243 lpSWOverlaySurface[pVia->dwFrameNum & 1], 1244 buf, dstPitch, width, height, 1); 1245 } else { 1246 (*viaFastVidCpy)(pVia->swov.SWDevice. 1247 lpSWOverlaySurface[pVia->dwFrameNum & 1], 1248 buf, dstPitch, width, height, 0); 1249 } 1250 break; 1251 case FOURCC_YV12: 1252 if (pVia->VideoEngine == VIDEO_ENGINE_CME) { 1253 nv12cp(pVia->swov.SWDevice. 1254 lpSWOverlaySurface[pVia->dwFrameNum & 1], 1255 buf, dstPitch, width, height, 0); 1256 } else { 1257 (*viaFastVidCpy)(pVia->swov.SWDevice. 1258 lpSWOverlaySurface[pVia->dwFrameNum & 1], 1259 buf, dstPitch, width, height, 0); 1260 } 1261 break; 1262 case FOURCC_RV32: 1263 (*viaFastVidCpy) (pVia->swov.SWDevice. 1264 lpSWOverlaySurface[pVia->dwFrameNum & 1], 1265 buf, dstPitch, width << 1, height, 1); 1266 break; 1267 case FOURCC_UYVY: 1268 case FOURCC_YUY2: 1269 case FOURCC_RV15: 1270 case FOURCC_RV16: 1271 default: 1272 (*viaFastVidCpy) (pVia->swov.SWDevice. 1273 lpSWOverlaySurface[pVia->dwFrameNum & 1], 1274 buf, dstPitch, width, height, 1); 1275 break; 1276 } 1277 } 1278 } 1279 1280 /* If there is bandwidth issue, block the H/W overlay */ 1281 if (!(DecideOverlaySupport(crtc))) { 1282 DBG_DD(ErrorF 1283 (" via_xv.c : Xv Overlay rejected due to insufficient " 1284 "memory bandwidth.\n")); 1285 viaXvError(pScrn, pPriv, xve_bandwidth); 1286 return BadAlloc; 1287 } 1288 1289 /* 1290 * fill video overlay parameter 1291 */ 1292 lpUpdateOverlay->SrcLeft = src_x; 1293 lpUpdateOverlay->SrcTop = src_y; 1294 lpUpdateOverlay->SrcRight = src_x + src_w; 1295 lpUpdateOverlay->SrcBottom = src_y + src_h; 1296 1297 lpUpdateOverlay->DstLeft = drw_x; 1298 lpUpdateOverlay->DstTop = drw_y; 1299 lpUpdateOverlay->DstRight = drw_x + drw_w; 1300 lpUpdateOverlay->DstBottom = drw_y + drw_h; 1301 1302 lpUpdateOverlay->dwFlags = DDOVER_KEYDEST; 1303 1304 if (pScrn->bitsPerPixel == 8) { 1305 lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey & 0xff; 1306 } else { 1307 lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey; 1308 } 1309 /* If use extend FIFO mode */ 1310 if (pScrn->currentMode->HDisplay > 1024) { 1311 dwUseExtendedFIFO = 1; 1312 } 1313 1314 if (FOURCC_XVMC != id) { 1315 1316 /* 1317 * XvMC flipping is done in the client lib. 1318 */ 1319 1320 DBG_DD(ErrorF(" : Flip\n")); 1321 Flip(pVia, pPriv, id, pVia->dwFrameNum & 1); 1322 } 1323 1324 pVia->dwFrameNum++; 1325 1326 /* If the dest rec. & extendFIFO doesn't change, don't do UpdateOverlay 1327 * unless the surface clipping has changed */ 1328 if ((pPriv->old_drw_x == drw_x) && (pPriv->old_drw_y == drw_y) 1329 && (pPriv->old_drw_w == drw_w) && (pPriv->old_drw_h == drw_h) 1330 && (pPriv->old_src_x == src_x) && (pPriv->old_src_y == src_y) 1331 && (pPriv->old_src_w == src_w) && (pPriv->old_src_h == src_h) 1332 && (pVia->old_dwUseExtendedFIFO == dwUseExtendedFIFO) 1333 && (pVia->VideoStatus & VIDEO_SWOV_ON) && 1334 REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 1335 DBG_DD(ErrorF(" via_xv.c : don't do UpdateOverlay! \n")); 1336 viaXvError(pScrn, pPriv, xve_none); 1337 return Success; 1338 } 1339 1340 pPriv->old_src_x = src_x; 1341 pPriv->old_src_y = src_y; 1342 pPriv->old_src_w = src_w; 1343 pPriv->old_src_h = src_h; 1344 1345 pPriv->old_drw_x = drw_x; 1346 pPriv->old_drw_y = drw_y; 1347 pPriv->old_drw_w = drw_w; 1348 pPriv->old_drw_h = drw_h; 1349 pVia->old_dwUseExtendedFIFO = dwUseExtendedFIFO; 1350 pVia->VideoStatus |= VIDEO_SWOV_ON; 1351 1352 /* BitBlt: Draw the colorkey rectangle */ 1353 if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { 1354 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); 1355 if (pPriv->autoPaint) { 1356 if (pDraw->type == DRAWABLE_WINDOW) { 1357 xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes); 1358 DamageDamageRegion(pDraw, clipBoxes); 1359 } else { 1360 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); 1361 } 1362 } 1363 } else { 1364 DBG_DD(ErrorF(" via_xv.c : // No need to draw Colorkey!! \n")); 1365 } 1366 /* 1367 * Update video overlay 1368 */ 1369 if (!VIAVidUpdateOverlay(crtc, lpUpdateOverlay)) { 1370 DBG_DD(ErrorF 1371 (" via_xv.c : call v4l updateoverlay fail. \n")); 1372 } else { 1373 DBG_DD(ErrorF(" via_xv.c : PutImage done OK\n")); 1374 viaXvError(pScrn, pPriv, xve_none); 1375 return Success; 1376 } 1377 break; 1378 } 1379 default: 1380 DBG_DD(ErrorF(" via_xv.c : XVPort not supported\n")); 1381 viaXvError(pScrn, pPriv, xve_adaptor); 1382 break; 1383 } 1384 DBG_DD(ErrorF(" via_xv.c : PutImage done OK\n")); 1385 viaXvError(pScrn, pPriv, xve_none); 1386 return Success; 1387} 1388 1389static int 1390viaQueryImageAttributes(ScrnInfoPtr pScrn, 1391 int id, unsigned short *w, unsigned short *h, int *pitches, 1392 int *offsets) 1393{ 1394 int size, tmp; 1395 VIAPtr pVia = VIAPTR(pScrn); 1396 1397 DBG_DD(ErrorF(" via_xv.c : viaQueryImageAttributes : FourCC=0x%x, ", 1398 id)); 1399 DBG_DD(ErrorF(" via_xv.c : Screen[%d], w=%d, h=%d\n", pScrn->scrnIndex, *w, *h)); 1400 1401 if ((!w) || (!h)) 1402 return 0; 1403 1404 if (*w > VIA_MAX_XVIMAGE_X) 1405 *w = VIA_MAX_XVIMAGE_X; 1406 if (*h > VIA_MAX_XVIMAGE_Y) 1407 *h = VIA_MAX_XVIMAGE_Y; 1408 1409 *w = (*w + 1) & ~1; 1410 if (offsets) 1411 offsets[0] = 0; 1412 1413 switch (id) { 1414 case FOURCC_I420: 1415 case FOURCC_YV12: /*Planar format : YV12 -4:2:0 */ 1416 *h = (*h + 1) & ~1; 1417 size = *w; 1418 if (pVia->useDmaBlit) 1419 size = (size + 15) & ~15; 1420 if (pitches) 1421 pitches[0] = size; 1422 size *= *h; 1423 if (offsets) 1424 offsets[1] = size; 1425 tmp = (*w >> 1); 1426 if (pVia->useDmaBlit) 1427 tmp = (tmp + 15) & ~15; 1428 if (pitches) 1429 pitches[1] = pitches[2] = tmp; 1430 tmp *= (*h >> 1); 1431 size += tmp; 1432 if (offsets) 1433 offsets[2] = size; 1434 size += tmp; 1435 break; 1436 case FOURCC_XVMC: 1437 *h = (*h + 1) & ~1; 1438#ifdef HAVE_DRI 1439 size = viaXvMCPutImageSize(pScrn); 1440#else 1441 size = 0; 1442#endif 1443 if (pitches) 1444 pitches[0] = size; 1445 break; 1446 case FOURCC_AI44: 1447 case FOURCC_IA44: 1448 size = *w * *h; 1449 if (pitches) 1450 pitches[0] = *w; 1451 if (offsets) 1452 offsets[0] = 0; 1453 break; 1454 case FOURCC_RV32: 1455 size = *w << 2; 1456 if (pVia->useDmaBlit) 1457 size = (size + 15) & ~15; 1458 if (pitches) 1459 pitches[0] = size; 1460 size *= *h; 1461 break; 1462 case FOURCC_UYVY: /*Packed format : UYVY -4:2:2 */ 1463 case FOURCC_YUY2: /*Packed format : YUY2 -4:2:2 */ 1464 case FOURCC_RV15: 1465 case FOURCC_RV16: 1466 default: 1467 size = *w << 1; 1468 if (pVia->useDmaBlit) 1469 size = (size + 15) & ~15; 1470 if (pitches) 1471 pitches[0] = size; 1472 size *= *h; 1473 break; 1474 } 1475 1476 if (pitches) 1477 DBG_DD(ErrorF(" pitches[0]=%d, pitches[1]=%d, pitches[2]=%d, ", 1478 pitches[0], pitches[1], pitches[2])); 1479 if (offsets) 1480 DBG_DD(ErrorF(" offsets[0]=%d, offsets[1]=%d, offsets[2]=%d, ", 1481 offsets[0], offsets[1], offsets[2])); 1482 1483 DBG_DD(ErrorF(" width=%d, height=%d \n", *w, *h)); 1484 return size; 1485} 1486 1487/* 1488 * 1489 */ 1490void 1491VIAVidAdjustFrame(ScrnInfoPtr pScrn, int x, int y) 1492{ 1493 VIAPtr pVia = VIAPTR(pScrn); 1494 1495 pVia->swov.panning_x = x; 1496 pVia->swov.panning_y = y; 1497} 1498 1499/* 1500 * Blit the U and V Fields. Used to Flip the U V for I420. 1501 */ 1502 1503static void 1504UVBlit(unsigned char *dst, 1505 const unsigned char *uBuffer, 1506 const unsigned char *vBuffer, 1507 unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines) 1508{ 1509 int i, j; 1510 1511 dstPitch >>= 1; 1512 1513 for(j = 0; j < lines; j++) 1514 { 1515 for(i = 0; i < width; i++) 1516 { 1517 dst[i] = (uBuffer[i] << 8) | (vBuffer[i] << 16); 1518 } 1519 1520 dst += dstPitch; 1521 uBuffer += srcPitch; 1522 vBuffer += srcPitch; 1523 } 1524 1525} 1526 1527 1528/* 1529 * Blit the chroma field from one buffer to another while at the same time converting from 1530 * YV12 to NV12. 1531 */ 1532 1533static void 1534nv12Blit(unsigned char *nv12Chroma, 1535 const unsigned char *uBuffer, 1536 const unsigned char *vBuffer, 1537 unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines) 1538{ 1539 int x; 1540 int dstAdd; 1541 int srcAdd; 1542 1543 dstAdd = dstPitch - (width << 1); 1544 srcAdd = srcPitch - width; 1545 1546 while (lines--) { 1547 x = width; 1548 while (x > 3) { 1549 register CARD32 1550 dst32, 1551 src32 = *((CARD32 *) vBuffer), 1552 src32_2 = *((CARD32 *) uBuffer); 1553 dst32 = 1554 (src32_2 & 0xff) | ((src32 & 0xff) << 8) | 1555 ((src32_2 & 0x0000ff00) << 8) | ((src32 & 0x0000ff00) << 16); 1556 *((CARD32 *) nv12Chroma) = dst32; 1557 nv12Chroma += 4; 1558 dst32 = 1559 ((src32_2 & 0x00ff0000) >> 16) | ((src32 & 0x00ff0000) >> 8) | 1560 ((src32_2 & 0xff000000) >> 8) | (src32 & 0xff000000); 1561 *((CARD32 *) nv12Chroma) = dst32; 1562 nv12Chroma += 4; 1563 x -= 4; 1564 vBuffer += 4; 1565 uBuffer += 4; 1566 } 1567 while (x--) { 1568 *nv12Chroma++ = *uBuffer++; 1569 *nv12Chroma++ = *vBuffer++; 1570 } 1571 nv12Chroma += dstAdd; 1572 vBuffer += srcAdd; 1573 uBuffer += srcAdd; 1574 } 1575} 1576 1577#endif /* !XvExtension */ 1578