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