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