1/* 2 * Permedia 2 Xv Driver 3 * 4 * Copyright (C) 1998-2000 Michael H. Schimek <m.schimek@netway.at> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions 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 NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include "xf86.h" 29#include "xf86_OSproc.h" 30#include "xf86Pci.h" 31#include "xf86fbman.h" 32#include "xf86i2c.h" 33#include "xf86xv.h" 34#include <X11/extensions/Xv.h> 35 36#include "glint_regs.h" 37#include "glint.h" 38#include <sys/types.h> 39#include <sys/stat.h> 40#include <fcntl.h> 41#include <sys/ioctl.h> 42#include <unistd.h> 43 44#undef MIN 45#undef ABS 46#undef CLAMP 47#undef ENTRIES 48 49#define MIN(a, b) (((a) < (b)) ? (a) : (b)) 50#define ABS(n) (((n) < 0) ? -(n) : (n)) 51#define CLAMP(v, min, max) (((v) < (min)) ? (min) : MIN(v, max)) 52#define ENTRIES(array) (sizeof(array) / sizeof((array)[0])) 53 54#define ADAPTORS 3 55#define PORTS 6 56 57#define PCI_SUBSYSTEM_ID_WINNER_2000_P2C 0x0a311048 58#define PCI_SUBSYSTEM_ID_GLORIA_SYNERGY_P2C 0x0a321048 59#define PCI_SUBSYSTEM_ID_GLORIA_SYNERGY_P2A 0x0a351048 60#define PCI_SUBSYSTEM_ID_WINNER_2000_P2A 0x0a441048 61 62/* 63 * Proprietary kernel backbone interface 64 */ 65 66#define XVIPC_MAGIC 0x6A5D70E6 67#define XVIPC_VERSION 1 68#define VIDIOC_PM2_XVIPC 0x00007F7F 69 70typedef enum { 71 OP_ATTR = 0, 72 OP_RESET = 8, /* unused */ 73 OP_START, 74 OP_STOP, 75 OP_PLUG, 76 OP_VIDEOSTD, 77 OP_WINDOW, /* unused */ 78 OP_CONNECT, 79 OP_EVENT, 80 OP_ALLOC, 81 OP_FREE, 82 OP_UPDATE, 83 OP_NOP, /* ignored */ 84 OP_ENTER, 85 OP_LEAVE, 86 OP_DISCONNECT 87} xvipc_op; 88 89typedef struct _pm2_xvipc { 90 int magic; 91 void *pm2p, *pAPriv; 92 int port, op, time, block; 93 int a, b, c, d, e, f; 94} pm2_xvipc; 95 96static pm2_xvipc xvipc; 97static int xvipc_fd = -1; 98 99 100#define MAX_BUFFERS 2 101 102typedef struct { 103 CARD32 xy, wh; /* 16.0 16.0 */ 104 INT32 s, t; /* 12.20 fp */ 105 short y1, y2; 106} CookieRec, *CookiePtr; 107 108typedef struct _PortPrivRec { 109 struct _AdaptorPrivRec * pAdaptor; 110 I2CDevRec I2CDev; 111 112 INT32 Attribute[8]; /* Brig, Con, Sat, Hue, Int, Filt, BkgCol, Alpha */ 113 114 int BuffersRequested; 115 int BuffersAllocated; 116 FBAreaPtr pFBArea[MAX_BUFFERS]; 117 CARD32 BufferBase[MAX_BUFFERS]; /* FB byte offset */ 118 CARD32 BufferStride; /* bytes */ 119 CARD32 BufferPProd; /* PProd(BufferStride in buffer pixels) */ 120 121 INT32 vx, vy, vw, vh; /* 12.10 fp */ 122 int dx, dy, dw, dh; 123 int fw, fh; 124 125 CookiePtr pCookies; 126 int nCookies; 127 INT32 dS, dT; /* 12.20 fp */ 128 129 int Id, Bpp; /* Scaler */ 130 131 int Plug; 132 int BkgCol; /* RGB 5:6:5; 5:6:5 */ 133 Bool StreamOn; /* buffer <-> hardware */ 134 int VideoOn; /* buffer <-> screen */ 135 int VideoStdReq; 136 137 int StopDelay; 138 139 int FramesPerSec, FrameAcc; 140 141} PortPrivRec, *PortPrivPtr; 142 143enum { VIDEO_OFF, VIDEO_ONE_SHOT, VIDEO_ON }; 144 145typedef struct _LFBAreaRec { 146 struct _LFBAreaRec * Next; 147 int Linear; 148 FBAreaPtr pFBArea; 149} LFBAreaRec, *LFBAreaPtr; 150 151typedef struct _AdaptorPrivRec { 152 struct _AdaptorPrivRec * Next; 153 ScrnInfoPtr pScrn; 154 155 void * pm2p; 156 LFBAreaPtr LFBList; 157 158 CARD32 dFifoControl; 159 CARD32 dDitherMode; 160 CARD32 dAlphaBlendMode; 161 CARD32 dTextureDataFormat; 162 163 OsTimerPtr Timer; 164 int TimerUsers; 165 int Delay, Instant; 166 167 int FramesPerSec; 168 int FrameLines; 169 int IntLine; /* Frame, not field */ 170 int LinePer; /* nsec */ 171 172 Bool VideoIO; 173 int VideoStd; 174 175 PortPrivRec Port[PORTS]; 176 177} AdaptorPrivRec, *AdaptorPrivPtr; 178 179static AdaptorPrivPtr AdaptorPrivList = NULL; 180 181#define FreeCookies(pPPriv) \ 182do { \ 183 free((pPPriv)->pCookies); \ 184 (pPPriv)->pCookies = NULL; \ 185} while (0) 186 187#define PORTNUM(p) ((int)((p) - &pAPriv->Port[0])) 188#define BPPSHIFT(g) (2 - (g)->BppShift) /* Bytes per pixel = 1 << BPPSHIFT(pGlint) */ 189 190#define DEBUG(x) 191 192static const Bool ColorBars = FALSE; 193 194 195/* 196 * XF86Config VideoAdaptor options 197 */ 198 199typedef enum { 200 OPTION_DEVICE, 201 OPTION_IN_FPS, 202 OPTION_IN_BUFFERS, 203 OPTION_IN_ENCODING, 204 OPTION_OUT_FPS, 205 OPTION_OUT_BUFFERS, 206 OPTION_OUT_ENCODING, 207} OptToken; 208 209static const OptionInfoRec pm2Options[] = { 210 { OPTION_DEVICE, "Device", OPTV_STRING, {0}, FALSE }, 211 { OPTION_IN_BUFFERS, "InputBuffers", OPTV_INTEGER, {0}, FALSE }, 212 { OPTION_IN_FPS, "InputFramesPerSec", OPTV_INTEGER, {0}, FALSE }, 213 { OPTION_IN_ENCODING, "InputEncoding", OPTV_STRING, {0}, FALSE }, 214 { OPTION_OUT_BUFFERS, "OutputBuffers", OPTV_INTEGER, {0}, FALSE }, 215 { OPTION_OUT_FPS, "OutputFramesPerSec", OPTV_INTEGER, {0}, FALSE }, 216 { OPTION_OUT_ENCODING, "OutputEncoding", OPTV_STRING, {0}, FALSE }, 217 { -1, NULL, OPTV_NONE, {0}, FALSE } 218}; 219 220 221/* 222 * Attributes 223 */ 224 225#define XV_ENCODING "XV_ENCODING" 226#define XV_BRIGHTNESS "XV_BRIGHTNESS" 227#define XV_CONTRAST "XV_CONTRAST" 228#define XV_SATURATION "XV_SATURATION" 229#define XV_HUE "XV_HUE" 230 231/* Proprietary */ 232 233#define XV_INTERLACE "XV_INTERLACE" /* Interlaced (bool) */ 234#define XV_FILTER "XV_FILTER" /* Bilinear filter (bool) */ 235#define XV_BKGCOLOR "XV_BKGCOLOR" /* Output background (0x00RRGGBB) */ 236#define XV_ALPHA "XV_ALPHA" /* Scaler alpha channel (bool) */ 237 238#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) 239 240static Atom xvEncoding, xvBrightness, xvContrast, xvSaturation, xvHue; 241static Atom xvInterlace, xvFilter, xvBkgColor, xvAlpha; 242 243/* Input */ 244 245static XF86VideoEncodingRec 246InputVideoEncodings[] = 247{ 248 { 0, "pal-composite", 704, 576, { 1, 50 }}, 249 { 1, "pal-composite_adaptor", 704, 576, { 1, 50 }}, 250 { 2, "pal-svideo", 704, 576, { 1, 50 }}, 251 { 3, "ntsc-composite", 704, 480, { 1001, 60000 }}, 252 { 4, "ntsc-composite_adaptor", 704, 480, { 1001, 60000 }}, 253 { 5, "ntsc-svideo", 704, 480, { 1001, 60000 }}, 254 { 6, "secam-composite", 704, 576, { 1, 50 }}, 255 { 7, "secam-composite_adaptor", 704, 576, { 1, 50 }}, 256 { 8, "secam-svideo", 704, 576, { 1, 50 }}, 257}; 258 259static XF86AttributeRec 260InputVideoAttributes[] = 261{ 262 { XvSettable | XvGettable, -1000, +1000, XV_BRIGHTNESS }, 263 { XvSettable | XvGettable, -3000, +1000, XV_CONTRAST }, 264 { XvSettable | XvGettable, -3000, +1000, XV_SATURATION }, 265 { XvSettable | XvGettable, -1000, +1000, XV_HUE }, 266 { XvSettable | XvGettable, 0, 2, XV_INTERLACE }, 267 { XvSettable | XvGettable, 0, 1, XV_FILTER }, 268}; 269 270static XF86VideoFormatRec 271InputVideoFormats[] = 272{ 273 { 8, TrueColor }, /* Dithered */ 274 { 15, TrueColor }, 275 { 16, TrueColor }, 276 { 24, TrueColor }, 277}; 278 279/* Output */ 280 281static XF86VideoEncodingRec 282OutputVideoEncodings[] = 283{ 284 { 0, "pal-composite_adaptor", 704, 576, { 1, 50 }}, 285 { 1, "pal-svideo", 704, 576, { 1, 50 }}, 286 { 2, "ntsc-composite_adaptor", 704, 480, { 1001, 60000 }}, 287 { 3, "ntsc-svideo", 704, 480, { 1001, 60000 }}, 288}; 289 290static XF86AttributeRec 291OutputVideoAttributes[] = 292{ 293 { XvSettable | XvGettable, 0, 2, XV_INTERLACE }, 294 { XvSettable | XvGettable, 0, 1, XV_FILTER }, 295 { XvSettable | XvGettable, 0x000000, 0xFFFFFF, XV_BKGCOLOR }, 296}; 297 298static XF86VideoFormatRec 299OutputVideoFormats[] = 300{ 301 { 8, TrueColor }, 302 { 8, PseudoColor }, /* Using .. */ 303 { 8, StaticColor }, 304 { 8, GrayScale }, 305 { 8, StaticGray }, /* .. TexelLUT */ 306 { 15, TrueColor }, 307 { 16, TrueColor }, 308 { 24, TrueColor }, 309}; 310 311/* Scaler */ 312 313static XF86VideoEncodingRec 314ScalerEncodings[] = 315{ 316 { 0, "XV_IMAGE", 2047, 2047, { 1, 1 }}, 317}; 318 319static XF86AttributeRec 320ScalerAttributes[] = 321{ 322 { XvSettable | XvGettable, 0, 1, XV_FILTER }, 323 { XvSettable | XvGettable, 0, 1, XV_ALPHA }, 324}; 325 326#define ScalerVideoFormats InputVideoFormats 327 328/* 329 * FOURCC from http://www.webartz.com/fourcc 330 * Generic GUID for legacy FOURCC XXXXXXXX-0000-0010-8000-00AA00389B71 331 */ 332#define LE4CC(a,b,c,d) (((CARD32)(a)&0xFF)|(((CARD32)(b)&0xFF)<<8)|(((CARD32)(c)&0xFF)<<16)|(((CARD32)(d)&0xFF)<<24)) 333#define GUID4CC(a,b,c,d) { a,b,c,d,0,0,0,0x10,0x80,0,0,0xAA,0,0x38,0x9B,0x71 } 334 335#define NoOrder LSBFirst 336 337static XF86ImageRec 338ScalerImages[] = 339{ 340 /* Planar YVU 4:2:0 (emulated) */ 341 { LE4CC('Y','V','1','2'), XvYUV, NoOrder, GUID4CC('Y','V','1','2'), 342 12, XvPlanar, 3, 0, 0, 0, 0, 343 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU", XvTopToBottom }, 344 345 /* Packed YUYV 4:2:2 */ 346 { LE4CC('Y','U','Y','2'), XvYUV, NoOrder, GUID4CC('Y','U','Y','2'), 347 16, XvPacked, 1, 0, 0, 0, 0, 348 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUYV", XvTopToBottom }, 349 350 /* Packed UYVY 4:2:2 */ 351 { LE4CC('U','Y','V','Y'), XvYUV, NoOrder, GUID4CC('U','Y','V','Y'), 352 16, XvPacked, 1, 0, 0, 0, 0, 353 8, 8, 8, 1, 2, 2, 1, 1, 1, "UYVY", XvTopToBottom }, 354 355 /* Packed YUVA 4:4:4 */ 356 { LE4CC('Y','U','V','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 }, 357 32, XvPacked, 1, 0, 0, 0, 0, 358 8, 8, 8, 1, 1, 1, 1, 1, 1, "YUVA", XvTopToBottom }, 359 360 /* Packed VUYA 4:4:4 */ 361 { LE4CC('V','U','Y','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 }, 362 32, XvPacked, 1, 0, 0, 0, 0, 363 8, 8, 8, 1, 1, 1, 1, 1, 1, "VUYA", XvTopToBottom }, 364 365 /* RGBA 8:8:8:8 */ 366 { 0x41, XvRGB, LSBFirst, { 0 }, 367 32, XvPacked, 1, 24, 0x0000FF, 0x00FF00, 0xFF0000, 368 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGBA", XvTopToBottom }, 369 370 /* RGB 5:6:5 */ 371 { 0x42, XvRGB, LSBFirst, { 0 }, 372 16, XvPacked, 1, 16, 0x001F, 0x07E0, 0xF800, 373 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGB", XvTopToBottom }, 374 375 /* RGBA 5:5:5:1 */ 376 { 0x43, XvRGB, LSBFirst, { 0 }, 377 16, XvPacked, 1, 15, 0x001F, 0x03E0, 0x7C00, 378 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGBA", XvTopToBottom }, 379 380 /* RGBA 4:4:4:4 */ 381 { 0x44, XvRGB, LSBFirst, { 0 }, 382 16, XvPacked, 1, 12, 0x000F, 0x00F0, 0x0F00, 383 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGBA", XvTopToBottom }, 384 385 /* RGBA 2:3:2:1 */ 386 { 0x45, XvRGB, NoOrder, { 0 }, 387 8, XvPacked, 1, 7, 0x03, 0x1C, 0x60, 388 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGBA", XvTopToBottom }, 389 390 /* RGB 3:3:2 */ 391 { 0x46, XvRGB, NoOrder, { 0 }, 392 8, XvPacked, 1, 8, 0x07, 0x38, 0xC0, 393 0, 0, 0, 0, 0, 0, 0, 0, 0, "RGB", XvTopToBottom }, 394 395 /* BGRA 8:8:8:8 */ 396 { 0x47, XvRGB, LSBFirst, { 0 }, 397 32, XvPacked, 1, 24, 0xFF0000, 0x00FF00, 0x0000FF, 398 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGRA", XvTopToBottom }, 399 400 /* BGR 5:6:5 */ 401 { 0x48, XvRGB, LSBFirst, { 0 }, 402 16, XvPacked, 1, 16, 0xF800, 0x07E0, 0x001F, 403 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGR", XvTopToBottom }, 404 405 /* BGRA 5:5:5:1 */ 406 { 0x49, XvRGB, LSBFirst, { 0 }, 407 16, XvPacked, 1, 15, 0x7C00, 0x03E0, 0x001F, 408 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGRA", XvTopToBottom }, 409 410 /* BGRA 4:4:4:4 */ 411 { 0x4A, XvRGB, LSBFirst, { 0 }, 412 16, XvPacked, 1, 12, 0x0F00, 0x00F0, 0x000F, 413 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGRA", XvTopToBottom }, 414 415 /* BGRA 2:3:2:1 */ 416 { 0x4B, XvRGB, NoOrder, { 0 }, 417 8, XvPacked, 1, 7, 0x60, 0x1C, 0x03, 418 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGRA", XvTopToBottom }, 419 420 /* BGR 2:3:3 */ 421 { 0x4C, XvRGB, NoOrder, { 0 }, 422 8, XvPacked, 1, 8, 0xC0, 0x38, 0x07, 423 0, 0, 0, 0, 0, 0, 0, 0, 0, "BGR", XvTopToBottom }, 424}; 425 426 427/* 428 * Video codec tables 429 */ 430 431#define SAA7111_SLAVE_ADDRESS 0x48 432#define SAA7125_SLAVE_ADDRESS 0x88 433 434static I2CByte 435DecInitVec[] = 436{ 437 0x11, 0x00, 438 0x02, 0xC1, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 439 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x4A, 440 0x0A, 0x80, 0x0B, 0x40, 0x0C, 0x40, 0x0D, 0x00, 441 0x0E, 0x01, 0x10, 0xC8, 0x12, 0x20, 442 0x13, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, 443}; 444 445static I2CByte 446EncInitVec[] = 447{ 448 0x3A, 0x83, 0x61, 0xC2, 449 0x5A, 119, 0x5B, 0x7D, 450 0x5C, 0xAF, 0x5D, 0x3C, 0x5E, 0x3F, 0x5F, 0x3F, 451 0x60, 0x70, 0x62, 0x4B, 0x67, 0x00, 452 0x68, 0x00, 0x69, 0x00, 0x6A, 0x00, 0x6B, 0x20, 453 0x6C, 0x03, 0x6D, 0x30, 0x6E, 0xA0, 0x6F, 0x00, 454 0x70, 0x80, 0x71, 0xE8, 0x72, 0x10, 455 0x7A, 0x13, 0x7B, 0xFB, 0x7C, 0x00, 0x7D, 0x00, 456}; 457 458static I2CByte Dec02[3] = { 0xC1, 0xC0, 0xC4 }; 459static I2CByte Dec09[3] = { 0x4A, 0x4A, 0xCA }; 460static I2CByte Enc3A[3] = { 0x03, 0x03, 0x23 }; 461static I2CByte Enc61[3] = { 0x06, 0x01, 0xC2 }; 462 463static I2CByte 464DecVS[3][8] = 465{ 466 { 0x06, 108, 0x07, 108, 0x08, 0x09, 0x0E, 0x01 }, 467 { 0x06, 107, 0x07, 107, 0x08, 0x49, 0x0E, 0x01 }, 468 { 0x06, 108, 0x07, 108, 0x08, 0x01, 0x0E, 0x51 } 469}; 470 471#define FSC(n) ((CARD32)((n) / 27e6 * 4294967296.0 + .5)) 472#define SUBCARRIER_FREQ_PAL (4.433619e6) 473#define SUBCARRIER_FREQ_NTSC (3.579545e6) 474 475static I2CByte 476EncVS[2][14] = 477{ 478 { 0x62, 0x4B, 0x6B, 0x28, 0x6E, 0xA0, 479 0x63, (I2CByte)(FSC(SUBCARRIER_FREQ_PAL) >> 0), 480 0x64, (I2CByte)(FSC(SUBCARRIER_FREQ_PAL) >> 8), 481 0x65, (I2CByte)(FSC(SUBCARRIER_FREQ_PAL) >> 16), 482 0x66, (I2CByte)(FSC(SUBCARRIER_FREQ_PAL) >> 24) }, 483 { 0x62, 0x6A, 0x6B, 0x20, 0x6E, 0x20, 484 0x63, (I2CByte)(FSC(SUBCARRIER_FREQ_NTSC) >> 0), 485 0x64, (I2CByte)(FSC(SUBCARRIER_FREQ_NTSC) >> 8), 486 0x65, (I2CByte)(FSC(SUBCARRIER_FREQ_NTSC) >> 16), 487 0x66, (I2CByte)(FSC(SUBCARRIER_FREQ_NTSC) >> 24) } 488}; 489 490/* Forward */ 491static void StopVideoStream(PortPrivPtr pPPriv, Bool shutdown); 492static void RestoreVideoStd(AdaptorPrivPtr pAPriv); 493static Bool xvipcHandshake(PortPrivPtr pPPriv, int op, Bool block); 494 495 496/* 497 * Video codec controls 498 */ 499 500static int 501SetAttr(PortPrivPtr pPPriv, int i, int value) 502{ 503 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 504 int v; 505 506 if (value < InputVideoAttributes[i].min_value) 507 value = InputVideoAttributes[i].min_value; 508 else 509 if (value > InputVideoAttributes[i].max_value) 510 value = InputVideoAttributes[i].max_value; 511 512 switch (i) { 513 case 0: 514 v = 128 + (MIN(value, 999) * 128) / 1000; 515 break; 516 517 case 1: 518 case 2: 519 v = 64 + (MIN(value, 999) * 64) / 1000; 520 break; 521 522 default: 523 v = (MIN(value, 999) * 128) / 1000; 524 break; 525 } 526 527 if (pAPriv->pm2p) { 528 xvipc.a = v << 8; 529 530 if (!xvipcHandshake(pPPriv, OP_ATTR + i, TRUE)) 531 return XvBadAlloc; 532 } else 533 if (!xf86I2CWriteByte(&pPPriv->I2CDev, 0x0A + i, v)) 534 return XvBadAlloc; 535 536 pPPriv->Attribute[i] = value; 537 538 return Success; 539} 540 541static int 542SetPlug(PortPrivPtr pPPriv, int Plug) 543{ 544 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 545 546 if (pAPriv->pm2p) { 547 xvipc.a = Plug - (pPPriv == &pAPriv->Port[1]); 548 549 if (!xvipcHandshake(pPPriv, OP_PLUG, TRUE)) 550 return XvBadAlloc; 551 } else { 552 if (pPPriv == &pAPriv->Port[0]) { 553 if (!xf86I2CWriteByte(&pPPriv->I2CDev, 0x02, Dec02[Plug]) || 554 !xf86I2CWriteByte(&pPPriv->I2CDev, 0x09, Dec09[Plug])) 555 return XvBadAlloc; 556 } else { 557 if (pPPriv->StreamOn) { 558 if (!xf86I2CWriteByte(&pPPriv->I2CDev, 0x3A, Enc3A[Plug])) 559 return XvBadAlloc; 560 } else 561 if (ColorBars) 562 xf86I2CWriteByte(&pPPriv->I2CDev, 0x3A, 0x83); 563 } 564 } 565 566 pPPriv->Plug = Plug; 567 568 return Success; 569} 570 571enum { PAL, NTSC, SECAM }; 572 573static int 574SetVideoStd(PortPrivPtr pPPriv, int VideoStd) 575{ 576 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 577 int r = Success; 578 579 if (pAPriv->pm2p) { 580 xvipc.a = VideoStd; 581 582 if (!xvipcHandshake(&pAPriv->Port[0], OP_VIDEOSTD, TRUE)) 583 return XvBadAlloc; 584 585 VideoStd = xvipc.a; /* Actual */ 586 } else { 587 if (VideoStd == SECAM) 588 xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, 0xC2); 589 /* Disable output, SECAM not supported */ 590 591 if (!xf86I2CWriteVec(&pAPriv->Port[0].I2CDev, &DecVS[VideoStd][0], 4)) { 592 pAPriv->VideoStd = -1; 593 return XvBadAlloc; 594 } 595 596 if (VideoStd != SECAM) 597 if (!xf86I2CWriteVec(&pAPriv->Port[1].I2CDev, &EncVS[VideoStd][0], 7)) { 598 pAPriv->VideoStd = -1; 599 return XvBadAlloc; 600 } 601 } 602 603 pAPriv->VideoStd = VideoStd; 604 pPPriv->VideoStdReq = VideoStd; 605 606 if (VideoStd == NTSC) { 607 pAPriv->FramesPerSec = 30; 608 pAPriv->FrameLines = 525; 609 pAPriv->IntLine = 513; 610 pAPriv->LinePer = 63555; 611 } else { 612 pAPriv->FramesPerSec = 25; 613 pAPriv->FrameLines = 625; 614 pAPriv->IntLine = 613; 615 pAPriv->LinePer = 64000; 616 } 617 618#if 0 /* XF86Config option */ 619 620 pAPriv->Port[0].FramesPerSec = pAPriv->FramesPerSec; 621 pAPriv->Port[1].FramesPerSec = pAPriv->FramesPerSec; 622 623#endif 624 625 return r; 626} 627 628 629/* 630 * Buffer management 631 */ 632 633static void 634RemoveAreaCallback(FBAreaPtr pFBArea) 635{ 636 PortPrivPtr pPPriv = (PortPrivPtr) pFBArea->devPrivate.ptr; 637 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 638 DEBUG(ScrnInfoPtr pScrn = pAPriv->pScrn;) 639 int i; 640 641 for (i = 0; i < MAX_BUFFERS && pPPriv->pFBArea[i] != pFBArea; i++); 642 643 if (i >= MAX_BUFFERS) 644 return; 645 646 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 647 "RemoveAreaCallback port #%d, buffer #%d, pFB=%p, off=0x%08x\n", 648 PORTNUM(pPPriv), i, pPPriv->pFBArea[i], pPPriv->BufferBase[i])); 649 650 if (pAPriv->VideoIO && PORTNUM(pPPriv) < 2) { 651 StopVideoStream(pPPriv, FALSE); 652 } 653 654 for (; i < MAX_BUFFERS - 1; i++) 655 pPPriv->pFBArea[i] = pPPriv->pFBArea[i + 1]; 656 657 pPPriv->pFBArea[MAX_BUFFERS - 1] = NULL; 658 659 pPPriv->BuffersAllocated--; 660} 661 662static void 663RemoveableBuffers(PortPrivPtr pPPriv, Bool remove) 664{ 665 int i; 666 667 for (i = 0; i < MAX_BUFFERS; i++) 668 if (pPPriv->pFBArea[i]) 669 pPPriv->pFBArea[i]->RemoveAreaCallback = 670 remove ? RemoveAreaCallback : NULL; 671} 672 673static void 674FreeBuffers(PortPrivPtr pPPriv) 675{ 676 DEBUG(AdaptorPrivPtr pAPriv = pPPriv->pAdaptor;) 677 DEBUG(ScrnInfoPtr pScrn = pAPriv->pScrn;) 678 int i; 679 680 RemoveableBuffers(pPPriv, FALSE); 681 682 for (i = MAX_BUFFERS - 1; i >= 0; i--) 683 if (pPPriv->pFBArea[i]) { 684 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 685 "FreeBuffers port #%d, buffer #%d, pFB=%p, off=0x%08x\n", 686 PORTNUM(pPPriv), i, pPPriv->pFBArea[i], pPPriv->BufferBase[i])); 687 688 xf86FreeOffscreenArea(pPPriv->pFBArea[i]); 689 690 pPPriv->pFBArea[i] = NULL; 691 } 692 693 pPPriv->BuffersAllocated = 0; 694} 695 696enum { FORCE_LINEAR = 1, FORCE_RECT }; 697 698static int 699AllocateBuffers(PortPrivPtr pPPriv, 700 int w, int h, int bytespp, 701 int num, int force) 702{ 703 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 704 ScrnInfoPtr pScrn = pAPriv->pScrn; 705 GLINTPtr pGlint = GLINTPTR(pScrn); 706 Bool linear = (force != FORCE_RECT); 707 int i, j, retry = 0; 708 709 FreeBuffers(pPPriv); 710 711 for (i = 0; i < num; i++) { 712 if (linear) { 713 for (j = (w + 31) >> 5; partprodPermedia[j] < 0; j++); 714 715 pPPriv->BufferStride = j * bytespp * 32; 716 pPPriv->BufferPProd = partprodPermedia[j]; 717 718 pPPriv->pFBArea[i] = xf86AllocateLinearOffscreenArea(pScrn->pScreen, 719 (pPPriv->BufferStride * h + (1 << BPPSHIFT(pGlint)) - 1) >> BPPSHIFT(pGlint), 720 8 >> BPPSHIFT(pGlint), NULL, NULL, (pointer) pPPriv); 721 722 if (pPPriv->pFBArea[i]) 723 /* pPPriv->BufferBase[i] = pPPriv->pFBArea[i].linear; */ 724 pPPriv->BufferBase[i] = 725 ((pPPriv->pFBArea[i]->box.y1 * pScrn->displayWidth) + 726 pPPriv->pFBArea[i]->box.x1) << BPPSHIFT(pGlint); 727 728 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 729 "New linear buffer %dx%d, rec %dx%d -> pFB=%p, off=0x%08x\n", 730 w, h, pPPriv->BufferStride, h, pPPriv->pFBArea[i], pPPriv->BufferBase[i])); 731 } else { 732 pPPriv->BufferStride = pScrn->displayWidth << BPPSHIFT(pGlint); 733 734 j = pPPriv->BufferStride / bytespp; 735 736 if (j <= w && j <= 2048 && (j & 31) == 0 && 737 partprodPermedia[j >> 5] >= 0) 738 { 739 pPPriv->BufferPProd = partprodPermedia[j >> 5]; 740 pPPriv->pFBArea[i] = xf86AllocateOffscreenArea(pScrn->pScreen, 741 w, h, 8 >> BPPSHIFT(pGlint), NULL, NULL, (pointer) pPPriv); 742 743 if (pPPriv->pFBArea[i]) 744 pPPriv->BufferBase[i] = 745 ((pPPriv->pFBArea[i]->box.y1 * pScrn->displayWidth) + 746 pPPriv->pFBArea[i]->box.x1) << BPPSHIFT(pGlint); 747 748 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 749 "New rect buffer %dx%d, stride %d, %d -> pFB=%p, off=0x%08x\n", 750 w, h, pPPriv->BufferStride, j, pPPriv->pFBArea[i], pPPriv->BufferBase[i])); 751 } 752 } 753 754 if (pPPriv->pFBArea[i]) 755 continue; 756 757 if (!force && i == 0 && retry++ < 1) { 758 linear ^= TRUE; 759 i = -1; 760 } else 761 break; 762 } 763 764 return pPPriv->BuffersAllocated = i; 765} 766 767 768/* 769 * Blitter 770 */ 771 772static Bool 773RemakePutCookies(PortPrivPtr pPPriv, RegionPtr pRegion) 774{ 775 BoxPtr pBox; 776 CookiePtr pCookie; 777 int nBox; 778 779 if (!pRegion) { 780 pBox = (BoxPtr) NULL; 781 nBox = pPPriv->nCookies; 782 } else { 783 pBox = REGION_RECTS(pRegion); 784 nBox = REGION_NUM_RECTS(pRegion); 785 786 if (!pPPriv->pCookies || pPPriv->nCookies < nBox) { 787 if (!(pCookie = (CookiePtr) realloc(pPPriv->pCookies, nBox * sizeof(CookieRec)))) 788 return FALSE; 789 790 pPPriv->pCookies = pCookie; 791 } 792 } 793 794 pPPriv->dS = (pPPriv->vw << 10) / pPPriv->dw; 795 pPPriv->dT = (pPPriv->vh << 10) / pPPriv->dh; 796 797 for (pCookie = pPPriv->pCookies; nBox--; pCookie++, pBox++) { 798 if (pRegion) { 799 pCookie->y1 = pBox->y1; 800 pCookie->y2 = pBox->x1; 801 pCookie->xy = (pBox->y1 << 16) | pBox->x1; 802 pCookie->wh = ((pBox->y2 - pBox->y1) << 16) | 803 (pBox->x2 - pBox->x1); 804 } 805 806 pCookie->s = (pPPriv->vx << 10) + (pCookie->y2 - pPPriv->dx) * pPPriv->dS; 807 pCookie->t = (pPPriv->vy << 10) + (pCookie->y1 - pPPriv->dy) * pPPriv->dT; 808 } 809 810 pPPriv->nCookies = pCookie - pPPriv->pCookies; 811 812 return TRUE; 813} 814 815#define FORMAT_YUYV ((0 << 5) + (1 << 4) + ((19 & 0x10) << 2) + ((19 & 0x0F) << 0)) 816#define FORMAT_UYVY ((1 << 5) + (1 << 4) + ((19 & 0x10) << 2) + ((19 & 0x0F) << 0)) 817#define FORMAT_YUVA ((0 << 5) + ((18 & 0x10) << 2) + ((18 & 0x0F) << 0)) 818#define FORMAT_VUYA ((1 << 5) + ((18 & 0x10) << 2) + ((18 & 0x0F) << 0)) 819 820static void 821PutYUV(PortPrivPtr pPPriv, int BufferBase, 822 int format, int bptshift, int alpha) 823{ 824 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 825 ScrnInfoPtr pScrn = pAPriv->pScrn; 826 GLINTPtr pGlint = GLINTPTR(pScrn); 827 CookiePtr pCookie = pPPriv->pCookies; 828 int nCookies = pPPriv->nCookies; 829 830 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "PutYUV %08x %08x\n", 831 BufferBase, format)); 832 833 if (!nCookies || (GLINT_READ_REG(InFIFOSpace) < 200)) 834 return; /* Denial of service fix, N/A for scaler */ 835 836 CHECKCLIPPING; 837 838 GLINT_WRITE_REG(1 << 16, dY); 839 GLINT_WRITE_REG(0, RasterizerMode); 840 GLINT_WRITE_REG(UNIT_DISABLE, AreaStippleMode); 841 GLINT_WRITE_REG(UNIT_ENABLE, TextureAddressMode); 842 GLINT_WRITE_REG(pPPriv->dS, dSdx); 843 GLINT_WRITE_REG(0, dSdyDom); 844 GLINT_WRITE_REG(0, dTdx); 845 GLINT_WRITE_REG(pPPriv->dT, dTdyDom); 846 GLINT_WRITE_REG(BufferBase >> bptshift, PMTextureBaseAddress); 847 GLINT_WRITE_REG((bptshift << 19) | pPPriv->BufferPProd, PMTextureMapFormat); 848 GLINT_WRITE_REG(format, PMTextureDataFormat); 849 GLINT_WRITE_REG((pPPriv->Attribute[5] << 17) | /* FilterMode */ 850 (11 << 13) | (11 << 9) | /* TextureSize log2 */ 851 UNIT_ENABLE, PMTextureReadMode); 852 GLINT_WRITE_REG((0 << 4) /* RGB */ | 853 (3 << 1) /* Copy */ | 854 UNIT_ENABLE, TextureColorMode); 855 if (alpha) 856 GLINT_WRITE_REG(pAPriv->dAlphaBlendMode, AlphaBlendMode); 857 GLINT_WRITE_REG(pAPriv->dDitherMode, DitherMode); 858 GLINT_WRITE_REG(UNIT_DISABLE, LogicalOpMode); 859 GLINT_WRITE_REG((alpha << 10) | /* ReadDestination */ 860 pGlint->pprod, FBReadMode); 861 GLINT_WRITE_REG(0xFFFFFFFF, FBHardwareWriteMask); 862 GLINT_WRITE_REG(UNIT_ENABLE, YUVMode); 863 864 for (; nCookies--; pCookie++) { 865 GLINT_WAIT(5); 866 GLINT_WRITE_REG(pCookie->xy, RectangleOrigin); 867 GLINT_WRITE_REG(pCookie->wh, RectangleSize); 868 GLINT_WRITE_REG(pCookie->s, SStart); 869 GLINT_WRITE_REG(pCookie->t, TStart); 870 GLINT_WRITE_REG(PrimitiveRectangle | 871 XPositive | 872 YPositive | 873 TextureEnable, Render); 874 } 875 876 pGlint->x = pGlint->y = -1; /* Force reload */ 877 pGlint->w = pGlint->h = -1; 878 pGlint->ROP = 0xFF; 879 pGlint->planemask = 0xFFFFFFFF; 880 881 GLINT_WAIT(8); 882 GLINT_WRITE_REG(UNIT_DISABLE, TextureAddressMode); 883 GLINT_WRITE_REG(pGlint->TexMapFormat, PMTextureMapFormat); 884 GLINT_WRITE_REG(UNIT_DISABLE, PMTextureReadMode); 885 GLINT_WRITE_REG(UNIT_DISABLE, TextureColorMode); 886 GLINT_WRITE_REG(UNIT_DISABLE, DitherMode); 887 if (alpha) { 888 GLINT_WRITE_REG(UNIT_DISABLE, AlphaBlendMode); 889 GLINT_WRITE_REG(pGlint->pprod, FBReadMode); 890 } 891 GLINT_WRITE_REG(UNIT_DISABLE, YUVMode); 892} 893 894#define FORMAT_RGB8888 ((0 << 5) + (0 << 4) + ((0 & 0x10) << 2) + ((0 & 0x0F) << 0)) 895#define FORMAT_RGB565 ((0 << 5) + (1 << 4) + ((16 & 0x10) << 2) + ((16 & 0x0F) << 0)) 896#define FORMAT_RGB5551 ((0 << 5) + (0 << 4) + ((1 & 0x10) << 2) + ((1 & 0x0F) << 0)) 897#define FORMAT_RGB4444 ((0 << 5) + (0 << 4) + ((2 & 0x10) << 2) + ((2 & 0x0F) << 0)) 898#define FORMAT_RGB332 ((0 << 5) + (1 << 4) + ((5 & 0x10) << 2) + ((5 & 0x0F) << 0)) 899#define FORMAT_RGB2321 ((0 << 5) + (0 << 4) + ((9 & 0x10) << 2) + ((9 & 0x0F) << 0)) 900#define FORMAT_BGR8888 ((1 << 5) + (0 << 4) + ((0 & 0x10) << 2) + ((0 & 0x0F) << 0)) 901#define FORMAT_BGR565 ((1 << 5) + (1 << 4) + ((16 & 0x10) << 2) + ((16 & 0x0F) << 0)) 902#define FORMAT_BGR5551 ((1 << 5) + (0 << 4) + ((1 & 0x10) << 2) + ((1 & 0x0F) << 0)) 903#define FORMAT_BGR4444 ((1 << 5) + (0 << 4) + ((2 & 0x10) << 2) + ((2 & 0x0F) << 0)) 904#define FORMAT_BGR332 ((1 << 5) + (1 << 4) + ((5 & 0x10) << 2) + ((5 & 0x0F) << 0)) 905#define FORMAT_BGR2321 ((1 << 5) + (0 << 4) + ((9 & 0x10) << 2) + ((9 & 0x0F) << 0)) 906 907static void 908PutRGB(PortPrivPtr pPPriv, int BufferBase, int format, int bptshift, int alpha) 909{ 910 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 911 ScrnInfoPtr pScrn = pAPriv->pScrn; 912 GLINTPtr pGlint = GLINTPTR(pScrn); 913 CookiePtr pCookie = pPPriv->pCookies; 914 int nCookies = pPPriv->nCookies; 915 916 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "PutRGB %08x %08x\n", 917 BufferBase, format)); 918 919 if (!nCookies) 920 return; 921 922 CHECKCLIPPING; 923 924 GLINT_WRITE_REG(1 << 16, dY); 925 GLINT_WRITE_REG(0, RasterizerMode); 926 GLINT_WRITE_REG(UNIT_DISABLE, AreaStippleMode); 927 GLINT_WRITE_REG(UNIT_ENABLE, TextureAddressMode); 928 GLINT_WRITE_REG(pPPriv->dS, dSdx); 929 GLINT_WRITE_REG(0, dSdyDom); 930 GLINT_WRITE_REG(0, dTdx); 931 GLINT_WRITE_REG(pPPriv->dT, dTdyDom); 932 GLINT_WRITE_REG(BufferBase >> bptshift, PMTextureBaseAddress); 933 GLINT_WRITE_REG((bptshift << 19) | pPPriv->BufferPProd, PMTextureMapFormat); 934 GLINT_WRITE_REG(format, PMTextureDataFormat); 935 GLINT_WRITE_REG((pPPriv->Attribute[5] << 17) | /* FilterMode */ 936 (11 << 13) | (11 << 9) | /* TextureSize log2 */ 937 UNIT_ENABLE, PMTextureReadMode); 938 GLINT_WRITE_REG((0 << 4) /* RGB */ | 939 (3 << 1) /* Copy */ | 940 UNIT_ENABLE, TextureColorMode); 941 if (alpha) 942 GLINT_WRITE_REG(pAPriv->dAlphaBlendMode, AlphaBlendMode); 943 GLINT_WRITE_REG(pAPriv->dDitherMode, DitherMode); 944 GLINT_WRITE_REG(UNIT_DISABLE, LogicalOpMode); 945 GLINT_WRITE_REG((alpha << 10) | /* ReadDestination */ 946 pGlint->pprod, FBReadMode); 947 GLINT_WRITE_REG(0xFFFFFFFF, FBHardwareWriteMask); 948 949 for (; nCookies--; pCookie++) { 950 GLINT_WAIT(5); 951 GLINT_WRITE_REG(pCookie->xy, RectangleOrigin); 952 GLINT_WRITE_REG(pCookie->wh, RectangleSize); 953 GLINT_WRITE_REG(pCookie->s, SStart); 954 GLINT_WRITE_REG(pCookie->t, TStart); 955 GLINT_WRITE_REG(PrimitiveRectangle | 956 XPositive | 957 YPositive | 958 TextureEnable, Render); 959 } 960 961 pGlint->x = pGlint->y = -1; /* Force reload */ 962 pGlint->w = pGlint->h = -1; 963 pGlint->ROP = 0xFF; 964 pGlint->planemask = 0xFFFFFFFF; 965 966 GLINT_WAIT(7); 967 GLINT_WRITE_REG(UNIT_DISABLE, TextureAddressMode); 968 GLINT_WRITE_REG(pGlint->TexMapFormat, PMTextureMapFormat); 969 GLINT_WRITE_REG(UNIT_DISABLE, PMTextureReadMode); 970 GLINT_WRITE_REG(UNIT_DISABLE, TextureColorMode); 971 GLINT_WRITE_REG(UNIT_DISABLE, DitherMode); 972 if (alpha) { 973 GLINT_WRITE_REG(UNIT_DISABLE, AlphaBlendMode); 974 GLINT_WRITE_REG(pGlint->pprod, FBReadMode); 975 } 976} 977 978static void 979BlackOut(PortPrivPtr pPPriv, RegionPtr pRegion) 980{ 981 ScrnInfoPtr pScrn = pPPriv->pAdaptor->pScrn; 982 ScreenPtr pScreen = pScrn->pScreen; 983 GLINTPtr pGlint = GLINTPTR(pScrn); 984 RegionRec DRegion; 985 BoxRec DBox; 986 BoxPtr pBox; 987 int nBox; 988 989 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, 990 "BlackOut %d,%d,%d,%d -- %d,%d,%d,%d\n", 991 pPPriv->vx, pPPriv->vy, pPPriv->vw, pPPriv->vh, 992 pPPriv->dx, pPPriv->dy, pPPriv->dw, pPPriv->dh)); 993 994 DBox.x1 = pPPriv->dx - (pPPriv->vx * pPPriv->dw) / pPPriv->vw; 995 DBox.y1 = pPPriv->dy - (pPPriv->vy * pPPriv->dh) / pPPriv->vh; 996 DBox.x2 = DBox.x1 + (pPPriv->fw * pPPriv->dw) / pPPriv->vw; 997 DBox.y2 = DBox.y1 + (pPPriv->fh * pPPriv->dh) / pPPriv->vh; 998 999 REGION_INIT(pScreen, &DRegion, &DBox, 1); 1000 1001 if (pRegion) 1002 REGION_SUBTRACT(pScreen, &DRegion, &DRegion, pRegion); 1003 1004 nBox = REGION_NUM_RECTS(&DRegion); 1005 pBox = REGION_RECTS(&DRegion); 1006 1007 GLINT_WAIT(15); 1008 CHECKCLIPPING; 1009 1010 GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode); 1011 GLINT_WRITE_REG(pPPriv->BufferPProd, FBReadMode); 1012 GLINT_WRITE_REG(0x1, FBReadPixel); /* 16 */ 1013 GLINT_WRITE_REG(pPPriv->BkgCol, FBBlockColor); 1014 GLINT_WRITE_REG(pPPriv->BufferBase[0] >> 1 /* 16 */, FBWindowBase); 1015 GLINT_WRITE_REG(UNIT_DISABLE, LogicalOpMode); 1016 1017 for (; nBox--; pBox++) { 1018 int w = ((pBox->x2 - pBox->x1) * pPPriv->vw + pPPriv->dw) / pPPriv->dw + 1; 1019 int h = ((pBox->y2 - pBox->y1) * pPPriv->vh + pPPriv->dh) / pPPriv->dh + 1; 1020 int x = ((pBox->x1 - DBox.x1) * pPPriv->vw + (pPPriv->dw >> 1)) / pPPriv->dw; 1021 int y = ((pBox->y1 - DBox.y1) * pPPriv->vh + (pPPriv->dh >> 1)) / pPPriv->dh; 1022 1023 if ((x + w) > pPPriv->fw) 1024 w = pPPriv->fw - x; 1025 if ((y + h) > pPPriv->fh) 1026 h = pPPriv->fh - y; 1027 1028 GLINT_WAIT(3); 1029 GLINT_WRITE_REG((y << 16) | x, RectangleOrigin); 1030 GLINT_WRITE_REG((h << 16) | w, RectangleSize); 1031 GLINT_WRITE_REG(PrimitiveRectangle | 1032 XPositive | YPositive | FastFillEnable, Render); 1033 } 1034 1035 REGION_UNINIT(pScreen, &DRegion); 1036 1037 pGlint->x = pGlint->y = -1; /* Force reload */ 1038 pGlint->w = pGlint->h = -1; 1039 pGlint->ROP = 0xFF; 1040 GLINT_WAIT(3); 1041 GLINT_WRITE_REG(0, FBWindowBase); 1042 GLINT_WRITE_REG(pGlint->pprod, FBReadMode); 1043 GLINT_WRITE_REG(pGlint->PixelWidth, FBReadPixel); 1044} 1045 1046static Bool 1047RemakeGetCookies(PortPrivPtr pPPriv, RegionPtr pRegion) 1048{ 1049 BoxPtr pBox; 1050 CookiePtr pCookie; 1051 int nBox; 1052 int dw1 = pPPriv->dw - 1; 1053 int dh1 = pPPriv->dh - 1; 1054 1055 if (!pRegion) { 1056 pBox = (BoxPtr) NULL; 1057 nBox = pPPriv->nCookies; 1058 } else { 1059 pBox = REGION_RECTS(pRegion); 1060 nBox = REGION_NUM_RECTS(pRegion); 1061 1062 if (!pPPriv->pCookies || pPPriv->nCookies < nBox) { 1063 if (!(pCookie = (CookiePtr) realloc(pPPriv->pCookies, nBox * sizeof(CookieRec)))) 1064 return FALSE; 1065 1066 pPPriv->pCookies = pCookie; 1067 } 1068 } 1069 1070 pPPriv->dS = (pPPriv->dw << 20) / pPPriv->vw; 1071 pPPriv->dT = (pPPriv->dh << 20) / pPPriv->vh; 1072 1073 for (pCookie = pPPriv->pCookies; nBox--; pBox++) { 1074 int n1, n2; 1075 1076 if (pRegion) { 1077 n1 = ((pBox->x1 - pPPriv->dx) * pPPriv->vw + dw1) / pPPriv->dw; 1078 n2 = ((pBox->x2 - pPPriv->dx) * pPPriv->vw - 1) / pPPriv->dw; 1079 1080 if (n1 > n2) 1081 continue; /* Clip is subpixel */ 1082 1083 pCookie->xy = n1 + pPPriv->vx; 1084 pCookie->wh = n2 - n1 + 1; 1085 pCookie->s = n1 * pPPriv->dS + (pPPriv->dx << 20); 1086 pCookie->y1 = pBox->y1; 1087 pCookie->y2 = pBox->y2; 1088 } 1089 1090 n1 = ((pCookie->y1 - pPPriv->dy) * pPPriv->vh + dh1) / pPPriv->dh; 1091 n2 = ((pCookie->y2 - pPPriv->dy) * pPPriv->vh - 1) / pPPriv->dh; 1092 pCookie->xy = (pCookie->xy & 0xFFFF) | ((n1 + pPPriv->vy) << 16); 1093 pCookie->wh = (pCookie->wh & 0xFFFF) | ((n2 - n1 + 1) << 16); 1094 pCookie->t = n1 * pPPriv->dT + (pPPriv->dy << 20); 1095 if (n1 > n2) pCookie->t = -1; 1096 1097 pCookie++; 1098 } 1099 1100 pPPriv->nCookies = pCookie - pPPriv->pCookies; 1101 return TRUE; 1102} 1103 1104static void 1105GetYUV(PortPrivPtr pPPriv) 1106{ 1107 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 1108 ScrnInfoPtr pScrn = pAPriv->pScrn; 1109 GLINTPtr pGlint = GLINTPTR(pScrn); 1110 CookiePtr pCookie = pPPriv->pCookies; 1111 int nCookies = pPPriv->nCookies; 1112 1113 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5, "GetYUV\n")); 1114 1115 if (!nCookies || (GLINT_READ_REG(InFIFOSpace) < 200)) 1116 return; 1117 1118 GLINT_WAIT(25); 1119 CHECKCLIPPING; 1120 1121 GLINT_WRITE_REG(1 << 16, dY); 1122 GLINT_WRITE_REG(0, RasterizerMode); 1123 GLINT_WRITE_REG(UNIT_DISABLE, AreaStippleMode); 1124 GLINT_WRITE_REG(UNIT_ENABLE, TextureAddressMode); 1125 GLINT_WRITE_REG(pPPriv->dS, dSdx); 1126 GLINT_WRITE_REG(0, dSdyDom); 1127 GLINT_WRITE_REG(0, dTdx); 1128 GLINT_WRITE_REG(pPPriv->dT, dTdyDom); 1129 GLINT_WRITE_REG(0, PMTextureBaseAddress); 1130 GLINT_WRITE_REG(pAPriv->dTextureDataFormat, PMTextureDataFormat); 1131 GLINT_WRITE_REG((pPPriv->Attribute[5] << 17) | /* FilterMode */ 1132 (11 << 13) | (11 << 9) | /* TextureSize log2 */ 1133 UNIT_ENABLE, PMTextureReadMode); 1134 if (pScrn->depth == 8) 1135 GLINT_WRITE_REG(UNIT_ENABLE, TexelLUTMode); 1136 GLINT_WRITE_REG((0 << 4) /* RGB */ | 1137 (3 << 1) /* Copy */ | 1138 UNIT_ENABLE, TextureColorMode); 1139 GLINT_WRITE_REG((1 << 10) | /* RGB */ 1140 ((16 & 0x10) << 12) | 1141 ((16 & 0x0F) << 2) | /* 5:6:5f */ 1142 UNIT_ENABLE, DitherMode); 1143 GLINT_WRITE_REG(UNIT_DISABLE, LogicalOpMode); 1144 GLINT_WRITE_REG(pPPriv->BufferPProd, FBReadMode); 1145 GLINT_WRITE_REG(pPPriv->BufferBase[0] >> 1 /* 16 */, FBWindowBase); 1146 GLINT_WRITE_REG(0x1, FBReadPixel); /* 16 */ 1147 GLINT_WRITE_REG(UNIT_DISABLE, YUVMode); 1148 1149 for (; nCookies--; pCookie++) 1150 if (pCookie->t >= 0) { 1151 GLINT_WAIT(5); 1152 GLINT_WRITE_REG(pCookie->xy, RectangleOrigin); 1153 GLINT_WRITE_REG(pCookie->wh, RectangleSize); 1154 GLINT_WRITE_REG(pCookie->s, SStart); 1155 GLINT_WRITE_REG(pCookie->t, TStart); 1156 GLINT_WRITE_REG(PrimitiveRectangle | 1157 XPositive | 1158 YPositive | 1159 TextureEnable, Render); 1160 } 1161 1162 pGlint->x = pGlint->y = -1; /* Force reload */ 1163 pGlint->w = pGlint->h = -1; 1164 pGlint->ROP = 0xFF; 1165 1166 GLINT_WAIT(9); 1167 GLINT_WRITE_REG(UNIT_DISABLE, TextureAddressMode); 1168 GLINT_WRITE_REG(UNIT_DISABLE, TextureColorMode); 1169 GLINT_WRITE_REG(UNIT_DISABLE, DitherMode); 1170 if (pScrn->depth == 8) 1171 GLINT_WRITE_REG(UNIT_DISABLE, TexelLUTMode); 1172 GLINT_WRITE_REG(UNIT_DISABLE, PMTextureReadMode); 1173 GLINT_WRITE_REG(pGlint->pprod, FBReadMode); 1174 GLINT_WRITE_REG(0, FBWindowBase); 1175 GLINT_WRITE_REG(pGlint->PixelWidth, FBReadPixel); 1176 GLINT_WRITE_REG(UNIT_DISABLE, YUVMode); 1177} 1178 1179static int 1180SetBkgCol(PortPrivPtr pPPriv, int value) 1181{ 1182 pPPriv->Attribute[6] = value; 1183 1184 pPPriv->BkgCol = ((value & 0xF80000) >> 8) | 1185 ((value & 0x00FC00) >> 5) | 1186 ((value & 0x0000F8) >> 3); 1187 1188 pPPriv->BkgCol += pPPriv->BkgCol << 16; 1189 1190 if (pPPriv->VideoOn) { 1191 BlackOut(pPPriv, NULL); 1192 GetYUV(pPPriv); 1193 } 1194 1195 return Success; 1196} 1197 1198/* os/WaitFor.c */ 1199 1200static CARD32 1201TimerCallback(OsTimerPtr pTim, CARD32 now, pointer p) 1202{ 1203 AdaptorPrivPtr pAPriv = (AdaptorPrivPtr) p; 1204 GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn); 1205 PortPrivPtr pPPriv; 1206 int i, delay; 1207 1208 if (!pAPriv->pm2p) { 1209 pPPriv = &pAPriv->Port[0]; 1210 1211 if (pPPriv->VideoOn > VIDEO_OFF) { 1212 pPPriv->FrameAcc += pPPriv->FramesPerSec; 1213 1214 if (pPPriv->FrameAcc >= pAPriv->FramesPerSec) { 1215 pPPriv->FrameAcc -= pAPriv->FramesPerSec; 1216 1217 PutYUV(pPPriv, (!pPPriv->pFBArea[1]) ? 1218 pPPriv->BufferBase[0] : pPPriv->BufferBase[1 - 1219 GLINT_READ_REG(VSABase + VSVideoAddressIndex)], FORMAT_YUYV, 1, 0); 1220 } 1221 } else 1222 if (pPPriv->StopDelay >= 0 && !(pPPriv->StopDelay--)) { 1223 StopVideoStream(pPPriv, TRUE); 1224 RestoreVideoStd(pAPriv); 1225 } 1226 1227 pPPriv = &pAPriv->Port[1]; 1228 1229 if (pPPriv->VideoOn > VIDEO_OFF) { 1230 pPPriv->FrameAcc += pPPriv->FramesPerSec; 1231 1232 if (pPPriv->FrameAcc >= pAPriv->FramesPerSec) { 1233 pPPriv->FrameAcc -= pAPriv->FramesPerSec; 1234 1235 GetYUV(pPPriv); 1236 } 1237 } else 1238 if (pPPriv->StopDelay >= 0 && !(pPPriv->StopDelay--)) { 1239 StopVideoStream(pPPriv, TRUE); 1240 RestoreVideoStd(pAPriv); 1241 } 1242 } 1243 1244 for (i = 2; i <= 5; i++) { 1245 if (pAPriv->Port[i].StopDelay >= 0) { 1246 if (!(pAPriv->Port[i].StopDelay--)) { 1247 FreeBuffers(&pAPriv->Port[i]); 1248 FreeCookies(&pAPriv->Port[i]); 1249 pAPriv->TimerUsers &= ~(1 << i); 1250 } 1251 } 1252 } 1253 1254 if (!pAPriv->pm2p) { 1255 if (pAPriv->Port[0].StreamOn) { 1256 delay = GLINT_READ_REG(VSABase + VSCurrentLine); 1257 1258 if (!(GLINT_READ_REG(VSStatus) & VS_FieldOne0A)) 1259 delay += pAPriv->FrameLines >> 1; 1260 1261 if (delay > (pAPriv->IntLine - 16)) 1262 delay -= pAPriv->FrameLines; 1263 1264 return (((pAPriv->IntLine - delay) * pAPriv->LinePer) + 999999) / 1000000; 1265 } else if (pAPriv->Port[1].StreamOn) { 1266 delay = GLINT_READ_REG(VSBBase + VSCurrentLine); 1267 1268 if (!(GLINT_READ_REG(VSStatus) & VS_FieldOne0B)) 1269 delay += pAPriv->FrameLines >> 1; 1270 1271 if (delay > (pAPriv->IntLine - 16)) 1272 delay -= pAPriv->FrameLines; 1273 1274 return (((pAPriv->IntLine - delay) * pAPriv->LinePer) + 999999) / 1000000; 1275 } 1276 } 1277 1278 if (pAPriv->TimerUsers) 1279 return pAPriv->Instant; 1280 1281 return 0; /* Cancel */ 1282} 1283 1284 1285/* 1286 * Video stream (bounce buffer <-> hardware) 1287 */ 1288 1289static void 1290StopVideoStream(PortPrivPtr pPPriv, Bool shutdown) 1291{ 1292 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 1293 GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn); 1294 int VideoOn; 1295 1296 pPPriv->StopDelay = -1; 1297 1298 VideoOn = pPPriv->VideoOn; 1299 pPPriv->VideoOn = VIDEO_OFF; 1300 1301 if (!pPPriv->StreamOn) 1302 return; 1303 1304 if (pAPriv->pm2p) { 1305 xvipcHandshake(pPPriv, OP_STOP, TRUE); 1306 1307 pPPriv->StreamOn = FALSE; 1308 1309 if (shutdown) 1310 FreeCookies(pPPriv); 1311 1312 if (VideoOn > VIDEO_OFF && pGlint->NoAccel) 1313 Permedia2Sync(pAPriv->pScrn); 1314 1315 return; 1316 } 1317 1318 if (pPPriv == &pAPriv->Port[0]) { 1319 int line, eeek = 0; 1320 1321 do { 1322 if (eeek++ > 1000000) break; 1323 line = GLINT_READ_REG(VSABase + VSCurrentLine); 1324 } while (line > 15); 1325 1326 GLINT_WRITE_REG(0, VSABase + VSControl); 1327 1328 pAPriv->Port[0].StreamOn = FALSE; 1329 1330 usleep(80000); 1331 } else { 1332 xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x3A, 0x83); 1333 if (!ColorBars) 1334 xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, 0xC2); 1335 1336 GLINT_WRITE_REG(0, VSBBase + VSControl); 1337 1338 pAPriv->Port[1].StreamOn = FALSE; 1339 } 1340 1341 if (!pAPriv->Port[0].StreamOn && !pAPriv->Port[1].StreamOn) { 1342 if (shutdown) 1343 xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, 0xC2); 1344 xf86I2CWriteByte(&pAPriv->Port[0].I2CDev, 0x11, 0x00); 1345 } 1346 1347 if (shutdown) { 1348 FreeBuffers(pPPriv); 1349 FreeCookies(pPPriv); 1350 1351 if (pAPriv->TimerUsers) { 1352 pAPriv->TimerUsers &= ~PORTNUM(pPPriv); 1353 if (!pAPriv->TimerUsers) 1354 TimerCancel(pAPriv->Timer); 1355 } 1356 1357 if (VideoOn > VIDEO_OFF && pGlint->NoAccel) 1358 Permedia2Sync(pAPriv->pScrn); 1359 } 1360} 1361 1362static Bool 1363StartVideoStream(PortPrivPtr pPPriv, RegionPtr pRegion) 1364{ 1365 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 1366 GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn); 1367 1368 if (pAPriv->VideoStd < 0) 1369 return FALSE; 1370 1371 pPPriv->StopDelay = -1; 1372 1373 if (pAPriv->pm2p) { 1374 if (pPPriv == &pAPriv->Port[0]) { 1375 if (!RemakePutCookies(pPPriv, pRegion)) 1376 return FALSE; 1377 if (pPPriv->StreamOn) 1378 return TRUE; 1379 } else { 1380 if (!RemakeGetCookies(pPPriv, pRegion)) 1381 return FALSE; 1382 if (pPPriv->StreamOn) { 1383 BlackOut(pPPriv, pRegion); 1384 return TRUE; 1385 } 1386 } 1387 1388 xvipc.a = pPPriv->BuffersRequested; 1389 xvipc.b = !pPPriv->Attribute[4]; 1390 xvipc.c = 1 + (pPPriv->Attribute[4] & 2); 1391 1392 if (!xvipcHandshake(pPPriv, OP_START, TRUE)) 1393 return FALSE; 1394 1395 if (pPPriv == &pAPriv->Port[1]) { 1396 pPPriv->BufferBase[0] = xvipc.d; 1397 BlackOut(pPPriv, pRegion); 1398 } 1399 1400 return pPPriv->StreamOn = TRUE; 1401 } else { 1402 CARD32 Base = (pPPriv == &pAPriv->Port[0]) ? VSABase : VSBBase; 1403 1404 if (pPPriv->BuffersAllocated < pPPriv->BuffersRequested) { 1405 int height = ((pAPriv->VideoStd == NTSC) ? 512 : 608) >> (!pPPriv->Attribute[4]); 1406 1407 if (!AllocateBuffers(pPPriv, 704, height, 2, pPPriv->BuffersRequested, 0)) 1408 return FALSE; 1409 1410 pPPriv->fw = 704; 1411 pPPriv->fh = InputVideoEncodings[pAPriv->VideoStd * 3].height >> 1412 (!pPPriv->Attribute[4]); 1413 } 1414 1415 if (pPPriv == &pAPriv->Port[0]) { 1416 if (!RemakePutCookies(pPPriv, pRegion)) 1417 return FALSE; 1418 } else { 1419 if (!RemakeGetCookies(pPPriv, pRegion)) 1420 return FALSE; 1421 1422 BlackOut(pPPriv, pRegion); 1423 } 1424 1425 if (pPPriv->StreamOn) 1426 return TRUE; 1427 1428 GLINT_WRITE_REG(pPPriv->BufferBase[0] / 8, Base + VSVideoAddress0); 1429 if (pPPriv->pFBArea[1]) 1430 GLINT_WRITE_REG(pPPriv->BufferBase[1] / 8, Base + VSVideoAddress1); 1431 else 1432 GLINT_WRITE_REG(pPPriv->BufferBase[0] / 8, Base + VSVideoAddress1); 1433 GLINT_WRITE_REG(pPPriv->BufferStride / 8, Base + VSVideoStride); 1434 1435 GLINT_WRITE_REG(0, Base + VSCurrentLine); 1436 1437 if (pAPriv->VideoStd == NTSC) { 1438 GLINT_WRITE_REG(16, Base + VSVideoStartLine); 1439 GLINT_WRITE_REG(16 + 240, Base + VSVideoEndLine); 1440 GLINT_WRITE_REG(288 + (8 & ~3) * 2, Base + VSVideoStartData); 1441 GLINT_WRITE_REG(288 + ((8 & ~3) + 704) * 2, Base + VSVideoEndData); 1442 } else { 1443 GLINT_WRITE_REG(16, Base + VSVideoStartLine); 1444 GLINT_WRITE_REG(16 + 288, Base + VSVideoEndLine); 1445 GLINT_WRITE_REG(288 + (8 & ~3) * 2, Base + VSVideoStartData); 1446 GLINT_WRITE_REG(288 + ((8 & ~3) + 704) * 2, Base + VSVideoEndData); 1447 } 1448 1449 GLINT_WRITE_REG(2, Base + VSVideoAddressHost); 1450 GLINT_WRITE_REG(0, Base + VSVideoAddressIndex); 1451 1452 if (pPPriv == &pAPriv->Port[0]) { 1453 int line, eeek = 0; 1454 1455 xf86I2CWriteByte(&pAPriv->Port[0].I2CDev, 0x11, 0x0D); 1456 1457 do { 1458 if (eeek++ > 1000000) break; 1459 line = GLINT_READ_REG(VSABase + VSCurrentLine); 1460 } while (line > 15); 1461 1462 GLINT_WRITE_REG(VSA_Video | 1463 (pPPriv->Attribute[4] ? 1464 VSA_CombineFields : VSA_Discard_FieldTwo), 1465 VSABase + VSControl); 1466 if (ColorBars) 1467 if (!pAPriv->Port[1].StreamOn) { 1468 xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x3A, 0x83); 1469 xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, Enc61[pAPriv->VideoStd]); 1470 } 1471 } else { 1472 GLINT_WRITE_REG(VSB_Video | 1473 (pPPriv->Attribute[4] ? VSB_CombineFields : 0) | 1474 /* VSB_GammaCorrect | */ 1475 (16 << 4) | /* 5:6:5 */ 1476 (1 << 9) | /* 16 */ 1477 VSB_RGBOrder, VSBBase + VSControl); 1478 xf86I2CWriteByte(&pAPriv->Port[0].I2CDev, 0x11, 0x0D); 1479 xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x3A, Enc3A[pPPriv->Plug]); 1480 xf86I2CWriteByte(&pAPriv->Port[1].I2CDev, 0x61, Enc61[pAPriv->VideoStd]); 1481 } 1482 1483 pAPriv->TimerUsers |= 1 << PORTNUM(pPPriv); 1484 TimerSet(pAPriv->Timer, 0, 80, TimerCallback, pAPriv); 1485 1486 return pPPriv->StreamOn = TRUE; 1487 } 1488 1489 return FALSE; 1490} 1491 1492 1493/* 1494 * Xv interface 1495 */ 1496 1497static int 1498Permedia2PutVideo(ScrnInfoPtr pScrn, 1499 short vid_x, short vid_y, short drw_x, short drw_y, 1500 short vid_w, short vid_h, short drw_w, short drw_h, 1501 RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 1502{ 1503 PortPrivPtr pPPriv = (PortPrivPtr) data; 1504 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 1505 int sw, sh; 1506 1507 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 1508 "PutVideo %d,%d,%d,%d -> %d,%d,%d,%d\n", 1509 vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)); 1510 1511 sw = InputVideoEncodings[pAPriv->VideoStd * 3].width; 1512 sh = InputVideoEncodings[pAPriv->VideoStd * 3].height; 1513 1514 if ((vid_x + vid_w) > sw || 1515 (vid_y + vid_h) > sh) 1516 return BadValue; 1517 1518 pPPriv->VideoOn = VIDEO_OFF; 1519 1520 pPPriv->vx = ((vid_x << 10) * pPPriv->fw) / sw; 1521 pPPriv->vy = ((vid_y << 10) * pPPriv->fh) / sh; 1522 pPPriv->vw = ((vid_w << 10) * pPPriv->fw) / sw; 1523 pPPriv->vh = ((vid_h << 10) * pPPriv->fh) / sh; 1524 1525 pPPriv->dx = drw_x; 1526 pPPriv->dy = drw_y; 1527 pPPriv->dw = drw_w; 1528 pPPriv->dh = drw_h; 1529 1530 pPPriv->FrameAcc = pAPriv->FramesPerSec; 1531 1532 if (!StartVideoStream(pPPriv, clipBoxes)) 1533 return XvBadAlloc; 1534 1535 pPPriv->VideoOn = VIDEO_ON; 1536 1537 return Success; 1538} 1539 1540static int 1541Permedia2PutStill(ScrnInfoPtr pScrn, 1542 short vid_x, short vid_y, short drw_x, short drw_y, 1543 short vid_w, short vid_h, short drw_w, short drw_h, 1544 RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 1545{ 1546 PortPrivPtr pPPriv = (PortPrivPtr) data; 1547 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 1548 GLINTPtr pGlint = GLINTPTR(pScrn); 1549 int sw, sh, r = Success; 1550 1551 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 1552 "PutStill %d,%d,%d,%d -> %d,%d,%d,%d\n", 1553 vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)); 1554 1555 sw = InputVideoEncodings[pAPriv->VideoStd * 3].width; 1556 sh = InputVideoEncodings[pAPriv->VideoStd * 3].height; 1557 1558 if ((vid_x + vid_w) > sw || 1559 (vid_y + vid_h) > sh) 1560 return BadValue; 1561 1562 pPPriv->VideoOn = VIDEO_OFF; 1563 1564 pPPriv->vx = ((vid_x << 10) * pPPriv->fw) / sw; 1565 pPPriv->vy = ((vid_y << 10) * pPPriv->fh) / sh; 1566 pPPriv->vw = ((vid_w << 10) * pPPriv->fw) / sw; 1567 pPPriv->vh = ((vid_h << 10) * pPPriv->fh) / sh; 1568 1569 pPPriv->dx = drw_x; 1570 pPPriv->dy = drw_y; 1571 pPPriv->dw = drw_w; 1572 pPPriv->dh = drw_h; 1573 1574 pPPriv->FrameAcc = pAPriv->FramesPerSec; 1575 1576 if (!StartVideoStream(pPPriv, clipBoxes)) 1577 return XvBadAlloc; 1578 1579 if (pAPriv->pm2p) { 1580 /* Sleep, not busy wait, until the very next frame is ready. 1581 Accept memory requests and other window's update events 1582 in the meantime. */ 1583 for (pPPriv->VideoOn = VIDEO_ONE_SHOT; pPPriv->VideoOn;) 1584 if (!xvipcHandshake(pPPriv, OP_UPDATE, TRUE)) { 1585 r = FALSE; 1586 break; 1587 } 1588 } else { 1589 usleep(80000); 1590 1591 PutYUV(pPPriv, (!pPPriv->pFBArea[1]) ? 1592 pPPriv->BufferBase[0] : pPPriv->BufferBase[1 - 1593 GLINT_READ_REG(VSABase + VSVideoAddressIndex)], FORMAT_YUYV, 1, 0); 1594 } 1595 1596 pPPriv->StopDelay = 125; 1597 1598 return r; 1599} 1600 1601static int 1602Permedia2GetVideo(ScrnInfoPtr pScrn, 1603 short vid_x, short vid_y, short drw_x, short drw_y, 1604 short vid_w, short vid_h, short drw_w, short drw_h, 1605 RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 1606{ 1607 PortPrivPtr pPPriv = (PortPrivPtr) data; 1608 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 1609 int sw, sh; 1610 1611 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 1612 "GetVideo %d,%d,%d,%d <- %d,%d,%d,%d\n", 1613 vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)); 1614 1615 sw = InputVideoEncodings[pAPriv->VideoStd * 3].width; 1616 sh = InputVideoEncodings[pAPriv->VideoStd * 3].height; 1617 1618 if ((vid_x + vid_w) > sw || 1619 (vid_y + vid_h) > sh) { 1620 return BadValue; 1621 } 1622 1623 pPPriv->VideoOn = VIDEO_OFF; 1624 1625 pPPriv->vx = (vid_x * pPPriv->fw) / sw; 1626 pPPriv->vy = (vid_y * pPPriv->fh) / sh; 1627 pPPriv->vw = (vid_w * pPPriv->fw) / sw; 1628 pPPriv->vh = (vid_h * pPPriv->fh) / sh; 1629 1630 pPPriv->dx = drw_x; 1631 pPPriv->dy = drw_y; 1632 pPPriv->dw = drw_w; 1633 pPPriv->dh = drw_h; 1634 1635 pPPriv->FrameAcc = pAPriv->FramesPerSec; 1636 1637 if (!StartVideoStream(pPPriv, clipBoxes)) { 1638 return XvBadAlloc; 1639 } 1640 1641 GetYUV(pPPriv); 1642 1643 pPPriv->VideoOn = VIDEO_ON; 1644 1645 return Success; 1646} 1647 1648static int 1649Permedia2GetStill(ScrnInfoPtr pScrn, 1650 short vid_x, short vid_y, short drw_x, short drw_y, 1651 short vid_w, short vid_h, short drw_w, short drw_h, 1652 RegionPtr clipBoxes, pointer data, DrawablePtr pDraw) 1653{ 1654 PortPrivPtr pPPriv = (PortPrivPtr) data; 1655 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 1656 int sw, sh; 1657 1658 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 1659 "GetStill %d,%d,%d,%d <- %d,%d,%d,%d\n", 1660 vid_x, vid_y, vid_w, vid_h, drw_x, drw_y, drw_w, drw_h)); 1661 1662 sw = InputVideoEncodings[pAPriv->VideoStd * 3].width; 1663 sh = InputVideoEncodings[pAPriv->VideoStd * 3].height; 1664 1665 if ((vid_x + vid_w) > sw || 1666 (vid_y + vid_h) > sh) 1667 return BadValue; 1668 1669 pPPriv->VideoOn = VIDEO_OFF; 1670 1671 pPPriv->vx = (vid_x * pPPriv->fw) / sw; 1672 pPPriv->vy = (vid_y * pPPriv->fh) / sh; 1673 pPPriv->vw = (vid_w * pPPriv->fw) / sw; 1674 pPPriv->vh = (vid_h * pPPriv->fh) / sh; 1675 1676 pPPriv->dx = drw_x; 1677 pPPriv->dy = drw_y; 1678 pPPriv->dw = drw_w; 1679 pPPriv->dh = drw_h; 1680 1681 pPPriv->FrameAcc = pAPriv->FramesPerSec; 1682 1683 if (!StartVideoStream(pPPriv, clipBoxes)) 1684 return XvBadAlloc; 1685 1686 GetYUV(pPPriv); 1687 1688 return Success; 1689} 1690 1691static void 1692CopyYV12(CARD8 *Y, CARD32 *dst, int width, int height, int pitch) 1693{ 1694 int Y_size = width * height; 1695 CARD8 *V = Y + Y_size; 1696 CARD8 *U = V + (Y_size >> 2); 1697 int pad = (pitch >> 2) - (width >> 1); 1698 int x; 1699 1700 width >>= 1; 1701 1702 for (height >>= 1; height > 0; height--) { 1703 for (x = 0; x < width; Y += 2, x++) 1704 *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24); 1705 dst += pad; 1706 for (x = 0; x < width; Y += 2, x++) 1707 *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24); 1708 dst += pad; 1709 U += width; 1710 V += width; 1711 } 1712} 1713 1714#if X_BYTE_ORDER == X_BIG_ENDIAN 1715 1716static void 1717CopyYV12_16(CARD8 *Y, CARD32 *dst, int width, int height, int pitch) 1718{ 1719 int Y_size = width * height; 1720 CARD8 *V = Y + Y_size; 1721 CARD8 *U = V + (Y_size >> 2); 1722 int pad = (pitch >> 2) - (width >> 1); 1723 int x; 1724 1725 width >>= 1; 1726 1727 for (height >>= 1; height > 0; height--) { 1728 for (x = 0; x < width; Y += 2, x++) 1729 *dst++ = Y[1] + (V[x] << 8) + (Y[0] << 16) + (U[x] << 24); 1730 dst += pad; 1731 for (x = 0; x < width; Y += 2, x++) 1732 *dst++ = Y[1] + (V[x] << 8) + (Y[0] << 16) + (U[x] << 24); 1733 dst += pad; 1734 U += width; 1735 V += width; 1736 } 1737} 1738 1739static void 1740CopyYV12_8(CARD8 *Y, CARD32 *dst, int width, int height, int pitch) 1741{ 1742 int Y_size = width * height; 1743 CARD8 *V = Y + Y_size; 1744 CARD8 *U = V + (Y_size >> 2); 1745 int pad = (pitch >> 2) - (width >> 1); 1746 int x; 1747 1748 width >>= 1; 1749 1750 for (height >>= 1; height > 0; height--) { 1751 for (x = 0; x < width; Y += 2, x++) 1752 *dst++ = V[x] + (Y[1] << 8) + (U[x] << 16) + (Y[0] << 24); 1753 dst += pad; 1754 for (x = 0; x < width; Y += 2, x++) 1755 *dst++ = V[x] + (Y[1] << 8) + (U[x] << 16) + (Y[0] << 24); 1756 dst += pad; 1757 U += width; 1758 V += width; 1759 } 1760} 1761 1762#endif 1763 1764static void 1765CopyFlat(CARD8 *src, CARD8 *dst, int width, int height, int pitch) 1766{ 1767 if (width == pitch) { 1768 memcpy(dst, src, width * height); 1769 return; 1770 } 1771 1772 while (height > 0) { 1773 memcpy(dst, src, width); 1774 dst += pitch; 1775 src += width; 1776 height--; 1777 } 1778} 1779 1780static int 1781Permedia2PutImage(ScrnInfoPtr pScrn, 1782 short src_x, short src_y, short drw_x, short drw_y, 1783 short src_w, short src_h, short drw_w, short drw_h, 1784 int id, unsigned char *buf, short width, short height, 1785 Bool sync, RegionPtr clipBoxes, pointer data, 1786 DrawablePtr pDraw) 1787{ 1788 PortPrivPtr pPPriv = (PortPrivPtr) data; 1789 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 1790 GLINTPtr pGlint = GLINTPTR(pScrn); 1791 int i; 1792 1793 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 1794 "PutImage %d,%d,%d,%d -> %d,%d,%d,%d id=0x%08x buf=%p w=%d h=%d sync=%d\n", 1795 src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, 1796 id, buf, width, height, sync)); 1797 1798 if ((src_x + src_w) > width || 1799 (src_y + src_h) > height) 1800 return BadValue; 1801 1802 pPPriv->vx = src_x << 10; 1803 pPPriv->vy = src_y << 10; 1804 pPPriv->vw = src_w << 10; 1805 pPPriv->vh = src_h << 10; 1806 1807 pPPriv->dx = drw_x; 1808 pPPriv->dy = drw_y; 1809 pPPriv->dw = drw_w; 1810 pPPriv->dh = drw_h; 1811 1812 if (!RemakePutCookies(pPPriv, clipBoxes)) 1813 return XvBadAlloc; 1814 1815 if (pPPriv->BuffersAllocated <= 0 || 1816 id != pPPriv->Id || /* same bpp */ 1817 width != pPPriv->fw || 1818 height != pPPriv->fh) 1819 { 1820 for (i = 0; i < ENTRIES(ScalerImages); i++) 1821 if (id == ScalerImages[i].id) 1822 break; 1823 1824 if (i >= ENTRIES(ScalerImages)) 1825 return XvBadAlloc; 1826#if 0 1827 if (pPPriv->BuffersAllocated <= 0 || 1828 pPPriv->Bpp != ScalerImages[i].bits_per_pixel || 1829 width > pPPriv->fw || height > pPPriv->fw || 1830 pPPriv->fw * pPPriv->fh > width * height * 2) 1831#else 1832 if (1) 1833#endif 1834 { 1835 Permedia2Sync(pScrn); 1836 1837 if (!AllocateBuffers(pPPriv, width, height, 1838 (ScalerImages[i].bits_per_pixel + 7) >> 3, 1, 0)) { 1839 pPPriv->Id = 0; 1840 pPPriv->Bpp = 0; 1841 pPPriv->fw = 0; 1842 pPPriv->fh = 0; 1843 1844 return XvBadAlloc; 1845 } 1846 1847 pPPriv->Id = id; 1848 pPPriv->Bpp = ScalerImages[i].bits_per_pixel; 1849 pPPriv->fw = width; 1850 pPPriv->fh = height; 1851 1852 RemoveableBuffers(pPPriv, TRUE); 1853 } else 1854 Permedia2Sync(pScrn); 1855 } else 1856 Permedia2Sync(pScrn); 1857 1858 switch (id) { 1859 case LE4CC('Y','V','1','2'): 1860 switch(pGlint->HwBpp) { 1861#if X_BYTE_ORDER == X_BIG_ENDIAN 1862 case 8: 1863 case 24: 1864 CopyYV12_8(buf, (CARD32 *)((CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0]), 1865 width, height, pPPriv->BufferStride); 1866 break; 1867 case 15: 1868 case 16: 1869 CopyYV12_16(buf, (CARD32 *)((CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0]), 1870 width, height, pPPriv->BufferStride); 1871 break; 1872#endif 1873 default: 1874 CopyYV12(buf, (CARD32 *)((CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0]), 1875 width, height, pPPriv->BufferStride); 1876 break; 1877 } 1878 PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_YUYV, 1, 0); 1879 break; 1880 1881 case LE4CC('Y','U','Y','2'): 1882 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1883 width << 1, height, pPPriv->BufferStride); 1884 PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_YUYV, 1, 0); 1885 break; 1886 1887 case LE4CC('U','Y','V','Y'): 1888 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1889 width << 1, height, pPPriv->BufferStride); 1890 PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_UYVY, 1, 0); 1891 break; 1892 1893 case LE4CC('Y','U','V','A'): 1894 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1895 width << 2, height, pPPriv->BufferStride); 1896 PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_YUVA, 2, pPPriv->Attribute[7]); 1897 break; 1898 1899 case LE4CC('V','U','Y','A'): 1900 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1901 width << 2, height, pPPriv->BufferStride); 1902 PutYUV(pPPriv, pPPriv->BufferBase[0], FORMAT_VUYA, 2, pPPriv->Attribute[7]); 1903 break; 1904 1905 case 0x41: /* RGBA 8:8:8:8 */ 1906 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1907 width << 2, height, pPPriv->BufferStride); 1908 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB8888, 2, pPPriv->Attribute[7]); 1909 break; 1910 1911 case 0x42: /* RGB 5:6:5 */ 1912 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1913 width << 1, height, pPPriv->BufferStride); 1914 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB565, 1, 0); 1915 break; 1916 1917 case 0x43: /* RGB 1:5:5:5 */ 1918 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1919 width << 1, height, pPPriv->BufferStride); 1920 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB5551, 1, pPPriv->Attribute[7]); 1921 break; 1922 1923 case 0x44: /* RGB 4:4:4:4 */ 1924 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1925 width << 1, height, pPPriv->BufferStride); 1926 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB4444, 1, pPPriv->Attribute[7]); 1927 break; 1928 1929 case 0x45: /* RGB 1:2:3:2 */ 1930 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1931 width, height, pPPriv->BufferStride); 1932 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB2321, 0, pPPriv->Attribute[7]); 1933 break; 1934 1935 case 0x46: /* RGB 2:3:3 */ 1936 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1937 width, height, pPPriv->BufferStride); 1938 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_RGB332, 0, 0); 1939 break; 1940 1941 case 0x47: /* BGRA 8:8:8:8 */ 1942 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1943 width << 2, height, pPPriv->BufferStride); 1944 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR8888, 2, pPPriv->Attribute[7]); 1945 break; 1946 1947 case 0x48: /* BGR 5:6:5 */ 1948 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1949 width << 1, height, pPPriv->BufferStride); 1950 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR565, 1, 0); 1951 break; 1952 1953 case 0x49: /* BGR 1:5:5:5 */ 1954 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1955 width << 1, height, pPPriv->BufferStride); 1956 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR5551, 1, pPPriv->Attribute[7]); 1957 break; 1958 1959 case 0x4A: /* BGR 4:4:4:4 */ 1960 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1961 width << 1, height, pPPriv->BufferStride); 1962 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR4444, 1, pPPriv->Attribute[7]); 1963 break; 1964 1965 case 0x4B: /* BGR 1:2:3:2 */ 1966 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1967 width << 0, height, pPPriv->BufferStride); 1968 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR2321, 0, pPPriv->Attribute[7]); 1969 break; 1970 1971 case 0x4C: /* BGR 2:3:3 */ 1972 CopyFlat(buf, (CARD8 *) pGlint->FbBase + pPPriv->BufferBase[0], 1973 width << 0, height, pPPriv->BufferStride); 1974 PutRGB(pPPriv, pPPriv->BufferBase[0], FORMAT_BGR332, 0, 0); 1975 break; 1976 1977 default: 1978 return XvBadAlloc; 1979 } 1980 1981 pPPriv->StopDelay = pAPriv->Delay; 1982 1983 if (!pAPriv->TimerUsers) { 1984 pAPriv->TimerUsers |= 1 << PORTNUM(pPPriv); 1985 TimerSet(pAPriv->Timer, 0, 80, TimerCallback, pAPriv); 1986 } 1987 1988 if (sync) /* sched_yield? */ 1989 Permedia2Sync(pScrn); 1990 1991 return Success; 1992} 1993 1994static void 1995Permedia2StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) 1996{ 1997 PortPrivPtr pPPriv = (PortPrivPtr) data; 1998 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 1999 GLINTPtr pGlint = GLINTPTR(pScrn); 2000 2001 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 2002 "StopVideo port=%d, shutdown=%d\n", PORTNUM(pPPriv), shutdown)); 2003 2004 if (shutdown) { 2005 if (PORTNUM(pPPriv) < 2) { 2006 StopVideoStream(pPPriv, TRUE); 2007 RestoreVideoStd(pAPriv); 2008 } else { 2009 FreeBuffers(pPPriv); 2010 FreeCookies(pPPriv); 2011 if (pAPriv->TimerUsers) { 2012 pAPriv->TimerUsers &= ~PORTNUM(pPPriv); 2013 if (!pAPriv->TimerUsers) 2014 TimerCancel(pAPriv->Timer); 2015 } 2016 } 2017 } else { 2018 pPPriv->VideoOn = VIDEO_OFF; 2019 pPPriv->StopDelay = 750; /* appx. 30 sec */ 2020 2021 if (pGlint->NoAccel) 2022 Permedia2Sync(pScrn); 2023 } 2024} 2025 2026static void 2027RestartVideo(PortPrivPtr pPPriv, int old_VideoOn) 2028{ 2029 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 2030 int new_fh; 2031 2032 if (pPPriv->VideoOn > VIDEO_OFF || 2033 pAPriv->VideoStd < 0 /* invalid */) 2034 return; 2035 2036 new_fh = InputVideoEncodings[pAPriv->VideoStd * 3].height >> 2037 (1 - (pPPriv->Attribute[4] & 1)); 2038 2039 if (new_fh != pPPriv->fh) { 2040 pPPriv->vy = (pPPriv->vy * new_fh) / pPPriv->fh; 2041 pPPriv->vh = (pPPriv->vh * new_fh) / pPPriv->fh; 2042 2043 pPPriv->fh = new_fh; 2044 } 2045 2046 if (old_VideoOn) { 2047 if (StartVideoStream(pPPriv, NULL)) { 2048 pPPriv->VideoOn = old_VideoOn; 2049 2050 if (pPPriv == &pAPriv->Port[1]) 2051 GetYUV(pPPriv); 2052 } else { 2053 DEBUG(xf86DrvMsgVerb(pAPriv->pScrn->scrnIndex, X_INFO, 4, 2054 "RestartVideo port=%d suspend\n", PORTNUM(pPPriv))); 2055 pPPriv->VideoOn = -old_VideoOn; /* suspend (not off) */ 2056 } 2057 } 2058} 2059 2060static int 2061Permedia2SetPortAttribute(ScrnInfoPtr pScrn, 2062 Atom attribute, INT32 value, pointer data) 2063{ 2064 PortPrivPtr pPPriv = (PortPrivPtr) data; 2065 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 2066 int old_VideoStd, old_Plug; 2067 int VideoStd = -1, Plug = 0; 2068 int r; 2069 2070 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 2071 "SPA attr=%d val=%d port=%d\n", 2072 attribute, value, PORTNUM(pPPriv))); 2073 2074 if (attribute == xvFilter) { 2075 pPPriv->Attribute[5] = !!value; 2076 return Success; 2077 } else if (attribute == xvAlpha) { 2078 pPPriv->Attribute[7] = !!value; 2079 return Success; 2080 } 2081 2082 if (PORTNUM(pPPriv) >= 2) 2083 return BadMatch; 2084 2085 if (attribute == xvInterlace) { 2086 int old_value = pPPriv->Attribute[4]; 2087 2088 value %= 3; 2089 2090 if (value != old_value) { 2091 int old_VideoOn = ABS(pPPriv->VideoOn); 2092#if 0 2093 if (old_VideoOn) 2094 return XvBadAlloc; 2095#endif 2096 StopVideoStream(pPPriv, FALSE); 2097 FreeBuffers(pPPriv); 2098 pPPriv->Attribute[4] = value; 2099 RestartVideo(pPPriv, old_VideoOn); 2100 2101 if (pPPriv->VideoOn < 0 /* suspended */) { 2102 pPPriv->Attribute[4] = old_value; 2103 RestartVideo(pPPriv, old_VideoOn); 2104 return XvBadAlloc; 2105 } 2106 } 2107 2108 return Success; 2109 } 2110 2111 if (pPPriv == &pAPriv->Port[0]) { 2112 /* 2113 * Input 2114 */ 2115 if (attribute == xvEncoding) { 2116 if (value < 0 || value > ENTRIES(InputVideoEncodings)) 2117 return XvBadEncoding; 2118 2119 VideoStd = value / 3; 2120 Plug = value % 3; 2121 2122 /* Fall through */ 2123 2124 } else if (attribute == xvBrightness) 2125 return SetAttr(&pAPriv->Port[0], 0, value); 2126 else if (attribute == xvContrast) 2127 return SetAttr(&pAPriv->Port[0], 1, value); 2128 else if (attribute == xvSaturation) 2129 return SetAttr(&pAPriv->Port[0], 2, value); 2130 else if (attribute == xvHue) 2131 return SetAttr(&pAPriv->Port[0], 3, value); 2132 } else { 2133 /* 2134 * Output 2135 */ 2136 if (attribute == xvEncoding) { 2137 if (value < 0 || value > ENTRIES(OutputVideoEncodings)) 2138 return XvBadEncoding; 2139 2140 VideoStd = value / 2; 2141 Plug = (value % 2) + 1; 2142 2143 /* Fall through */ 2144 2145 } else if (attribute == xvBkgColor) 2146 return SetBkgCol(pPPriv, value); 2147#if 1 2148 else if (attribute == xvBrightness || 2149 attribute == xvContrast || 2150 attribute == xvSaturation || 2151 attribute == xvHue) 2152 return Success; 2153#endif 2154 } 2155 2156 if (attribute != xvEncoding) 2157 return BadMatch; 2158 2159 old_VideoStd = pAPriv->VideoStd; 2160 old_Plug = pPPriv->Plug; 2161 2162#if 0 2163 if (pAPriv->Port[0].VideoOn || 2164 pAPriv->Port[1].VideoOn) 2165 return XvBadAlloc; 2166#endif 2167 2168 if (Plug != old_Plug) 2169 if ((r = SetPlug(pPPriv, Plug)) != Success) 2170 return r; 2171 2172 if (VideoStd != old_VideoStd) { 2173 int old_VideoOn0 = ABS(pAPriv->Port[0].VideoOn); 2174 int old_VideoOn1 = ABS(pAPriv->Port[1].VideoOn); 2175 2176 StopVideoStream(&pAPriv->Port[0], FALSE); 2177 StopVideoStream(&pAPriv->Port[1], FALSE); 2178 2179 if (VideoStd == NTSC || pAPriv->VideoStd == NTSC) { 2180 FreeBuffers(&pAPriv->Port[0]); 2181 FreeBuffers(&pAPriv->Port[1]); 2182 } 2183 2184 if (SetVideoStd(pPPriv, VideoStd) == Success) { 2185 RestartVideo(&pAPriv->Port[0], old_VideoOn0); 2186 RestartVideo(&pAPriv->Port[1], old_VideoOn1); 2187 } 2188 2189 if (pAPriv->Port[0].VideoOn < 0 || 2190 pAPriv->Port[1].VideoOn < 0 || 2191 VideoStd != pAPriv->VideoStd) { 2192 if (SetVideoStd(pPPriv, old_VideoStd) == Success) { 2193 RestartVideo(&pAPriv->Port[0], old_VideoOn0); 2194 RestartVideo(&pAPriv->Port[1], old_VideoOn1); 2195 } 2196 2197 if (Plug != old_Plug) 2198 SetPlug(pPPriv, old_Plug); 2199 2200 return XvBadAlloc; 2201 } 2202 } 2203 2204 return Success; 2205} 2206 2207static void 2208RestoreVideoStd(AdaptorPrivPtr pAPriv) 2209{ 2210 if (pAPriv->Port[0].VideoOn && !pAPriv->Port[1].VideoOn && 2211 pAPriv->Port[0].VideoStdReq != pAPriv->VideoStd) 2212 Permedia2SetPortAttribute(pAPriv->pScrn, xvEncoding, 2213 pAPriv->Port[0].VideoStdReq * 3 + pAPriv->Port[0].Plug, 2214 (pointer) &pAPriv->Port[0]); 2215 else 2216 if (pAPriv->Port[1].VideoOn && !pAPriv->Port[0].VideoOn && 2217 pAPriv->Port[1].VideoStdReq != pAPriv->VideoStd) 2218 Permedia2SetPortAttribute(pAPriv->pScrn, xvEncoding, 2219 pAPriv->Port[2].VideoStdReq * 2 + pAPriv->Port[1].Plug - 1, 2220 (pointer) &pAPriv->Port[1]); 2221} 2222 2223static int 2224Permedia2GetPortAttribute(ScrnInfoPtr pScrn, 2225 Atom attribute, INT32 *value, pointer data) 2226{ 2227 PortPrivPtr pPPriv = (PortPrivPtr) data; 2228 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 2229 2230 if (PORTNUM(pPPriv) >= 2 && 2231 attribute != xvFilter && 2232 attribute != xvAlpha) 2233 return BadMatch; 2234 2235 if (attribute == xvEncoding) { 2236 if (pAPriv->VideoStd < 0) 2237 return XvBadAlloc; 2238 else 2239 if (pPPriv == &pAPriv->Port[0]) 2240 *value = pAPriv->VideoStd * 3 + pPPriv->Plug; 2241 else 2242 *value = pAPriv->VideoStd * 2 + pPPriv->Plug - 1; 2243 } else if (attribute == xvBrightness) 2244 *value = pPPriv->Attribute[0]; 2245 else if (attribute == xvContrast) 2246 *value = pPPriv->Attribute[1]; 2247 else if (attribute == xvSaturation) 2248 *value = pPPriv->Attribute[2]; 2249 else if (attribute == xvHue) 2250 *value = pPPriv->Attribute[3]; 2251 else if (attribute == xvInterlace) 2252 *value = pPPriv->Attribute[4]; 2253 else if (attribute == xvFilter) 2254 *value = pPPriv->Attribute[5]; 2255 else if (attribute == xvBkgColor) 2256 *value = pPPriv->Attribute[6]; 2257 else if (attribute == xvAlpha) 2258 *value = pPPriv->Attribute[7]; 2259 else 2260 return BadMatch; 2261 2262 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, 2263 "GPA attr=%d val=%d port=%d\n", 2264 attribute, *value, PORTNUM(pPPriv))); 2265 2266 return Success; 2267} 2268 2269static void 2270Permedia2QueryBestSize(ScrnInfoPtr pScrn, Bool motion, 2271 short vid_w, short vid_h, short drw_w, short drw_h, 2272 unsigned int *p_w, unsigned int *p_h, pointer data) 2273{ 2274 *p_w = drw_w; 2275 *p_h = drw_h; 2276} 2277 2278static int 2279Permedia2QueryImageAttributes(ScrnInfoPtr pScrn, 2280 int id, unsigned short *width, unsigned short *height, 2281 int *pitches, int *offsets) 2282{ 2283 int i, pitch; 2284 2285 *width = CLAMP(*width, 1, 2047); 2286 *height = CLAMP(*height, 1, 2047); 2287 2288 if (offsets) 2289 offsets[0] = 0; 2290 2291 switch (id) { 2292 case LE4CC('Y','V','1','2'): /* Planar YVU 4:2:0 (emulated) */ 2293 *width = CLAMP((*width + 1) & ~1, 2, 2046); 2294 *height = CLAMP((*height + 1) & ~1, 2, 2046); 2295 2296 pitch = *width; /* luma component */ 2297 2298 if (offsets) { 2299 offsets[1] = pitch * *height; 2300 offsets[2] = offsets[1] + (offsets[1] >> 2); 2301 } 2302 2303 if (pitches) { 2304 pitches[0] = pitch; 2305 pitches[1] = pitches[2] = pitch >> 1; 2306 } 2307 2308 return pitch * *height * 3 / 2; 2309 2310 case LE4CC('Y','U','Y','2'): /* Packed YUYV 4:2:2 */ 2311 case LE4CC('U','Y','V','Y'): /* Packed UYVY 4:2:2 */ 2312 *width = CLAMP((*width + 1) & ~1, 2, 2046); 2313 2314 pitch = *width * 2; 2315 2316 if (pitches) 2317 pitches[0] = pitch; 2318 2319 return pitch * *height; 2320 2321 default: 2322 for (i = 0; i < ENTRIES(ScalerImages); i++) 2323 if (ScalerImages[i].id == id) 2324 break; 2325 2326 if (i >= ENTRIES(ScalerImages)) 2327 break; 2328 2329 pitch = *width * (ScalerImages[i].bits_per_pixel >> 3); 2330 2331 if (pitches) 2332 pitches[0] = pitch; 2333 2334 return pitch * *height; 2335 } 2336 2337 return 0; 2338} 2339 2340static void 2341RestoreVideo(AdaptorPrivPtr pAPriv) 2342{ 2343 GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn); 2344 2345 GLINT_WRITE_REG(pAPriv->dFifoControl, PMFifoControl); 2346 GLINT_WRITE_REG(0, VSABase + VSControl); 2347 GLINT_WRITE_REG(0, VSBBase + VSControl); 2348 usleep(160000); 2349 GLINT_MASK_WRITE_REG(VS_UnitMode_ROM, ~VS_UnitMode_Mask, VSConfiguration); 2350} 2351 2352static void 2353InitializeVideo(AdaptorPrivPtr pAPriv) 2354{ 2355 GLINTPtr pGlint = GLINTPTR(pAPriv->pScrn); 2356 int i; 2357 2358 GLINT_WRITE_REG(0, VSABase + VSControl); 2359 GLINT_WRITE_REG(0, VSBBase + VSControl); 2360 2361#if 0 2362 GLINT_MASK_WRITE_REG(0, ~(VSAIntFlag | VSBIntFlag), IntEnable); 2363 GLINT_WRITE_REG(VSAIntFlag | VSBIntFlag, IntFlags); /* Reset */ 2364#endif 2365 2366 for (i = 0x0018; i <= 0x00B0; i += 8) { 2367 GLINT_WRITE_REG(0, VSABase + i); 2368 GLINT_WRITE_REG(0, VSBBase + i); 2369 } 2370 2371 GLINT_WRITE_REG((0 << 8) | (132 << 0), VSABase + VSFifoControl); 2372 GLINT_WRITE_REG((0 << 8) | (132 << 0), VSBBase + VSFifoControl); 2373 2374 GLINT_MASK_WRITE_REG( 2375 VS_UnitMode_AB8 | 2376 VS_GPBusMode_A | 2377 /* VS_HRefPolarityA | */ 2378 VS_VRefPolarityA | 2379 VS_VActivePolarityA | 2380 /* VS_UseFieldA | */ 2381 VS_FieldPolarityA | 2382 /* VS_FieldEdgeA | */ 2383 /* VS_VActiveVBIA | */ 2384 VS_InterlaceA | 2385 VS_ReverseDataA | 2386 2387 /* VS_HRefPolarityB | */ 2388 VS_VRefPolarityB | 2389 VS_VActivePolarityB | 2390 /* VS_UseFieldB | */ 2391 VS_FieldPolarityB | 2392 /* VS_FieldEdgeB | */ 2393 /* VS_VActiveVBIB | */ 2394 VS_InterlaceB | 2395 /* VS_ColorSpaceB_RGB | */ 2396 /* VS_ReverseDataB | */ 2397 /* VS_DoubleEdgeB | */ 2398 0, ~0x1FFFFE0F, VSConfiguration); 2399 2400 pAPriv->dFifoControl = GLINT_READ_REG(PMFifoControl); 2401 GLINT_WRITE_REG((12 << 8) | 8, PMFifoControl); 2402} 2403 2404static Bool 2405xvipcHandshake(PortPrivPtr pPPriv, int op, Bool block) 2406{ 2407 int r; 2408 int brake = 150; 2409 2410 xvipc.magic = XVIPC_MAGIC; 2411 xvipc.op = op; 2412 xvipc.block = block; 2413 2414 if (pPPriv) { 2415 AdaptorPrivPtr pAPriv = pPPriv->pAdaptor; 2416 2417 xvipc.pm2p = pAPriv->pm2p; 2418 xvipc.pAPriv = pAPriv; 2419 xvipc.port = PORTNUM(pPPriv); 2420 } else { 2421 xvipc.pm2p = (void *) -1; 2422 xvipc.pAPriv = NULL; 2423 xvipc.port = -1; 2424 } 2425 2426 for (;;) { 2427 if (brake-- <= 0) 2428 return FALSE; /* I brake for bugs. */ 2429 2430 DEBUG(xf86MsgVerb(X_INFO, 4, 2431 "PM2 XVIPC send op=%d bl=%d po=%d a=%d b=%d c=%d\n", 2432 xvipc.op, xvipc.block, xvipc.port, xvipc.a, xvipc.b, xvipc.c)); 2433 2434 r = ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc); 2435 2436 DEBUG(xf86MsgVerb(X_INFO, 4, 2437 "PM2 XVIPC recv op=%d bl=%d po=%d a=%d b=%d c=%d err=%d/%d\n", 2438 xvipc.op, xvipc.block, xvipc.port, xvipc.a, xvipc.b, xvipc.c, r, errno)); 2439 2440 switch (xvipc.op) { 2441 case OP_ALLOC: 2442 { 2443 AdaptorPrivPtr pAPriv = xvipc.pAPriv; 2444 ScrnInfoPtr pScrn = pAPriv->pScrn; 2445 GLINTPtr pGlint = GLINTPTR(pScrn); 2446 FBAreaPtr pFBArea = NULL; 2447 LFBAreaPtr pLFBArea; 2448 2449 xvipc.a = -1; 2450 2451 pLFBArea = malloc(sizeof(LFBAreaRec)); 2452 2453 if (pLFBArea) { 2454 pLFBArea->pFBArea = pFBArea = 2455 xf86AllocateLinearOffscreenArea(pScrn->pScreen, 2456 xvipc.b >> BPPSHIFT(pGlint), 2, NULL, NULL, NULL); 2457 2458 if (pFBArea) { 2459 /* xvipc.a = pFBArea->linear; */ 2460 pLFBArea->Linear = xvipc.a = 2461 ((pFBArea->box.y1 * pScrn->displayWidth) + 2462 pFBArea->box.x1) << BPPSHIFT(pGlint); 2463 } else 2464 free(pLFBArea); 2465 } 2466 2467 /* Report results */ 2468 2469 if (ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc) != 0) 2470 if (pFBArea) { 2471 xf86FreeOffscreenArea(pFBArea); 2472 free(pLFBArea); 2473 pFBArea = NULL; 2474 } 2475 2476 if (pFBArea) { 2477 pLFBArea->Next = pAPriv->LFBList; 2478 pAPriv->LFBList = pLFBArea; 2479 } 2480 2481 DEBUG(xf86MsgVerb(X_INFO, 3, "PM2 XVIPC alloc addr=%d=0x%08x pFB=%p\n", 2482 xvipc.a, xvipc.a, pFBArea)); 2483 2484 goto event; 2485 } 2486 2487 case OP_FREE: 2488 { 2489 AdaptorPrivPtr pAPriv = xvipc.pAPriv; 2490 LFBAreaPtr pLFBArea, *ppLFBArea; 2491 2492 for (ppLFBArea = &pAPriv->LFBList; (pLFBArea = *ppLFBArea); 2493 ppLFBArea = &pLFBArea->Next) 2494 if (pLFBArea->Linear == xvipc.a) 2495 break; 2496 2497 if (!pLFBArea) 2498 xvipc.a = -1; 2499 2500 DEBUG(xf86MsgVerb(X_INFO, 3, "PM2 XVIPC free addr=%d=0x%08x pFB=%p\n", 2501 xvipc.a, xvipc.a, pLFBArea ? pLFBArea->pFBArea : NULL)); 2502 2503 if (ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc) == 0 && pLFBArea) { 2504 xf86FreeOffscreenArea(pLFBArea->pFBArea); 2505 *ppLFBArea = pLFBArea->Next; 2506 free(pLFBArea); 2507 } 2508 2509 goto event; 2510 } 2511 2512 case OP_UPDATE: 2513 { 2514 AdaptorPrivPtr pAPriv = xvipc.pAPriv; 2515 PortPrivPtr pPPriv; 2516 2517 pPPriv = &pAPriv->Port[0]; 2518 2519 if (pPPriv->VideoOn > VIDEO_OFF && xvipc.a > 0) { 2520 pPPriv->FrameAcc += pPPriv->FramesPerSec; 2521 if (pPPriv->FrameAcc >= pAPriv->FramesPerSec) { 2522 pPPriv->FrameAcc -= pAPriv->FramesPerSec; 2523 2524 /* Asynchronous resizing caused by kernel app */ 2525 2526 if (xvipc.c != pPPriv->fw || 2527 xvipc.d != pPPriv->fh) { 2528 pPPriv->vx = (pPPriv->vx * xvipc.c) / pPPriv->fw; 2529 pPPriv->vw = (pPPriv->vw * xvipc.c) / pPPriv->fw; 2530 pPPriv->vy = (pPPriv->vy * xvipc.d) / pPPriv->fh; 2531 pPPriv->vh = (pPPriv->vh * xvipc.d) / pPPriv->fh; 2532 2533 pPPriv->fw = xvipc.c; 2534 pPPriv->fh = xvipc.d; 2535 pPPriv->BufferPProd = xvipc.e; 2536 2537 RemakePutCookies(pPPriv, NULL); 2538 } 2539 2540 PutYUV(pPPriv, xvipc.a, FORMAT_YUYV, 1, 0); 2541 2542 if (pPPriv->VideoOn == VIDEO_ONE_SHOT) 2543 pPPriv->VideoOn = VIDEO_OFF; 2544 } 2545 } else 2546 if (pPPriv->StopDelay >= 0 && !(pPPriv->StopDelay--)) { 2547 StopVideoStream(pPPriv, TRUE); 2548 RestoreVideoStd(pAPriv); 2549 } 2550 2551 pPPriv = &pAPriv->Port[1]; 2552 2553 if (pPPriv->VideoOn > VIDEO_OFF && xvipc.b > 0) { 2554 pPPriv->FrameAcc += pPPriv->FramesPerSec; 2555 if (pPPriv->FrameAcc >= pAPriv->FramesPerSec) { 2556 pPPriv->FrameAcc -= pAPriv->FramesPerSec; 2557 2558 pPPriv->BufferBase[0] = xvipc.b; 2559 2560 /* Output is always exclusive, no async resizing */ 2561 2562 GetYUV(pPPriv); 2563 2564 if (pPPriv->VideoOn == VIDEO_ONE_SHOT) 2565 pPPriv->VideoOn = VIDEO_OFF; 2566 } 2567 } else 2568 if (pPPriv->StopDelay >= 0 && !(pPPriv->StopDelay--)) { 2569 StopVideoStream(pPPriv, TRUE); 2570 RestoreVideoStd(pAPriv); 2571 } 2572 2573 /* Fall through */ 2574 } 2575 2576 default: 2577 event: 2578 if (xvipc.op == op) 2579 return r == 0; 2580 2581 xvipc.op = OP_EVENT; 2582 xvipc.block = block; 2583 } 2584 } 2585 2586 return TRUE; 2587} 2588 2589static void 2590Permedia2ReadInput(int fd, pointer unused) 2591{ 2592 xvipcHandshake(NULL, OP_EVENT, FALSE); 2593} 2594 2595static Bool 2596xvipcOpen(const char *name, ScrnInfoPtr pScrn) 2597{ 2598#ifdef __linux__ 2599 if (xvipc_fd >= 0) 2600 return TRUE; 2601 2602 for (;;) { 2603 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, 2604 "XVIPC probing device %s\n", name)); 2605 2606 if ((xvipc_fd = open(name, O_RDWR /* | O_TRUNC */, 0)) < 0) 2607 break; 2608 2609 xvipc.magic = XVIPC_MAGIC; 2610 xvipc.pm2p = (void *) -1; 2611 xvipc.pAPriv = NULL; 2612 xvipc.op = OP_CONNECT; 2613 xvipc.a = 0; 2614 xvipc.b = 0; 2615 xvipc.c = 0; 2616 xvipc.d = 0; 2617 2618 if (ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc) < 0 || xvipc.pm2p) 2619 break; 2620 2621 if (xvipc.c != XVIPC_VERSION) { 2622 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2623 "Your Permedia 2 kernel driver %d.%d uses XVIPC protocol " 2624 "V.%d while this Xv driver expects V.%d. Please update.\n", 2625 xvipc.a, xvipc.b, xvipc.c, XVIPC_VERSION); 2626 break; 2627 } 2628 2629 xf86AddInputHandler(xvipc_fd, Permedia2ReadInput, NULL); 2630 2631 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv driver opened %s\n", name); 2632 2633 return TRUE; 2634 } 2635 2636 if (xvipc_fd >= 0) 2637 close(xvipc_fd); 2638 2639 xvipc_fd = -1; 2640 2641 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cannot find Permedia 2 kernel driver.\n"); 2642#endif 2643 2644 return FALSE; 2645} 2646 2647static void 2648DeleteAdaptorPriv(AdaptorPrivPtr pAPriv) 2649{ 2650 int i; 2651 2652 if (pAPriv->VideoIO) { 2653 StopVideoStream(&pAPriv->Port[0], TRUE); 2654 StopVideoStream(&pAPriv->Port[1], TRUE); 2655 } 2656 2657 for (i = 0; i < 6; i++) { 2658 FreeBuffers(&pAPriv->Port[i]); 2659 FreeCookies(&pAPriv->Port[i]); 2660 } 2661 2662 TimerFree(pAPriv->Timer); 2663 2664 if (pAPriv->VideoIO) { 2665 if (pAPriv->pm2p) 2666 xvipcHandshake(&pAPriv->Port[0], OP_DISCONNECT, TRUE); 2667 else { 2668 xf86DestroyI2CDevRec(&pAPriv->Port[0].I2CDev, FALSE); 2669 xf86DestroyI2CDevRec(&pAPriv->Port[1].I2CDev, FALSE); 2670 2671 RestoreVideo(pAPriv); 2672 } 2673 } 2674 2675 free(pAPriv); 2676} 2677 2678static AdaptorPrivPtr 2679NewAdaptorPriv(ScrnInfoPtr pScrn, Bool VideoIO) 2680{ 2681 GLINTPtr pGlint = GLINTPTR(pScrn); 2682 AdaptorPrivPtr pAPriv = (AdaptorPrivPtr) calloc(1, sizeof(AdaptorPrivRec)); 2683 int i; 2684 2685 if (!pAPriv) 2686 return NULL; 2687 2688 pAPriv->pScrn = pScrn; 2689 2690 for (i = 0; i < PORTS; i++) 2691 pAPriv->Port[i].pAdaptor = pAPriv; 2692 2693 switch (pScrn->depth) { 2694 case 8: 2695 pAPriv->dDitherMode = 2696 (0 << 10) | /* BGR */ 2697 (1 << 1) | /* Dither */ 2698 ((5 & 0x10) << 12) | 2699 ((5 & 0x0F) << 2) | /* 3:3:2f */ 2700 UNIT_ENABLE; 2701 pAPriv->dAlphaBlendMode = 2702 (0 << 13) | 2703 ((5 & 0x10) << 12) | 2704 ((5 & 0x0F) << 8) | 2705 (84 << 1) | /* Blend (decal) RGB */ 2706 UNIT_ENABLE; 2707 pAPriv->dTextureDataFormat = 2708 (1 << 4) | /* No alpha */ 2709 ((14 & 0x10) << 2) | 2710 ((14 & 0x0F) << 0); /* CI8 */ 2711 break; 2712 2713 case 15: 2714 pAPriv->dDitherMode = 2715 (1 << 10) | /* RGB */ 2716 ((1 & 0x10) << 12) | 2717 ((1 & 0x0F) << 2) | /* 5:5:5:1f */ 2718 UNIT_ENABLE; 2719 pAPriv->dAlphaBlendMode = 2720 (1 << 13) | 2721 ((1 & 0x10) << 12) | 2722 ((1 & 0x0F) << 8) | 2723 (84 << 1) | 2724 UNIT_ENABLE; 2725 pAPriv->dTextureDataFormat = 2726 (1 << 5) | /* RGB */ 2727 (1 << 4) | 2728 ((1 & 0x10) << 2) | 2729 ((1 & 0x0F) << 0); 2730 break; 2731 2732 case 16: 2733 pAPriv->dDitherMode = 2734 (1 << 10) | /* RGB */ 2735 ((16 & 0x10) << 12) | 2736 ((16 & 0x0F) << 2) | /* 5:6:5f */ 2737 UNIT_ENABLE; 2738 pAPriv->dAlphaBlendMode = 2739 (1 << 13) | 2740 ((16 & 0x10) << 12) | 2741 ((16 & 0x0F) << 8) | 2742 (84 << 1) | 2743 UNIT_ENABLE; 2744 pAPriv->dTextureDataFormat = 2745 (1 << 5) | 2746 (1 << 4) | 2747 ((16 & 0x10) << 2) | 2748 ((16 & 0x0F) << 0); 2749 break; 2750 2751 case 24: 2752 pAPriv->dDitherMode = 2753 (1 << 10) | /* RGB */ 2754 ((0 & 0x10) << 12) | 2755 ((0 & 0x0F) << 2) | /* 8:8:8:8 */ 2756 UNIT_ENABLE; 2757 pAPriv->dAlphaBlendMode = 2758 (1 << 13) | 2759 ((0 & 0x10) << 12) | 2760 ((0 & 0x0F) << 8) | 2761 (84 << 1) | 2762 UNIT_ENABLE; 2763 pAPriv->dTextureDataFormat = 2764 (1 << 5) | 2765 (1 << 4) | 2766 ((0 & 0x10) << 2) | 2767 ((0 & 0x0F) << 0); 2768 break; 2769 2770 default: 2771 free(pAPriv); 2772 return NULL; 2773 } 2774 2775 pAPriv->VideoIO = VideoIO; 2776 2777 if (VideoIO) { 2778 if (xvipc_fd >= 0) { 2779 /* Initial handshake, take over control of this head */ 2780 2781 xvipc.magic = XVIPC_MAGIC; 2782 xvipc.pm2p = (void *) -1; /* Kernel head ID */ 2783 xvipc.pAPriv = pAPriv; /* Server head ID */ 2784 xvipc.op = OP_CONNECT; 2785 2786 xvipc.a = PCI_DEV_BUS(pGlint->PciInfo); 2787 xvipc.b = PCI_DEV_DEV(pGlint->PciInfo); 2788 xvipc.c = PCI_DEV_FUNC(pGlint->PciInfo); 2789 2790 xvipc.d = pScrn->videoRam << 10; /* XF86Config overrides probing */ 2791 2792 if (ioctl(xvipc_fd, VIDIOC_PM2_XVIPC, (void *) &xvipc) < 0) { 2793 if (errno == EBUSY) 2794 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2795 "Another application already opened the Permedia 2 " 2796 "kernel driver for this board. To enable " 2797 "shared access please start the server first.\n"); 2798 else 2799 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2800 "Failed to initialize kernel backbone " 2801 "due to error %d: %s.\n", errno, strerror(errno)); 2802 goto failed; 2803 } 2804 2805 pAPriv->pm2p = xvipc.pm2p; 2806 } else { 2807 InitializeVideo(pAPriv); 2808 2809 if (!xf86I2CProbeAddress(pGlint->VSBus, SAA7111_SLAVE_ADDRESS)) 2810 goto failed; 2811 2812 pAPriv->Port[0].I2CDev.DevName = "Decoder SAA 7111A"; 2813 pAPriv->Port[0].I2CDev.SlaveAddr = SAA7111_SLAVE_ADDRESS; 2814 pAPriv->Port[0].I2CDev.pI2CBus = pGlint->VSBus; 2815 2816 if (!xf86I2CDevInit(&pAPriv->Port[0].I2CDev)) 2817 goto failed; 2818 2819 if (!xf86I2CWriteVec(&pAPriv->Port[0].I2CDev, DecInitVec, ENTRIES(DecInitVec) / 2)) 2820 goto failed; 2821 2822 if (!xf86I2CProbeAddress(pGlint->VSBus, SAA7125_SLAVE_ADDRESS)) 2823 goto failed; 2824 2825 pAPriv->Port[1].I2CDev.DevName = "Encoder SAA 7125"; 2826 pAPriv->Port[1].I2CDev.SlaveAddr = SAA7125_SLAVE_ADDRESS; 2827 pAPriv->Port[1].I2CDev.pI2CBus = pGlint->VSBus; 2828 2829 if (!xf86I2CDevInit(&pAPriv->Port[1].I2CDev)) 2830 goto failed; 2831 2832 if (!xf86I2CWriteVec(&pAPriv->Port[1].I2CDev, EncInitVec, ENTRIES(EncInitVec) / 2)) 2833 goto failed; 2834 } 2835 2836 if (SetVideoStd(&pAPriv->Port[0], PAL) != Success || 2837 SetPlug(&pAPriv->Port[0], 0) != Success || /* composite */ 2838 SetPlug(&pAPriv->Port[1], 1) != Success) /* composite-adaptor */ 2839 goto failed; 2840 2841 pAPriv->Port[1].VideoStdReq = pAPriv->Port[0].VideoStdReq; 2842 2843 pAPriv->Port[0].BuffersRequested = 2; 2844 pAPriv->Port[1].BuffersRequested = 1; 2845 2846 for (i = 0; i < 2; i++) { 2847 pAPriv->Port[i].fw = 704; 2848 pAPriv->Port[i].fh = 576; 2849 pAPriv->Port[i].FramesPerSec = 30; 2850 pAPriv->Port[i].BufferPProd = partprodPermedia[704 >> 5]; 2851 } 2852 2853 SetAttr(&pAPriv->Port[0], 0, 0); /* Brightness (-1000..+1000) */ 2854 SetAttr(&pAPriv->Port[0], 1, 0); /* Contrast (-3000..+1000) */ 2855 SetAttr(&pAPriv->Port[0], 2, 0); /* Color saturation (-3000..+1000) */ 2856 SetAttr(&pAPriv->Port[0], 3, 0); /* Hue (-1000..+1000) */ 2857 2858 pAPriv->Port[0].Attribute[4] = 1; /* Interlaced (0 = not, 1 = yes, 2859 2 = double scan 50/60 Hz) */ 2860 pAPriv->Port[0].Attribute[5] = 0; /* Bilinear Filter (Bool) */ 2861 2862 pAPriv->Port[1].Attribute[4] = 1; /* Interlaced (Bool) */ 2863 pAPriv->Port[1].Attribute[5] = 0; /* Bilinear Filter (Bool) */ 2864 2865 SetBkgCol(&pAPriv->Port[1], 0x000000); /* BkgColor 0x00RRGGBB */ 2866 } /* VideoIO */ 2867 2868 if (!(pAPriv->Timer = TimerSet(NULL, 0, 0, TimerCallback, pAPriv))) 2869 goto failed; 2870 2871 for (i = 0; i < PORTS; i++) 2872 pAPriv->Port[i].StopDelay = -1; 2873 2874 /* Frontend scaler */ 2875 2876 for (i = 2; i < 6; i++) { 2877 pAPriv->Port[i].fw = 0; 2878 pAPriv->Port[i].fh = 0; 2879 pAPriv->Port[i].BuffersRequested = 1; 2880 pAPriv->Delay = 125; 2881 pAPriv->Instant = 1000 / 25; 2882 2883 if (!VideoIO || pAPriv->pm2p) { 2884 pAPriv->Delay = 5; 2885 pAPriv->Instant = 1000; 2886 } 2887 2888 pAPriv->Port[i].Attribute[5] = 0; /* Bilinear Filter (Bool) */ 2889 pAPriv->Port[i].Attribute[7] = 0; /* Alpha Enable (Bool) */ 2890 } 2891 2892 return pAPriv; 2893 2894failed: 2895 2896 DeleteAdaptorPriv(pAPriv); 2897 2898 return NULL; 2899} 2900 2901 2902/* 2903 * Glint interface 2904 */ 2905 2906void 2907Permedia2VideoEnterVT(ScrnInfoPtr pScrn) 2908{ 2909 GLINTPtr pGlint = GLINTPTR(pScrn); 2910 AdaptorPrivPtr pAPriv; 2911 2912 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv enter VT\n")); 2913 2914 for (pAPriv = AdaptorPrivList; pAPriv != NULL; pAPriv = pAPriv->Next) 2915 if (pAPriv->pScrn == pScrn) { 2916 if (pAPriv->VideoIO) { 2917 if (pAPriv->pm2p) 2918 xvipcHandshake(&pAPriv->Port[0], OP_ENTER, TRUE); 2919 else { 2920 InitializeVideo(pAPriv); 2921 2922 xf86I2CWriteVec(&pAPriv->Port[1].I2CDev, EncInitVec, ENTRIES(EncInitVec) / 2); 2923 } 2924 2925 SetVideoStd(&pAPriv->Port[0], pAPriv->VideoStd); 2926 SetPlug(&pAPriv->Port[0], pAPriv->Port[0].Plug); 2927 SetPlug(&pAPriv->Port[1], pAPriv->Port[1].Plug); 2928 } 2929 2930 if (pGlint->NoAccel) 2931 Permedia2InitializeEngine(pScrn); 2932 2933 break; 2934 } 2935} 2936 2937void 2938Permedia2VideoLeaveVT(ScrnInfoPtr pScrn) 2939{ 2940 AdaptorPrivPtr pAPriv; 2941 2942 for (pAPriv = AdaptorPrivList; pAPriv != NULL; pAPriv = pAPriv->Next) 2943 if (pAPriv->pScrn == pScrn) { 2944 if (pAPriv->VideoIO) { 2945 StopVideoStream(&pAPriv->Port[0], TRUE); 2946 StopVideoStream(&pAPriv->Port[1], TRUE); 2947 2948 if (pAPriv->pm2p) 2949 xvipcHandshake(&pAPriv->Port[0], OP_LEAVE, TRUE); 2950 else 2951 RestoreVideo(pAPriv); 2952 } 2953 break; 2954 } 2955 2956 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Elvis left the building\n")); 2957} 2958 2959void 2960Permedia2VideoUninit(ScrnInfoPtr pScrn) 2961{ 2962 AdaptorPrivPtr pAPriv, *ppAPriv; 2963 2964 for (ppAPriv = &AdaptorPrivList; (pAPriv = *ppAPriv); ppAPriv = &(pAPriv->Next)) 2965 if (pAPriv->pScrn == pScrn) { 2966 *ppAPriv = pAPriv->Next; 2967 DeleteAdaptorPriv(pAPriv); 2968 break; 2969 } 2970 2971 if (xvipc_fd >= 0) { 2972 close(xvipc_fd); 2973 xvipc_fd = -1; 2974 } 2975 2976 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "Xv cleanup\n")); 2977} 2978 2979void 2980Permedia2VideoInit(ScreenPtr pScreen) 2981{ 2982 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2983 GLINTPtr pGlint = GLINTPTR(pScrn); 2984 AdaptorPrivPtr pAPriv; 2985 DevUnion Private[PORTS]; 2986 XF86VideoAdaptorRec VAR[ADAPTORS]; 2987 XF86VideoAdaptorPtr VARPtrs[ADAPTORS]; 2988 Bool VideoIO = TRUE; 2989 int i; 2990 /* Glint is still intializing, so pGlint->Options is off-limits. */ 2991 OptionInfoPtr VidOpts; 2992 2993 switch (pGlint->Chipset) { 2994 case PCI_VENDOR_TI_CHIP_PERMEDIA2: 2995 case PCI_VENDOR_3DLABS_CHIP_PERMEDIA2: 2996 case PCI_VENDOR_3DLABS_CHIP_PERMEDIA2V: 2997 break; 2998 2999 default: 3000 return; 3001 } 3002 3003 xf86CollectOptions(pScrn, NULL); 3004 /* Process the options */ 3005 if (!(VidOpts = malloc(sizeof(pm2Options)))) 3006 return; 3007 3008 memcpy(VidOpts, pm2Options, sizeof(pm2Options)); 3009 3010 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, VidOpts); 3011 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 3012 3013 /* Don't complain about no Xv support unless they asked for Xv support. 3014 Assume they want Xv if OPTION_DEVICE is set, since that's required. */ 3015 if (xf86IsOptionSet(VidOpts, OPTION_DEVICE)) { 3016 unsigned int temp; 3017 PCI_READ_LONG(pGlint->PciInfo, &temp, PCI_SUBSYSTEM_ID_REG); 3018 switch (temp) { 3019 case PCI_SUBSYSTEM_ID_WINNER_2000_P2A: 3020 case PCI_SUBSYSTEM_ID_WINNER_2000_P2C: 3021 case PCI_SUBSYSTEM_ID_GLORIA_SYNERGY_P2A: 3022 case PCI_SUBSYSTEM_ID_GLORIA_SYNERGY_P2C: 3023 break; 3024 default: 3025 VideoIO = FALSE; 3026 xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 1, "No Xv vio support for this board\n"); 3027 } 3028 } 3029 else 3030 /* Assume they don't, even if other options are set. */ 3031 VideoIO = FALSE; 3032 3033 if (pGlint->NoAccel && !VideoIO) { 3034 free(VidOpts); 3035 return; 3036 } 3037 3038 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 1, "Initializing Xv driver rev. 4\n"); 3039 3040 if (VideoIO) { 3041 if (!xvipcOpen(xf86GetOptValString(VidOpts, OPTION_DEVICE), pScrn)) 3042 VideoIO = FALSE; 3043 } 3044 3045 if (!(pAPriv = NewAdaptorPriv(pScrn, VideoIO))) { 3046 free(VidOpts); 3047 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv driver initialization failed\n"); 3048 return; 3049 } 3050 3051 if (VideoIO) { 3052 int n; 3053 3054 if (xf86GetOptValInteger(VidOpts, OPTION_IN_BUFFERS, &n)) 3055 pAPriv->Port[0].BuffersRequested = CLAMP(n, 1, 2); 3056 if (xf86GetOptValInteger(VidOpts, OPTION_IN_FPS, &n)) 3057 pAPriv->Port[0].FramesPerSec = CLAMP(n, 1, 30); 3058 3059 if (xf86GetOptValInteger(VidOpts, OPTION_OUT_BUFFERS, &n)) 3060 pAPriv->Port[1].BuffersRequested = 1; 3061 if (xf86GetOptValInteger(VidOpts, OPTION_OUT_FPS, &n)) 3062 pAPriv->Port[1].FramesPerSec = CLAMP(n, 1, 30); 3063 } 3064 3065 if (pGlint->NoAccel) { 3066 BoxRec AvailFBArea; 3067 3068 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Xv driver overrides NoAccel option\n"); 3069 3070 Permedia2InitializeEngine(pScrn); 3071 3072 AvailFBArea.x1 = 0; 3073 AvailFBArea.y1 = 0; 3074 AvailFBArea.x2 = pScrn->displayWidth; 3075 AvailFBArea.y2 = pGlint->FbMapSize / 3076 (pScrn->displayWidth * pScrn->bitsPerPixel / 8); 3077 3078 xf86InitFBManager(pScreen, &AvailFBArea); 3079 } 3080 3081#if defined(XFree86LOADER) && 0 3082 if (xf86LoaderCheckSymbol("xf86InitLinearFBManagerRegion")) { 3083 int last = pGlint->FbMapSize / (pScrn->bitsPerPixel / 8) - 1; 3084 BoxRec AvailFBArea; 3085 RegionPtr Region; 3086 3087 AvailFBArea.x1 = 0; 3088 AvailFBArea.y1 = pScrn->virtualY; 3089 AvailFBArea.x2 = last % pScrn->displayWidth + 1; 3090 AvailFBArea.y2 = last / pScrn->displayWidth + 1; 3091 3092 DEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, 3093 "Using linear FB %d,%d-%d,%d pitch %d (%dk)\n", 3094 AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, AvailFBArea.y2, 3095 pScrn->displayWidth, (((AvailFBArea.y2 - AvailFBArea.y1) 3096 * pScrn->displayWidth) << BPPSHIFT(pGlint)) / 1024)); 3097 3098 Region = xf86LinearFBRegion(pScreen, &AvailFBArea, pScrn->displayWidth); 3099 xf86InitLinearFBManagerRegion(pScreen, Region); 3100 REGION_DESTROY(pScreen, Region); 3101 } 3102#endif 3103 3104 memset(VAR, 0, sizeof(VAR)); 3105 3106 for (i = 0; i < PORTS; i++) 3107 Private[i].ptr = (pointer) &pAPriv->Port[i]; 3108 3109 for (i = 0; i < ADAPTORS; i++) { 3110 VARPtrs[i] = &VAR[i]; 3111 switch (i) { 3112 case 0: 3113 VAR[i].name = "Permedia 2 Video Input"; 3114 VAR[i].type = XvInputMask | XvWindowMask | XvVideoMask | XvStillMask; 3115 VAR[i].nPorts = 1; 3116 VAR[i].pPortPrivates = &Private[0]; 3117 VAR[i].nAttributes = ENTRIES(InputVideoAttributes); 3118 VAR[i].pAttributes = InputVideoAttributes; 3119 VAR[i].nEncodings = ENTRIES(InputVideoEncodings); 3120 VAR[i].pEncodings = InputVideoEncodings; 3121 VAR[i].nFormats = ENTRIES(InputVideoFormats); 3122 VAR[i].pFormats = InputVideoFormats; 3123 break; 3124 3125 case 1: 3126 VAR[i].name = "Permedia 2 Video Output"; 3127 VAR[i].type = XvOutputMask | XvWindowMask | XvVideoMask | XvStillMask; 3128 VAR[i].nPorts = 1; 3129 VAR[i].pPortPrivates = &Private[1]; 3130 VAR[i].nAttributes = ENTRIES(OutputVideoAttributes); 3131 VAR[i].pAttributes = OutputVideoAttributes; 3132 VAR[i].nEncodings = ENTRIES(OutputVideoEncodings); 3133 VAR[i].pEncodings = OutputVideoEncodings; 3134 VAR[i].nFormats = ENTRIES(OutputVideoFormats); 3135 VAR[i].pFormats = OutputVideoFormats; 3136 break; 3137 3138 case 2: 3139 VAR[i].name = "Permedia 2 Frontend Scaler"; 3140 VAR[i].type = XvInputMask | XvWindowMask | XvImageMask; 3141 VAR[i].nPorts = 3; 3142 VAR[i].pPortPrivates = &Private[2]; 3143 VAR[i].nAttributes = ENTRIES(ScalerAttributes); 3144 VAR[i].pAttributes = ScalerAttributes; 3145 VAR[i].nEncodings = ENTRIES(ScalerEncodings); 3146 VAR[i].pEncodings = ScalerEncodings; 3147 VAR[i].nFormats = ENTRIES(ScalerVideoFormats); 3148 VAR[i].pFormats = ScalerVideoFormats; 3149 VAR[i].nImages = ENTRIES(ScalerImages); 3150 VAR[i].pImages = ScalerImages; 3151 break; 3152 } 3153 3154 VAR[i].PutVideo = Permedia2PutVideo; 3155 VAR[i].PutStill = Permedia2PutStill; 3156 VAR[i].GetVideo = Permedia2GetVideo; 3157 VAR[i].GetStill = Permedia2GetStill; 3158 VAR[i].StopVideo = Permedia2StopVideo; 3159 VAR[i].SetPortAttribute = Permedia2SetPortAttribute; 3160 VAR[i].GetPortAttribute = Permedia2GetPortAttribute; 3161 VAR[i].QueryBestSize = Permedia2QueryBestSize; 3162 VAR[i].PutImage = Permedia2PutImage; 3163 VAR[i].QueryImageAttributes = Permedia2QueryImageAttributes; 3164 } 3165 3166 if (VideoIO ? xf86XVScreenInit(pScreen, &VARPtrs[0], 3) : 3167 xf86XVScreenInit(pScreen, &VARPtrs[2], 1)) { 3168 const char *s; 3169 3170 xvEncoding = MAKE_ATOM(XV_ENCODING); 3171 xvHue = MAKE_ATOM(XV_HUE); 3172 xvSaturation = MAKE_ATOM(XV_SATURATION); 3173 xvBrightness = MAKE_ATOM(XV_BRIGHTNESS); 3174 xvContrast = MAKE_ATOM(XV_CONTRAST); 3175 xvInterlace = MAKE_ATOM(XV_INTERLACE); 3176 xvFilter = MAKE_ATOM(XV_FILTER); 3177 xvBkgColor = MAKE_ATOM(XV_BKGCOLOR); 3178 xvAlpha = MAKE_ATOM(XV_ALPHA); 3179 3180 pAPriv->Next = AdaptorPrivList; 3181 AdaptorPrivList = pAPriv; 3182 3183 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv frontend scaler enabled\n"); 3184 3185 if (VideoIO) { 3186 if ((s = xf86GetOptValString(VidOpts, OPTION_IN_ENCODING))) 3187 for (i = 0; i < ENTRIES(InputVideoEncodings); i++) 3188 if (!strncmp(s, InputVideoEncodings[i].name, strlen(s))) { 3189 Permedia2SetPortAttribute(pScrn, xvEncoding, i, (pointer) &pAPriv->Port[0]); 3190 break; 3191 } 3192 3193 if ((s = xf86GetOptValString(VidOpts, OPTION_OUT_ENCODING))) 3194 for (i = 0; i < ENTRIES(OutputVideoEncodings); i++) 3195 if (!strncmp(s, OutputVideoEncodings[i].name, strlen(s))) { 3196 Permedia2SetPortAttribute(pScrn, xvEncoding, i, (pointer) &pAPriv->Port[1]); 3197 break; 3198 } 3199 3200 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv vio driver %senabled\n", 3201 pAPriv->pm2p ? "with kernel backbone " : ""); 3202 } 3203 } else { 3204 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Xv initialization failed\n"); 3205 DeleteAdaptorPriv(pAPriv); 3206 } 3207 3208 free(VidOpts); 3209} 3210