1 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis6326_video.c,v 1.9 2003/08/07 12:52:23 twini Exp $ */
3 * Xv driver for SiS 5597/5598, 6236 and 530/620.
5 * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria.
7 * Based on sis_video.c which is
8 * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria.
10 * Permission to use, copy, modify, distribute, and sell this software and its
11 * documentation for any purpose is hereby granted without fee, provided that
12 * the above copyright notice appear in all copies and that both that
13 * copyright notice and this permission notice appear in supporting
14 * documentation, and that the name of the copyright holder not be used in
15 * advertising or publicity pertaining to distribution of the software without
16 * specific, written prior permission. The copyright holder makes no representations
17 * about the suitability of this software for any purpose. It is provided
18 * "as is" without express or implied warranty.
20 * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
22 * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
23 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
24 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
25 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26 * PERFORMANCE OF THIS SOFTWARE.
28 * Author: Thomas Winischhofer <thomas@winischhofer.net>
34 #include "xf86_OSproc.h"
35 #include "xf86Resources.h"
36 #include "xf86_ansic.h"
38 #include "xf86PciInfo.h"
40 #include "xf86fbman.h"
41 #include "regionstr.h"
47 #include "dixstruct.h"
52 #define OFF_DELAY 200 /* milliseconds */
53 #define FREE_DELAY 60000
55 #define OFF_TIMER 0x01
56 #define FREE_TIMER 0x02
57 #define CLIENT_VIDEO_ON 0x04
59 #define TIMER_MASK (OFF_TIMER | FREE_TIMER)
61 #define WATCHDOG_DELAY 500000 /* Watchdog counter for Vertical Restrace waiting */
63 static XF86VideoAdaptorPtr
SIS6326SetupImageVideo(ScreenPtr
);
64 static void SIS6326StopVideo(ScrnInfoPtr
, pointer
, Bool
);
65 static int SIS6326SetPortAttribute(ScrnInfoPtr
, Atom
, INT32
, pointer
);
66 static int SIS6326GetPortAttribute(ScrnInfoPtr
, Atom
,INT32
*, pointer
);
67 static void SIS6326QueryBestSize(ScrnInfoPtr
, Bool
, short, short, short,
68 short, unsigned int *,unsigned int *, pointer
);
69 static int SIS6326PutImage( ScrnInfoPtr
,
70 short, short, short, short, short, short, short, short,
71 int, unsigned char*, short, short, Bool
, RegionPtr
, pointer
);
72 static int SIS6326QueryImageAttributes(ScrnInfoPtr
,
73 int, unsigned short *, unsigned short *, int *, int *);
74 static void SIS6326VideoTimerCallback(ScrnInfoPtr pScrn
, Time now
);
75 static void SIS6326InitOffscreenImages(ScreenPtr pScrn
);
77 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
79 static Atom xvBrightness
, xvContrast
, xvColorKey
;
80 static Atom xvAutopaintColorKey
, xvSetDefaults
;
81 static Atom xvDisableGfx
;
83 #define IMAGE_MIN_WIDTH 32 /* Minimum and maximum image sizes */
84 #define IMAGE_MIN_HEIGHT 24
85 #define IMAGE_MAX_WIDTH 720 /* Are these correct for the chips ? */
86 #define IMAGE_MAX_HEIGHT 576
87 #define IMAGE_MAX_WIDTH_5597 384
88 #define IMAGE_MAX_HEIGHT_5597 288
91 static int oldH
, oldW
;
94 /****************************************************************************
95 * Raw register access : These routines directly interact with the sis's
96 * control aperature. Must not be called until after
97 * the board's pci memory has been mapped.
98 ****************************************************************************/
101 static CARD32
_sisread(SISPtr pSiS
, CARD32 reg
)
103 return *(pSiS
->IOBase
+ reg
);
106 static void _siswrite(SISPtr pSiS
, CARD32 reg
, CARD32 data
)
108 *(pSiS
->IOBase
+ reg
) = data
;
112 static CARD8
getvideoreg(SISPtr pSiS
, CARD8 reg
)
115 inSISIDXREG(SISCR
, reg
, ret
);
119 static __inline
void setvideoreg(SISPtr pSiS
, CARD8 reg
, CARD8 data
)
121 outSISIDXREG(SISCR
, reg
, data
);
124 static void setvideoregmask(SISPtr pSiS
, CARD8 reg
, CARD8 data
, CARD8 mask
)
128 inSISIDXREG(SISCR
, reg
, old
);
129 data
= (data
& mask
) | (old
& (~mask
));
130 outSISIDXREG(SISCR
, reg
, data
);
134 static CARD8
vblank_active_CRT1(SISPtr pSiS
)
136 return (inSISREG(SISINPSTAT
) & 0x08);
139 /* Scanline - unused */
141 static CARD32
get_scanline_CRT1(SISPtr pSiS
)
145 temp
= getvideoreg(pSiS
, 0x20);
146 temp
= getvideoreg(pSiS
, 0x1b);
147 return((getvideoreg(pSiS
, 0x1d) << 8) | getvideoreg(pSiS
, 0x1c));
151 void SIS6326InitVideo(ScreenPtr pScreen
)
153 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
154 XF86VideoAdaptorPtr
*adaptors
, *newAdaptors
= NULL
;
155 XF86VideoAdaptorPtr newAdaptor
= NULL
;
158 newAdaptor
= SIS6326SetupImageVideo(pScreen
);
160 SIS6326InitOffscreenImages(pScreen
);
162 num_adaptors
= xf86XVListGenericAdaptors(pScrn
, &adaptors
);
167 adaptors
= &newAdaptor
;
169 /* need to free this someplace */
170 newAdaptors
= xalloc((num_adaptors
+ 1) * sizeof(XF86VideoAdaptorPtr
*));
172 memcpy(newAdaptors
, adaptors
, num_adaptors
*
173 sizeof(XF86VideoAdaptorPtr
));
174 newAdaptors
[num_adaptors
] = newAdaptor
;
175 adaptors
= newAdaptors
;
182 xf86XVScreenInit(pScreen
, adaptors
, num_adaptors
);
187 oldW
= 0; oldH
= 0; /* DEBUG */
191 /* client libraries expect an encoding */
192 static XF86VideoEncodingRec DummyEncoding
=
196 IMAGE_MAX_WIDTH
, IMAGE_MAX_HEIGHT
,
200 static XF86VideoEncodingRec DummyEncoding5597
=
204 IMAGE_MAX_WIDTH_5597
, IMAGE_MAX_HEIGHT_5597
,
208 #define NUM_FORMATS 4
210 static XF86VideoFormatRec SIS6326Formats
[NUM_FORMATS
] =
218 #define NUM_ATTRIBUTES 6
220 static XF86AttributeRec SIS6326Attributes
[NUM_ATTRIBUTES
] =
222 {XvSettable
| XvGettable
, 0, (1 << 24) - 1, "XV_COLORKEY"},
223 {XvSettable
| XvGettable
, -128, 127, "XV_BRIGHTNESS"},
224 {XvSettable
| XvGettable
, 0, 7, "XV_CONTRAST"},
225 {XvSettable
| XvGettable
, 0, 1, "XV_AUTOPAINT_COLORKEY"},
226 {XvSettable
, 0, 0, "XV_SET_DEFAULTS"},
227 {XvSettable
| XvGettable
, 0, 1, "XV_DISABLE_GRAPHICS"}
231 #define NUM_IMAGES_NOYV12 4
232 #define PIXEL_FMT_YV12 FOURCC_YV12 /* 0x32315659 */
233 #define PIXEL_FMT_UYVY FOURCC_UYVY /* 0x59565955 */
234 #define PIXEL_FMT_YUY2 FOURCC_YUY2 /* 0x32595559 */
235 #define PIXEL_FMT_I420 FOURCC_I420 /* 0x30323449 */
236 #define PIXEL_FMT_RGB5 0x35315652
237 #define PIXEL_FMT_RGB6 0x36315652
239 static XF86ImageRec SIS6326Images
[NUM_IMAGES
] =
241 XVIMAGE_YUY2
, /* TW: If order is changed, SIS6326OffscreenImages must be adapted */
250 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
254 /* 15, 0x001F, 0x03E0, 0x7C00, - incorrect! */
255 15, 0x7C00, 0x03E0, 0x001F,
260 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
268 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
272 /* 16, 0x001F, 0x07E0, 0xF800, - incorrect! */
273 16, 0xF800, 0x07E0, 0x001F,
278 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
283 static XF86ImageRec SIS6326ImagesNoYV12
[NUM_IMAGES_NOYV12
] =
285 XVIMAGE_YUY2
, /* TW: If order is changed, SIS6326OffscreenImages must be adapted */
292 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
296 /* 15, 0x001F, 0x03E0, 0x7C00, */
297 15, 0x7C00, 0x03E0, 0x001F, /* TW: Should be more correct than the other... */
302 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
310 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
314 /* 16, 0x001F, 0x07E0, 0xF800, */
315 16, 0xF800, 0x07E0, 0x001F, /* TW: Should be more correct than the other... */
320 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
350 CARD8 (*VBlankActiveFunc
)(SISPtr
);
351 /* CARD32 (*GetScanLineFunc)(SISPtr pSiS); */
353 } SISOverlayRec
, *SISOverlayPtr
;
356 FBLinearPtr linear
; /* TW: We now use Linear, not Area */
359 unsigned char currentBuf
;
361 short drw_x
, drw_y
, drw_w
, drw_h
;
362 short src_x
, src_y
, src_w
, src_h
;
364 short srcPitch
, height
, width
;
368 unsigned char contrast
;
372 Bool autopaintColorKey
;
380 short oldx1
, oldx2
, oldy1
, oldy2
;
383 Bool grabbedByV4L
; /* V4L stuff */
387 } SISPortPrivRec
, *SISPortPrivPtr
;
389 #define GET_PORT_PRIVATE(pScrn) \
390 (SISPortPrivPtr)((SISPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
393 SIS6326SetPortDefaults (ScrnInfoPtr pScrn
, SISPortPrivPtr pPriv
)
395 SISPtr pSiS
= SISPTR(pScrn
);
397 pPriv
->colorKey
= 0x000101fe;
398 pPriv
->videoStatus
= 0;
399 pPriv
->brightness
= pSiS
->XvDefBri
; /* 0; - see sis_opt.c */
400 pPriv
->contrast
= pSiS
->XvDefCon
; /* 4; */
401 pPriv
->autopaintColorKey
= TRUE
;
402 pPriv
->disablegfx
= pSiS
->XvDefDisableGfx
;
406 SIS6326ResetVideo(ScrnInfoPtr pScrn
)
408 SISPtr pSiS
= SISPTR(pScrn
);
410 /* Unlock registers */
412 sisSaveUnlockExtRegisterLock(pSiS
, NULL
, NULL
);
414 if(getvideoreg (pSiS
, Index_VI6326_Passwd
) != 0xa1) {
415 setvideoreg (pSiS
, Index_VI6326_Passwd
, 0x86);
416 if(getvideoreg (pSiS
, Index_VI6326_Passwd
) != 0xa1)
417 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
418 "Xv: Video password could not unlock video registers\n");
421 /* Initialize the overlay ----------------------------------- */
423 switch(pSiS
->Chipset
) {
424 case PCI_CHIP_SIS6326
:
425 /* Disable overlay (D[1]) & capture (D[0]) */
426 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x03);
428 /* What do these do? (Datasheet names these bits "reserved") */
429 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x18);
430 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x0c);
432 /* Select YUV format (D[6]) and "gfx + video" mode (D[4]), odd polarity? (D[7]) */
433 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x40, 0xD0);
434 /* No interrupt, no filter, disable dithering */
435 setvideoregmask(pSiS
, Index_VI6326_Control_Misc1
, 0x00, 0x7A);
436 /* Disable VMI (D[4:3]), Brooktree support (D[6]) and system memory framebuffer (D[7]) */
437 setvideoregmask(pSiS
, Index_VI6326_Control_Misc3
, 0x00, 0xF8);
438 /* Disable video decimation */
439 setvideoregmask(pSiS
, Index_VI6326_Control_Misc6
, 0x00, 0x80);
441 case PCI_CHIP_SIS5597
:
442 /* Disable overlay (D[1]) & capture (D[0]) */
443 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x03);
445 /* What do these do? (Datasheet names these bits "reserved") */
446 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x18);
447 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x0c);
449 /* Select YUV format (D[6]) and "gfx + video" mode (D[4]), odd polarity? (D[7]) */
450 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x40, 0xD0);
451 /* No interrupt, no filter, disable dithering */
452 setvideoregmask(pSiS
, Index_VI6326_Control_Misc1
, 0x00, 0x7A);
453 /* Disable Brooktree support (D[6]) and system memory framebuffer (D[7]) */
454 setvideoregmask(pSiS
, Index_VI6326_Control_Misc3
, 0x00, 0xC0);
455 /* Disable video decimation (has a really strange effect if enabled) */
456 setvideoregmask(pSiS
, Index_VI6326_Control_Misc6
, 0x00, 0x80);
458 case PCI_CHIP_SIS530
:
459 /* What is this? (Bit is "reserved") */
460 setvideoregmask (pSiS
, Index_VI6326_Control_Misc4
, 0x40, 0x40);
461 /* Disable overlay (D[1]) */
462 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x02);
464 /* What do these do? (Datasheet names these bits "reserved") */
465 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x18);
466 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x0c);
468 /* Select YUV format (D[6]) and "gfx + video" mode (D[4]) */
469 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x40, 0x50);
472 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
473 "Internal error: SiS6326ResetVideo() called with invalid chipset (%x)\n",
478 /* Clear format selection */
479 setvideoregmask(pSiS
, Index_VI6326_Control_Misc1
, 0x00, 0x04);
480 setvideoregmask(pSiS
, Index_VI6326_Control_Misc4
, 0x00, 0x07);
482 /* Select RGB Chromakey format (D[2]=0), CCIR 601 UV data format (D[1]=0) */
483 /* D[1]: 1 = 2's complement, 0 = CCIR 601 format */
484 setvideoregmask(pSiS
, Index_VI6326_Control_Misc3
, 0x00, 0x06);
486 /* Reset contrast control */
487 setvideoregmask(pSiS
, Index_VI6326_Contrast_Enh_Ctrl
, 0x04, 0x1F);
490 if(pSiS
->oldChipset
< OC_SIS6326
) {
492 inSISIDXREG(SISSR
, 0x33, temp
); /* Synchronous DRAM Timing? */
493 if(temp
& 0x01) temp
= 0x50;
495 setvideoreg(pSiS
, Index_VI6326_Play_Threshold_Low
, temp
);
496 setvideoreg(pSiS
, Index_VI6326_Play_Threshold_High
, temp
);
499 setvideoreg(pSiS
, Index_VI6326_Play_Threshold_Low
, 0x00);
500 setvideoreg(pSiS
, Index_VI6326_Play_Threshold_High
, 0x00);
501 inSISIDXREG(SISSR
, 0x33, temp
); /* Are we using SGRAM Timing? */
502 if(temp
& 0x01) temp
= 0x10;
504 setvideoregmask(pSiS
, Index_VI6326_Control_Misc4
, temp
, 0x10);
507 /* set default properties for overlay ------------------------------- */
509 setvideoregmask (pSiS
, Index_VI6326_Contrast_Enh_Ctrl
, 0x04, 0x07);
510 setvideoreg (pSiS
, Index_VI6326_Brightness
, 0x20);
512 if(pSiS
->oldChipset
< OC_SIS6205A
|| pSiS
->oldChipset
> OC_SIS82204
) {
513 setvideoregmask(pSiS
, Index_VI6326_AlphaGraph
, 0x00, 0xF8);
514 setvideoregmask(pSiS
, Index_VI6326_AlphaVideo
, 0xF8, 0xF8);
516 setvideoregmask(pSiS
, Index_VI6326_AlphaGraph
, 0x00, 0xE1);
517 setvideoregmask(pSiS
, Index_VI6326_AlphaVideo
, 0xE1, 0xE1);
521 static XF86VideoAdaptorPtr
522 SIS6326SetupImageVideo(ScreenPtr pScreen
)
524 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
525 SISPtr pSiS
= SISPTR(pScrn
);
526 XF86VideoAdaptorPtr adapt
;
527 SISPortPrivPtr pPriv
;
529 if(!(adapt
= xcalloc(1, sizeof(XF86VideoAdaptorRec
) +
530 sizeof(SISPortPrivRec
) +
534 adapt
->type
= XvWindowMask
| XvInputMask
| XvImageMask
;
535 adapt
->flags
= VIDEO_OVERLAID_IMAGES
| VIDEO_CLIP_TO_VIEWPORT
;
536 adapt
->name
= "SIS 5597/5598/6326/530/620 Video Overlay";
537 adapt
->nEncodings
= 1;
538 if(pSiS
->oldChipset
< OC_SIS6326
) {
539 adapt
->pEncodings
= &DummyEncoding5597
;
541 adapt
->pEncodings
= &DummyEncoding
;
543 adapt
->nFormats
= NUM_FORMATS
;
544 adapt
->pFormats
= SIS6326Formats
;
546 adapt
->pPortPrivates
= (DevUnion
*)(&adapt
[1]);
548 pPriv
= (SISPortPrivPtr
)(&adapt
->pPortPrivates
[1]);
550 adapt
->pPortPrivates
[0].ptr
= (pointer
)(pPriv
);
551 adapt
->pAttributes
= SIS6326Attributes
;
552 adapt
->nAttributes
= NUM_ATTRIBUTES
;
553 if(pSiS
->NoYV12
== 1) {
554 adapt
->nImages
= NUM_IMAGES_NOYV12
;
555 adapt
->pImages
= SIS6326ImagesNoYV12
;
557 adapt
->nImages
= NUM_IMAGES
;
558 adapt
->pImages
= SIS6326Images
;
560 adapt
->PutVideo
= NULL
;
561 adapt
->PutStill
= NULL
;
562 adapt
->GetVideo
= NULL
;
563 adapt
->GetStill
= NULL
;
564 adapt
->StopVideo
= SIS6326StopVideo
;
565 adapt
->SetPortAttribute
= SIS6326SetPortAttribute
;
566 adapt
->GetPortAttribute
= SIS6326GetPortAttribute
;
567 adapt
->QueryBestSize
= SIS6326QueryBestSize
;
568 adapt
->PutImage
= SIS6326PutImage
;
569 adapt
->QueryImageAttributes
= SIS6326QueryImageAttributes
;
571 pPriv
->videoStatus
= 0;
572 pPriv
->currentBuf
= 0;
573 pPriv
->linear
= NULL
;
574 pPriv
->grabbedByV4L
= FALSE
;
576 SIS6326SetPortDefaults(pScrn
, pPriv
);
578 /* gotta uninit this someplace */
579 REGION_INIT(pScreen
, &pPriv
->clip
, NullBox
, 0);
581 pSiS
->adaptor
= adapt
;
583 xvBrightness
= MAKE_ATOM("XV_BRIGHTNESS");
584 xvContrast
= MAKE_ATOM("XV_CONTRAST");
585 xvColorKey
= MAKE_ATOM("XV_COLORKEY");
586 xvAutopaintColorKey
= MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
587 xvSetDefaults
= MAKE_ATOM("XV_SET_DEFAULTS");
588 xvDisableGfx
= MAKE_ATOM("XV_DISABLE_GRAPHICS");
590 SIS6326ResetVideo(pScrn
);
595 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0)
597 RegionsEqual(RegionPtr A
, RegionPtr B
)
602 num
= REGION_NUM_RECTS(A
);
603 if(num
!= REGION_NUM_RECTS(B
))
606 if((A
->extents
.x1
!= B
->extents
.x1
) ||
607 (A
->extents
.x2
!= B
->extents
.x2
) ||
608 (A
->extents
.y1
!= B
->extents
.y1
) ||
609 (A
->extents
.y2
!= B
->extents
.y2
))
612 dataA
= (int*)REGION_RECTS(A
);
613 dataB
= (int*)REGION_RECTS(B
);
616 if((dataA
[0] != dataB
[0]) || (dataA
[1] != dataB
[1]))
627 SIS6326SetPortAttribute(ScrnInfoPtr pScrn
, Atom attribute
,
628 INT32 value
, pointer data
)
630 SISPortPrivPtr pPriv
= (SISPortPrivPtr
)data
;
632 if(attribute
== xvBrightness
) {
633 if((value
< -128) || (value
> 127))
635 pPriv
->brightness
= value
;
636 } else if(attribute
== xvContrast
) {
637 if((value
< 0) || (value
> 7))
639 pPriv
->contrast
= value
;
640 } else if(attribute
== xvColorKey
) {
641 pPriv
->colorKey
= value
;
642 REGION_EMPTY(pScrn
->pScreen
, &pPriv
->clip
);
643 } else if (attribute
== xvAutopaintColorKey
) {
644 if((value
< 0) || (value
> 1))
646 pPriv
->autopaintColorKey
= value
;
647 } else if(attribute
== xvDisableGfx
) {
648 if((value
< 0) || (value
> 1))
650 pPriv
->disablegfx
= value
;
651 } else if (attribute
== xvSetDefaults
) {
652 SIS6326SetPortDefaults(pScrn
, pPriv
);
653 } else return BadMatch
;
658 SIS6326GetPortAttribute(
664 SISPortPrivPtr pPriv
= (SISPortPrivPtr
)data
;
666 if(attribute
== xvBrightness
) {
667 *value
= pPriv
->brightness
;
668 } else if(attribute
== xvContrast
) {
669 *value
= pPriv
->contrast
;
670 } else if(attribute
== xvColorKey
) {
671 *value
= pPriv
->colorKey
;
672 } else if (attribute
== xvAutopaintColorKey
) {
673 *value
= (pPriv
->autopaintColorKey
) ? 1 : 0;
674 } else if (attribute
== xvDisableGfx
) {
675 *value
= (pPriv
->disablegfx
) ? 1 : 0;
676 } else return BadMatch
;
681 SIS6326QueryBestSize(
684 short vid_w
, short vid_h
,
685 short drw_w
, short drw_h
,
686 unsigned int *p_w
, unsigned int *p_h
,
692 /* TODO: report the HW limitation */
695 static void /* V 530/6326 */
696 calc_scale_factor(SISPtr pSiS
, SISOverlayPtr pOverlay
, ScrnInfoPtr pScrn
,
697 SISPortPrivPtr pPriv
)
701 int dstW
= pOverlay
->dstBox
.x2
- pOverlay
->dstBox
.x1
;
702 int dstH
= pOverlay
->dstBox
.y2
- pOverlay
->dstBox
.y1
;
703 int srcW
= pOverlay
->srcW
;
704 int srcH
= pOverlay
->srcH
;
708 if((oldH
!= dstH
) || (oldW
!= dstW
)){
709 xf86DrvMsg(0, X_INFO
, "Video size %dx%d\n", dstW
, dstH
);
710 oldH
= dstH
; oldW
= dstW
;
715 /* TW: For double scan modes, we need to double the height */
716 if(pSiS
->CurrentLayout
.mode
->Flags
& V_DBLSCAN
) {
719 /* TW: For interlace modes, we need to half the height */
720 if(pSiS
->CurrentLayout
.mode
->Flags
& V_INTERLACE
) {
725 if(dstW
< IMAGE_MIN_WIDTH
) dstW
= IMAGE_MIN_WIDTH
;
727 pOverlay
->HUSF
= 0x00;
728 pOverlay
->HIntBit
= 0x01;
729 } else if(dstW
> srcW
) {
730 pOverlay
->HIntBit
= 0x00;
731 temp
= srcW
* 64 / (dstW
+ 1);
732 if(temp
> 63) temp
= 63;
733 pOverlay
->HUSF
= temp
;
735 /* 6326 can't scale below factor .440 - to check with 530/620 */
736 if(((dstW
* 1000) / srcW
) < 440) dstW
= ((srcW
* 440) / 1000) + 1;
738 if(temp
> 15) temp
= 15;
739 pOverlay
->HIntBit
= temp
;
740 temp
= srcW
* 64 / dstW
;
741 pOverlay
->HUSF
= temp
- (pOverlay
->HIntBit
* 64);
745 if(dstH
< IMAGE_MIN_HEIGHT
) dstH
= IMAGE_MIN_HEIGHT
;
747 pOverlay
->VUSF
= 0x00;
748 pOverlay
->PitchMult
= 1;
749 } else if(dstH
> srcH
) {
750 temp
= srcH
* 64 / (dstH
+ 1);
751 if (temp
> 63) temp
= 63;
752 pOverlay
->VUSF
= temp
;
753 pOverlay
->PitchMult
= 1;
755 /* 6326 can't scale below factor .440 - to check with 530/620 */
756 if(((dstH
* 1000) / srcH
) < 440) dstH
= ((srcH
* 440) / 1000) + 1;
760 pOverlay
->VUSF
= (srcH
* 64) / (temp
* dstH
);
762 pOverlay
->VUSF
= 0x00;
764 pOverlay
->PitchMult
= temp
;
769 calc_line_buf_size(SISOverlayPtr pOverlay
)
772 CARD32 line
= pOverlay
->srcW
;
774 if( (pOverlay
->pixelFormat
== PIXEL_FMT_YV12
) ||
775 (pOverlay
->pixelFormat
== PIXEL_FMT_I420
) )
777 I
= (line
>> 5) + (((line
>> 6) * 2)) + 3;
779 } else { /* YUV2, UYVY, RGB */
785 pOverlay
->lineBufSize
= (CARD8
)I
;
789 merge_line_buf(SISPtr pSiS
, SISPortPrivPtr pPriv
, Bool enable
)
792 setvideoregmask(pSiS
, Index_VI6326_Control_Misc5
, 0x10, 0x10);
794 setvideoregmask(pSiS
, Index_VI6326_Control_Misc5
, 0x00, 0x10);
799 set_format(SISPtr pSiS
, SISOverlayPtr pOverlay
)
801 CARD8 fmt
, misc0
, misc1
, misc4
;
803 switch (pOverlay
->pixelFormat
){
805 case PIXEL_FMT_I420
: /* V/530 V/6326 */
806 fmt
= 0x80; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */
807 misc0
= 0x40; /* D[6]: 1 = YUV, 0 = RGB */
808 misc4
= 0x05; /* D[1:0] 00 RGB 555, 01 YUV 422, 10 RGB 565; D[2] 1 = YUV420 mode */
812 fmt
= 0x00; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */
813 misc0
= 0x40; /* D[6]: 1 = YUV, 0 = RGB */
814 misc4
= 0x00; /* D[1:0] 00 RGB 555, 01 YUV 422, 10 RGB 565; D[2] 1 = YUV420 mode */
817 case PIXEL_FMT_YUY2
: /* V/530 V/6326 */
818 fmt
= 0x80; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */
819 misc0
= 0x40; /* D[6]: 1 = YUV, 0 = RGB */
820 misc4
= 0x00; /* D[1:0] 00 RGB 555, 01 YUV 422, 10 RGB 565; D[2] 1 = YUV420 mode */
823 case PIXEL_FMT_RGB6
: /* V/530 V/6326 */
824 fmt
= 0x40; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */
825 misc0
= 0x00; /* D[6]: 1 = YUV, 0 = RGB */
827 misc1
= 0x00; /* D[2] = Capture format selection (DS5597) - WDR sets this */
829 case PIXEL_FMT_RGB5
: /* V/530 V/6326 */
831 fmt
= 0x00; /* D[7:6] 10 YUV2(=YUYV), 01 VYUY, 00 UYVY, 11 YVYU / 00 RGB 555, 01 RGB 565 */
832 misc0
= 0x00; /* D[6]: 1 = YUV, 0 = RGB */
834 misc1
= 0x04; /* D[2] = Capture format selection (DS5597) - WDR sets this */
838 setvideoregmask(pSiS
, Index_VI6326_VideoFormatSelect
, fmt
, 0xC0);
839 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, misc0
, 0x40);
841 setvideoregmask(pSiS
, Index_VI6326_Control_Misc1
, misc1
, 0x04);
842 if(pSiS
->oldChipset
>= OC_SIS5597
) {
843 setvideoregmask(pSiS
, Index_VI6326_Control_Misc4
, 0x00, 0x05);
846 if(pSiS
->oldChipset
>= OC_SIS5597
) {
847 setvideoregmask(pSiS
, Index_VI6326_Control_Misc4
, misc4
, 0x05);
849 setvideoregmask(pSiS
, Index_VI6326_Control_Misc1
, 0x00, 0x04);
854 set_colorkey(SISPtr pSiS
, CARD32 colorkey
)
858 b
= (CARD8
)(colorkey
& 0xFF);
859 g
= (CARD8
)((colorkey
>>8) & 0xFF);
860 r
= (CARD8
)((colorkey
>>16) & 0xFF);
862 if(pSiS
->CurrentLayout
.bitsPerPixel
>= 24) {
868 setvideoreg(pSiS
, Index_VI6326_Overlay_ColorKey_Blue_Min
,(CARD8
)b
);
869 setvideoreg(pSiS
, Index_VI6326_Overlay_ColorKey_Green_Min
,(CARD8
)g
);
870 setvideoreg(pSiS
, Index_VI6326_Overlay_ColorKey_Red_Min
,(CARD8
)r
);
872 setvideoreg(pSiS
, Index_VI6326_Overlay_ColorKey_Blue_Max
,(CARD8
)b
);
873 setvideoreg(pSiS
, Index_VI6326_Overlay_ColorKey_Green_Max
,(CARD8
)g
);
874 setvideoreg(pSiS
, Index_VI6326_Overlay_ColorKey_Red_Max
,(CARD8
)r
);
878 set_brightness(SISPtr pSiS
, CARD8 brightness
)
880 setvideoreg(pSiS
, Index_VI6326_Brightness
, brightness
);
884 set_contrast(SISPtr pSiS
, CARD8 contrast
)
886 setvideoregmask(pSiS
, Index_VI6326_Contrast_Enh_Ctrl
, contrast
, 0x07);
890 set_contrast_data(SISPtr pSiS
, int value
)
894 if(value
< 10000) temp
= 0;
895 else temp
= (value
- 10000) / 20000;
896 if(temp
> 3) temp
= 3;
897 setvideoregmask(pSiS
, Index_VI6326_Contrast_Enh_Ctrl
, (temp
<< 6), 0xC0);
899 case 0: temp
= 2048; break;
900 case 1: temp
= 4096; break;
901 case 2: temp
= 8192; break;
902 case 3: temp
= 16384; break;
906 setvideoreg(pSiS
, Index_VI6326_Contrast_Factor
, temp
);
910 set_disablegfx(SISPtr pSiS
, Bool mybool
)
912 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, mybool
? 0x10 : 0x00, 0x10);
916 set_overlay(SISPtr pSiS
, SISOverlayPtr pOverlay
, SISPortPrivPtr pPriv
, int index
)
918 ScrnInfoPtr pScrn
= pSiS
->pScrn
;
921 CARD8 h_over
=0, v_over
=0;
922 CARD16 top
, bottom
, left
, right
;
923 CARD16 screenX
= pSiS
->CurrentLayout
.mode
->HDisplay
;
924 CARD16 screenY
= pSiS
->CurrentLayout
.mode
->VDisplay
;
927 top
= pOverlay
->dstBox
.y1
;
928 bottom
= pOverlay
->dstBox
.y2
;
929 if(bottom
> screenY
) {
933 left
= pOverlay
->dstBox
.x1
;
934 right
= pOverlay
->dstBox
.x2
;
935 if(right
> screenX
) {
939 /* TW: DoubleScan modes require Y coordinates * 2 */
940 if(pSiS
->CurrentLayout
.mode
->Flags
& V_DBLSCAN
) {
944 /* TW: Interlace modes require Y coordinates / 2 */
945 if(pSiS
->CurrentLayout
.mode
->Flags
& V_INTERLACE
) {
950 h_over
= (((left
>>8) & 0x07) | ((right
>>4) & 0x70));
951 v_over
= (((top
>>8) & 0x07) | ((bottom
>>4) & 0x70));
953 pitch
= pOverlay
->pitch
* pOverlay
->PitchMult
;
954 pitch
>>= 2; /* Datasheet: Unit = double word - verified */
956 pitch
= pOverlay
->pitch
* (0xFFF * 2 / pOverlay
->pitch
);
957 pOverlay
->VUSF
= 0x3F;
961 set_colorkey(pSiS
, pPriv
->colorKey
);
963 /* set color key mode */
964 setvideoregmask(pSiS
, Index_VI6326_Key_Overlay_OP
, pOverlay
->keyOP
, 0x0f);
966 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x0c);
967 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x18);
969 /* Set Y buf pitch */ /* Datasheet: Unit = double word - verified */
970 setvideoreg(pSiS
, Index_VI6326_Disp_Y_Buf_Pitch_Low
, (CARD8
)(pitch
));
971 setvideoregmask(pSiS
, Index_VI6326_Disp_Y_Buf_Pitch_High
, (CARD8
)(pitch
>>8), 0x0f);
972 /* Set U/V pitch if using planar formats */
973 if( (pOverlay
->pixelFormat
== PIXEL_FMT_YV12
) ||
974 (pOverlay
->pixelFormat
== PIXEL_FMT_I420
) ) {
975 /* Set U/V pitch */ /* Datasheet: Unit = double word - verified */
976 setvideoreg(pSiS
, Index_VI6326_Disp_UV_Buf_Pitch_Low
, (CARD8
)pitch
>> 1);
977 setvideoregmask(pSiS
, Index_VI6326_Disp_UV_Buf_Pitch_High
, (CARD8
)(pitch
>> 9), 0x0f);
980 /* set line buffer size */
981 setvideoreg(pSiS
, Index_VI6326_Line_Buffer_Size
, pOverlay
->lineBufSize
);
983 /* set scale factor */
984 setvideoreg(pSiS
, Index_VI6326_Hor_Scale
, (CARD8
)((pOverlay
->HUSF
) | 0xC0));
985 setvideoregmask(pSiS
, Index_VI6326_Hor_Scale_Integer
, (CARD8
)(pOverlay
->HIntBit
), 0x0F);
986 setvideoregmask(pSiS
, Index_VI6326_Ver_Scale
, (CARD8
)(pOverlay
->VUSF
), 0x3F);
988 /* TW: We don't have to wait for vertical retrace in all cases */
989 if(pPriv
->mustwait
) {
990 watchdog
= WATCHDOG_DELAY
;
991 while ((!pOverlay
->VBlankActiveFunc(pSiS
)) && --watchdog
);
992 if(!watchdog
) xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
993 "Xv: Waiting for vertical retrace timed-out\n");
996 /* set destination window position */
997 setvideoreg(pSiS
, Index_VI6326_Win_Hor_Disp_Start_Low
, (CARD8
)left
);
998 setvideoreg(pSiS
, Index_VI6326_Win_Hor_Disp_End_Low
, (CARD8
)right
);
999 setvideoreg(pSiS
, Index_VI6326_Win_Hor_Over
, (CARD8
)h_over
);
1001 setvideoreg(pSiS
, Index_VI6326_Win_Ver_Disp_Start_Low
, (CARD8
)top
);
1002 setvideoreg(pSiS
, Index_VI6326_Win_Ver_Disp_End_Low
, (CARD8
)bottom
);
1003 setvideoreg(pSiS
, Index_VI6326_Win_Ver_Over
, (CARD8
)v_over
);
1005 /* Set Y start address */
1006 setvideoreg (pSiS
, Index_VI6326_Disp_Y_Buf_Start_Low
, (CARD8
)(pOverlay
->PSY
));
1007 setvideoreg (pSiS
, Index_VI6326_Disp_Y_Buf_Start_Middle
, (CARD8
)((pOverlay
->PSY
)>>8));
1008 if(pSiS
->oldChipset
<= OC_SIS6326
) { /* all old chipsets incl 6326 */
1009 /* Set overflow bits */
1010 setvideoregmask (pSiS
, Index_VI6326_Disp_Capt_Y_Buf_Start_High
,
1011 (CARD8
)(((pOverlay
->PSY
)>>12) & 0xF0), 0xF0);
1012 /* Set framebuffer end address */
1013 setvideoreg (pSiS
, Index_VI6326_Disp_Y_End
, (CARD8
)(pOverlay
->YUVEnd
));
1014 } else { /* 530/620 */
1015 /* Set overflow bits */
1016 setvideoregmask (pSiS
, Index_VI6326_Disp_Capt_Y_Buf_Start_High
,
1017 (CARD8
)(((pOverlay
->PSY
)>>13) & 0xF8), 0xF8);
1020 /* Set U/V start addresses if using plane formats */
1021 if( (pOverlay
->pixelFormat
== PIXEL_FMT_YV12
) ||
1022 (pOverlay
->pixelFormat
== PIXEL_FMT_I420
) ) {
1024 CARD32 PSU
= pOverlay
->PSU
;
1025 CARD32 PSV
= pOverlay
->PSV
;
1027 /* set U/V start address */
1028 setvideoreg (pSiS
, Index_VI6326_U_Buf_Start_Low
, (CARD8
)PSU
);
1029 setvideoreg (pSiS
, Index_VI6326_U_Buf_Start_Middle
,(CARD8
)(PSU
>> 8));
1031 setvideoreg (pSiS
, Index_VI6326_V_Buf_Start_Low
, (CARD8
)PSV
);
1032 setvideoreg (pSiS
, Index_VI6326_V_Buf_Start_Middle
,(CARD8
)(PSV
>> 8));
1034 setvideoreg (pSiS
, Index_VI6326_UV_Buf_Start_High
,
1035 (CARD8
)(((PSU
>> 16) & 0x0F) | ((PSV
>> 12) & 0xF0)) );
1037 if(pSiS
->oldChipset
> OC_SIS6326
) {
1038 /* Set bit 20 of the addresses in Misc5 (530/620 only) */
1039 setvideoreg (pSiS
, Index_VI6326_Control_Misc5
,
1040 (CARD8
)(((PSU
>> (20-1)) & 0x02) | ((PSV
>> (20-2)) & 0x04)) );
1044 /* set brightness and contrast */
1045 set_brightness(pSiS
, pPriv
->brightness
);
1046 if(pSiS
->oldChipset
> OC_SIS6205C
) {
1047 set_contrast_data(pSiS
, (pOverlay
->dstBox
.x2
- pOverlay
->dstBox
.x1
) *
1048 (pOverlay
->dstBox
.y2
- pOverlay
->dstBox
.y1
));
1049 set_contrast(pSiS
, pPriv
->contrast
);
1052 /* enable/disable graphics display around overlay */
1053 set_disablegfx(pSiS
, pPriv
->disablegfx
);
1056 set_format(pSiS
, pOverlay
);
1059 /* Overlay MUST NOT be switched off while beam is over it */
1061 close_overlay(SISPtr pSiS
, SISPortPrivPtr pPriv
)
1065 watchdog
= WATCHDOG_DELAY
;
1066 while((!vblank_active_CRT1(pSiS
)) && --watchdog
);
1067 if(pSiS
->oldChipset
> OC_SIS6326
) {
1069 setvideoregmask(pSiS
, Index_VI6326_Control_Misc4
, 0x40, 0x40);
1071 /* disable overlay */
1072 setvideoregmask(pSiS
, Index_VI6326_Control_Misc0
, 0x00, 0x02);
1076 SIS6326DisplayVideo(ScrnInfoPtr pScrn
, SISPortPrivPtr pPriv
)
1078 SISPtr pSiS
= SISPTR(pScrn
);
1080 short srcPitch
= pPriv
->srcPitch
;
1081 short height
= pPriv
->height
;
1082 short width
= pPriv
->width
;
1083 SISOverlayRec overlay
;
1084 int srcOffsetX
=0, srcOffsetY
=0;
1089 memset(&overlay
, 0, sizeof(overlay
));
1090 overlay
.pixelFormat
= pPriv
->id
;
1091 overlay
.pitch
= srcPitch
;
1092 overlay
.keyOP
= VI6326_ROP_DestKey
; /* DestKey mode */
1094 overlay
.dstBox
.x1
= pPriv
->drw_x
- pScrn
->frameX0
;
1095 overlay
.dstBox
.x2
= pPriv
->drw_x
+ pPriv
->drw_w
- pScrn
->frameX0
;
1096 overlay
.dstBox
.y1
= pPriv
->drw_y
- pScrn
->frameY0
;
1097 overlay
.dstBox
.y2
= pPriv
->drw_y
+ pPriv
->drw_h
- pScrn
->frameY0
;
1099 if((overlay
.dstBox
.x1
> overlay
.dstBox
.x2
) ||
1100 (overlay
.dstBox
.y1
> overlay
.dstBox
.y2
))
1103 if((overlay
.dstBox
.x2
< 0) || (overlay
.dstBox
.y2
< 0))
1106 if(overlay
.dstBox
.x1
< 0) {
1107 srcOffsetX
= pPriv
->src_w
* (-overlay
.dstBox
.x1
) / pPriv
->drw_w
;
1108 overlay
.dstBox
.x1
= 0;
1110 if(overlay
.dstBox
.y1
< 0) {
1111 srcOffsetY
= pPriv
->src_h
* (-overlay
.dstBox
.y1
) / pPriv
->drw_h
;
1112 overlay
.dstBox
.y1
= 0;
1116 case PIXEL_FMT_YV12
:
1117 sx
= (pPriv
->src_x
+ srcOffsetX
) & ~7;
1118 sy
= (pPriv
->src_y
+ srcOffsetY
) & ~1;
1119 pitch
= (width
+ 3) & ~3;
1120 overlay
.PSY
= pPriv
->bufAddr
[pPriv
->currentBuf
] + sx
+ sy
* pitch
;
1121 overlay
.PSV
= overlay
.PSY
+ pitch
* height
;
1122 overlay
.PSU
= overlay
.PSV
+ ((((width
>> 1) + 3) & ~3) * (height
>> 1));
1127 case PIXEL_FMT_I420
:
1128 sx
= (pPriv
->src_x
+ srcOffsetX
) & ~7;
1129 sy
= (pPriv
->src_y
+ srcOffsetY
) & ~1;
1130 pitch
= (width
+ 3) & ~3;
1131 overlay
.PSY
= pPriv
->bufAddr
[pPriv
->currentBuf
] + sx
+ sy
* pitch
;
1132 overlay
.PSU
= overlay
.PSY
+ pitch
* height
;
1133 overlay
.PSV
= overlay
.PSU
+ ((((width
>> 1) + 3) & ~3) * (height
>> 1));
1138 case PIXEL_FMT_YUY2
:
1139 case PIXEL_FMT_UYVY
:
1140 case PIXEL_FMT_RGB6
:
1141 case PIXEL_FMT_RGB5
:
1143 sx
= (pPriv
->src_x
+ srcOffsetX
) & ~1;
1144 sy
= (pPriv
->src_y
+ srcOffsetY
);
1145 overlay
.PSY
= (pPriv
->bufAddr
[pPriv
->currentBuf
] + sx
*2 + sy
*srcPitch
);
1150 /* FIXME: Is this correct? (Is it required to set the end address?
1151 * Datasheet is not clear) - (reg does not exist on 530/620)
1153 overlay
.YUVEnd
= (pPriv
->bufAddr
[pPriv
->currentBuf
] + pPriv
->totalSize
) >> 14;
1155 /* FIXME: is it possible that srcW < 0 */
1156 overlay
.srcW
= pPriv
->src_w
- (sx
- pPriv
->src_x
);
1157 overlay
.srcH
= pPriv
->src_h
- (sy
- pPriv
->src_y
);
1159 if ( (pPriv
->oldx1
!= overlay
.dstBox
.x1
) ||
1160 (pPriv
->oldx2
!= overlay
.dstBox
.x2
) ||
1161 (pPriv
->oldy1
!= overlay
.dstBox
.y1
) ||
1162 (pPriv
->oldy2
!= overlay
.dstBox
.y2
) ) {
1163 pPriv
->mustwait
= 1;
1164 pPriv
->oldx1
= overlay
.dstBox
.x1
; pPriv
->oldx2
= overlay
.dstBox
.x2
;
1165 pPriv
->oldy1
= overlay
.dstBox
.y1
; pPriv
->oldy2
= overlay
.dstBox
.y2
;
1168 /* calculate line buffer length */
1169 calc_line_buf_size(&overlay
);
1171 overlay
.VBlankActiveFunc
= vblank_active_CRT1
;
1172 /* overlay.GetScanLineFunc = get_scanline_CRT1; */
1174 /* calculate scale factor */
1175 calc_scale_factor(pSiS
, &overlay
, pScrn
, pPriv
);
1177 /* set (not only determine) if line buffer is to be merged */
1178 if(pSiS
->oldChipset
> OC_SIS5597
) {
1180 if(pSiS
->oldChipset
<= OC_SIS6326
) temp
= 352;
1182 merge_line_buf(pSiS
, pPriv
, (overlay
.srcW
> temp
));
1186 set_overlay(pSiS
, &overlay
, pPriv
, index
);
1188 /* enable overlay */
1189 if(pSiS
->oldChipset
> OC_SIS6326
) {
1190 setvideoregmask (pSiS
, Index_VI6326_Control_Misc4
, 0x40, 0x40);
1192 setvideoregmask (pSiS
, Index_VI6326_Control_Misc0
, 0x02, 0x02);
1194 pPriv
->mustwait
= 0;
1198 SIS6326AllocateOverlayMemory(
1204 FBLinearPtr new_linear
;
1207 if(linear
->size
>= size
)
1210 if(xf86ResizeOffscreenLinear(linear
, size
))
1213 xf86FreeOffscreenLinear(linear
);
1216 pScreen
= screenInfo
.screens
[pScrn
->scrnIndex
];
1218 new_linear
= xf86AllocateOffscreenLinear(pScreen
, size
, 32,
1224 xf86QueryLargestOffscreenLinear(pScreen
, &max_size
, 32,
1227 if(max_size
< size
) return NULL
;
1229 xf86PurgeUnlockedOffscreenAreas(pScreen
);
1230 new_linear
= xf86AllocateOffscreenLinear(pScreen
, size
, 32,
1234 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
1235 "Xv: Failed to allocate %dK of video memory\n", size
/1024);
1241 SIS6326FreeOverlayMemory(ScrnInfoPtr pScrn
)
1243 SISPortPrivPtr pPriv
= GET_PORT_PRIVATE(pScrn
);
1246 xf86FreeOffscreenLinear(pPriv
->linear
);
1247 pPriv
->linear
= NULL
;
1252 SIS6326StopVideo(ScrnInfoPtr pScrn
, pointer data
, Bool shutdown
)
1254 SISPortPrivPtr pPriv
= (SISPortPrivPtr
)data
;
1255 SISPtr pSiS
= SISPTR(pScrn
);
1257 if(pPriv
->grabbedByV4L
)
1260 REGION_EMPTY(pScrn
->pScreen
, &pPriv
->clip
);
1263 if(pPriv
->videoStatus
& CLIENT_VIDEO_ON
) {
1264 close_overlay(pSiS
, pPriv
);
1265 pPriv
->mustwait
= 1;
1267 SIS6326FreeOverlayMemory(pScrn
);
1268 pPriv
->videoStatus
= 0;
1269 pSiS
->VideoTimerCallback
= NULL
;
1271 if(pPriv
->videoStatus
& CLIENT_VIDEO_ON
) {
1272 pPriv
->videoStatus
= OFF_TIMER
| CLIENT_VIDEO_ON
;
1273 pPriv
->offTime
= currentTime
.milliseconds
+ OFF_DELAY
;
1274 pSiS
->VideoTimerCallback
= SIS6326VideoTimerCallback
;
1282 short src_x
, short src_y
,
1283 short drw_x
, short drw_y
,
1284 short src_w
, short src_h
,
1285 short drw_w
, short drw_h
,
1286 int id
, unsigned char* buf
,
1287 short width
, short height
,
1289 RegionPtr clipBoxes
, pointer data
1291 SISPtr pSiS
= SISPTR(pScrn
);
1292 SISPortPrivPtr pPriv
= (SISPortPrivPtr
)data
;
1294 int depth
= pSiS
->CurrentLayout
.bitsPerPixel
>> 3;
1298 if(pPriv
->grabbedByV4L
)
1301 pPriv
->drw_x
= drw_x
;
1302 pPriv
->drw_y
= drw_y
;
1303 pPriv
->drw_w
= drw_w
;
1304 pPriv
->drw_h
= drw_h
;
1305 pPriv
->src_x
= src_x
;
1306 pPriv
->src_y
= src_y
;
1307 pPriv
->src_w
= src_w
;
1308 pPriv
->src_h
= src_h
;
1310 pPriv
->height
= height
;
1311 pPriv
->width
= width
;
1313 /* TW: Pixel formats:
1314 1. YU12: 3 planes: H V
1315 Y sample period 1 1 (8 bit per pixel)
1316 V sample period 2 2 (8 bit per pixel, subsampled)
1317 U sample period 2 2 (8 bit per pixel, subsampled)
1319 Y plane is fully sampled (width*height), U and V planes
1320 are sampled in 2x2 blocks, hence a group of 4 pixels requires
1321 4 + 1 + 1 = 6 bytes. The data is planar, ie in single planes
1323 2. UYVY: 3 planes: H V
1324 Y sample period 1 1 (8 bit per pixel)
1325 V sample period 2 1 (8 bit per pixel, subsampled)
1326 U sample period 2 1 (8 bit per pixel, subsampled)
1327 Y plane is fully sampled (width*height), U and V planes
1328 are sampled in 2x1 blocks, hence a group of 4 pixels requires
1329 4 + 2 + 2 = 8 bytes. The data is bit packed, there are no separate
1331 Bit order: U0 Y0 V0 Y1 U2 Y2 V2 Y3 ...
1332 3. I420: Like YU12, but planes U and V are in reverse order.
1333 4. YUY2: Like UYVY, but order is
1334 Y0 U0 Y1 V0 Y2 U2 Y3 V2 ...
1338 case PIXEL_FMT_YV12
:
1339 case PIXEL_FMT_I420
:
1340 pPriv
->srcPitch
= (width
+ 7) & ~7;
1341 /* Size = width * height * 3 / 2 */
1342 totalSize
= (pPriv
->srcPitch
* height
* 3) >> 1;
1344 case PIXEL_FMT_YUY2
:
1345 case PIXEL_FMT_UYVY
:
1346 case PIXEL_FMT_RGB5
:
1347 case PIXEL_FMT_RGB6
:
1349 pPriv
->srcPitch
= ((width
<< 1) + 3) & ~3;
1350 /* Size = width * 2 * height */
1351 totalSize
= pPriv
->srcPitch
* height
;
1354 /* make it a multiple of 16 to simplify to copy loop */
1358 pPriv
->totalSize
= totalSize
;
1360 /* allocate memory (we do doublebuffering) */
1361 if(!(pPriv
->linear
= SIS6326AllocateOverlayMemory(pScrn
, pPriv
->linear
,
1365 /* fixup pointers */
1366 pPriv
->bufAddr
[0] = (pPriv
->linear
->offset
* depth
);
1367 pPriv
->bufAddr
[1] = pPriv
->bufAddr
[0] + totalSize
;
1370 if((pSiS
->XvUseMemcpy
) || (totalSize
< 16)) {
1371 memcpy(pSiS
->FbBase
+ pPriv
->bufAddr
[pPriv
->currentBuf
], buf
, totalSize
);
1373 dest
= (CARD32
*)(pSiS
->FbBase
+ pPriv
->bufAddr
[pPriv
->currentBuf
]);
1374 src
= (CARD32
*)buf
;
1375 for(i
= 0; i
< (totalSize
/16); i
++) {
1383 SIS6326DisplayVideo(pScrn
, pPriv
);
1385 /* update cliplist */
1386 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0)
1387 if( pPriv
->autopaintColorKey
&&
1388 (pPriv
->grabbedByV4L
||
1389 !RegionsEqual(&pPriv
->clip
, clipBoxes
)) ) {
1390 /* We always paint colorkey for V4L */
1391 if(!pPriv
->grabbedByV4L
)
1392 REGION_COPY(pScrn
->pScreen
, &pPriv
->clip
, clipBoxes
);
1394 XAAFillSolidRects(pScrn
, pPriv
->colorKey
, GXcopy
, ~0,
1395 REGION_NUM_RECTS(clipBoxes
),
1396 REGION_RECTS(clipBoxes
));
1399 if( pPriv
->autopaintColorKey
&&
1400 (pPriv
->grabbedByV4L
||
1401 !REGION_EQUAL(pScrn
->pScreen
, &pPriv
->clip
, clipBoxes
)) ) {
1402 /* We always paint colorkey for V4L */
1403 if(!pPriv
->grabbedByV4L
)
1404 REGION_COPY(pScrn
->pScreen
, &pPriv
->clip
, clipBoxes
);
1406 xf86XVFillKeyHelper(pScrn
->pScreen
, pPriv
->colorKey
, clipBoxes
);
1410 pPriv
->currentBuf
^= 1;
1412 pPriv
->videoStatus
= CLIENT_VIDEO_ON
;
1414 pSiS
->VideoTimerCallback
= SIS6326VideoTimerCallback
;
1420 SIS6326QueryImageAttributes(
1423 unsigned short *w
, unsigned short *h
,
1424 int *pitches
, int *offsets
1426 SISPtr pSiS
= SISPTR(pScrn
);
1427 int pitchY
, pitchUV
;
1428 int size
, sizeY
, sizeUV
;
1430 if(*w
< IMAGE_MIN_WIDTH
) *w
= IMAGE_MIN_WIDTH
;
1431 if(*h
< IMAGE_MIN_HEIGHT
) *h
= IMAGE_MIN_HEIGHT
;
1433 if(pSiS
->oldChipset
< OC_SIS6326
) {
1434 if(*w
> IMAGE_MAX_WIDTH_5597
) *w
= IMAGE_MAX_WIDTH_5597
;
1435 if(*h
> IMAGE_MAX_HEIGHT_5597
) *h
= IMAGE_MAX_HEIGHT_5597
;
1437 if(*w
> IMAGE_MAX_WIDTH
) *w
= IMAGE_MAX_WIDTH
;
1438 if(*h
> IMAGE_MAX_HEIGHT
) *h
= IMAGE_MAX_HEIGHT
;
1442 case PIXEL_FMT_YV12
:
1443 case PIXEL_FMT_I420
:
1449 pitches
[0] = pitchY
;
1450 pitches
[1] = pitches
[2] = pitchUV
;
1452 sizeY
= pitchY
* (*h
);
1453 sizeUV
= pitchUV
* ((*h
) >> 1);
1457 offsets
[2] = sizeY
+ sizeUV
;
1459 size
= sizeY
+ (sizeUV
<< 1);
1461 case PIXEL_FMT_YUY2
:
1462 case PIXEL_FMT_UYVY
:
1463 case PIXEL_FMT_RGB5
:
1464 case PIXEL_FMT_RGB6
:
1468 if(pitches
) pitches
[0] = pitchY
;
1469 if(offsets
) offsets
[0] = 0;
1470 size
= pitchY
* (*h
);
1478 SIS6326VideoTimerCallback (ScrnInfoPtr pScrn
, Time now
)
1480 SISPtr pSiS
= SISPTR(pScrn
);
1481 SISPortPrivPtr pPriv
= NULL
;
1482 unsigned char sridx
, cridx
;
1484 pSiS
->VideoTimerCallback
= NULL
;
1486 if(!pScrn
->vtSema
) return;
1489 pPriv
= GET_PORT_PRIVATE(pScrn
);
1490 if(!pPriv
->videoStatus
)
1495 if(pPriv
->videoStatus
& TIMER_MASK
) {
1496 UpdateCurrentTime();
1497 if(pPriv
->offTime
< currentTime
.milliseconds
) {
1498 if(pPriv
->videoStatus
& OFF_TIMER
) {
1499 /* Turn off the overlay */
1500 sridx
= inSISREG(SISSR
); cridx
= inSISREG(SISCR
);
1501 close_overlay(pSiS
, pPriv
);
1502 outSISREG(SISSR
, sridx
); outSISREG(SISCR
, cridx
);
1503 pPriv
->mustwait
= 1;
1504 pPriv
->videoStatus
= FREE_TIMER
;
1505 pPriv
->freeTime
= currentTime
.milliseconds
+ FREE_DELAY
;
1506 pSiS
->VideoTimerCallback
= SIS6326VideoTimerCallback
;
1508 if(pPriv
->videoStatus
& FREE_TIMER
) {
1509 SIS6326FreeOverlayMemory(pScrn
);
1510 pPriv
->mustwait
= 1;
1511 pPriv
->videoStatus
= 0;
1514 pSiS
->VideoTimerCallback
= SIS6326VideoTimerCallback
;
1519 /* Offscreen surface stuff for v4l */
1522 SIS6326AllocSurface (
1527 XF86SurfacePtr surface
1530 SISPtr pSiS
= SISPTR(pScrn
);
1531 SISPortPrivPtr pPriv
= GET_PORT_PRIVATE(pScrn
);
1534 if((w
< IMAGE_MIN_WIDTH
) || (h
< IMAGE_MIN_HEIGHT
))
1537 if(pSiS
->oldChipset
< OC_SIS6326
) {
1538 if((w
> IMAGE_MAX_WIDTH_5597
) || (h
> IMAGE_MAX_HEIGHT_5597
))
1541 if((w
> IMAGE_MAX_WIDTH
) || (h
> IMAGE_MAX_HEIGHT
))
1545 if(pPriv
->grabbedByV4L
)
1548 depth
= pSiS
->CurrentLayout
.bitsPerPixel
>> 3;
1551 pPriv
->pitch
= ((w
<< 1) + 63) & ~63; /* Only packed pixel modes supported */
1552 size
= h
* pPriv
->pitch
;
1553 pPriv
->linear
= SIS6326AllocateOverlayMemory(pScrn
, pPriv
->linear
, size
);
1557 pPriv
->totalSize
= size
;
1559 pPriv
->offset
= pPriv
->linear
->offset
* depth
;
1562 surface
->height
= h
;
1563 surface
->pScrn
= pScrn
;
1565 surface
->pitches
= &pPriv
->pitch
;
1566 surface
->offsets
= &pPriv
->offset
;
1567 surface
->devPrivate
.ptr
= (pointer
)pPriv
;
1569 close_overlay(pSiS
, pPriv
);
1570 pPriv
->videoStatus
= 0;
1571 REGION_EMPTY(pScrn
->pScreen
, &pPriv
->clip
);
1572 pSiS
->VideoTimerCallback
= NULL
;
1573 pPriv
->grabbedByV4L
= TRUE
;
1578 SIS6326StopSurface (XF86SurfacePtr surface
)
1580 SISPortPrivPtr pPriv
= (SISPortPrivPtr
)(surface
->devPrivate
.ptr
);
1581 SISPtr pSiS
= SISPTR(surface
->pScrn
);
1583 if(pPriv
->grabbedByV4L
&& pPriv
->videoStatus
) {
1584 close_overlay(pSiS
, pPriv
);
1585 pPriv
->mustwait
= 1;
1586 pPriv
->videoStatus
= 0;
1592 SIS6326FreeSurface (XF86SurfacePtr surface
)
1594 SISPortPrivPtr pPriv
= (SISPortPrivPtr
)(surface
->devPrivate
.ptr
);
1596 if(pPriv
->grabbedByV4L
) {
1597 SIS6326StopSurface(surface
);
1598 SIS6326FreeOverlayMemory(surface
->pScrn
);
1599 pPriv
->grabbedByV4L
= FALSE
;
1605 SIS6326GetSurfaceAttribute (
1611 SISPortPrivPtr pPriv
= GET_PORT_PRIVATE(pScrn
);
1613 return SIS6326GetPortAttribute(pScrn
, attribute
, value
, (pointer
)pPriv
);
1617 SIS6326SetSurfaceAttribute(
1623 SISPortPrivPtr pPriv
= GET_PORT_PRIVATE(pScrn
);;
1625 return SIS6326SetPortAttribute(pScrn
, attribute
, value
, (pointer
)pPriv
);
1629 SIS6326DisplaySurface (
1630 XF86SurfacePtr surface
,
1631 short src_x
, short src_y
,
1632 short drw_x
, short drw_y
,
1633 short src_w
, short src_h
,
1634 short drw_w
, short drw_h
,
1638 ScrnInfoPtr pScrn
= surface
->pScrn
;
1639 SISPortPrivPtr pPriv
= (SISPortPrivPtr
)(surface
->devPrivate
.ptr
);
1641 if(!pPriv
->grabbedByV4L
)
1644 pPriv
->drw_x
= drw_x
;
1645 pPriv
->drw_y
= drw_y
;
1646 pPriv
->drw_w
= drw_w
;
1647 pPriv
->drw_h
= drw_h
;
1648 pPriv
->src_x
= src_x
;
1649 pPriv
->src_y
= src_y
;
1650 pPriv
->src_w
= src_w
;
1651 pPriv
->src_h
= src_h
;
1652 pPriv
->id
= surface
->id
;
1653 pPriv
->height
= surface
->height
;
1654 pPriv
->bufAddr
[0] = surface
->offsets
[0];
1655 pPriv
->currentBuf
= 0;
1656 pPriv
->srcPitch
= surface
->pitches
[0];
1658 SIS6326DisplayVideo(pScrn
, pPriv
);
1660 if(pPriv
->autopaintColorKey
) {
1661 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0)
1662 XAAFillSolidRects(pScrn
, pPriv
->colorKey
, GXcopy
, ~0,
1663 REGION_NUM_RECTS(clipBoxes
),
1664 REGION_RECTS(clipBoxes
));
1666 xf86XVFillKeyHelper(pScrn
->pScreen
, pPriv
->colorKey
, clipBoxes
);
1670 pPriv
->videoStatus
= CLIENT_VIDEO_ON
;
1675 XF86OffscreenImageRec SIS6326OffscreenImages
[2] =
1678 &SIS6326Images
[0], /* YUV2 */
1679 VIDEO_OVERLAID_IMAGES
| VIDEO_CLIP_TO_VIEWPORT
,
1680 SIS6326AllocSurface
,
1682 SIS6326DisplaySurface
,
1684 SIS6326GetSurfaceAttribute
,
1685 SIS6326SetSurfaceAttribute
,
1686 IMAGE_MAX_WIDTH
, IMAGE_MAX_HEIGHT
,
1688 &SIS6326Attributes
[0] /* Support all attributes */
1691 &SIS6326Images
[1], /* UYVY */
1692 VIDEO_OVERLAID_IMAGES
| VIDEO_CLIP_TO_VIEWPORT
,
1693 SIS6326AllocSurface
,
1695 SIS6326DisplaySurface
,
1697 SIS6326GetSurfaceAttribute
,
1698 SIS6326SetSurfaceAttribute
,
1699 IMAGE_MAX_WIDTH
, IMAGE_MAX_HEIGHT
,
1701 &SIS6326Attributes
[0] /* Support all attributes */
1706 SIS6326InitOffscreenImages(ScreenPtr pScrn
)
1708 xf86XVRegisterOffscreenImages(pScrn
, SIS6326OffscreenImages
, 2);