1 /*
2  * Xv driver for SiS 300, 315 and 330 series.
3  *
4  * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1) Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2) Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3) The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * Author:    Thomas Winischhofer <thomas@winischhofer.net>
29  *
30  * Formerly based on a mostly non-working code fragment for the 630 by
31  * Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan which is
32  * Copyright (C) 2000 Silicon Integrated Systems Corp, Inc.
33  *
34  * Basic structure based on the mga Xv driver by Mark Vojkovich
35  * and i810 Xv driver by Jonathan Bian <jonathan.bian@intel.com>.
36  *
37  * All comments in this file are by Thomas Winischhofer.
38  *
39  * The overlay adaptor supports the following chipsets:
40  *  SiS300: No registers >0x65, two overlays (one used for CRT1, one for CRT2)
41  *  SiS630/730: No registers >0x6b, two overlays (one used for CRT1, one for CRT2)
42  *  SiS550: Full register range, two overlays (one used for CRT1, one for CRT2)
43  *  SiS315: Full register range, one overlay (used for both CRT1 and CRT2 alt.)
44  *  SiS650/740: Full register range, one overlay (used for both CRT1 and CRT2 alt.)
45  *  SiSM650/651: Full register range, two overlays (one used for CRT1, one for CRT2)
46  *  SiS330: Full register range, one overlay (used for both CRT1 and CRT2 alt.)
47  *  SiS661/741/760: Full register range, two overlays (one used for CRT1, one for CRT2)
48  *  SiS340: - ? overlays. Extended registers for DDA.
49  *  SiS761: - ? overlays. Extended registers for DDA.
50  *  XGI Volari V3XT/V5/V8: 1 Overlay. Extended registers for DDA.
51  *
52  * Help for reading the code:
53  * 315/550/650/740/M650/651/330/661/741/76x/340/XGI = SIS_315_VGA
54  * 300/630/730                                      = SIS_300_VGA
55  * For chipsets with 2 overlays, hasTwoOverlays will be true
56  *
57  * Notes on display modes:
58  *
59  * -) dual head mode:
60  *    DISPMODE is either SINGLE1 or SINGLE2, hence you need to check dualHeadMode flag
61  *    DISPMODE is _never_ MIRROR.
62  *    a) Chipsets with 2 overlays:
63  *       315/330 series: Only half sized overlays available (width 960), 660: 1536
64  *       Overlay 1 is used on CRT1, overlay 2 for CRT2.
65  *    b) Chipsets with 1 overlay:
66  *       Full size overlays available.
67  *       Overlay is used for either CRT1 or CRT2
68  * -) merged fb mode:
69  *    a) Chipsets with 2 overlays:
70  *       315/330 series: Only half sized overlays available (width 960), 660: 1536
71  *       DISPMODE is always MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2.
72  *    b) Chipsets with 1 overlay:
73  *       Full size overlays available.
74  *       DISPMODE is either SINGLE1 or SINGLE2. Overlay is used accordingly on either
75  *       CRT1 or CRT2 (automatically, where it is located)
76  * -) mirror mode (without dualhead or mergedfb)
77  *    a) Chipsets with 2 overlays:
78  *       315/330 series: Only half sized overlays available (width 960), 660: 1536
79  *       DISPMODE is MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2.
80  *    b) Chipsets with 1 overlay:
81  *       Full size overlays available.
82  *       DISPMODE is either SINGLE1 or SINGLE2. Overlay is used depending on
83  * 	 XvOnCRT2 flag.
84  *
85  * About the video blitter:
86  * The video blitter adaptor supports 16 ports. By default, adaptor 0 will
87  * be the overlay adaptor, adaptor 1 the video blitter. The option XvDefaultAdaptor
88  * allows reversing this.
89  * Since SiS does not provide information on the 3D engine, I could not
90  * implement scaling. Instead, the driver paints a black border around the unscaled
91  * video if the destination area is bigger than the video.
92  *
93  */
94 
95 #ifdef HAVE_CONFIG_H
96 #include "config.h"
97 #endif
98 
99 #include "sis.h"
100 #ifdef SIS_USE_XAA
101 #include "xf86fbman.h"
102 #endif
103 #include "regionstr.h"
104 
105 #include "xf86xv.h"
106 #include <X11/extensions/Xv.h>
107 #include "dixstruct.h"
108 #include "fourcc.h"
109 
110 #define SIS_NEED_inSISREG
111 #define SIS_NEED_outSISREG
112 #define SIS_NEED_inSISIDXREG
113 #define SIS_NEED_outSISIDXREG
114 #define SIS_NEED_setSISIDXREGmask
115 #define SIS_NEED_MYMMIO
116 #include "sis_regs.h"
117 
118 #ifdef INCL_YUV_BLIT_ADAPTOR
119 #include "sis310_accel.h"
120 #endif
121 
122 #include "sis_video.h"
123 
124 /*********************************
125  *       Raw register access     *
126  *********************************/
127 
128 #if 0
129 static CARD32 _sisread(SISPtr pSiS, CARD32 reg)
130 {
131     return *(pSiS->IOBase + reg);
132 }
133 
134 static void _siswrite(SISPtr pSiS, CARD32 reg, CARD32 data)
135 {
136     *(pSiS->IOBase + reg) = data;
137 }
138 #endif
139 
getsrreg(SISPtr pSiS,CARD8 reg)140 static CARD8 getsrreg(SISPtr pSiS, CARD8 reg)
141 {
142     CARD8 ret;
143     inSISIDXREG(SISSR, reg, ret);
144     return ret;
145 }
146 
getvideoreg(SISPtr pSiS,CARD8 reg)147 static CARD8 getvideoreg(SISPtr pSiS, CARD8 reg)
148 {
149     CARD8 ret;
150     inSISIDXREG(SISVID, reg, ret);
151     return ret;
152 }
153 
setvideoreg(SISPtr pSiS,CARD8 reg,CARD8 data)154 static __inline void setvideoreg(SISPtr pSiS, CARD8 reg, CARD8 data)
155 {
156     outSISIDXREG(SISVID, reg, data);
157 }
158 
setvideoregmask(SISPtr pSiS,CARD8 reg,CARD8 data,CARD8 mask)159 static __inline void setvideoregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask)
160 {
161     setSISIDXREGmask(SISVID, reg, data, mask);
162 }
163 
setsrregmask(SISPtr pSiS,CARD8 reg,CARD8 data,CARD8 mask)164 static void setsrregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask)
165 {
166     setSISIDXREGmask(SISSR, reg, data, mask);
167 }
168 
169 /* VBlank */
vblank_active_CRT1(SISPtr pSiS,SISPortPrivPtr pPriv)170 static CARD8 vblank_active_CRT1(SISPtr pSiS, SISPortPrivPtr pPriv)
171 {
172     return(inSISREG(SISINPSTAT) & 0x08); /* Verified */
173 }
174 
vblank_active_CRT2(SISPtr pSiS,SISPortPrivPtr pPriv)175 static CARD8 vblank_active_CRT2(SISPtr pSiS, SISPortPrivPtr pPriv)
176 {
177     CARD8 ret;
178 
179     if(pPriv->bridgeIsSlave) return(vblank_active_CRT1(pSiS, pPriv));
180 
181     if(pSiS->VGAEngine == SIS_315_VGA) {
182        inSISIDXREG(SISPART1, 0x30, ret);
183     } else {
184        inSISIDXREG(SISPART1, 0x25, ret);
185     }
186     return(ret & 0x02);  /* Verified */
187 }
188 
189 /* Scanline - unused */
190 #if 0
191 static CARD16 get_scanline_CRT1(SISPtr pSiS)
192 {
193     CARD32 line;
194 
195     _siswrite(pSiS, REG_PRIM_CRT_COUNTER, 0x00000001);
196     line = _sisread(pSiS, REG_PRIM_CRT_COUNTER);
197 
198     return((CARD16)((line >> 16) & 0x07FF));
199 }
200 #endif
201 
get_scanline_CRT2(SISPtr pSiS,SISPortPrivPtr pPriv)202 static CARD16 get_scanline_CRT2(SISPtr pSiS, SISPortPrivPtr pPriv)
203 {
204     CARD8 reg1, reg2;
205 
206     if(pSiS->VGAEngine == SIS_315_VGA) {
207        inSISIDXREG(SISPART1, 0x32, reg1);
208        inSISIDXREG(SISPART1, 0x33, reg2);
209     } else {
210        inSISIDXREG(SISPART1, 0x27, reg1);
211        inSISIDXREG(SISPART1, 0x28, reg2);
212     }
213 
214     return((CARD16)(reg1 | ((reg2 & 0x70) << 4)));
215 }
216 
217 /* Helper: Count attributes */
218 static int
SiSCountAttributes(XF86AttributeRec * attrs)219 SiSCountAttributes(XF86AttributeRec *attrs)
220 {
221    int num = 0;
222 
223    while(attrs[num].name) num++;
224 
225    return num;
226 }
227 
228 /*********************************
229  *          Video gamma          *
230  *********************************/
231 
232 static void
SiSComputeXvGamma(SISPtr pSiS)233 SiSComputeXvGamma(SISPtr pSiS)
234 {
235     int num = 255, i;
236     double red = 1.0 / (double)((double)pSiS->XvGammaRed / 1000);
237     double green = 1.0 / (double)((double)pSiS->XvGammaGreen / 1000);
238     double blue = 1.0 / (double)((double)pSiS->XvGammaBlue / 1000);
239 
240     for(i = 0; i <= num; i++) {
241         pSiS->XvGammaRampRed[i] =
242 	    (red == 1.0) ? i : (CARD8)(pow((double)i / (double)num, red) * (double)num + 0.5);
243 
244 	pSiS->XvGammaRampGreen[i] =
245 	    (green == 1.0) ? i : (CARD8)(pow((double)i / (double)num, green) * (double)num + 0.5);
246 
247 	pSiS->XvGammaRampBlue[i] =
248 	    (blue == 1.0) ? i : (CARD8)(pow((double)i / (double)num, blue) * (double)num + 0.5);
249     }
250 }
251 
252 static void
SiSSetXvGamma(SISPtr pSiS)253 SiSSetXvGamma(SISPtr pSiS)
254 {
255     int i;
256     UChar backup = getsrreg(pSiS, 0x1f);
257     setsrregmask(pSiS, 0x1f, 0x08, 0x18);
258     for(i = 0; i <= 255; i++) {
259        SIS_MMIO_OUT32(pSiS->IOBase, 0x8570,
260 			(i << 24)			 |
261 			(pSiS->XvGammaRampBlue[i] << 16) |
262 			(pSiS->XvGammaRampGreen[i] << 8) |
263 			pSiS->XvGammaRampRed[i]);
264     }
265     setsrregmask(pSiS, 0x1f, backup, 0xff);
266 }
267 
268 void
SiSUpdateXvGamma(SISPtr pSiS,SISPortPrivPtr pPriv)269 SiSUpdateXvGamma(SISPtr pSiS, SISPortPrivPtr pPriv)
270 {
271     UChar sr7 = getsrreg(pSiS, 0x07);
272 
273     if(!pSiS->XvGamma) return;
274     if(!(pSiS->MiscFlags & MISC_CRT1OVERLAYGAMMA)) return;
275 
276 #ifdef SISDUALHEAD
277     if((pPriv->dualHeadMode) && (!pSiS->SecondHead)) return;
278 #endif
279 
280     if(!(sr7 & 0x04)) return;
281 
282     SiSComputeXvGamma(pSiS);
283     SiSSetXvGamma(pSiS);
284 }
285 
286 static void
SISResetXvGamma(ScrnInfoPtr pScrn)287 SISResetXvGamma(ScrnInfoPtr pScrn)
288 {
289     SISPtr pSiS = SISPTR(pScrn);
290     SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
291 
292     SiSUpdateXvGamma(pSiS, pPriv);
293 }
294 
295 /*********************************
296  *          InitVideo()          *
297  *********************************/
298 
299 void
SISInitVideo(ScreenPtr pScreen)300 SISInitVideo(ScreenPtr pScreen)
301 {
302     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
303     SISPtr pSiS = SISPTR(pScrn);
304     XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
305     XF86VideoAdaptorPtr newAdaptor = NULL, newBlitAdaptor = NULL;
306     int num_adaptors;
307 
308     newAdaptor = SISSetupImageVideo(pScreen);
309     if(newAdaptor) {
310        SISInitOffscreenImages(pScreen);
311     }
312 
313 #ifdef INCL_YUV_BLIT_ADAPTOR
314     if( ( (pSiS->ChipFlags & SiSCF_Is65x) ||
315           (pSiS->ChipType >= SIS_330) ) &&
316         (pScrn->bitsPerPixel != 8) ) {
317        newBlitAdaptor = SISSetupBlitVideo(pScreen);
318     }
319 #endif
320 
321     num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
322 
323     if(newAdaptor || newBlitAdaptor) {
324        int size = num_adaptors;
325 
326        if(newAdaptor)     size++;
327        if(newBlitAdaptor) size++;
328 
329        newAdaptors = malloc(size * sizeof(XF86VideoAdaptorPtr*));
330        if(newAdaptors) {
331           if(num_adaptors) {
332              memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
333 	  }
334 	  if(pSiS->XvDefAdaptorBlit) {
335 	     if(newBlitAdaptor) {
336                 newAdaptors[num_adaptors] = newBlitAdaptor;
337                 num_adaptors++;
338              }
339 	  }
340 	  if(newAdaptor) {
341              newAdaptors[num_adaptors] = newAdaptor;
342              num_adaptors++;
343           }
344 	  if(!pSiS->XvDefAdaptorBlit) {
345 	     if(newBlitAdaptor) {
346                 newAdaptors[num_adaptors] = newBlitAdaptor;
347                 num_adaptors++;
348              }
349 	  }
350 	  adaptors = newAdaptors;
351        }
352     }
353 
354     if(num_adaptors) {
355        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
356     }
357 
358     if(newAdaptors) {
359        free(newAdaptors);
360     }
361 }
362 
363 /*********************************
364  *       SetPortsDefault()       *
365  *********************************/
366 
367 void
SISSetPortDefaults(ScrnInfoPtr pScrn,SISPortPrivPtr pPriv)368 SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
369 {
370     SISPtr    pSiS = SISPTR(pScrn);
371 #ifdef SISDUALHEAD
372     SISEntPtr pSiSEnt = pSiS->entityPrivate;;
373 #endif
374 
375     pPriv->colorKey    = pSiS->colorKey = 0x000101fe;
376     pPriv->brightness  = pSiS->XvDefBri;
377     pPriv->contrast    = pSiS->XvDefCon;
378     pPriv->hue         = pSiS->XvDefHue;
379     pPriv->saturation  = pSiS->XvDefSat;
380     pPriv->autopaintColorKey = TRUE;
381     pPriv->disablegfx  = pSiS->XvDefDisableGfx;
382     pPriv->disablegfxlr= pSiS->XvDefDisableGfxLR;
383     pSiS->disablecolorkeycurrent = pSiS->XvDisableColorKey;
384     pPriv->usechromakey    = pSiS->XvUseChromaKey;
385     pPriv->insidechromakey = pSiS->XvInsideChromaKey;
386     pPriv->yuvchromakey    = pSiS->XvYUVChromaKey;
387     pPriv->chromamin       = pSiS->XvChromaMin;
388     pPriv->chromamax       = pSiS->XvChromaMax;
389     if(pPriv->dualHeadMode) {
390 #ifdef SISDUALHEAD
391        if(!pSiS->SecondHead) {
392           pPriv->tvxpos      = pSiS->tvxpos;
393           pPriv->tvypos      = pSiS->tvypos;
394 	  pPriv->updatetvxpos = TRUE;
395           pPriv->updatetvypos = TRUE;
396        }
397 #endif
398     } else {
399        pPriv->tvxpos      = pSiS->tvxpos;
400        pPriv->tvypos      = pSiS->tvypos;
401        pPriv->updatetvxpos = TRUE;
402        pPriv->updatetvypos = TRUE;
403     }
404 #ifdef SIS_CP
405     SIS_CP_VIDEO_DEF
406 #endif
407     if(pPriv->dualHeadMode) {
408 #ifdef SISDUALHEAD
409        pPriv->crtnum =
410 	  pSiSEnt->curxvcrtnum =
411 	     pSiSEnt->XvOnCRT2 ? 1 : 0;
412 #endif
413     } else
414        pPriv->crtnum = pSiS->XvOnCRT2 ? 1 : 0;
415 
416     pSiS->XvGammaRed = pSiS->XvGammaRedDef;
417     pSiS->XvGammaGreen = pSiS->XvGammaGreenDef;
418     pSiS->XvGammaBlue = pSiS->XvGammaBlueDef;
419     SiSUpdateXvGamma(pSiS, pPriv);
420 }
421 
422 /*********************************
423  *          ResetVideo()         *
424  *********************************/
425 
426 static void
SISResetVideo(ScrnInfoPtr pScrn)427 SISResetVideo(ScrnInfoPtr pScrn)
428 {
429     SISPtr pSiS = SISPTR(pScrn);
430     SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
431 
432     /* Unlock registers */
433 #ifdef UNLOCK_ALWAYS
434     sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
435 #endif
436     if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1) {
437        setvideoreg (pSiS, Index_VI_Passwd, 0x86);
438        if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1)
439 	  xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
440 		 "Xv: Video password could not unlock registers\n");
441     }
442 
443     /* Initialize first overlay (CRT1) ------------------------------- */
444 
445     /* This bit has obviously a different meaning on 315 series (linebuffer-related) */
446     if(pSiS->VGAEngine == SIS_300_VGA) {
447        /* Write-enable video registers */
448        setvideoregmask(pSiS, Index_VI_Control_Misc2,      0x80, 0x81);
449     } else {
450        /* Select overlay 2, clear all linebuffer related bits */
451        setvideoregmask(pSiS, Index_VI_Control_Misc2,      0x00, 0xb1);
452     }
453 
454     /* Disable overlay */
455     setvideoregmask(pSiS, Index_VI_Control_Misc0,         0x00, 0x02);
456 
457     /* Disable bob de-interlacer and some strange bit */
458     setvideoregmask(pSiS, Index_VI_Control_Misc1,         0x00, 0x82);
459 
460     /* Select RGB chroma key format (300 series only) */
461     if(pSiS->VGAEngine == SIS_300_VGA) {
462        setvideoregmask(pSiS, Index_VI_Control_Misc0,      0x00, 0x40);
463     }
464 
465     /* Reset scale control and contrast */
466     /* (Enable DDA (interpolation)) */
467     setvideoregmask(pSiS, Index_VI_Scale_Control,         0x60, 0x60);
468     setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl,     0x04, 0x1F);
469 
470     setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low,     0x00);
471     setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle,  0x00);
472     setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low,         0x00);
473     setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle,      0x00);
474     setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00);
475     setvideoreg(pSiS, Index_VI_Play_Threshold_Low,        0x00);
476     setvideoreg(pSiS, Index_VI_Play_Threshold_High,       0x00);
477     if(pSiS->Chipset == PCI_CHIP_SIS330) {
478        /* Disable contrast enhancement (?) */
479        setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
480     } else if(pPriv->is661741760) {
481        setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0);
482        if(pPriv->is760) {
483           setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x3c, 0x3c);
484        } else { /* 661, 741 */
485           setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x2c, 0x3c);
486        }
487     } else if((pSiS->Chipset == PCI_CHIP_SIS340) ||
488 	      (pSiS->Chipset == PCI_CHIP_XGIXG20) ||
489 	      (pSiS->Chipset == PCI_CHIP_XGIXG40)) {
490        /* Disable contrast enhancement (?) */
491        setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
492        /* Threshold high */
493        setvideoregmask(pSiS, 0xb5, 0x00, 0x01);
494        setvideoregmask(pSiS, 0xb6, 0x00, 0x01);
495        /* Enable horizontal, disable vertical 4-tap DDA scaler */
496        setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xc0);
497        set_dda_regs(pSiS, 1.0);
498        /* Enable software-flip */
499        setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x20, 0x20);
500        /* "Disable video processor" */
501        setsrregmask(pSiS, 0x3f, 0x00, 0x02);
502     } else if(pPriv->is761) {
503        /* Disable contrast enhancement (?) */
504        setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
505        /* Threshold high */
506        setvideoregmask(pSiS, 0xb5, 0x00, 0x01);
507        setvideoregmask(pSiS, 0xb6, 0x00, 0x01);
508        /* Enable horizontal, disable vertical 4-tap DDA scaler */
509        setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xC0);
510        /* ? */
511        setvideoregmask(pSiS, 0xb6, 0x02, 0x02);
512        set_dda_regs(pSiS, 1.0);
513        setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x00, 0x3c);
514     }
515 
516     if((pSiS->ChipFlags & SiSCF_Is65x) || (pPriv->is661741760)) {
517        setvideoregmask(pSiS, Index_VI_Control_Misc2,  0x00, 0x04);
518     }
519 
520     /* Reset top window position for scanline check */
521     setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, 0x00);
522     setvideoreg(pSiS, Index_VI_Win_Ver_Over, 0x00);
523 
524     /* Initialize second overlay (CRT2) - only for 300, 630/730, 550, M650/651, 661/741/660/760 */
525     if(pSiS->hasTwoOverlays) {
526 
527 	if(pSiS->VGAEngine == SIS_300_VGA) {
528 	   /* Write-enable video registers */
529 	   setvideoregmask(pSiS, Index_VI_Control_Misc2,      0x81, 0x81);
530 	} else {
531 	   /* Select overlay 2, clear all linebuffer related bits */
532 	   setvideoregmask(pSiS, Index_VI_Control_Misc2,      0x01, 0xb1);
533 	}
534 
535 	/* Disable overlay */
536 	setvideoregmask(pSiS, Index_VI_Control_Misc0,         0x00, 0x02);
537 
538 	/* Disable bob de-interlacer and some strange bit */
539 	setvideoregmask(pSiS, Index_VI_Control_Misc1,         0x00, 0x82);
540 
541 	/* Select RGB chroma key format */
542 	if(pSiS->VGAEngine == SIS_300_VGA) {
543 	   setvideoregmask(pSiS, Index_VI_Control_Misc0,      0x00, 0x40);
544 	}
545 
546 	/* Reset scale control and contrast */
547 	/* (Enable DDA (interpolation)) */
548 	setvideoregmask(pSiS, Index_VI_Scale_Control,         0x60, 0x60);
549 	setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl,     0x04, 0x1F);
550 
551 	setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low,     0x00);
552 	setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle,  0x00);
553 	setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low,         0x00);
554 	setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle,      0x00);
555 	setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00);
556 	setvideoreg(pSiS, Index_VI_Play_Threshold_Low,        0x00);
557 	setvideoreg(pSiS, Index_VI_Play_Threshold_High,       0x00);
558 
559 	if(pPriv->is661741760) {
560 	   CARD8 temp;
561 	   setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0);
562 	   switch(pSiS->ChipType) {
563 	   case SIS_661: temp = 0x24; break;
564 	   case SIS_741: temp = 0x2c; break;
565 	   default: 	 temp = 0x3c;
566 	   }
567 	   setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, temp, 0x3c);
568 	} else if(pPriv->is761) {
569 	   setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x00, 0x3c);
570 	} else if(pSiS->Chipset == PCI_CHIP_SIS340) {  /* 2 overlays? */
571 	   setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
572 	   setvideoregmask(pSiS, 0xb5, 0x00, 0x01);
573 	   setvideoregmask(pSiS, 0xb6, 0x00, 0x01);
574 	   setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x40, 0xC0);
575 	   set_dda_regs(pSiS, 1.0);
576            setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x20, 0x20);
577 	}
578 
579 	setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, 0x00);
580 	setvideoreg(pSiS, Index_VI_Win_Ver_Over, 0x00);
581 
582     }
583 
584     /* set default properties for overlay 1 (CRT1) -------------------------- */
585     setvideoregmask(pSiS, Index_VI_Control_Misc2,         0x00, 0x01);
586     setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl,     0x04, 0x07);
587     setvideoreg(pSiS, Index_VI_Brightness,                0x20);
588     if(pSiS->VGAEngine == SIS_315_VGA) {
589        setvideoreg(pSiS, Index_VI_Hue,          	  0x00);
590        setvideoreg(pSiS, Index_VI_Saturation,             0x00);
591     }
592 
593     /* set default properties for overlay 2(CRT2)  -------------------------- */
594     if(pSiS->hasTwoOverlays) {
595        setvideoregmask(pSiS, Index_VI_Control_Misc2,      0x01, 0x01);
596        setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl,  0x04, 0x07);
597        setvideoreg(pSiS, Index_VI_Brightness,             0x20);
598        if(pSiS->VGAEngine == SIS_315_VGA) {
599           setvideoreg(pSiS, Index_VI_Hue,                 0x00);
600           setvideoreg(pSiS, Index_VI_Saturation,    	  0x00);
601        }
602     }
603 
604     /* Reset Xv gamma correction */
605     if(pSiS->VGAEngine == SIS_315_VGA) {
606        SiSUpdateXvGamma(pSiS, pPriv);
607     }
608 
609     pPriv->mustresettap = TRUE;
610 #ifdef SISMERGED
611     pPriv->mustresettap2 = TRUE;
612 #endif
613 }
614 
615 /*********************************
616  *       Set displaymode         *
617  *********************************/
618 
619 /* Set display mode (single CRT1/CRT2, mirror).
620  * MIRROR mode is only available on chipsets with two overlays.
621  * On the other chipsets, if only CRT1 or only CRT2 are used,
622  * the correct display CRT is chosen automatically. If both
623  * CRT1 and CRT2 are connected, the user can choose between CRT1 and
624  * CRT2 by using the option XvOnCRT2.
625  */
626 
627 static void
set_dispmode(ScrnInfoPtr pScrn,SISPortPrivPtr pPriv)628 set_dispmode(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
629 {
630     SISPtr pSiS = SISPTR(pScrn);
631 
632     pPriv->dualHeadMode = pPriv->bridgeIsSlave = FALSE;
633 
634     if(SiSBridgeIsInSlaveMode(pScrn)) {
635        pPriv->bridgeIsSlave = TRUE;
636     }
637 
638     if( (pSiS->VBFlags & VB_DISPMODE_MIRROR) ||
639         ((pPriv->bridgeIsSlave) && (pSiS->VBFlags & DISPTYPE_DISP2)) )  {
640        if(pPriv->hasTwoOverlays)
641 	   pPriv->displayMode = DISPMODE_MIRROR;     /* CRT1+CRT2 (2 overlays) */
642        else if(pPriv->crtnum)
643 	  pPriv->displayMode = DISPMODE_SINGLE2;    /* CRT2 only */
644        else
645 	  pPriv->displayMode = DISPMODE_SINGLE1;    /* CRT1 only */
646     } else {
647 #ifdef SISDUALHEAD
648        if(pSiS->DualHeadMode) {
649 	  pPriv->dualHeadMode = TRUE;
650 	  if(pSiS->SecondHead)
651 	     pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */
652 	  else
653 	     pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */
654        } else
655 #endif
656        if(pSiS->VBFlags & DISPTYPE_DISP1) {
657 	  pPriv->displayMode = DISPMODE_SINGLE1;    /* CRT1 only */
658        } else {
659 	  pPriv->displayMode = DISPMODE_SINGLE2;    /* CRT2 only */
660        }
661     }
662 }
663 
664 static void
set_disptype_regs(ScrnInfoPtr pScrn,SISPortPrivPtr pPriv)665 set_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
666 {
667     SISPtr pSiS = SISPTR(pScrn);
668 #ifdef SISDUALHEAD
669     SISEntPtr pSiSEnt = pSiS->entityPrivate;
670     int crtnum = 0;
671 
672     if(pPriv->dualHeadMode) crtnum = pSiSEnt->curxvcrtnum;
673 #endif
674 
675     /*
676      *     SR06[7:6]
677      *	      Bit 7: Enable overlay 1 on CRT2
678      *	      Bit 6: Enable overlay 0 on CRT2
679      *     SR32[7:6]
680      *        Bit 7: DCLK/TCLK overlay 1
681      *               0=DCLK (overlay on CRT1)
682      *               1=TCLK (overlay on CRT2)
683      *        Bit 6: DCLK/TCLK overlay 0
684      *               0=DCLK (overlay on CRT1)
685      *               1=TCLK (overlay on CRT2)
686      *
687      * On chipsets with two overlays, we can freely select and also
688      * have a mirror mode. However, we use overlay 0 for CRT1 and
689      * overlay 1 for CRT2.
690      * ATTENTION: CRT2 can only take up to 1 (one) overlay. Setting
691      * SR06/32 to 0xc0 DOES NOT WORK. THAT'S CONFIRMED.
692      * Therefore, we use overlay 0 on CRT2 if in SINGLE2 mode.
693      *
694      * For chipsets with only one overlay, user must choose whether
695      * to display the overlay on CRT1 or CRT2 by setting XvOnCRT2
696      * to TRUE (CRT2) or FALSE (CRT1). The driver does this auto-
697      * matically if only CRT1 or only CRT2 is used.
698      */
699 #ifdef UNLOCK_ALWAYS
700     sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
701 #endif
702 
703     switch (pPriv->displayMode)
704     {
705        case DISPMODE_SINGLE1:				/* CRT1-only mode: */
706 	  if(pPriv->hasTwoOverlays) {
707 	      if(pPriv->dualHeadMode) {
708 		 setsrregmask(pSiS, 0x06, 0x00, 0x40);  /* overlay 0 -> CRT1 */
709 		 setsrregmask(pSiS, 0x32, 0x00, 0x40);
710 	      } else {
711 		 setsrregmask(pSiS, 0x06, 0x00, 0xc0);  /* both overlays -> CRT1 */
712 		 setsrregmask(pSiS, 0x32, 0x00, 0xc0);
713 	      }
714 	  } else {
715 #ifdef SISDUALHEAD
716 	      if((!pPriv->dualHeadMode) || (crtnum == 0)) {
717 #endif
718 		 setsrregmask(pSiS, 0x06, 0x00, 0xc0);  /* only overlay -> CRT1 */
719 		 setsrregmask(pSiS, 0x32, 0x00, 0xc0);
720 #ifdef SISDUALHEAD
721 	      }
722 #endif
723 	  }
724 	  break;
725 
726        case DISPMODE_SINGLE2:			/* CRT2-only mode: */
727 	  if(pPriv->hasTwoOverlays) {
728 	      if(pPriv->dualHeadMode) {
729 		 setsrregmask(pSiS, 0x06, 0x80, 0x80);  /* overlay 1 -> CRT2 */
730 		 setsrregmask(pSiS, 0x32, 0x80, 0x80);
731 	      } else {
732 		 setsrregmask(pSiS, 0x06, 0x40, 0xc0);  /* overlay 0 -> CRT2 */
733 		 setsrregmask(pSiS, 0x32, 0xc0, 0xc0);  /* (although both clocks for CRT2!) */
734 	      }
735 	  } else {
736 #ifdef SISDUALHEAD
737 	      if((!pPriv->dualHeadMode) || (crtnum == 1)) {
738 #endif
739 		 if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
740 		    setsrregmask(pSiS, 0x06, 0x40, 0xc0);  /* overlay 0 -> CRT2 */
741 		    setsrregmask(pSiS, 0x32, 0xc0, 0xc0);  /* (although both clocks for CRT2!) */
742 		 } else {
743 		    setsrregmask(pSiS, 0x06, 0x40, 0xc0);  /* only overlay -> CRT2 */
744 		    setsrregmask(pSiS, 0x32, 0x40, 0xc0);
745 		 }
746 #ifdef SISDUALHEAD
747               }
748 #endif
749 	  }
750 	  break;
751 
752        case DISPMODE_MIRROR:				/* CRT1+CRT2-mode: (only on chips with 2 overlays) */
753        default:
754 	  setsrregmask(pSiS, 0x06, 0x80, 0xc0);         /* overlay 0 -> CRT1, overlay 1 -> CRT2 */
755 	  setsrregmask(pSiS, 0x32, 0x80, 0xc0);
756 	  break;
757     }
758 }
759 
760 static void
set_hastwooverlays(SISPtr pSiS,SISPortPrivPtr pPriv)761 set_hastwooverlays(SISPtr pSiS, SISPortPrivPtr pPriv)
762 {
763     int temp, watchdog;
764 
765     if(pSiS->hasTwoOverlays) {
766        if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
767           if(pPriv->hasTwoOverlays) {
768 	     /* Disable overlay 1 on change */
769 	     setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
770 	     setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
771 	     temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
772 	     if(temp & 0x02) {
773 	        watchdog = WATCHDOG_DELAY;
774 	        while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
775 	        watchdog = WATCHDOG_DELAY;
776 	        while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
777 	        setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
778 	     }
779 	  }
780           pPriv->hasTwoOverlays = FALSE;
781        } else {
782           pPriv->hasTwoOverlays = TRUE;
783        }
784     } else {
785        pPriv->hasTwoOverlays = FALSE;
786     }
787 }
788 
789 static void
set_allowswitchcrt(SISPtr pSiS,SISPortPrivPtr pPriv)790 set_allowswitchcrt(SISPtr pSiS, SISPortPrivPtr pPriv)
791 {
792     if(pPriv->hasTwoOverlays) {
793        pPriv->AllowSwitchCRT = FALSE;
794     } else if((!(pSiS->VBFlags & DISPTYPE_DISP1)) || (!(pSiS->VBFlags & DISPTYPE_DISP2))) {
795        pPriv->AllowSwitchCRT = FALSE;
796        if(!(pSiS->VBFlags & DISPTYPE_DISP1)) pPriv->crtnum = 1;
797        else                                  pPriv->crtnum = 0;
798     } else {
799        pPriv->AllowSwitchCRT = TRUE;
800     }
801 }
802 
803 static void
set_maxencoding(SISPtr pSiS,SISPortPrivPtr pPriv)804 set_maxencoding(SISPtr pSiS, SISPortPrivPtr pPriv)
805 {
806     int half;
807 
808     if(pSiS->VGAEngine == SIS_300_VGA) {
809        DummyEncoding.width = IMAGE_MAX_WIDTH_300;
810        DummyEncoding.height = IMAGE_MAX_HEIGHT_300;
811     } else {
812        DummyEncoding.width = IMAGE_MAX_WIDTH_315;
813        DummyEncoding.height = IMAGE_MAX_HEIGHT_315;
814        half = IMAGE_MAX_WIDTH_315 >> 1;
815        if(pPriv->is661741760) {
816           half = 768 * 2;
817        } else if(pPriv->is340) { /* 2 overlays? */
818           DummyEncoding.width = IMAGE_MAX_WIDTH_340;
819 	  half = 1280; /* ? */
820        } else if(pPriv->is761) {
821           DummyEncoding.width = IMAGE_MAX_WIDTH_761;
822           half = 1920; /* ? */
823        }
824        if(pPriv->hasTwoOverlays) {
825 #ifdef SISDUALHEAD
826           if(pSiS->DualHeadMode) {
827 	     DummyEncoding.width = half;
828           } else
829 #endif
830 #ifdef SISMERGED
831           if(pSiS->MergedFB) {
832 	     DummyEncoding.width = half;
833           } else
834 #endif
835           if(pPriv->displayMode == DISPMODE_MIRROR) {
836 	     DummyEncoding.width = half;
837           }
838        }
839     }
840 }
841 
842 /*********************************
843  *       ResetXvDisplay()        *
844  *********************************/
845 
846 static void
SISResetXvDisplay(ScrnInfoPtr pScrn)847 SISResetXvDisplay(ScrnInfoPtr pScrn)
848 {
849    SISPtr pSiS = SISPTR(pScrn);
850    SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
851 
852    if(!pPriv) return;
853 
854    set_hastwooverlays(pSiS, pPriv);
855    set_allowswitchcrt(pSiS, pPriv);
856    set_dispmode(pScrn, pPriv);
857    set_maxencoding(pSiS, pPriv);
858 }
859 
860 /*********************************
861  *       SetupImageVideo()       *
862  *********************************/
863 
864 static XF86VideoAdaptorPtr
SISSetupImageVideo(ScreenPtr pScreen)865 SISSetupImageVideo(ScreenPtr pScreen)
866 {
867     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
868     SISPtr pSiS = SISPTR(pScrn);
869     XF86VideoAdaptorPtr adapt;
870     SISPortPrivPtr pPriv;
871 
872 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
873     XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr;
874 
875     if(!pXAA || !pXAA->FillSolidRects) {
876        return NULL;
877     }
878 #endif
879 
880     if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
881                             sizeof(SISPortPrivRec) +
882                             sizeof(DevUnion)))) {
883        return NULL;
884     }
885 
886     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
887     adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
888     adapt->name = "SIS 300/315/330 series Video Overlay";
889     adapt->nEncodings = 1;
890     adapt->pEncodings = &DummyEncoding;
891 
892     adapt->nFormats = NUM_FORMATS;
893     adapt->pFormats = SISFormats;
894     adapt->nPorts = 1;
895     adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
896 
897     pPriv = (SISPortPrivPtr)(&adapt->pPortPrivates[1]);
898 
899     pPriv->videoStatus = 0;
900     pPriv->currentBuf  = 0;
901     pPriv->handle      = NULL;
902     pPriv->grabbedByV4L= FALSE;
903     pPriv->NoOverlay   = FALSE;
904     pPriv->PrevOverlay = FALSE;
905     pPriv->is661741760 = ((pSiS->ChipType >= SIS_661) &&
906 			  (pSiS->ChipType <= SIS_760)) ? TRUE : FALSE;
907     pPriv->is760       = (pSiS->ChipType == SIS_760)   ? TRUE : FALSE;
908     pPriv->is761       = (pSiS->ChipType == SIS_761)   ? TRUE : FALSE;
909     pPriv->is340       = (pSiS->Chipset == PCI_CHIP_SIS340) ? TRUE : FALSE;
910     pPriv->isXGI       = (pSiS->Chipset == PCI_CHIP_XGIXG20 ||
911 			  pSiS->Chipset == PCI_CHIP_XGIXG40) ? TRUE : FALSE;
912 
913     /* Setup chipset type helpers */
914     set_hastwooverlays(pSiS, pPriv);
915     set_allowswitchcrt(pSiS, pPriv);
916 
917     pPriv->havetapscaler = FALSE;
918     if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) {
919        pPriv->havetapscaler = TRUE;
920     }
921 
922     adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
923     if(pSiS->VGAEngine == SIS_300_VGA) {
924        adapt->nImages = NUM_IMAGES_300;
925        adapt->pAttributes = SISAttributes_300;
926        adapt->nAttributes = SiSCountAttributes(&SISAttributes_300[0]);
927     } else {
928        if(pSiS->ChipType >= SIS_330) {
929           adapt->nImages = NUM_IMAGES_330;
930        } else {
931           adapt->nImages = NUM_IMAGES_315;
932        }
933        adapt->pAttributes = SISAttributes_315;
934        adapt->nAttributes = SiSCountAttributes(&SISAttributes_315[0]);
935        if((pSiS->hasTwoOverlays) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO))) {
936           adapt->nAttributes--;
937        }
938     }
939 
940     adapt->pImages = SISImages;
941     adapt->PutVideo = NULL;
942     adapt->PutStill = NULL;
943     adapt->GetVideo = NULL;
944     adapt->GetStill = NULL;
945     adapt->StopVideo = SISStopVideo;
946     adapt->SetPortAttribute = SISSetPortAttribute;
947     adapt->GetPortAttribute = SISGetPortAttribute;
948     adapt->QueryBestSize = SISQueryBestSize;
949     adapt->PutImage = SISPutImage;
950     adapt->QueryImageAttributes = SISQueryImageAttributes;
951 
952     /* gotta uninit this someplace */
953 #if defined(REGION_NULL)
954     REGION_NULL(pScreen, &pPriv->clip);
955 #else
956     REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
957 #endif
958 
959     pSiS->adaptor = adapt;
960 
961     pSiS->xvBrightness        = MAKE_ATOM(sisxvbrightness);
962     pSiS->xvContrast          = MAKE_ATOM(sisxvcontrast);
963     pSiS->xvColorKey          = MAKE_ATOM(sisxvcolorkey);
964     pSiS->xvSaturation        = MAKE_ATOM(sisxvsaturation);
965     pSiS->xvHue               = MAKE_ATOM(sisxvhue);
966     pSiS->xvSwitchCRT  	      = MAKE_ATOM(sisxvswitchcrt);
967     pSiS->xvAutopaintColorKey = MAKE_ATOM(sisxvautopaintcolorkey);
968     pSiS->xvSetDefaults       = MAKE_ATOM(sisxvsetdefaults);
969     pSiS->xvDisableGfx        = MAKE_ATOM(sisxvdisablegfx);
970     pSiS->xvDisableGfxLR      = MAKE_ATOM(sisxvdisablegfxlr);
971     pSiS->xvTVXPosition       = MAKE_ATOM(sisxvtvxposition);
972     pSiS->xvTVYPosition       = MAKE_ATOM(sisxvtvyposition);
973     pSiS->xvGammaRed	      = MAKE_ATOM(sisxvgammared);
974     pSiS->xvGammaGreen	      = MAKE_ATOM(sisxvgammagreen);
975     pSiS->xvGammaBlue	      = MAKE_ATOM(sisxvgammablue);
976     pSiS->xvDisableColorkey   = MAKE_ATOM(sisxvdisablecolorkey);
977     pSiS->xvUseChromakey      = MAKE_ATOM(sisxvusechromakey);
978     pSiS->xvInsideChromakey   = MAKE_ATOM(sisxvinsidechromakey);
979     pSiS->xvYUVChromakey      = MAKE_ATOM(sisxvyuvchromakey);
980     pSiS->xvChromaMin	      = MAKE_ATOM(sisxvchromamin);
981     pSiS->xvChromaMax         = MAKE_ATOM(sisxvchromamax);
982 #ifdef SISDEINT
983     pSiS->xvdeintmeth	      = MAKE_ATOM(sisxvdeinterlace);
984 #endif
985 #ifdef XV_SD_DEPRECATED
986     pSiS->xv_QVF              = MAKE_ATOM(sisxvqueryvbflags);
987     pSiS->xv_GDV	      = MAKE_ATOM(sisxvsdgetdriverversion);
988     pSiS->xv_GHI	      = MAKE_ATOM(sisxvsdgethardwareinfo);
989     pSiS->xv_GBI	      = MAKE_ATOM(sisxvsdgetbusid);
990     pSiS->xv_QVV              = MAKE_ATOM(sisxvsdqueryvbflagsversion);
991     pSiS->xv_GSF              = MAKE_ATOM(sisxvsdgetsdflags);
992     pSiS->xv_GSF2             = MAKE_ATOM(sisxvsdgetsdflags2);
993     pSiS->xv_USD              = MAKE_ATOM(sisxvsdunlocksisdirect);
994     pSiS->xv_SVF              = MAKE_ATOM(sisxvsdsetvbflags);
995     pSiS->xv_QDD	      = MAKE_ATOM(sisxvsdquerydetecteddevices);
996     pSiS->xv_CT1	      = MAKE_ATOM(sisxvsdcrt1status);
997     pSiS->xv_CMD	      = MAKE_ATOM(sisxvsdcheckmodeindexforcrt2);
998     pSiS->xv_CMDR	      = MAKE_ATOM(sisxvsdresultcheckmodeindexforcrt2);
999     pSiS->xv_RDT	      = MAKE_ATOM(sisxvsdredetectcrt2);
1000     pSiS->xv_TAF	      = MAKE_ATOM(sisxvsdsisantiflicker);
1001     pSiS->xv_TSA	      = MAKE_ATOM(sisxvsdsissaturation);
1002     pSiS->xv_TEE	      = MAKE_ATOM(sisxvsdsisedgeenhance);
1003     pSiS->xv_COC	      = MAKE_ATOM(sisxvsdsiscolcalibc);
1004     pSiS->xv_COF	      = MAKE_ATOM(sisxvsdsiscolcalibf);
1005     pSiS->xv_CFI	      = MAKE_ATOM(sisxvsdsiscfilter);
1006     pSiS->xv_YFI	      = MAKE_ATOM(sisxvsdsisyfilter);
1007     pSiS->xv_TCO	      = MAKE_ATOM(sisxvsdchcontrast);
1008     pSiS->xv_TTE	      = MAKE_ATOM(sisxvsdchtextenhance);
1009     pSiS->xv_TCF	      = MAKE_ATOM(sisxvsdchchromaflickerfilter);
1010     pSiS->xv_TLF	      = MAKE_ATOM(sisxvsdchlumaflickerfilter);
1011     pSiS->xv_TCC	      = MAKE_ATOM(sisxvsdchcvbscolor);
1012     pSiS->xv_OVR	      = MAKE_ATOM(sisxvsdchoverscan);
1013     pSiS->xv_SGA	      = MAKE_ATOM(sisxvsdenablegamma);
1014     pSiS->xv_TXS	      = MAKE_ATOM(sisxvsdtvxscale);
1015     pSiS->xv_TYS	      = MAKE_ATOM(sisxvsdtvyscale);
1016     pSiS->xv_GSS	      = MAKE_ATOM(sisxvsdgetscreensize);
1017     pSiS->xv_BRR	      = MAKE_ATOM(sisxvsdstorebrir);
1018     pSiS->xv_BRG	      = MAKE_ATOM(sisxvsdstorebrig);
1019     pSiS->xv_BRB	      = MAKE_ATOM(sisxvsdstorebrib);
1020     pSiS->xv_PBR	      = MAKE_ATOM(sisxvsdstorepbrir);
1021     pSiS->xv_PBG	      = MAKE_ATOM(sisxvsdstorepbrig);
1022     pSiS->xv_PBB	      = MAKE_ATOM(sisxvsdstorepbrib);
1023     pSiS->xv_BRR2	      = MAKE_ATOM(sisxvsdstorebrir2);
1024     pSiS->xv_BRG2	      = MAKE_ATOM(sisxvsdstorebrig2);
1025     pSiS->xv_BRB2	      = MAKE_ATOM(sisxvsdstorebrib2);
1026     pSiS->xv_PBR2	      = MAKE_ATOM(sisxvsdstorepbrir2);
1027     pSiS->xv_PBG2	      = MAKE_ATOM(sisxvsdstorepbrig2);
1028     pSiS->xv_PBB2	      = MAKE_ATOM(sisxvsdstorepbrib2);
1029     pSiS->xv_GARC2	      = MAKE_ATOM(sisxvsdstoregarc2);
1030     pSiS->xv_GAGC2	      = MAKE_ATOM(sisxvsdstoregagc2);
1031     pSiS->xv_GABC2	      = MAKE_ATOM(sisxvsdstoregabc2);
1032     pSiS->xv_BRRC2	      = MAKE_ATOM(sisxvsdstorebrirc2);
1033     pSiS->xv_BRGC2	      = MAKE_ATOM(sisxvsdstorebrigc2);
1034     pSiS->xv_BRBC2	      = MAKE_ATOM(sisxvsdstorebribc2);
1035     pSiS->xv_PBRC2	      = MAKE_ATOM(sisxvsdstorepbrirc2);
1036     pSiS->xv_PBGC2	      = MAKE_ATOM(sisxvsdstorepbrigc2);
1037     pSiS->xv_PBBC2	      = MAKE_ATOM(sisxvsdstorepbribc2);
1038     pSiS->xv_SHC	      = MAKE_ATOM(sisxvsdhidehwcursor);
1039     pSiS->xv_PMD	      = MAKE_ATOM(sisxvsdpanelmode);
1040 #ifdef TWDEBUG
1041     pSiS->xv_STR	      = MAKE_ATOM(sisxvsetreg);
1042 #endif
1043 #endif /* XV_SD_DEPRECATED */
1044 #ifdef SIS_CP
1045     SIS_CP_VIDEO_ATOMS
1046 #endif
1047 
1048     pSiS->xv_sisdirectunlocked = 0;
1049 #ifdef XV_SD_DEPRECATED
1050     pSiS->xv_sd_result = 0;
1051 #endif
1052 
1053     /* 300 series require double words for addresses and pitches,
1054      * 315/330 series require word.
1055      */
1056     switch (pSiS->VGAEngine) {
1057     case SIS_315_VGA:
1058 	pPriv->shiftValue = 1;
1059 	break;
1060     case SIS_300_VGA:
1061     default:
1062 	pPriv->shiftValue = 2;
1063 	break;
1064     }
1065 
1066     /* Set displayMode according to VBFlags */
1067     set_dispmode(pScrn, pPriv);
1068 
1069     /* Now for the linebuffer stuff.
1070      * All chipsets have a certain number of linebuffers, each of a certain
1071      * size. The number of buffers is per overlay.
1072      * Chip        number      size     	  max video size
1073      *  300          2		 ?		     720x576
1074      *  630/730      2		 ?		     720x576
1075      *  315          2		960?		    1920x1080
1076      *  550	     2?		960?		    1920x1080?
1077      *  650/740      2		960 ("120x128")	    1920x1080
1078      *  M650/651..   4		480		    1920x1080
1079      *  330          2		960		    1920x1080
1080      *  661/741/760  4		768 		    1920x1080
1081      *  340          4	       1280?		    1920x1080?
1082      *  761          4         1536?		    1920x1080?
1083      * The unit of size is unknown; I just know that a size of 480 limits
1084      * the video source width to 384. Beyond that, line buffers must be
1085      * merged (otherwise the video output is garbled).
1086      * To use the maximum width (eg 1920x1080 on the 315 series, including
1087      * the M650, 651 and later), *all* line buffers must be merged. Hence,
1088      * we can only use one overlay. This should be set up for modes where
1089      * either only CRT1 or only CRT2 is used.
1090      * If both overlays are going to be used (such as in modes were both
1091      * CRT1 and CRT2 are active), we are limited to the half of the
1092      * maximum width, or 1536 on 661/741/760.
1093      * There is a known hardware problem with the 760 and 761 if the video
1094      * data is in the UMA area: The memory access latency is too big to
1095      * allow two overlays under some circumstances. Therefore, we must
1096      * support switching between hasTwoOverlays and !hasTwoOverlays on
1097      * the fly.
1098      */
1099 
1100     if(pSiS->VGAEngine == SIS_300_VGA) {
1101        pPriv->linebufmask = 0x11;
1102        pPriv->linebufMergeLimit = 384;
1103     } else {
1104        pPriv->linebufmask = 0xb1;
1105        pPriv->linebufMergeLimit = 384;			/* should be 480 */
1106        if(pPriv->is661741760) {
1107           pPriv->linebufMergeLimit = 576;		/* should be 768 */
1108        } else if(pPriv->is340) {
1109           pPriv->linebufMergeLimit = 1280;		/* should be 1280 */
1110        } else if(pPriv->is761) {
1111           pPriv->linebufMergeLimit = 1280;		/* should be 1536 */
1112        } else if(pPriv->isXGI) {
1113           pPriv->linebufMergeLimit = 1280;		/* FIXME */
1114        } else if(!(pPriv->hasTwoOverlays)) {
1115           pPriv->linebufMergeLimit = 720;		/* should be 960 */
1116        }
1117        /* No special treatment for 760/761 required */
1118     }
1119 
1120     set_maxencoding(pSiS, pPriv);
1121 
1122     /* Reset the properties to their defaults */
1123     SISSetPortDefaults(pScrn, pPriv);
1124 
1125     /* Set SR(06, 32) registers according to DISPMODE */
1126     set_disptype_regs(pScrn, pPriv);
1127 
1128     SISResetVideo(pScrn);
1129     pSiS->ResetXv = SISResetVideo;
1130     pSiS->ResetXvDisplay = SISResetXvDisplay;
1131     if(pSiS->VGAEngine == SIS_315_VGA) {
1132        pSiS->ResetXvGamma = SISResetXvGamma;
1133     }
1134 
1135     return adapt;
1136 }
1137 
1138 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0)
1139 static Bool
RegionsEqual(RegionPtr A,RegionPtr B)1140 RegionsEqual(RegionPtr A, RegionPtr B)
1141 {
1142     int *dataA, *dataB;
1143     int num;
1144 
1145     num = REGION_NUM_RECTS(A);
1146     if(num != REGION_NUM_RECTS(B))
1147        return FALSE;
1148 
1149     if((A->extents.x1 != B->extents.x1) ||
1150        (A->extents.x2 != B->extents.x2) ||
1151        (A->extents.y1 != B->extents.y1) ||
1152        (A->extents.y2 != B->extents.y2))
1153        return FALSE;
1154 
1155     dataA = (int*)REGION_RECTS(A);
1156     dataB = (int*)REGION_RECTS(B);
1157 
1158     while(num--) {
1159       if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
1160          return FALSE;
1161       dataA += 2;
1162       dataB += 2;
1163     }
1164 
1165     return TRUE;
1166 }
1167 #endif
1168 
1169 /*********************************
1170  *       SetPortAttribute()      *
1171  *********************************/
1172 
1173 void
SISUpdateVideoParms(SISPtr pSiS,SISPortPrivPtr pPriv)1174 SISUpdateVideoParms(SISPtr pSiS, SISPortPrivPtr pPriv)
1175 {
1176   set_hastwooverlays(pSiS, pPriv);
1177   set_allowswitchcrt(pSiS, pPriv);
1178   set_dispmode(pSiS->pScrn, pPriv);
1179   set_maxencoding(pSiS, pPriv);
1180 }
1181 
1182 static int
SISSetPortAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 value,pointer data)1183 SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1184 		    INT32 value, pointer data)
1185 {
1186   SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
1187   SISPtr pSiS = SISPTR(pScrn);
1188 #ifdef SISDUALHEAD
1189   SISEntPtr pSiSEnt = pSiS->entityPrivate;;
1190 #endif
1191 
1192   if(attribute == pSiS->xvBrightness) {
1193      if((value < -128) || (value > 127))
1194         return BadValue;
1195      pPriv->brightness = value;
1196   } else if(attribute == pSiS->xvContrast) {
1197      if((value < 0) || (value > 7))
1198         return BadValue;
1199      pPriv->contrast = value;
1200   } else if(attribute == pSiS->xvColorKey) {
1201      pPriv->colorKey = pSiS->colorKey = value;
1202      REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1203   } else if(attribute == pSiS->xvAutopaintColorKey) {
1204      if((value < 0) || (value > 1))
1205         return BadValue;
1206      pPriv->autopaintColorKey = value;
1207   } else if(attribute == pSiS->xvSetDefaults) {
1208      SISSetPortDefaults(pScrn, pPriv);
1209   } else if(attribute == pSiS->xvDisableGfx) {
1210      if((value < 0) || (value > 1))
1211         return BadValue;
1212      pPriv->disablegfx = value;
1213   } else if(attribute == pSiS->xvDisableGfxLR) {
1214      if((value < 0) || (value > 1))
1215         return BadValue;
1216      pPriv->disablegfxlr = value;
1217   } else if(attribute == pSiS->xvTVXPosition) {
1218      if((value < -32) || (value > 32))
1219         return BadValue;
1220      pPriv->tvxpos = value;
1221      if(pSiS->xv_sisdirectunlocked) {
1222         SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
1223         pPriv->updatetvxpos = FALSE;
1224      } else {
1225         pSiS->tvxpos = pPriv->tvxpos;
1226 #ifdef SISDUALHEAD
1227         if(pPriv->dualHeadMode) pSiSEnt->tvxpos = pPriv->tvxpos;
1228 #endif
1229         pPriv->updatetvxpos = TRUE;
1230      }
1231   } else if(attribute == pSiS->xvTVYPosition) {
1232      if((value < -32) || (value > 32)) return BadValue;
1233      pPriv->tvypos = value;
1234      if(pSiS->xv_sisdirectunlocked) {
1235         SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
1236         pPriv->updatetvypos = FALSE;
1237      } else {
1238         pSiS->tvypos = pPriv->tvypos;
1239 #ifdef SISDUALHEAD
1240         if(pPriv->dualHeadMode) pSiSEnt->tvypos = pPriv->tvypos;
1241 #endif
1242         pPriv->updatetvypos = TRUE;
1243      }
1244   } else if(attribute == pSiS->xvDisableColorkey) {
1245      if((value < 0) || (value > 1)) return BadValue;
1246      pSiS->disablecolorkeycurrent = value;
1247   } else if(attribute == pSiS->xvUseChromakey) {
1248      if((value < 0) || (value > 1)) return BadValue;
1249      pPriv->usechromakey = value;
1250   } else if(attribute == pSiS->xvInsideChromakey) {
1251      if((value < 0) || (value > 1)) return BadValue;
1252      pPriv->insidechromakey = value;
1253   } else if(attribute == pSiS->xvYUVChromakey) {
1254      if((value < 0) || (value > 1)) return BadValue;
1255      pPriv->yuvchromakey = value;
1256   } else if(attribute == pSiS->xvChromaMin) {
1257      pPriv->chromamin = value;
1258   } else if(attribute == pSiS->xvChromaMax) {
1259      pPriv->chromamax = value;
1260 #ifdef SISDEINT
1261   } else if(attribute == pSiS->xvdeintmeth) {
1262      if(value < 0) value = 0;
1263      if(value > 4) value = 4;
1264      pPriv->deinterlacemethod = value;
1265 #endif
1266 #ifdef SIS_CP
1267   SIS_CP_VIDEO_SETATTRIBUTE
1268 #endif
1269   } else if(attribute == pSiS->xvHue) {
1270      if(pSiS->VGAEngine == SIS_315_VGA) {
1271         if((value < -8) || (value > 7)) return BadValue;
1272         pPriv->hue = value;
1273      } else return BadMatch;
1274   } else if(attribute == pSiS->xvSaturation) {
1275      if(pSiS->VGAEngine == SIS_315_VGA) {
1276         if((value < -7) || (value > 7)) return BadValue;
1277         pPriv->saturation = value;
1278      } else return BadMatch;
1279   } else if(attribute == pSiS->xvGammaRed) {
1280      if(pSiS->VGAEngine == SIS_315_VGA) {
1281         if((value < 100) || (value > 10000))  return BadValue;
1282         pSiS->XvGammaRed = value;
1283         SiSUpdateXvGamma(pSiS, pPriv);
1284      } else return BadMatch;
1285   } else if(attribute == pSiS->xvGammaGreen) {
1286      if(pSiS->VGAEngine == SIS_315_VGA) {
1287         if((value < 100) || (value > 10000)) return BadValue;
1288         pSiS->XvGammaGreen = value;
1289         SiSUpdateXvGamma(pSiS, pPriv);
1290      } else return BadMatch;
1291   } else if(attribute == pSiS->xvGammaBlue) {
1292      if(pSiS->VGAEngine == SIS_315_VGA) {
1293         if((value < 100) || (value > 10000)) return BadValue;
1294         pSiS->XvGammaBlue = value;
1295         SiSUpdateXvGamma(pSiS, pPriv);
1296      } else return BadMatch;
1297   } else if(attribute == pSiS->xvSwitchCRT) {
1298      if(pSiS->VGAEngine == SIS_315_VGA) {
1299         if(pPriv->AllowSwitchCRT) {
1300            if((value < 0) || (value > 1))
1301               return BadValue;
1302 	   pPriv->crtnum = value;
1303 #ifdef SISDUALHEAD
1304            if(pPriv->dualHeadMode) pSiSEnt->curxvcrtnum = value;
1305 #endif
1306         }
1307      } else return BadMatch;
1308   } else {
1309 #ifdef XV_SD_DEPRECATED
1310      return(SISSetPortUtilAttribute(pScrn, attribute, value, pPriv));
1311 #else
1312      return BadMatch;
1313 #endif
1314   }
1315   return Success;
1316 }
1317 
1318 /*********************************
1319  *       GetPortAttribute()      *
1320  *********************************/
1321 
1322 static int
SISGetPortAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 * value,pointer data)1323 SISGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1324 			INT32 *value, pointer data)
1325 {
1326   SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
1327   SISPtr pSiS = SISPTR(pScrn);
1328 #ifdef SISDUALHEAD
1329   SISEntPtr pSiSEnt = pSiS->entityPrivate;;
1330 #endif
1331 
1332   if(attribute == pSiS->xvBrightness) {
1333      *value = pPriv->brightness;
1334   } else if(attribute == pSiS->xvContrast) {
1335      *value = pPriv->contrast;
1336   } else if(attribute == pSiS->xvColorKey) {
1337      *value = pPriv->colorKey;
1338   } else if(attribute == pSiS->xvAutopaintColorKey) {
1339      *value = (pPriv->autopaintColorKey) ? 1 : 0;
1340   } else if(attribute == pSiS->xvDisableGfx) {
1341      *value = (pPriv->disablegfx) ? 1 : 0;
1342   } else if(attribute == pSiS->xvDisableGfxLR) {
1343      *value = (pPriv->disablegfxlr) ? 1 : 0;
1344   } else if(attribute == pSiS->xvTVXPosition) {
1345      *value = SiS_GetTVxposoffset(pScrn);
1346   } else if(attribute == pSiS->xvTVYPosition) {
1347      *value = SiS_GetTVyposoffset(pScrn);
1348   } else if(attribute == pSiS->xvDisableColorkey) {
1349      *value = (pSiS->disablecolorkeycurrent) ? 1 : 0;
1350   } else if(attribute == pSiS->xvUseChromakey) {
1351      *value = (pPriv->usechromakey) ? 1 : 0;
1352   } else if(attribute == pSiS->xvInsideChromakey) {
1353      *value = (pPriv->insidechromakey) ? 1 : 0;
1354   } else if(attribute == pSiS->xvYUVChromakey) {
1355      *value = (pPriv->yuvchromakey) ? 1 : 0;
1356   } else if(attribute == pSiS->xvChromaMin) {
1357      *value = pPriv->chromamin;
1358   } else if(attribute == pSiS->xvChromaMax) {
1359      *value = pPriv->chromamax;
1360 #ifdef SISDEINT
1361   } else if(attribute == pSiS->xvdeintmeth) {
1362      *value = pPriv->deinterlacemethod;
1363 #endif
1364 #ifdef SIS_CP
1365   SIS_CP_VIDEO_GETATTRIBUTE
1366 #endif
1367   } else if(attribute == pSiS->xvHue) {
1368      if(pSiS->VGAEngine == SIS_315_VGA) {
1369         *value = pPriv->hue;
1370      } else return BadMatch;
1371   } else if(attribute == pSiS->xvSaturation) {
1372      if(pSiS->VGAEngine == SIS_315_VGA) {
1373         *value = pPriv->saturation;
1374      } else return BadMatch;
1375   } else if(attribute == pSiS->xvGammaRed) {
1376      if(pSiS->VGAEngine == SIS_315_VGA) {
1377         *value = pSiS->XvGammaRed;
1378      } else return BadMatch;
1379   } else if(attribute == pSiS->xvGammaGreen) {
1380      if(pSiS->VGAEngine == SIS_315_VGA) {
1381         *value = pSiS->XvGammaGreen;
1382      } else return BadMatch;
1383   } else if(attribute == pSiS->xvGammaBlue) {
1384      if(pSiS->VGAEngine == SIS_315_VGA) {
1385         *value = pSiS->XvGammaBlue;
1386      } else return BadMatch;
1387   } else if(attribute == pSiS->xvSwitchCRT) {
1388      if(pSiS->VGAEngine == SIS_315_VGA) {
1389 #ifdef SISDUALHEAD
1390         if(pPriv->dualHeadMode)
1391            *value = pSiSEnt->curxvcrtnum;
1392         else
1393 #endif
1394            *value = pPriv->crtnum;
1395      } else return BadMatch;
1396   } else {
1397 #ifdef XV_SD_DEPRECATED
1398      return(SISGetPortUtilAttribute(pScrn, attribute, value, pPriv));
1399 #else
1400      return BadMatch;
1401 #endif
1402   }
1403   return Success;
1404 }
1405 
1406 /*********************************
1407  *         QueryBestSize()       *
1408  *********************************/
1409 
1410 static void
SISQueryBestSize(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)1411 SISQueryBestSize(
1412   ScrnInfoPtr pScrn,
1413   Bool motion,
1414   short vid_w, short vid_h,
1415   short drw_w, short drw_h,
1416   unsigned int *p_w, unsigned int *p_h,
1417   pointer data
1418 ){
1419   *p_w = drw_w;
1420   *p_h = drw_h;
1421 }
1422 
1423 /*********************************
1424  *       Calc scaling factor     *
1425  *********************************/
1426 
1427 static void
calc_scale_factor(SISOverlayPtr pOverlay,ScrnInfoPtr pScrn,SISPortPrivPtr pPriv,int index,int iscrt2)1428 calc_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn,
1429                  SISPortPrivPtr pPriv, int index, int iscrt2)
1430 {
1431   SISPtr pSiS = SISPTR(pScrn);
1432   CARD32 I=0,mult=0;
1433   int flag=0, flag2=0;
1434 
1435   int dstW = pOverlay->dstBox.x2 - pOverlay->dstBox.x1;
1436   int dstH = pOverlay->dstBox.y2 - pOverlay->dstBox.y1;
1437   int srcW = pOverlay->srcW;
1438   int srcH = pOverlay->srcH;
1439   CARD16 LCDheight = pSiS->LCDheight;
1440   int srcPitch = pOverlay->origPitch;
1441   int origdstH = dstH;
1442   int modeflags = pOverlay->currentmode->Flags;
1443 
1444   /* Stretch image due to panel link scaling */
1445   if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) {
1446      if(pPriv->bridgeIsSlave) {
1447 	if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
1448 	   if(pSiS->MiscFlags & MISC_PANELLINKSCALER) {
1449 	      dstH = (dstH * LCDheight) / pOverlay->SCREENheight;
1450 	   }
1451 	}
1452      } else if((iscrt2 && (pSiS->VBFlags & CRT2_LCD)) ||
1453 	       (!iscrt2 && (pSiS->VBFlags & CRT1_LCDA))) {
1454 	if((pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) || (pSiS->VBFlags & CRT1_LCDA)) {
1455 	   if(pSiS->MiscFlags & MISC_PANELLINKSCALER) {
1456 	      dstH = (dstH * LCDheight) / pOverlay->SCREENheight;
1457 	      if(pPriv->displayMode == DISPMODE_MIRROR) flag = 1;
1458 	   }
1459 	}
1460      }
1461      if((pPriv->bridgeIsSlave || iscrt2) &&
1462         (pSiS->MiscFlags & MISC_STNMODE)) {
1463 	flag2 = 1;
1464      }
1465   }
1466 
1467   /* For double scan modes, we need to double the height
1468    * On 315 and 550 (?), we need to double the width as well.
1469    * Interlace mode vice versa.
1470    */
1471   if((modeflags & V_DBLSCAN) && !flag2) {
1472      dstH = origdstH << 1;
1473      flag = 0;
1474      if((pSiS->ChipType >= SIS_315H) &&
1475 	(pSiS->ChipType <= SIS_550)) {
1476 	dstW <<= 1;
1477      }
1478   } else if(modeflags & V_INTERLACE) {
1479      dstH = origdstH >> 1;
1480      flag = 0;
1481   }
1482 
1483   pOverlay->tap_scale = 1.0;
1484 
1485   if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH;
1486 
1487   if(dstW == srcW) {
1488 
1489      pOverlay->HUSF   = 0x00;
1490      pOverlay->IntBit = 0x05;
1491      pOverlay->wHPre  = 0;
1492 
1493   } else if(dstW > srcW) {
1494 
1495      pOverlay->IntBit = 0x04;
1496      pOverlay->wHPre  = 0;
1497 
1498      if(pPriv->havetapscaler) {
1499         if((dstW > 2) && (srcW > 2)) {
1500            pOverlay->HUSF = (((srcW - 2) << 16) + dstW - 3) / (dstW - 2);
1501         } else {
1502            pOverlay->HUSF = ((srcW << 16) + dstW - 1) / dstW;
1503         }
1504      } else {
1505         dstW += 2;
1506         pOverlay->HUSF = (srcW << 16) / dstW;
1507      }
1508 
1509   } else {
1510 
1511      int tmpW = dstW;
1512 
1513      /* It seems, the hardware can't scale below factor .125 (=1/8) if the
1514         pitch isn't a multiple of 256.
1515 	TODO: Test this on the 315 series!
1516       */
1517      if((srcPitch % 256) || (srcPitch < 256)) {
1518         if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1;
1519      }
1520 
1521      I = 0;
1522      pOverlay->IntBit = 0x01;
1523      while(srcW >= tmpW) {
1524         tmpW <<= 1;
1525         I++;
1526      }
1527      pOverlay->wHPre = (CARD8)(I - 1);
1528      dstW <<= (I - 1);
1529 
1530      pOverlay->tap_scale = (float)srcW / (float)dstW;
1531      if(pOverlay->tap_scale < 1.0) pOverlay->tap_scale = 1.0;
1532 
1533      if((srcW % dstW))
1534         pOverlay->HUSF = ((srcW - dstW) << 16) / dstW;
1535      else
1536         pOverlay->HUSF = 0;
1537   }
1538 
1539   if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT;
1540 
1541   if(dstH == srcH) {
1542 
1543      pOverlay->VUSF   = 0x00;
1544      pOverlay->IntBit |= 0x0A;
1545 
1546   } else if(dstH > srcH) {
1547 
1548      dstH += 2;
1549      pOverlay->IntBit |= 0x08;
1550 
1551      if(pPriv->havetapscaler) {
1552         if((dstH > 2) && (srcH > 2)) {
1553            pOverlay->VUSF = (((srcH - 2) << 16) - 32768 + dstH - 3) / (dstH - 2);
1554         } else {
1555            pOverlay->VUSF = ((srcH << 16) + dstH - 1) / dstH;
1556         }
1557      } else {
1558         pOverlay->VUSF = (srcH << 16) / dstH;
1559      }
1560 
1561   } else {
1562 
1563      I = srcH / dstH;
1564      pOverlay->IntBit |= 0x02;
1565 
1566      if(I < 2) {
1567 	pOverlay->VUSF = ((srcH - dstH) << 16) / dstH;
1568 	/* Needed for LCD-scaling modes */
1569 	if((flag) && (mult = (srcH / origdstH)) >= 2) {
1570 	   pOverlay->pitch /= mult;
1571 	}
1572      } else {
1573 #if 0
1574 	if(((pOverlay->bobEnable & 0x08) == 0x00) &&
1575 	   (((srcPitch * I) >> 2) > 0xFFF)){
1576 	   pOverlay->bobEnable |= 0x08;
1577 	   srcPitch >>= 1;
1578 	}
1579 #endif
1580 	if(((srcPitch * I) >> 2) > 0xFFF) {
1581 	   I = (0xFFF * 2 / srcPitch);
1582 	   pOverlay->VUSF = 0xFFFF;
1583 	} else {
1584 	   dstH = I * dstH;
1585 	   if(srcH % dstH)
1586 	      pOverlay->VUSF = ((srcH - dstH) << 16) / dstH;
1587 	   else
1588 	      pOverlay->VUSF = 0;
1589 	}
1590 	/* set video frame buffer offset */
1591 	pOverlay->pitch = (CARD16)(srcPitch * I);
1592      }
1593   }
1594 }
1595 
1596 #ifdef SISMERGED
1597 static void
calc_scale_factor_2(SISOverlayPtr pOverlay,ScrnInfoPtr pScrn,SISPortPrivPtr pPriv,int index,int iscrt2)1598 calc_scale_factor_2(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn,
1599                  SISPortPrivPtr pPriv, int index, int iscrt2)
1600 {
1601   SISPtr pSiS = SISPTR(pScrn);
1602   CARD32 I=0,mult=0;
1603   int flag=0, flag2=0;
1604 
1605   int dstW = pOverlay->dstBox2.x2 - pOverlay->dstBox2.x1;
1606   int dstH = pOverlay->dstBox2.y2 - pOverlay->dstBox2.y1;
1607   int srcW = pOverlay->srcW2;
1608   int srcH = pOverlay->srcH2;
1609   CARD16 LCDheight = pSiS->LCDheight;
1610   int srcPitch = pOverlay->origPitch;
1611   int origdstH = dstH;
1612   int modeflags = pOverlay->currentmode2->Flags;
1613 
1614   /* Stretch image due to panel link scaling */
1615   if(pSiS->VBFlags & CRT2_LCD) {
1616      if(pSiS->VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
1617 	if(pSiS->MiscFlags & MISC_PANELLINKSCALER) {
1618 	   dstH = (dstH * LCDheight) / pOverlay->SCREENheight2;
1619 	   flag = 1;
1620 	}
1621 	if(pSiS->MiscFlags & MISC_STNMODE) flag2 = 1;
1622      }
1623   }
1624   /* For double scan modes, we need to double the height
1625    * On 315 and 550 (?), we need to double the width as well.
1626    * Interlace mode vice versa.
1627    */
1628   if((modeflags & V_DBLSCAN) && !flag2) {
1629      dstH = origdstH << 1;
1630      flag = 0;
1631      if((pSiS->ChipType >= SIS_315H) &&
1632 	(pSiS->ChipType <= SIS_550)) {
1633 	dstW <<= 1;
1634      }
1635   }
1636   if(modeflags & V_INTERLACE) {
1637      dstH = origdstH >> 1;
1638      flag = 0;
1639   }
1640 
1641   pOverlay->tap_scale2 = 1.0;
1642 
1643   if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH;
1644 
1645   if(dstW == srcW) {
1646 
1647      pOverlay->HUSF2   = 0x00;
1648      pOverlay->IntBit2 = 0x05;
1649      pOverlay->wHPre2  = 0;
1650 
1651   } else if(dstW > srcW) {
1652 
1653      pOverlay->IntBit2 = 0x04;
1654      pOverlay->wHPre2  = 0;
1655 
1656      if(pPriv->havetapscaler) {
1657         if((dstW > 2) && (srcW > 2)) {
1658            pOverlay->HUSF2 = (((srcW - 2) << 16) + dstW - 3) / (dstW - 2);
1659         } else {
1660            pOverlay->HUSF2 = ((srcW << 16) + dstW - 1) / dstW;
1661         }
1662      } else {
1663         dstW += 2;
1664         pOverlay->HUSF2 = (srcW << 16) / dstW;
1665      }
1666 
1667   } else {
1668 
1669      int tmpW = dstW;
1670 
1671      /* It seems, the hardware can't scale below factor .125 (=1/8) if the
1672 	pitch isn't a multiple of 256.
1673 	TODO: Test this on the 315 series!
1674       */
1675      if((srcPitch % 256) || (srcPitch < 256)) {
1676 	if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1;
1677      }
1678 
1679      I = 0;
1680      pOverlay->IntBit2 = 0x01;
1681      while(srcW >= tmpW) {
1682         tmpW <<= 1;
1683         I++;
1684      }
1685      pOverlay->wHPre2 = (CARD8)(I - 1);
1686      dstW <<= (I - 1);
1687 
1688      pOverlay->tap_scale2 = (float)srcW / (float)dstW;
1689      if(pOverlay->tap_scale2 < 1.0) pOverlay->tap_scale2 = 1.0;
1690 
1691      if((srcW % dstW))
1692         pOverlay->HUSF2 = ((srcW - dstW) << 16) / dstW;
1693      else
1694         pOverlay->HUSF2 = 0x00;
1695   }
1696 
1697   if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT;
1698 
1699   if(dstH == srcH) {
1700 
1701      pOverlay->VUSF2   = 0x00;
1702      pOverlay->IntBit2 |= 0x0A;
1703 
1704   } else if(dstH > srcH) {
1705 
1706      dstH += 2;
1707      pOverlay->IntBit2 |= 0x08;
1708 
1709      if(pPriv->havetapscaler) {
1710         if((dstH > 2) && (srcH > 2)) {
1711            pOverlay->VUSF2 = (((srcH - 2) << 16) - 32768 + dstH - 3) / (dstH - 2);
1712         } else {
1713            pOverlay->VUSF2 = ((srcH << 16) + dstH - 1) / dstH;
1714         }
1715      } else {
1716         pOverlay->VUSF2 = (srcH << 16) / dstH;
1717      }
1718 
1719   } else {
1720 
1721      I = srcH / dstH;
1722      pOverlay->IntBit2 |= 0x02;
1723 
1724      if(I < 2) {
1725 	pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH;
1726 	/* Needed for LCD-scaling modes */
1727 	if(flag && ((mult = (srcH / origdstH)) >= 2)) {
1728 	   pOverlay->pitch2 /= mult;
1729 	}
1730      } else {
1731 #if 0
1732 	if(((pOverlay->bobEnable & 0x08) == 0x00) &&
1733 	   (((srcPitch * I)>>2) > 0xFFF)){
1734 	   pOverlay->bobEnable |= 0x08;
1735 	   srcPitch >>= 1;
1736 	}
1737 #endif
1738 	if(((srcPitch * I) >> 2) > 0xFFF) {
1739 	   I = (0xFFF * 2 / srcPitch);
1740 	   pOverlay->VUSF2 = 0xFFFF;
1741 	} else {
1742 	   dstH = I * dstH;
1743 	   if(srcH % dstH)
1744 	      pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH;
1745 	   else
1746 	      pOverlay->VUSF2 = 0x00;
1747 	}
1748 	/* set video frame buffer offset */
1749 	pOverlay->pitch2 = (CARD16)(srcPitch * I);
1750      }
1751   }
1752 }
1753 #endif
1754 
1755 /*********************************
1756  *    Handle 4-tap scaler (340)  *
1757  *********************************/
1758 
1759 static float
tap_dda_func(float x)1760 tap_dda_func(float x)
1761 {
1762     double pi = 3.14159265358979;
1763     float  r = 0.5, y;
1764 
1765     if(x == 0.0) {
1766        y = 1.0;
1767     } else if(x == -1.0 || x == 1.0) {
1768        y = 0.0;
1769        /* case ((x == -1.0 / (r * 2.0)) || (x == 1.0 / (r * 2.0))): */
1770        /* y = (float)(r / 2.0 * sin(pi / (2.0 * r))); = 0.013700916287197;    */
1771     } else {
1772        y = sin(pi * x) / (pi * x) * cos(r * pi * x) / (1 - x * x);
1773        /* y = sin(pi * x) / (pi * x) * cos(r * pi * x) / (1 - 4 * r * r * x * x); */
1774     }
1775 
1776     return y;
1777 }
1778 
1779 static void
set_dda_regs(SISPtr pSiS,float scale)1780 set_dda_regs(SISPtr pSiS, float scale)
1781 {
1782     float W[4], WS, myadd;
1783     int   *temp[4], *wm1, *wm2, *wm3, *wm4;
1784     int   i, j, w, tidx, weightmatrix[16][4];
1785 
1786     for(i = 0; i < 16; i++) {
1787 
1788        myadd = ((float)i) / 16.0;
1789        WS = W[0] = tap_dda_func((myadd + 1.0) / scale);
1790        W[1] = tap_dda_func(myadd / scale);
1791        WS += W[1];
1792        W[2] = tap_dda_func((myadd - 1.0) / scale);
1793        WS += W[2];
1794        W[3] = tap_dda_func((myadd - 2.0) / scale);
1795        WS += W[3];
1796 
1797        w = 0;
1798        for(j = 0; j < 4; j++) {
1799 	  weightmatrix[i][j] = (int)(((float)((W[j] * 16.0 / WS) + 0.5)));
1800 	  w += weightmatrix[i][j];
1801        }
1802 
1803        if(w == 12) {
1804 
1805 	  weightmatrix[i][0]++;
1806 	  weightmatrix[i][1]++;
1807 	  weightmatrix[i][2]++;
1808 	  weightmatrix[i][3]++;
1809 
1810        } else if(w == 20) {
1811 
1812 	  weightmatrix[i][0]--;
1813 	  weightmatrix[i][1]--;
1814 	  weightmatrix[i][2]--;
1815 	  weightmatrix[i][3]--;
1816 
1817        } else if(w != 16) {
1818 
1819 	  tidx = (weightmatrix[i][0] > weightmatrix[i][1]) ? 0 : 1;
1820 	  temp[0] = &weightmatrix[i][tidx];
1821 	  temp[1] = &weightmatrix[i][tidx ^ 1];
1822 
1823 	  tidx = (weightmatrix[i][2] > weightmatrix[i][3]) ? 2 : 3;
1824 	  temp[2] = &weightmatrix[i][tidx];
1825 	  temp[3] = &weightmatrix[i][tidx ^ 1];
1826 
1827 	  tidx = (*(temp[0]) > *(temp[2])) ? 0 : 2;
1828 	  wm1 = temp[tidx];
1829 	  wm2 = temp[tidx ^ 2];
1830 
1831 	  tidx = (*(temp[1]) > *(temp[3])) ? 1 : 3;
1832 	  wm3 = temp[tidx];
1833 	  wm4 = temp[tidx ^ 2];
1834 
1835 	  switch(w) {
1836 	     case 13:
1837 		(*wm1)++;
1838 		(*wm4)++;
1839 		if(*wm2 > *wm3) (*wm2)++;
1840 		else            (*wm3)++;
1841 		break;
1842 	     case 14:
1843 		(*wm1)++;
1844 		(*wm4)++;
1845 		break;
1846 	     case 15:
1847 		(*wm1)++;
1848 		break;
1849 	     case 17:
1850 		(*wm4)--;
1851 		break;
1852 	     case 18:
1853 		(*wm1)--;
1854 		(*wm4)--;
1855 		break;
1856 	     case 19:
1857 		(*wm1)--;
1858 		(*wm4)--;
1859 		if(*wm2 > *wm3) (*wm3)--;
1860 		else            (*wm2)--;
1861 	  }
1862        }
1863     }
1864 
1865     /* Set 4-tap scaler video regs 0x75-0xb4 */
1866     w = 0x75;
1867     for(i = 0; i < 16; i++) {
1868        for(j = 0; j < 4; j++, w++) {
1869           setvideoregmask(pSiS, w, weightmatrix[i][j], 0x3f);
1870        }
1871     }
1872 }
1873 
1874 /*********************************
1875  *     Calc line buffer size     *
1876  *********************************/
1877 
1878 static CARD16
calc_line_buf_size(CARD32 srcW,CARD8 wHPre,CARD8 planar,SISPortPrivPtr pPriv)1879 calc_line_buf_size(CARD32 srcW, CARD8 wHPre, CARD8 planar, SISPortPrivPtr pPriv)
1880 {
1881     CARD32 I, mask = 0xffffffff, shift = pPriv->is761 ? 1 : 0;
1882 
1883     if(planar) {
1884 
1885 	switch(wHPre & 0x07) {
1886 	    case 3:
1887 		shift += 8;
1888 		mask <<= shift;
1889 		I = srcW >> shift;
1890 		if((mask & srcW) != srcW) I++;
1891 		I <<= 5;
1892 		break;
1893 	    case 4:
1894 		shift += 9;
1895 		mask <<= shift;
1896 		I = srcW >> shift;
1897 		if((mask & srcW) != srcW) I++;
1898 		I <<= 6;
1899 		break;
1900 	    case 5:
1901 		shift += 10;
1902 		mask <<= shift;
1903 		I = srcW >> shift;
1904 		if((mask & srcW) != srcW) I++;
1905 		I <<= 7;
1906 		break;
1907 	    case 6:
1908 		if(pPriv->is340 || pPriv->isXGI || pPriv->is761) {
1909 		   shift += 11;
1910 		   mask <<= shift;
1911 		   I = srcW >> shift;
1912 		   if((mask & srcW) != srcW) I++;
1913 		   I <<= 8;
1914 		   break;
1915 		} else {
1916 		   return((CARD16)(255));
1917 		}
1918 	    default:
1919 		shift += 7;
1920 		mask <<= shift;
1921 		I = srcW >> shift;
1922 		if((mask & srcW) != srcW) I++;
1923 		I <<= 4;
1924 		break;
1925 	}
1926 
1927     } else { /* packed */
1928 
1929 	shift += 3;
1930 	mask <<= shift;
1931 	I = srcW >> shift;
1932 	if((mask & srcW) != srcW) I++;
1933 
1934     }
1935 
1936     if(I <= 3) I = 4;
1937 
1938     return((CARD16)(I - 1));
1939 }
1940 
1941 static __inline void
calc_line_buf_size_1(SISOverlayPtr pOverlay,SISPortPrivPtr pPriv)1942 calc_line_buf_size_1(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv)
1943 {
1944     pOverlay->lineBufSize =
1945 	calc_line_buf_size(pOverlay->srcW, pOverlay->wHPre, pOverlay->planar, pPriv);
1946 }
1947 
1948 #ifdef SISMERGED
1949 static __inline void
calc_line_buf_size_2(SISOverlayPtr pOverlay,SISPortPrivPtr pPriv)1950 calc_line_buf_size_2(SISOverlayPtr pOverlay, SISPortPrivPtr pPriv)
1951 {
1952     pOverlay->lineBufSize2 =
1953 	calc_line_buf_size(pOverlay->srcW2, pOverlay->wHPre2, pOverlay->planar, pPriv);
1954 }
1955 
1956 /**********************************
1957  *En/Disable merging of linebuffer*
1958  **********************************/
1959 
1960 static void
merge_line_buf_mfb(SISPtr pSiS,SISPortPrivPtr pPriv,Bool enable1,Bool enable2,short width1,short width2,short limit)1961 merge_line_buf_mfb(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable1, Bool enable2,
1962                    short width1, short width2, short limit)
1963 {
1964     UChar misc1, misc2, mask = pPriv->linebufmask;
1965 
1966     if(pPriv->hasTwoOverlays) {     /* This means we are in MIRROR mode */
1967 
1968        misc2 = 0x00;
1969        if(enable1) misc1 = 0x04;
1970        else 	   misc1 = 0x00;
1971        setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
1972        setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
1973 
1974        misc2 = 0x01;
1975        if(enable2) misc1 = 0x04;
1976        else        misc1 = 0x00;
1977        setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
1978        setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
1979 
1980     } else {			/* This means we are either in SINGLE1 or SINGLE2 mode */
1981 
1982        misc2 = 0x00;
1983        if(enable1 || enable2) {
1984           if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
1985 	     if((width1 > (limit * 2)) || (width2 > (limit * 2))) {
1986 		 misc2 = 0x20;
1987 	      } else {
1988 		 misc2 = 0x10;
1989 	      }
1990 	      misc1 = 0x00;
1991 	  } else {
1992              misc1 = 0x04;
1993 	  }
1994        } else {
1995           misc1 = 0x00;
1996        }
1997 
1998        setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
1999        setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
2000 
2001     }
2002 }
2003 #endif
2004 
2005 /* About linebuffer merging:
2006  *
2007  * For example the 651:
2008  * Each overlay has 4 line buffers, 384 bytes each (<-- Is that really correct? 1920 / 384 = 5 !!!)
2009  * If the source width is greater than 384, line buffers must be merged.
2010  * Dual merge: Only O1 usable (uses overlay 2's linebuffer), maximum width 384*2
2011  * Individual merge: Both overlays available, maximum width 384*2
2012  * All merge: Only overlay 1 available, maximum width = 384*4 (<--- should be 1920, is 1536...)
2013  *
2014  *
2015  *        Normally:                  Dual merge:                 Individual merge
2016  *  Overlay 1    Overlay 2         Overlay 1 only!                Both overlays
2017  *  ___1___      ___5___           ___1___ ___2___ -\         O1  ___1___ ___2___
2018  *  ___2___      ___6___           ___3___ ___4___   \_ O 1   O1  ___3___ ___4___
2019  *  ___3___      ___7___	   ___5___ ___6___   /        O2  ___5___ ___6___
2020  *  ___4___      ___8___           ___7___ ___8___ -/         O2  ___7___ ___8___
2021  *
2022  *
2023  * All merge:          ___1___ ___2___ ___3___ ___4___
2024  * (Overlay 1 only!)   ___5___ ___6___ ___7___ ___8___
2025  *
2026  * Individual merge is supported on all chipsets.
2027  * Dual merge is only supported on the 300 series and M650/651 and later.
2028  * All merge is only supported on the M650/651 and later.
2029  * Single-Overlay-chipsets only support Individual merge.
2030  *
2031  */
2032 
2033 static void
merge_line_buf(SISPtr pSiS,SISPortPrivPtr pPriv,Bool enable,short width,short limit)2034 merge_line_buf(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable, short width, short limit)
2035 {
2036   UChar misc1, misc2, mask = pPriv->linebufmask;
2037 
2038   if(enable) { 		/* ----- enable linebuffer merge */
2039 
2040     switch(pPriv->displayMode){
2041     case DISPMODE_SINGLE1:
2042         if(pSiS->VGAEngine == SIS_300_VGA) {
2043            if(pPriv->dualHeadMode) {
2044 	       misc2 = 0x00;
2045 	       misc1 = 0x04;
2046 	   } else {
2047 	       misc2 = 0x10;
2048 	       misc1 = 0x00;
2049 	   }
2050         } else {
2051 	   if(pPriv->hasTwoOverlays) {
2052 	      if(pPriv->dualHeadMode) {
2053 		 misc2 = 0x00;
2054 		 misc1 = 0x04;
2055 	      } else {
2056 		 if(width > (limit * 2)) {
2057 		    misc2 = 0x20;
2058 		 } else {
2059 		    misc2 = 0x10;
2060 		 }
2061 		 misc1 = 0x00;
2062 	      }
2063 	   } else if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
2064 	      if(width > (limit * 2)) {
2065 		 misc2 = 0x20;
2066 	      } else {
2067 		 misc2 = 0x10;
2068 	      }
2069 	      misc1 = 0x00;
2070 	   } else {
2071 	      misc2 = 0x00;
2072 	      misc1 = 0x04;
2073 	   }
2074 	}
2075 	setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
2076 	setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
2077       	break;
2078 
2079     case DISPMODE_SINGLE2:
2080         if(pSiS->VGAEngine == SIS_300_VGA) {
2081 	   if(pPriv->dualHeadMode) {
2082 	      misc2 = 0x01;
2083 	      misc1 = 0x04;
2084 	   } else {
2085 	      misc2 = 0x10;
2086 	      misc1 = 0x00;
2087 	   }
2088 	} else {
2089 	   if(pPriv->hasTwoOverlays) {
2090 	      if(pPriv->dualHeadMode) {
2091 		 misc2 = 0x01;
2092 		 misc1 = 0x04;
2093 	      } else {
2094 		 if(width > (limit * 2)) {
2095 		    misc2 = 0x20;
2096 		 } else {
2097 		    misc2 = 0x10;
2098 		 }
2099 		 misc1 = 0x00;
2100 	      }
2101 	   } else if(pSiS->MiscFlags & MISC_SIS760ONEOVERLAY) {
2102 	      if(width > (limit * 2)) {
2103 		 misc2 = 0x20;
2104 	      } else {
2105 		 misc2 = 0x10;
2106 	      }
2107 	      misc1 = 0x00;
2108 	   } else {
2109 	      misc2 = 0x00;
2110 	      misc1 = 0x04;
2111 	   }
2112 	}
2113 	setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
2114 	setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
2115      	break;
2116 
2117     case DISPMODE_MIRROR:   /* This can only be on chips with 2 overlays */
2118     default:
2119         setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask);
2120       	setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04);
2121 	setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask);
2122       	setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04);
2123         break;
2124     }
2125 
2126   } else {		/* ----- disable linebuffer merge */
2127 
2128     switch(pPriv->displayMode) {
2129 
2130     case DISPMODE_SINGLE1:
2131 	setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask);
2132 	setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
2133 	break;
2134 
2135     case DISPMODE_SINGLE2:
2136 	if(pSiS->VGAEngine == SIS_300_VGA) {
2137 	   if(pPriv->dualHeadMode) misc2 = 0x01;
2138 	   else       		   misc2 = 0x00;
2139 	} else {
2140 	   if(pPriv->hasTwoOverlays) {
2141 	      if(pPriv->dualHeadMode) misc2 = 0x01;
2142 	      else                    misc2 = 0x00;
2143 	   } else {
2144 	      misc2 = 0x00;
2145 	   }
2146 	}
2147 	setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
2148 	setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
2149 	break;
2150 
2151     case DISPMODE_MIRROR:   /* This can only be on chips with 2 overlays */
2152     default:
2153 	setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask);
2154 	setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
2155 	setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask);
2156 	setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
2157 	break;
2158     }
2159   }
2160 }
2161 
2162 /*********************************
2163  *      Select video format      *
2164  *********************************/
2165 
2166 static __inline void
set_format(SISPtr pSiS,SISOverlayPtr pOverlay)2167 set_format(SISPtr pSiS, SISOverlayPtr pOverlay)
2168 {
2169     CARD8 fmt;
2170 
2171     switch (pOverlay->pixelFormat){
2172     case PIXEL_FMT_YV12:
2173     case PIXEL_FMT_I420:
2174 	fmt = 0x0c;
2175 	break;
2176     case PIXEL_FMT_YUY2:
2177 	fmt = 0x28;
2178 	break;
2179     case PIXEL_FMT_UYVY:
2180 	fmt = 0x08;
2181 	break;
2182     case PIXEL_FMT_YVYU:
2183 	fmt = 0x38;
2184 	break;
2185     case PIXEL_FMT_NV12:
2186 	fmt = 0x4c;
2187 	break;
2188     case PIXEL_FMT_NV21:
2189 	fmt = 0x5c;
2190 	break;
2191     case PIXEL_FMT_RGB5:   /* D[5:4] : 00 RGB555, 01 RGB 565 */
2192 	fmt = 0x00;
2193 	break;
2194     case PIXEL_FMT_RGB6:
2195 	fmt = 0x10;
2196 	break;
2197     default:
2198 	fmt = 0x00;
2199     }
2200     setvideoregmask(pSiS, Index_VI_Control_Misc0, fmt, 0xfc);
2201 }
2202 
2203 /*********************************
2204  *  Set various video registers  *
2205  *********************************/
2206 
2207 static __inline void
set_colorkey(SISPtr pSiS,CARD32 colorkey)2208 set_colorkey(SISPtr pSiS, CARD32 colorkey)
2209 {
2210     CARD8 r, g, b;
2211 
2212     b = (CARD8)(colorkey & 0xFF);
2213     g = (CARD8)((colorkey >> 8) & 0xFF);
2214     r = (CARD8)((colorkey >> 16) & 0xFF);
2215 
2216     setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Min  ,(CARD8)b);
2217     setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Min ,(CARD8)g);
2218     setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Min   ,(CARD8)r);
2219 
2220     setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Max  ,(CARD8)b);
2221     setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Max ,(CARD8)g);
2222     setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Max   ,(CARD8)r);
2223 }
2224 
2225 static __inline void
set_chromakey(SISPtr pSiS,CARD32 chromamin,CARD32 chromamax)2226 set_chromakey(SISPtr pSiS, CARD32 chromamin, CARD32 chromamax)
2227 {
2228     CARD8 r1, g1, b1;
2229     CARD8 r2, g2, b2;
2230 
2231     b1 = (CARD8)(chromamin & 0xFF);
2232     g1 = (CARD8)((chromamin >> 8) & 0xFF);
2233     r1 = (CARD8)((chromamin >> 16) & 0xFF);
2234     b2 = (CARD8)(chromamax & 0xFF);
2235     g2 = (CARD8)((chromamax >> 8) & 0xFF);
2236     r2 = (CARD8)((chromamax >> 16) & 0xFF);
2237 
2238     setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Min  ,(CARD8)b1);
2239     setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Min ,(CARD8)g1);
2240     setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Min   ,(CARD8)r1);
2241 
2242     setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Max  ,(CARD8)b2);
2243     setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Max ,(CARD8)g2);
2244     setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Max   ,(CARD8)r2);
2245 }
2246 
2247 static __inline void
set_brightness(SISPtr pSiS,CARD8 brightness)2248 set_brightness(SISPtr pSiS, CARD8 brightness)
2249 {
2250     setvideoreg(pSiS, Index_VI_Brightness, brightness);
2251 }
2252 
2253 static __inline void
set_contrast(SISPtr pSiS,CARD8 contrast)2254 set_contrast(SISPtr pSiS, CARD8 contrast)
2255 {
2256     setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, contrast, 0x07);
2257 }
2258 
2259 /* 315 series and later only */
2260 static __inline void
set_saturation(SISPtr pSiS,short saturation)2261 set_saturation(SISPtr pSiS, short saturation)
2262 {
2263     CARD8 temp = 0;
2264 
2265     if(saturation < 0) {
2266     	temp |= 0x88;
2267 	saturation = -saturation;
2268     }
2269     temp |= (saturation & 0x07);
2270     temp |= ((saturation & 0x07) << 4);
2271 
2272     setvideoreg(pSiS, Index_VI_Saturation, temp);
2273 }
2274 
2275 /* 315 series and later only */
2276 static __inline void
set_hue(SISPtr pSiS,CARD8 hue)2277 set_hue(SISPtr pSiS, CARD8 hue)
2278 {
2279     setvideoregmask(pSiS, Index_VI_Hue, (hue & 0x08) ? (hue ^ 0x07) : hue, 0x0F);
2280 }
2281 
2282 static __inline void
set_disablegfx(SISPtr pSiS,Bool mybool,SISOverlayPtr pOverlay)2283 set_disablegfx(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay)
2284 {
2285     /* This is not supported on M65x, 65x (x>0) or later */
2286     /* For CRT1 ONLY!!! */
2287     if((!(pSiS->ChipFlags & SiSCF_Is65x)) &&
2288        (pSiS->Chipset != PCI_CHIP_SIS660) &&
2289        (pSiS->Chipset != PCI_CHIP_SIS340) &&
2290        (pSiS->Chipset != PCI_CHIP_XGIXG20) &&
2291        (pSiS->Chipset != PCI_CHIP_XGIXG40)) {
2292        setvideoregmask(pSiS, Index_VI_Control_Misc2, mybool ? 0x04 : 0x00, 0x04);
2293        if(mybool) pOverlay->keyOP = VI_ROP_Always;
2294     }
2295 }
2296 
2297 static __inline void
set_disablegfxlr(SISPtr pSiS,Bool mybool,SISOverlayPtr pOverlay)2298 set_disablegfxlr(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay)
2299 {
2300     setvideoregmask(pSiS, Index_VI_Control_Misc1, mybool ? 0x01 : 0x00, 0x01);
2301     if(mybool) pOverlay->keyOP = VI_ROP_Always;
2302 }
2303 
2304 #ifdef SIS_CP
2305     SIS_CP_VIDEO_SUBS
2306 #endif
2307 
2308 /*********************************
2309  *   Set main overlay registers  *
2310  *********************************/
2311 
2312 static void
set_overlay(SISPtr pSiS,SISOverlayPtr pOverlay,SISPortPrivPtr pPriv,int index,int iscrt2)2313 set_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index, int iscrt2)
2314 {
2315     CARD8  h_over, v_over;
2316     CARD16 top, bottom, left, right, pitch = 0;
2317     CARD16 screenX, screenY;
2318     CARD32 PSY;
2319     int    modeflags, totalPixels, confactor, sample, watchdog = 0;
2320 
2321 #ifdef SISMERGED
2322     if(pSiS->MergedFB && iscrt2) {
2323        screenX = pOverlay->currentmode2->HDisplay;
2324        screenY = pOverlay->currentmode2->VDisplay;
2325        modeflags = pOverlay->currentmode2->Flags;
2326        top = pOverlay->dstBox2.y1;
2327        bottom = pOverlay->dstBox2.y2;
2328        left = pOverlay->dstBox2.x1;
2329        right = pOverlay->dstBox2.x2;
2330        pitch = pOverlay->pitch2 >> pPriv->shiftValue;
2331     } else {
2332 #endif
2333        screenX = pOverlay->currentmode->HDisplay;
2334        screenY = pOverlay->currentmode->VDisplay;
2335        modeflags = pOverlay->currentmode->Flags;
2336        top = pOverlay->dstBox.y1;
2337        bottom = pOverlay->dstBox.y2;
2338        left = pOverlay->dstBox.x1;
2339        right = pOverlay->dstBox.x2;
2340        pitch = pOverlay->pitch >> pPriv->shiftValue;
2341 #ifdef SISMERGED
2342     }
2343 #endif
2344 
2345     if(bottom > screenY) bottom = screenY;
2346     if(right  > screenX) right  = screenX;
2347 
2348     /* calculate contrast factor */
2349     totalPixels = (right - left) * (bottom - top);
2350     confactor = (totalPixels - 10000) / 20000;
2351     if(confactor > 3) confactor = 3;
2352     switch(confactor) {
2353     case 1:  sample = 4096 << 10; break;
2354     case 2:
2355     case 3:  sample = 8192 << 10; break;
2356     default: sample = 2048 << 10;
2357     }
2358     sample /= totalPixels;
2359     confactor <<= 6;
2360 
2361     /* Correct coordinates for doublescan/interlace modes */
2362     if( (modeflags & V_DBLSCAN) &&
2363         (!((pPriv->bridgeIsSlave || iscrt2) && (pSiS->MiscFlags & MISC_STNMODE))) ) {
2364        /* DoubleScan modes require Y coordinates * 2 */
2365        top <<= 1;
2366        bottom <<= 1;
2367     } else if(modeflags & V_INTERLACE) {
2368        /* Interlace modes require Y coordinates / 2 */
2369        top >>= 1;
2370        bottom >>= 1;
2371     }
2372 
2373     h_over = (((left >> 8) & 0x0f) | ((right >> 4) & 0xf0));
2374     v_over = (((top >> 8) & 0x0f) | ((bottom >> 4) & 0xf0));
2375 
2376     /* set line buffer size */
2377 #ifdef SISMERGED
2378     if(pSiS->MergedFB && iscrt2) {
2379        setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize2);
2380        if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) {
2381           setvideoreg(pSiS, Index_VI_Line_Buffer_Size_High, (CARD8)(pOverlay->lineBufSize2 >> 8));
2382        }
2383     } else {
2384 #endif
2385        setvideoreg(pSiS, Index_VI_Line_Buffer_Size, (CARD8)pOverlay->lineBufSize);
2386        if(pPriv->is340 || pPriv->is761 || pPriv->isXGI) {
2387           setvideoreg(pSiS, Index_VI_Line_Buffer_Size_High, (CARD8)(pOverlay->lineBufSize >> 8));
2388        }
2389 #ifdef SISMERGED
2390     }
2391 #endif
2392 
2393     /* set color key mode */
2394     setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, pOverlay->keyOP, 0x0f);
2395 
2396     /* We don't have to wait for vertical retrace in all cases */
2397     if(pPriv->mustwait) {
2398        if(pSiS->VGAEngine == SIS_315_VGA) {
2399 
2400           if(index) {
2401 	     CARD16 mytop = getvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low);
2402 	     mytop |= ((getvideoreg(pSiS, Index_VI_Win_Ver_Over) & 0x0f) << 8);
2403 	     pOverlay->oldtop = mytop;
2404 	     watchdog = 0xffff;
2405 	     if(mytop < screenY - 2) {
2406 		do {
2407 		   watchdog = get_scanline_CRT2(pSiS, pPriv);
2408 		} while((watchdog <= mytop) || (watchdog >= screenY));
2409 	     }
2410 	     pOverlay->oldLine = watchdog;
2411 	  }
2412 
2413        } else {
2414 
2415 	  watchdog = WATCHDOG_DELAY;
2416 	  while(pOverlay->VBlankActiveFunc(pSiS, pPriv) && --watchdog);
2417 	  watchdog = WATCHDOG_DELAY;
2418 	  while((!pOverlay->VBlankActiveFunc(pSiS, pPriv)) && --watchdog);
2419 
2420        }
2421     }
2422 
2423     /* Unlock address registers */
2424     setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x20, 0x20);
2425 
2426     /* Set destination window position */
2427     setvideoreg(pSiS, Index_VI_Win_Hor_Disp_Start_Low, (CARD8)left);
2428     setvideoreg(pSiS, Index_VI_Win_Hor_Disp_End_Low,   (CARD8)right);
2429     setvideoreg(pSiS, Index_VI_Win_Hor_Over,           (CARD8)h_over);
2430 
2431     setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, (CARD8)top);
2432     setvideoreg(pSiS, Index_VI_Win_Ver_Disp_End_Low,   (CARD8)bottom);
2433     setvideoreg(pSiS, Index_VI_Win_Ver_Over,           (CARD8)v_over);
2434 
2435     /* Contrast factor */
2436     setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl,  (CARD8)confactor, 0xc0);
2437     setvideoreg(pSiS, Index_VI_Contrast_Factor,        sample);
2438 
2439     /* Set Y buf pitch */
2440     setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_Low, (CARD8)(pitch));
2441     setvideoregmask(pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 8), 0x0f);
2442 
2443     /* Set Y start address */
2444 #ifdef SISMERGED
2445     if(pSiS->MergedFB && iscrt2) {
2446        PSY = pOverlay->PSY2;
2447     } else
2448 #endif
2449        PSY = pOverlay->PSY;
2450 
2451     setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Low,    (CARD8)(PSY));
2452     setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Middle, (CARD8)(PSY >> 8));
2453     setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_High,   (CARD8)(PSY >> 16));
2454 
2455     /* Set 315 series overflow bits for Y plane */
2456     if(pSiS->VGAEngine == SIS_315_VGA) {
2457        setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_High, (CARD8)(pitch >> 12));
2458        setvideoreg(pSiS, Index_VI_Y_Buf_Start_Over, ((CARD8)(PSY >> 24) & 0x03));
2459     }
2460 
2461     /* Set U/V data if using planar formats */
2462     if(pOverlay->planar) {
2463 
2464 	CARD32  PSU = pOverlay->PSU;
2465 	CARD32  PSV = pOverlay->PSV;
2466 
2467 #ifdef SISMERGED
2468 	if(pSiS->MergedFB && iscrt2) {
2469 	   PSU = pOverlay->PSU2;
2470 	   PSV = pOverlay->PSV2;
2471 	}
2472 #endif
2473 
2474 	if(pOverlay->planar_shiftpitch) pitch >>= 1;
2475 
2476 	/* Set U/V pitch */
2477 	setvideoreg(pSiS, Index_VI_Disp_UV_Buf_Pitch_Low, (CARD8)pitch);
2478 	setvideoregmask(pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 4), 0xf0);
2479 
2480 	/* Set U/V start address */
2481 	setvideoreg(pSiS, Index_VI_U_Buf_Start_Low,   (CARD8)PSU);
2482 	setvideoreg(pSiS, Index_VI_U_Buf_Start_Middle,(CARD8)(PSU >> 8));
2483 	setvideoreg(pSiS, Index_VI_U_Buf_Start_High,  (CARD8)(PSU >> 16));
2484 
2485 	setvideoreg(pSiS, Index_VI_V_Buf_Start_Low,   (CARD8)PSV);
2486 	setvideoreg(pSiS, Index_VI_V_Buf_Start_Middle,(CARD8)(PSV >> 8));
2487 	setvideoreg(pSiS, Index_VI_V_Buf_Start_High,  (CARD8)(PSV >> 16));
2488 
2489 	/* 315 series overflow bits */
2490 	if(pSiS->VGAEngine == SIS_315_VGA) {
2491 	   setvideoreg(pSiS, Index_VI_Disp_UV_Buf_Pitch_High, (CARD8)(pitch >> 12));
2492 	   setvideoreg(pSiS, Index_VI_U_Buf_Start_Over, ((CARD8)(PSU >> 24) & 0x03));
2493 	   if(pPriv->is661741760) {
2494 	      setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03), 0xc3);
2495 	   } else {
2496 	      setvideoreg(pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03));
2497 	   }
2498 	}
2499     }
2500 
2501     setvideoregmask(pSiS, Index_VI_Control_Misc1, pOverlay->bobEnable, 0x1a);
2502 
2503     /* Lock the address registers */
2504     setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x20);
2505 
2506     /* Set scale factor */
2507 #ifdef SISMERGED
2508     if(pSiS->MergedFB && iscrt2) {
2509        setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF2));
2510        setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF2) >> 8));
2511        setvideoreg(pSiS, Index_VI_Ver_Up_Scale_Low,      (CARD8)(pOverlay->VUSF2));
2512        setvideoreg(pSiS, Index_VI_Ver_Up_Scale_High,     (CARD8)((pOverlay->VUSF2) >> 8));
2513 
2514        setvideoregmask(pSiS, Index_VI_Scale_Control,     (pOverlay->IntBit2 << 3) |
2515                                                          (pOverlay->wHPre2), 0x7f);
2516 
2517        if(pPriv->havetapscaler) {
2518 	  if((pOverlay->tap_scale2 != pOverlay->tap_scale2_old) || pPriv->mustresettap2) {
2519 	     set_dda_regs(pSiS, pOverlay->tap_scale2);
2520 	     pOverlay->tap_scale2_old = pOverlay->tap_scale2;
2521 	     pPriv->mustresettap2 = FALSE;
2522 	  }
2523        }
2524     } else {
2525 #endif
2526        setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF));
2527        setvideoreg(pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF) >> 8));
2528        setvideoreg(pSiS, Index_VI_Ver_Up_Scale_Low,      (CARD8)(pOverlay->VUSF));
2529        setvideoreg(pSiS, Index_VI_Ver_Up_Scale_High,     (CARD8)((pOverlay->VUSF) >> 8));
2530 
2531        setvideoregmask(pSiS, Index_VI_Scale_Control,     (pOverlay->IntBit << 3) |
2532                                                          (pOverlay->wHPre), 0x7f);
2533        if(pPriv->havetapscaler) {
2534 	  if((pOverlay->tap_scale != pOverlay->tap_scale_old) || pPriv->mustresettap) {
2535 	     set_dda_regs(pSiS, pOverlay->tap_scale);
2536 	     pOverlay->tap_scale_old = pOverlay->tap_scale;
2537 	     pPriv->mustresettap = FALSE;
2538 	  }
2539        }
2540 #ifdef SISMERGED
2541     }
2542 #endif
2543 
2544 }
2545 
2546 /*********************************
2547  *       Shut down overlay       *
2548  *********************************/
2549 
2550 /* Overlay MUST NOT be switched off while beam is over it */
2551 static void
close_overlay(SISPtr pSiS,SISPortPrivPtr pPriv)2552 close_overlay(SISPtr pSiS, SISPortPrivPtr pPriv)
2553 {
2554   int watchdog;
2555 
2556   if(!pPriv->overlayStatus) return;
2557 
2558   pPriv->overlayStatus = FALSE;
2559 
2560   pPriv->mustresettap = TRUE;
2561 #ifdef SISMERGED
2562   pPriv->mustresettap2 = TRUE;
2563 #endif
2564 
2565   if(pPriv->displayMode & (DISPMODE_MIRROR | DISPMODE_SINGLE2)) {
2566 
2567      /* CRT2: MIRROR or SINGLE2
2568       * 1 overlay:  Uses overlay 0
2569       * 2 overlays: Uses Overlay 1 if MIRROR or DUAL HEAD
2570       *             Uses Overlay 0 if SINGLE2 and not DUAL HEAD
2571       */
2572 
2573      if(pPriv->hasTwoOverlays) {
2574 
2575 	if((pPriv->dualHeadMode) || (pPriv->displayMode == DISPMODE_MIRROR)) {
2576 	   setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
2577 	} else {
2578 	   setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01);
2579 	}
2580 
2581      } else if(pPriv->displayMode == DISPMODE_SINGLE2) {
2582 
2583 #ifdef SISDUALHEAD
2584 	if(pPriv->dualHeadMode) {
2585 	   /* Check if overlay already grabbed by other head */
2586 	   if(!(getsrreg(pSiS, 0x06) & 0x40)) return;
2587 	}
2588 #endif
2589 	setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01);
2590 
2591      }
2592 
2593      setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
2594 
2595      watchdog = WATCHDOG_DELAY;
2596      while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
2597      watchdog = WATCHDOG_DELAY;
2598      while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
2599      setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
2600      watchdog = WATCHDOG_DELAY;
2601      while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
2602      watchdog = WATCHDOG_DELAY;
2603      while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
2604 
2605 #ifdef SIS_CP
2606      SIS_CP_RESET_CP
2607 #endif
2608 
2609   }
2610 
2611   if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) {
2612 
2613      /* CRT1: Always uses overlay 0
2614       */
2615 
2616 #ifdef SISDUALHEAD
2617      if(pPriv->dualHeadMode) {
2618 	if(!pPriv->hasTwoOverlays) {
2619 	   /* Check if overlay already grabbed by other head */
2620 	   if(getsrreg(pSiS, 0x06) & 0x40) return;
2621 	}
2622      }
2623 #endif
2624 
2625      setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05);
2626      setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
2627 
2628      watchdog = WATCHDOG_DELAY;
2629      while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
2630      watchdog = WATCHDOG_DELAY;
2631      while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
2632      setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
2633      watchdog = WATCHDOG_DELAY;
2634      while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
2635      watchdog = WATCHDOG_DELAY;
2636      while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
2637 
2638   }
2639 }
2640 
2641 /*********************************
2642  *         DisplayVideo()        *
2643  *********************************/
2644 
2645 static void
SISDisplayVideo(ScrnInfoPtr pScrn,SISPortPrivPtr pPriv)2646 SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
2647 {
2648    SISPtr pSiS = SISPTR(pScrn);
2649 #ifdef SISDUALHEAD
2650    SISEntPtr pSiSEnt = pSiS->entityPrivate;
2651 #endif
2652    short  srcPitch = pPriv->srcPitch;
2653    short  height = pPriv->height;
2654    UShort screenwidth;
2655    SISOverlayRec overlay;
2656    int    srcOffsetX = 0, srcOffsetY = 0;
2657    int    sx = 0, sy = 0, watchdog;
2658    int    index = 0, iscrt2 = 0;
2659 #ifdef SISMERGED
2660    UChar  temp;
2661    UShort screen2width = 0;
2662    int    srcOffsetX2 = 0, srcOffsetY2 = 0;
2663    int    sx2 = 0, sy2 = 0;
2664 #endif
2665 
2666    /* Determine whether we have two overlays or only one */
2667    set_hastwooverlays(pSiS, pPriv);
2668 
2669    pPriv->NoOverlay = FALSE;
2670 #ifdef SISDUALHEAD
2671    if(pPriv->dualHeadMode) {
2672       if(!pPriv->hasTwoOverlays) {
2673 	 if(pSiS->SecondHead) {
2674 	    if(pSiSEnt->curxvcrtnum != 0) {
2675 	       if(pPriv->overlayStatus) {
2676 		  close_overlay(pSiS, pPriv);
2677 	       }
2678 	       pPriv->NoOverlay = TRUE;
2679 	       return;
2680 	    }
2681 	 } else {
2682 	    if(pSiSEnt->curxvcrtnum != 1) {
2683 	       if(pPriv->overlayStatus) {
2684 		  close_overlay(pSiS, pPriv);
2685 	       }
2686 	       pPriv->NoOverlay = TRUE;
2687 	       return;
2688 	    }
2689 	 }
2690       }
2691    }
2692 #endif
2693 
2694    /* setup dispmode (MIRROR, SINGLEx) */
2695    set_dispmode(pScrn, pPriv);
2696 
2697    /* Check if overlay is supported with current mode */
2698 #ifdef SISMERGED
2699    if(!pSiS->MergedFB) {
2700 #endif
2701       if( ((pPriv->displayMode & DISPMODE_MIRROR) &&
2702            ((pSiS->MiscFlags & (MISC_CRT1OVERLAY|MISC_CRT2OVERLAY)) != (MISC_CRT1OVERLAY|MISC_CRT2OVERLAY))) ||
2703 	  ((pPriv->displayMode & DISPMODE_SINGLE1) &&
2704 	   (!(pSiS->MiscFlags & MISC_CRT1OVERLAY))) ||
2705 	  ((pPriv->displayMode & DISPMODE_SINGLE2) &&
2706 	   (!(pSiS->MiscFlags & MISC_CRT2OVERLAY))) ) {
2707 	 if(pPriv->overlayStatus) {
2708 	    close_overlay(pSiS, pPriv);
2709 	 }
2710 	 pPriv->NoOverlay = TRUE;
2711 	 return;
2712       }
2713 #ifdef SISMERGED
2714    }
2715 #endif
2716 
2717    memset(&overlay, 0, sizeof(overlay));
2718 
2719    overlay.pixelFormat = pPriv->id;
2720    overlay.pitch = overlay.origPitch = srcPitch;
2721    if(pPriv->usechromakey) {
2722       overlay.keyOP = (pPriv->insidechromakey) ? VI_ROP_ChromaKey : VI_ROP_NotChromaKey;
2723    } else {
2724       overlay.keyOP = VI_ROP_DestKey;
2725    }
2726 
2727 #ifdef SISDEINT
2728    switch(pPriv->deinterlacemethod) {
2729    case 1:
2730       overlay.bobEnable = 0x02;
2731       /* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */
2732       break;
2733    case 2:
2734       overlay.bobEnable = 0x08;
2735       /* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */
2736       break;
2737    case 3:
2738       overlay.bobEnable = 0x0a;
2739       /* overlay.bobEnable |= (pPriv->currentBuf) ? 0x00 : 0x10; */
2740       break;
2741    default:
2742 #endif
2743       overlay.bobEnable = 0x00;    /* Disable BOB de-interlacer */
2744 #ifdef SISDEINT
2745    }
2746 #endif
2747 
2748 #ifdef SISMERGED
2749    if(pSiS->MergedFB) {
2750       overlay.DoFirst = TRUE;
2751       overlay.DoSecond = TRUE;
2752       overlay.pitch2 = overlay.origPitch;
2753       overlay.currentmode = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT1;
2754       overlay.currentmode2 = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2;
2755       overlay.SCREENheight  = overlay.currentmode->VDisplay;
2756       overlay.SCREENheight2 = overlay.currentmode2->VDisplay;
2757       screenwidth = overlay.currentmode->HDisplay;
2758       screen2width = overlay.currentmode2->HDisplay;
2759       overlay.dstBox.x1  = pPriv->drw_x - pSiS->CRT1frameX0;
2760       overlay.dstBox.x2  = overlay.dstBox.x1 + pPriv->drw_w;
2761       overlay.dstBox.y1  = pPriv->drw_y - pSiS->CRT1frameY0;
2762       overlay.dstBox.y2  = overlay.dstBox.y1 + pPriv->drw_h;
2763       overlay.dstBox2.x1 = pPriv->drw_x - pSiS->CRT2pScrn->frameX0;
2764       overlay.dstBox2.x2 = overlay.dstBox2.x1 + pPriv->drw_w;
2765       overlay.dstBox2.y1 = pPriv->drw_y - pSiS->CRT2pScrn->frameY0;
2766       overlay.dstBox2.y2 = overlay.dstBox2.y1 + pPriv->drw_h;
2767    } else {
2768 #endif
2769       overlay.currentmode = pSiS->CurrentLayout.mode;
2770       overlay.SCREENheight = overlay.currentmode->VDisplay;
2771       screenwidth = overlay.currentmode->HDisplay;
2772       overlay.dstBox.x1 = pPriv->drw_x - pScrn->frameX0;
2773       overlay.dstBox.x2 = pPriv->drw_x + pPriv->drw_w - pScrn->frameX0;
2774       overlay.dstBox.y1 = pPriv->drw_y - pScrn->frameY0;
2775       overlay.dstBox.y2 = pPriv->drw_y + pPriv->drw_h - pScrn->frameY0;
2776 #ifdef SISMERGED
2777    }
2778 #endif
2779 
2780    /* Note: x2/y2 is actually real coordinate + 1 */
2781 
2782    if((overlay.dstBox.x1 >= overlay.dstBox.x2) ||
2783       (overlay.dstBox.y1 >= overlay.dstBox.y2)) {
2784 #ifdef SISMERGED
2785       if(pSiS->MergedFB) overlay.DoFirst = FALSE;
2786       else
2787 #endif
2788            return;
2789    }
2790 
2791    if((overlay.dstBox.x2 <= 0) || (overlay.dstBox.y2 <= 0)) {
2792 #ifdef SISMERGED
2793       if(pSiS->MergedFB) overlay.DoFirst = FALSE;
2794       else
2795 #endif
2796            return;
2797    }
2798 
2799    if((overlay.dstBox.x1 >= screenwidth) || (overlay.dstBox.y1 >= overlay.SCREENheight)) {
2800 #ifdef SISMERGED
2801       if(pSiS->MergedFB) overlay.DoFirst = FALSE;
2802       else
2803 #endif
2804            return;
2805    }
2806 
2807 #ifdef SISMERGED
2808    if(pSiS->MergedFB) {
2809       /* Check if dotclock is within limits for CRT1 */
2810       if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) {
2811          if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) {
2812             overlay.DoFirst = FALSE;
2813          }
2814       }
2815    }
2816 #endif
2817 
2818    if(overlay.dstBox.x1 < 0) {
2819       srcOffsetX = pPriv->src_w * (-overlay.dstBox.x1) / pPriv->drw_w;
2820       overlay.dstBox.x1 = 0;
2821    }
2822    if(overlay.dstBox.y1 < 0) {
2823       srcOffsetY = pPriv->src_h * (-overlay.dstBox.y1) / pPriv->drw_h;
2824       overlay.dstBox.y1 = 0;
2825    }
2826 
2827    if((overlay.dstBox.x1 >= overlay.dstBox.x2 - 2) ||
2828       (overlay.dstBox.x1 >= screenwidth - 2)       ||
2829       (overlay.dstBox.y1 >= overlay.dstBox.y2)) {
2830 #ifdef SISMERGED
2831       if(pSiS->MergedFB) overlay.DoFirst = FALSE;
2832       else
2833 #endif
2834            return;
2835    }
2836 
2837 #ifdef SISMERGED
2838    if(pSiS->MergedFB) {
2839       if((overlay.dstBox2.x2 <= 0) || (overlay.dstBox2.y2 <= 0))
2840 	 overlay.DoSecond = FALSE;
2841 
2842       if((overlay.dstBox2.x1 >= screen2width) || (overlay.dstBox2.y1 >= overlay.SCREENheight2))
2843 	 overlay.DoSecond = FALSE;
2844 
2845       if(overlay.dstBox2.x1 < 0) {
2846 	 srcOffsetX2 = pPriv->src_w * (-overlay.dstBox2.x1) / pPriv->drw_w;
2847 	 overlay.dstBox2.x1 = 0;
2848       }
2849 
2850       if(overlay.dstBox2.y1 < 0) {
2851 	 srcOffsetY2 = pPriv->src_h * (-overlay.dstBox2.y1) / pPriv->drw_h;
2852 	 overlay.dstBox2.y1 = 0;
2853       }
2854 
2855       if((overlay.dstBox2.x1 >= overlay.dstBox2.x2 - 2) ||
2856 	 (overlay.dstBox2.x1 >= screen2width - 2)       ||
2857 	 (overlay.dstBox2.y1 >= overlay.dstBox2.y2))
2858 	 overlay.DoSecond = FALSE;
2859 
2860       /* Check if dotclock is within limits for CRT2 */
2861       if(pPriv->displayMode & (DISPMODE_SINGLE2 | DISPMODE_MIRROR)) {
2862 	 if(!(pSiS->MiscFlags & MISC_CRT2OVERLAY)) {
2863 	    overlay.DoSecond = FALSE;
2864 	 }
2865       }
2866 
2867       /* If neither overlay is to be displayed, disable them if they are currently enabled */
2868       if((!overlay.DoFirst) && (!overlay.DoSecond)) {
2869 	 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05);
2870 	 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
2871 	 temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
2872 	 if(temp & 0x02) {
2873 	    watchdog = WATCHDOG_DELAY;
2874 	    if(pPriv->hasTwoOverlays) {
2875 	       while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
2876 	       watchdog = WATCHDOG_DELAY;
2877 	       while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
2878 	    } else {
2879 	       temp = getsrreg(pSiS, 0x06);
2880 	       if(!(temp & 0x40)) {
2881 		  while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
2882 		  watchdog = WATCHDOG_DELAY;
2883 		  while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
2884 	       } else {
2885 		  while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
2886 		  watchdog = WATCHDOG_DELAY;
2887 		  while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
2888 	       }
2889 	    }
2890 	    setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
2891 	 }
2892 	 if(pPriv->hasTwoOverlays) {
2893 	    setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
2894 	    setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
2895 	    temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
2896 	    if(temp & 0x02) {
2897 	       watchdog = WATCHDOG_DELAY;
2898 	       while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
2899 	       watchdog = WATCHDOG_DELAY;
2900 	       while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
2901 	       setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
2902 	    }
2903 	 }
2904 	 pPriv->overlayStatus = FALSE;
2905          return;
2906       }
2907    }
2908 #endif
2909 
2910    switch(pPriv->id) {
2911 
2912      case PIXEL_FMT_YV12:
2913        overlay.planar = 1;
2914        overlay.planar_shiftpitch = 1;
2915 #ifdef SISMERGED
2916        if((!pSiS->MergedFB) || (overlay.DoFirst)) {
2917 #endif
2918           sx = (pPriv->src_x + srcOffsetX) & ~7;
2919           sy = (pPriv->src_y + srcOffsetY) & ~1;
2920           overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch;
2921           overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1);
2922           overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1);
2923           overlay.PSY += FBOFFSET;
2924           overlay.PSV += FBOFFSET;
2925           overlay.PSU += FBOFFSET;
2926           overlay.PSY >>= pPriv->shiftValue;
2927           overlay.PSV >>= pPriv->shiftValue;
2928           overlay.PSU >>= pPriv->shiftValue;
2929 #ifdef SISMERGED
2930        }
2931        if((pSiS->MergedFB) && (overlay.DoSecond)) {
2932           sx2 = (pPriv->src_x + srcOffsetX2) & ~7;
2933           sy2 = (pPriv->src_y + srcOffsetY2) & ~1;
2934           overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch;
2935           overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1);
2936           overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1);
2937           overlay.PSY2 += FBOFFSET;
2938           overlay.PSV2 += FBOFFSET;
2939           overlay.PSU2 += FBOFFSET;
2940           overlay.PSY2 >>= pPriv->shiftValue;
2941           overlay.PSV2 >>= pPriv->shiftValue;
2942           overlay.PSU2 >>= pPriv->shiftValue;
2943        }
2944 #endif
2945        break;
2946 
2947      case PIXEL_FMT_I420:
2948        overlay.planar = 1;
2949        overlay.planar_shiftpitch = 1;
2950 #ifdef SISMERGED
2951        if((!pSiS->MergedFB) || (overlay.DoFirst)) {
2952 #endif
2953           sx = (pPriv->src_x + srcOffsetX) & ~7;
2954           sy = (pPriv->src_y + srcOffsetY) & ~1;
2955           overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch;
2956           overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1);
2957           overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1);
2958           overlay.PSY += FBOFFSET;
2959           overlay.PSV += FBOFFSET;
2960           overlay.PSU += FBOFFSET;
2961           overlay.PSY >>= pPriv->shiftValue;
2962           overlay.PSV >>= pPriv->shiftValue;
2963           overlay.PSU >>= pPriv->shiftValue;
2964 #ifdef SISMERGED
2965        }
2966        if((pSiS->MergedFB) && (overlay.DoSecond)) {
2967           sx2 = (pPriv->src_x + srcOffsetX2) & ~7;
2968           sy2 = (pPriv->src_y + srcOffsetY2) & ~1;
2969           overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch;
2970           overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1);
2971           overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1);
2972           overlay.PSY2 += FBOFFSET;
2973           overlay.PSV2 += FBOFFSET;
2974           overlay.PSU2 += FBOFFSET;
2975           overlay.PSY2 >>= pPriv->shiftValue;
2976           overlay.PSV2 >>= pPriv->shiftValue;
2977           overlay.PSU2 >>= pPriv->shiftValue;
2978        }
2979 #endif
2980        break;
2981 
2982      case PIXEL_FMT_NV12:
2983      case PIXEL_FMT_NV21:
2984        overlay.planar = 1;
2985        overlay.planar_shiftpitch = 0;
2986 #ifdef SISMERGED
2987        if((!pSiS->MergedFB) || (overlay.DoFirst)) {
2988 #endif
2989           sx = (pPriv->src_x + srcOffsetX) & ~7;
2990           sy = (pPriv->src_y + srcOffsetY) & ~1;
2991           overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch;
2992           overlay.PSV =	pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1);
2993           overlay.PSY += FBOFFSET;
2994           overlay.PSV += FBOFFSET;
2995           overlay.PSY >>= pPriv->shiftValue;
2996           overlay.PSV >>= pPriv->shiftValue;
2997           overlay.PSU = overlay.PSV;
2998 #ifdef SISMERGED
2999        }
3000        if((pSiS->MergedFB) && (overlay.DoSecond)) {
3001           sx2 = (pPriv->src_x + srcOffsetX2) & ~7;
3002           sy2 = (pPriv->src_y + srcOffsetY2) & ~1;
3003           overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch;
3004           overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1);
3005           overlay.PSY2 += FBOFFSET;
3006           overlay.PSV2 += FBOFFSET;
3007           overlay.PSY2 >>= pPriv->shiftValue;
3008           overlay.PSV2 >>= pPriv->shiftValue;
3009           overlay.PSU2 = overlay.PSV2;
3010        }
3011 #endif
3012        break;
3013 
3014      case PIXEL_FMT_YUY2:
3015      case PIXEL_FMT_UYVY:
3016      case PIXEL_FMT_YVYU:
3017      case PIXEL_FMT_RGB6:
3018      case PIXEL_FMT_RGB5:
3019      default:
3020        overlay.planar = 0;
3021 #ifdef SISMERGED
3022        if((!pSiS->MergedFB) || (overlay.DoFirst)) {
3023 #endif
3024           sx = (pPriv->src_x + srcOffsetX) & ~1;
3025           sy = (pPriv->src_y + srcOffsetY);
3026           overlay.PSY = (pPriv->bufAddr[pPriv->currentBuf] + sx*2 + sy*srcPitch);
3027           overlay.PSY += FBOFFSET;
3028           overlay.PSY >>= pPriv->shiftValue;
3029 #ifdef SISMERGED
3030        }
3031        if((pSiS->MergedFB) && (overlay.DoSecond)) {
3032           sx2 = (pPriv->src_x + srcOffsetX2) & ~1;
3033           sy2 = (pPriv->src_y + srcOffsetY2);
3034           overlay.PSY2 = (pPriv->bufAddr[pPriv->currentBuf] + sx2*2 + sy2*srcPitch);
3035           overlay.PSY2 += FBOFFSET;
3036           overlay.PSY2 >>= pPriv->shiftValue;
3037        }
3038 #endif
3039        break;
3040    }
3041 
3042    /* Some clipping checks */
3043 #ifdef SISMERGED
3044    if((!pSiS->MergedFB) || (overlay.DoFirst)) {
3045 #endif
3046       overlay.srcW = pPriv->src_w - (sx - pPriv->src_x);
3047       overlay.srcH = pPriv->src_h - (sy - pPriv->src_y);
3048       if( (pPriv->oldx1 != overlay.dstBox.x1) ||
3049 	  (pPriv->oldx2 != overlay.dstBox.x2) ||
3050 	  (pPriv->oldy1 != overlay.dstBox.y1) ||
3051 	  (pPriv->oldy2 != overlay.dstBox.y2) ) {
3052 	 pPriv->mustwait = 1;
3053 	 pPriv->oldx1 = overlay.dstBox.x1; pPriv->oldx2 = overlay.dstBox.x2;
3054 	 pPriv->oldy1 = overlay.dstBox.y1; pPriv->oldy2 = overlay.dstBox.y2;
3055       }
3056 #ifdef SISMERGED
3057    }
3058    if((pSiS->MergedFB) && (overlay.DoSecond)) {
3059       overlay.srcW2 = pPriv->src_w - (sx2 - pPriv->src_x);
3060       overlay.srcH2 = pPriv->src_h - (sy2 - pPriv->src_y);
3061       if( (pPriv->oldx1_2 != overlay.dstBox2.x1) ||
3062 	  (pPriv->oldx2_2 != overlay.dstBox2.x2) ||
3063 	  (pPriv->oldy1_2 != overlay.dstBox2.y1) ||
3064 	  (pPriv->oldy2_2 != overlay.dstBox2.y2) ) {
3065 	 pPriv->mustwait = 1;
3066 	 pPriv->oldx1_2 = overlay.dstBox2.x1; pPriv->oldx2_2 = overlay.dstBox2.x2;
3067 	 pPriv->oldy1_2 = overlay.dstBox2.y1; pPriv->oldy2_2 = overlay.dstBox2.y2;
3068       }
3069    }
3070 #endif
3071 
3072 #ifdef SISMERGED
3073    /* Disable an overlay if it is not to be displayed (but enabled currently) */
3074    if((pSiS->MergedFB) && (pPriv->hasTwoOverlays)) {
3075       if(!overlay.DoFirst) {
3076 	 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05);
3077 	 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
3078 	 temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
3079 	 if(temp & 0x02) {
3080 	    watchdog = WATCHDOG_DELAY;
3081 	    while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
3082 	    watchdog = WATCHDOG_DELAY;
3083 	    while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
3084 	    setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
3085 	 }
3086       } else if(!overlay.DoSecond) {
3087 	 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
3088 	 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
3089 	 temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
3090 	 if(temp & 0x02) {
3091 	    watchdog = WATCHDOG_DELAY;
3092 	    while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
3093 	    watchdog = WATCHDOG_DELAY;
3094 	    while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
3095 	    setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
3096 	 }
3097       }
3098    }
3099 #endif
3100 
3101    /* Loop head */
3102    /* Note: index can only be 1 for CRT2, ie overlay 1
3103     * is only used for CRT2.
3104     */
3105    if(pPriv->displayMode & DISPMODE_SINGLE2) {
3106       if(pPriv->hasTwoOverlays) {			/* We have 2 overlays: */
3107 	 if(pPriv->dualHeadMode) {
3108 	    /* Dual head: We use overlay 2 for CRT2 */
3109 	    index = 1; iscrt2 = 1;
3110 	 } else {
3111 	    /* Single head: We use overlay 1 for CRT2 */
3112 	    index = 0; iscrt2 = 1;
3113 	 }
3114       } else {						/* We have 1 overlay */
3115 	 /* We use that only overlay for CRT2 */
3116 	 index = 0; iscrt2 = 1;
3117       }
3118       overlay.VBlankActiveFunc = vblank_active_CRT2;
3119 #ifdef SISMERGED
3120       if(!pPriv->hasTwoOverlays) {
3121 	 if((pSiS->MergedFB) && (!overlay.DoSecond)) {
3122 	    index = 0; iscrt2 = 0;
3123 	    overlay.VBlankActiveFunc = vblank_active_CRT1;
3124 	    pPriv->displayMode = DISPMODE_SINGLE1;
3125 	 }
3126       }
3127 #endif
3128    } else {
3129       index = 0; iscrt2 = 0;
3130       overlay.VBlankActiveFunc = vblank_active_CRT1;
3131 #ifdef SISMERGED
3132       if((pSiS->MergedFB) && (!overlay.DoFirst)) {
3133 	 if(pPriv->hasTwoOverlays) index = 1;
3134 	 iscrt2 = 1;
3135 	 overlay.VBlankActiveFunc = vblank_active_CRT2;
3136 	 if(!pPriv->hasTwoOverlays) {
3137 	    pPriv->displayMode = DISPMODE_SINGLE2;
3138 	 }
3139       }
3140 #endif
3141    }
3142 
3143    /* set display mode SR06,32 (CRT1, CRT2 or mirror) */
3144    set_disptype_regs(pScrn, pPriv);
3145 
3146    /* set (not only calc) merge line buffer */
3147 #ifdef SISMERGED
3148    if(!pSiS->MergedFB) {
3149 #endif
3150       merge_line_buf(pSiS, pPriv, (overlay.srcW > pPriv->linebufMergeLimit), overlay.srcW,
3151       		     pPriv->linebufMergeLimit);
3152 #ifdef SISMERGED
3153    } else {
3154       Bool temp1 = FALSE, temp2 = FALSE;
3155       if(overlay.DoFirst) {
3156          if(overlay.srcW > pPriv->linebufMergeLimit)  temp1 = TRUE;
3157       }
3158       if(overlay.DoSecond) {
3159          if(overlay.srcW2 > pPriv->linebufMergeLimit) temp2 = TRUE;
3160       }
3161       merge_line_buf_mfb(pSiS, pPriv, temp1, temp2, overlay.srcW, overlay.srcW2,
3162 			 pPriv->linebufMergeLimit);
3163    }
3164 #endif
3165 
3166    /* calculate (not set!) line buffer length */
3167 #ifdef SISMERGED
3168    if((!pSiS->MergedFB) || (overlay.DoFirst))
3169 #endif
3170       calc_line_buf_size_1(&overlay, pPriv);
3171 #ifdef SISMERGED
3172    if((pSiS->MergedFB) && (overlay.DoSecond))
3173       calc_line_buf_size_2(&overlay, pPriv);
3174 #endif
3175 
3176    if(pPriv->dualHeadMode) {
3177 #ifdef SISDUALHEAD
3178       if(!pSiS->SecondHead) {
3179          if(pPriv->updatetvxpos) {
3180             SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
3181             pPriv->updatetvxpos = FALSE;
3182          }
3183          if(pPriv->updatetvypos) {
3184             SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
3185             pPriv->updatetvypos = FALSE;
3186          }
3187       }
3188 #endif
3189    } else {
3190       if(pPriv->updatetvxpos) {
3191          SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
3192          pPriv->updatetvxpos = FALSE;
3193       }
3194       if(pPriv->updatetvypos) {
3195          SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
3196          pPriv->updatetvypos = FALSE;
3197       }
3198    }
3199 
3200 #if 0 /* Clearing this does not seem to be required */
3201       /* and might even be dangerous. */
3202    if(pSiS->VGAEngine == SIS_315_VGA) {
3203       watchdog = WATCHDOG_DELAY;
3204       while(overlay.VBlankActiveFunc(pSiS, pPriv) && --watchdog);
3205       setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x00, 0x03);
3206    }
3207 #endif
3208    setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x03, 0x03);
3209 
3210    /* Do the following in a loop for CRT1 and CRT2 ----------------- */
3211 MIRROR:
3212 
3213    /* calculate scale factor */
3214 #ifdef SISMERGED
3215    if(pSiS->MergedFB && iscrt2)
3216       calc_scale_factor_2(&overlay, pScrn, pPriv, index, iscrt2);
3217    else
3218 #endif
3219       calc_scale_factor(&overlay, pScrn, pPriv, index, iscrt2);
3220 
3221    /* Select overlay 0 (used for CRT1/or CRT2) or overlay 1 (used for CRT2 only) */
3222    setvideoregmask(pSiS, Index_VI_Control_Misc2, index, 0x01);
3223 
3224    /* set format (before color and chroma keys) */
3225    set_format(pSiS, &overlay);
3226 
3227    /* set color key */
3228    set_colorkey(pSiS, pPriv->colorKey);
3229 
3230    if(pPriv->usechromakey) {
3231       /* Select chroma key format (300 series only) */
3232       if(pSiS->VGAEngine == SIS_300_VGA) {
3233 	 setvideoregmask(pSiS, Index_VI_Control_Misc0,
3234 	                 (pPriv->yuvchromakey ? 0x40 : 0x00), 0x40);
3235       }
3236       set_chromakey(pSiS, pPriv->chromamin, pPriv->chromamax);
3237    }
3238 
3239    /* set brightness, contrast, hue, saturation */
3240    set_brightness(pSiS, pPriv->brightness);
3241    set_contrast(pSiS, pPriv->contrast);
3242    if(pSiS->VGAEngine == SIS_315_VGA) {
3243       set_hue(pSiS, pPriv->hue);
3244       set_saturation(pSiS, pPriv->saturation);
3245    }
3246 
3247    /* enable/disable graphics display around overlay
3248     * (Since disabled overlays don't get treated in this
3249     * loop, we omit respective checks here)
3250     */
3251    if(!iscrt2) {
3252      set_disablegfx(pSiS, pPriv->disablegfx, &overlay);
3253    } else if(!pSiS->hasTwoOverlays) {
3254      set_disablegfx(pSiS, FALSE, &overlay);
3255    }
3256    set_disablegfxlr(pSiS, pPriv->disablegfxlr, &overlay);
3257 
3258 #ifdef SIS_CP
3259    SIS_CP_VIDEO_SET_CP
3260 #endif
3261 
3262    /* set remaining overlay parameters */
3263    set_overlay(pSiS, &overlay, pPriv, index, iscrt2);
3264 
3265    /* enable overlay */
3266    setvideoregmask (pSiS, Index_VI_Control_Misc0, 0x02, 0x02);
3267 
3268    /* loop foot */
3269    if(pPriv->displayMode & DISPMODE_MIRROR &&
3270       index == 0			   &&
3271       pPriv->hasTwoOverlays) {
3272 #ifdef SISMERGED
3273       if((!pSiS->MergedFB) || overlay.DoSecond) {
3274 #endif
3275 	 index = 1; iscrt2 = 1;
3276 	 overlay.VBlankActiveFunc = vblank_active_CRT2;
3277 	 goto MIRROR;
3278 #ifdef SISMERGED
3279       }
3280 #endif
3281    }
3282 
3283    /* Now for the trigger: This is a bad hack to work-around
3284     * an obvious hardware bug: Overlay 1 (which is ONLY used
3285     * for CRT2 in this driver) does not always update its
3286     * window position and some other stuff. Earlier, this was
3287     * solved be disabling the overlay, but this took forever
3288     * and was ugly on the screen.
3289     * Now: We write 0x03 to 0x74 from the beginning. This is
3290     * meant as a "lock" - the driver is supposed to write 0
3291     * to this register, bit 0 for overlay 0, bit 1 for over-
3292     * lay 1, then change buffer addresses, pitches, window
3293     * position, scaler registers, format, etc., then write
3294     * 1 to 0x74. The hardware then reads the registers into
3295     * its internal engine and clears these bits.
3296     * All this works for overlay 0, but not 1. Overlay 1
3297     * has assumingly the following restrictions:
3298     * - New data written to the registers is only read
3299     *   correctly by the engine if the registers are written
3300     *   when the current scanline is beyond the current
3301     *   overlay position and below the maximum visible
3302     *   scanline (vertical screen resolution)
3303     * - If a vertical retrace occures during writing the
3304     *   registers, the registers written BEFORE this re-
3305     *   trace happened, are not being read into the
3306     *   engine if the trigger is set after the retrace.
3307     * Therefore: We write the overlay registers above in
3308     * set_overlay only if the scanline matches, and save
3309     * the then current scanline. If this scanline is higher
3310     * than the now current scanline, we assume a retrace,
3311     * wait for the scanline to match the criteria above again,
3312     * and rewrite all relevant registers.
3313     * I have no idea if this is meant that way, but after
3314     * fiddling three entire days with this crap, I found this
3315     * to be the only solution.
3316     */
3317    if(pSiS->VGAEngine == SIS_315_VGA) {
3318       if((pPriv->mustwait) && index) {
3319 	 watchdog = get_scanline_CRT2(pSiS, pPriv);
3320 	 if(watchdog <= overlay.oldLine) {
3321 	    int i, mytop = overlay.oldtop;
3322 	    int screenHeight = overlay.SCREENheight;
3323 #ifdef SISMERGED
3324 	    if(pSiS->MergedFB) {
3325 	       screenHeight = overlay.SCREENheight2;
3326 	    }
3327 #endif
3328 	    if(mytop < screenHeight - 2) {
3329 	       do {
3330 	          watchdog = get_scanline_CRT2(pSiS, pPriv);
3331 	       } while((watchdog <= mytop) || (watchdog >= screenHeight));
3332 	    }
3333 	    for(i=0x02; i<=0x12; i++) {
3334 	       setvideoreg(pSiS, i, getvideoreg(pSiS, i));
3335 	    }
3336 	    for(i=0x18; i<=0x1c; i++) {
3337 	       setvideoreg(pSiS, i, getvideoreg(pSiS, i));
3338 	    }
3339 	    for(i=0x2c; i<=0x2e; i++) {
3340 	       setvideoreg(pSiS, i, getvideoreg(pSiS, i));
3341 	    }
3342 	    for(i=0x6b; i<=0x6f; i++) {
3343 	       setvideoreg(pSiS, i, getvideoreg(pSiS, i));
3344 	    }
3345 	 }
3346       }
3347       /* Trigger register copy for 315/330 series */
3348       setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x03, 0x03);
3349    }
3350 
3351    pPriv->mustwait = 0;
3352    pPriv->overlayStatus = TRUE;
3353 }
3354 
3355 /*********************************
3356  *        Memory management      *
3357  *********************************/
3358 
3359 #ifdef SIS_USE_EXA
3360 static void
SiSDestroyArea(ScreenPtr pScreen,ExaOffscreenArea * area)3361 SiSDestroyArea(ScreenPtr pScreen, ExaOffscreenArea *area)
3362 {
3363    void **handle = (void *)area->privData;
3364    *handle = NULL;
3365 }
3366 #endif
3367 
3368 unsigned int
SISAllocateFBMemory(ScrnInfoPtr pScrn,void ** handle,int bytesize)3369 SISAllocateFBMemory(
3370   ScrnInfoPtr pScrn,
3371   void **handle,
3372   int bytesize
3373 ){
3374    SISPtr pSiS = SISPTR(pScrn);
3375    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
3376 
3377 #ifdef SIS_USE_XAA
3378    if(!pSiS->useEXA) {
3379       FBLinearPtr linear = (FBLinearPtr)(*handle);
3380       FBLinearPtr new_linear;
3381       int depth = pSiS->CurrentLayout.bitsPerPixel >> 3;
3382       int size = ((bytesize + depth - 1) / depth);
3383 
3384       if(linear) {
3385          if(linear->size >= size) {
3386 	    return (unsigned int)(linear->offset * depth);
3387 	 }
3388 
3389          if(xf86ResizeOffscreenLinear(linear, size)) {
3390 	    return (unsigned int)(linear->offset * depth);
3391 	 }
3392 
3393          xf86FreeOffscreenLinear(linear);
3394 	 *handle = NULL;
3395       }
3396 
3397       new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL);
3398 
3399       if(!new_linear) {
3400          int max_size;
3401 
3402          xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, PRIORITY_EXTREME);
3403 
3404          if(max_size < size)
3405 	    return 0;
3406 
3407          xf86PurgeUnlockedOffscreenAreas(pScreen);
3408          new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL);
3409       }
3410       if(!new_linear) {
3411          xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3412 	           "Xv: Failed to allocate %d pixels of linear video memory\n", size);
3413 	 return 0;
3414       } else {
3415          *handle = (void *)new_linear;
3416 	 return (unsigned int)(new_linear->offset * depth);
3417       }
3418    }
3419 #endif
3420 #ifdef SIS_USE_EXA
3421    if(pSiS->useEXA && !pSiS->NoAccel) {
3422       ExaOffscreenArea *area = (ExaOffscreenArea *)(*handle);
3423 
3424       if(area) {
3425 	 if(area->size >= bytesize) return (unsigned int)(area->offset);
3426 
3427 	 exaOffscreenFree(pScreen, area);
3428 	 *handle = NULL;
3429       }
3430 
3431       if(!(area = exaOffscreenAlloc(pScreen, bytesize, 8, TRUE, SiSDestroyArea, (pointer)handle))) {
3432 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3433 	           "Xv: Failed to allocate %d bytes of video memory\n", bytesize);
3434 	 return 0;
3435       } else {
3436 	 *handle = (void *)area;
3437 	 return (unsigned int)(area->offset);
3438       }
3439    }
3440 #endif
3441 
3442    return 0;
3443 }
3444 
3445 void
SISFreeFBMemory(ScrnInfoPtr pScrn,void ** handle)3446 SISFreeFBMemory(ScrnInfoPtr pScrn, void **handle)
3447 {
3448     SISPtr pSiS = SISPTR(pScrn);
3449 #ifdef SIS_USE_EXA
3450     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
3451 #endif
3452 
3453 #ifdef SIS_USE_XAA
3454     if(!pSiS->useEXA) {
3455        if(*handle) {
3456           xf86FreeOffscreenLinear((FBLinearPtr)(*handle));
3457        }
3458     }
3459 #endif
3460 #ifdef SIS_USE_EXA
3461    if(pSiS->useEXA && !pSiS->NoAccel) {
3462       if(*handle) {
3463          exaOffscreenFree(pScreen, (ExaOffscreenArea *)(*handle));
3464       }
3465    }
3466 #endif
3467    *handle = NULL;
3468 }
3469 
3470 /*********************************
3471  *           StopVideo()         *
3472  *********************************/
3473 
3474 static void
SISStopVideo(ScrnInfoPtr pScrn,pointer data,Bool shutdown)3475 SISStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
3476 {
3477   SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
3478   SISPtr pSiS = SISPTR(pScrn);
3479 
3480   if(pPriv->grabbedByV4L) return;
3481 
3482   REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
3483 
3484   if(shutdown) {
3485      if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
3486         close_overlay(pSiS, pPriv);
3487         pPriv->mustwait = 1;
3488      }
3489      SISFreeFBMemory(pScrn, &pPriv->handle);
3490      pPriv->videoStatus = 0;
3491   } else {
3492      if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
3493         UpdateCurrentTime();
3494         pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
3495         pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
3496         pSiS->VideoTimerCallback = SISVideoTimerCallback;
3497      }
3498   }
3499 }
3500 
3501 /*********************************
3502  *          PutImage()           *
3503  *********************************/
3504 
3505 static int
SISPutImage(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,UChar * buf,short width,short height,Bool sync,RegionPtr clipBoxes,pointer data,DrawablePtr pDraw)3506 SISPutImage(
3507   ScrnInfoPtr pScrn,
3508   short src_x, short src_y,
3509   short drw_x, short drw_y,
3510   short src_w, short src_h,
3511   short drw_w, short drw_h,
3512   int id, UChar *buf,
3513   short width, short height,
3514   Bool sync,
3515   RegionPtr clipBoxes, pointer data,
3516   DrawablePtr pDraw
3517 ){
3518    SISPtr pSiS = SISPTR(pScrn);
3519    SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
3520 #ifdef SIS_USE_XAA
3521    XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr;
3522    int depth = pSiS->CurrentLayout.bitsPerPixel >> 3;
3523    int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 };
3524 #endif
3525    int totalSize = 0;
3526 #ifdef SISDEINT
3527    Bool	deintfm = (pPriv->deinterlacemethod > 1) ? TRUE : FALSE;
3528 #endif
3529 
3530 #if 0
3531    xf86DrvMsg(0, X_INFO, "PutImage: src %dx%d-%dx%d, drw %dx%d-%dx%d, id %x, w %d h %d, buf %p\n",
3532 	src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, id, width, height, buf);
3533 #endif
3534 
3535    if(pPriv->grabbedByV4L) return Success;
3536 
3537    pPriv->drw_x = drw_x;
3538    pPriv->drw_y = drw_y;
3539    pPriv->drw_w = drw_w;
3540    pPriv->drw_h = drw_h;
3541    pPriv->src_x = src_x;
3542    pPriv->src_y = src_y;
3543    pPriv->src_w = src_w;
3544    pPriv->src_h = src_h;
3545    pPriv->id = id;
3546    pPriv->height = height;
3547 
3548    /* Pixel formats:
3549       1. YU12:  3 planes:       H    V
3550                Y sample period  1    1   (8 bit per pixel)
3551 	       V sample period  2    2	 (8 bit per pixel, subsampled)
3552 	       U sample period  2    2   (8 bit per pixel, subsampled)
3553 
3554 	 Y plane is fully sampled (width*height), U and V planes
3555 	 are sampled in 2x2 blocks, hence a group of 4 pixels requires
3556 	 4 + 1 + 1 = 6 bytes. The data is planar, ie in single planes
3557 	 for Y, U and V.
3558       2. UYVY: 3 planes:        H    V
3559 	       Y sample period  1    1   (8 bit per pixel)
3560 	       V sample period  2    1	 (8 bit per pixel, subsampled)
3561 	       U sample period  2    1   (8 bit per pixel, subsampled)
3562 	 Y plane is fully sampled (width*height), U and V planes
3563 	 are sampled in 2x1 blocks, hence a group of 4 pixels requires
3564 	 4 + 2 + 2 = 8 bytes. The data is bit packed, there are no separate
3565 	 Y, U or V planes.
3566 	 Bit order:  U0 Y0 V0 Y1  U2 Y2 V2 Y3 ...
3567       3. I420: Like YU12, but planes U and V are in reverse order.
3568       4. YUY2: Like UYVY, but order is
3569 		     Y0 U0 Y1 V0  Y2 U2 Y3 V2 ...
3570       5. YVYU: Like YUY2, but order is
3571 		     Y0 V0 Y1 U0  Y2 V2 Y3 U2 ...
3572       6. NV12, NV21: 2 planes   H    V
3573 	       Y sample period  1    1   (8 bit per pixel)
3574 	       V sample period  2    1	 (8 bit per pixel, subsampled)
3575 	       U sample period  2    1   (8 bit per pixel, subsampled)
3576 	 Y plane is fully samples (width*height), U and V planes are
3577 	 interleaved in memory (one byte U, one byte V for NV12, NV21
3578 	 other way round) and sampled in 2x1 blocks. Otherwise such
3579 	 as all other planar formats.
3580    */
3581 
3582    switch(id){
3583      case PIXEL_FMT_YV12:
3584      case PIXEL_FMT_I420:
3585      case PIXEL_FMT_NV12:
3586      case PIXEL_FMT_NV21:
3587        pPriv->srcPitch = (width + 7) & ~7;
3588        /* Size = width * height * 3 / 2 */
3589        totalSize = (pPriv->srcPitch * height * 3) >> 1; /* Verified */
3590        break;
3591      case PIXEL_FMT_YUY2:
3592      case PIXEL_FMT_UYVY:
3593      case PIXEL_FMT_YVYU:
3594      case PIXEL_FMT_RGB6:
3595      case PIXEL_FMT_RGB5:
3596      default:
3597        pPriv->srcPitch = ((width << 1) + 3) & ~3;	/* Verified */
3598        /* Size = width * 2 * height */
3599        totalSize = pPriv->srcPitch * height;
3600    }
3601 
3602    /* make it a multiple of 16 to simplify to copy loop */
3603    totalSize += 15;
3604    totalSize &= ~15; /* in bytes */
3605 
3606    /* allocate memory (we do doublebuffering) - size is in bytes */
3607    if(!(pPriv->bufAddr[0] = SISAllocateFBMemory(pScrn, &pPriv->handle, totalSize << 1)))
3608       return BadAlloc;
3609 
3610 #ifdef SISDEINT
3611    if(deintfm) {
3612       pPriv->bufAddr[1] = pPriv->bufAddr[0] + pPriv->srcPitch;
3613 
3614       {
3615          CARD8 *src = (CARD8 *)buf;
3616          CARD8 *dest = (CARD8 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]);
3617          int i = height;
3618          while(i--) {
3619 	    SiSMemCopyToVideoRam(pSiS, dest, src, pPriv->srcPitch);
3620 	    src += pPriv->srcPitch;
3621 	    dest += (pPriv->srcPitch << 1);
3622          }
3623       }
3624 
3625    } else {
3626 #endif
3627       pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize;
3628 
3629       /* copy data */
3630       if((pSiS->XvUseMemcpy) || (totalSize < 16)) {
3631          SiSMemCopyToVideoRam(pSiS, pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize);
3632       } else {
3633          ULong i;
3634          CARD32 *src = (CARD32 *)buf;
3635          CARD32 *dest = (CARD32 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]);
3636          for(i = 0; i < (totalSize/16); i++) {
3637             *dest++ = *src++;
3638 	    *dest++ = *src++;
3639 	    *dest++ = *src++;
3640 	    *dest++ = *src++;
3641          }
3642       }
3643 #ifdef SISDEINT
3644    }
3645 #endif
3646 
3647    SISDisplayVideo(pScrn, pPriv);
3648 
3649    /* update cliplist */
3650    if(pPriv->autopaintColorKey &&
3651       (pPriv->grabbedByV4L ||
3652 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0)
3653        (!RegionsEqual(&pPriv->clip, clipBoxes)) ||
3654 #else
3655        (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) ||
3656 #endif
3657        (pPriv->PrevOverlay != pPriv->NoOverlay))) {
3658      /* We always paint the colorkey for V4L */
3659      if(!pPriv->grabbedByV4L) {
3660      	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
3661      }
3662      /* draw these */
3663      pPriv->PrevOverlay = pPriv->NoOverlay;
3664 #ifdef SIS_USE_XAA
3665      if((pPriv->NoOverlay) && pXAA && pXAA->FillMono8x8PatternRects) {
3666         (*pXAA->FillMono8x8PatternRects)(pScrn, myreds[depth-1],
3667 			0x000000, GXcopy, ~0,
3668 			REGION_NUM_RECTS(clipBoxes),
3669 			REGION_RECTS(clipBoxes),
3670 			0x00422418, 0x18244200, 0, 0);
3671      } else {
3672 #endif
3673         if(!pSiS->disablecolorkeycurrent) {
3674 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
3675            (*pXAA->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0,
3676                            REGION_NUM_RECTS(clipBoxes),
3677                            REGION_RECTS(clipBoxes));
3678 #else
3679 	   xf86XVFillKeyHelper(pScrn->pScreen, (pPriv->NoOverlay) ? 0x00ff0000 : pPriv->colorKey, clipBoxes);
3680 #endif
3681 	}
3682 #ifdef SIS_USE_XAA
3683      }
3684 #endif
3685 
3686    }
3687 
3688    pPriv->currentBuf ^= 1;
3689 
3690    pPriv->videoStatus = CLIENT_VIDEO_ON;
3691 
3692    pSiS->VideoTimerCallback = SISVideoTimerCallback;
3693 
3694    return Success;
3695 }
3696 
3697 /*********************************
3698  *     QueryImageAttributes()    *
3699  *********************************/
3700 
3701 static int
SISQueryImageAttributes(ScrnInfoPtr pScrn,int id,UShort * w,UShort * h,int * pitches,int * offsets)3702 SISQueryImageAttributes(
3703   ScrnInfoPtr pScrn,
3704   int id,
3705   UShort *w, UShort *h,
3706   int *pitches, int *offsets
3707 ){
3708     int    pitchY, pitchUV;
3709     int    size, sizeY, sizeUV;
3710 
3711     if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH;
3712     if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT;
3713 
3714     if(*w > DummyEncoding.width) *w = DummyEncoding.width;
3715     if(*h > DummyEncoding.height) *h = DummyEncoding.height;
3716 
3717     switch(id) {
3718     case PIXEL_FMT_YV12:
3719     case PIXEL_FMT_I420:
3720         *w = (*w + 7) & ~7;
3721         *h = (*h + 1) & ~1;
3722         pitchY = *w;
3723     	pitchUV = *w >> 1;
3724     	if(pitches) {
3725       	    pitches[0] = pitchY;
3726             pitches[1] = pitches[2] = pitchUV;
3727         }
3728     	sizeY = pitchY * (*h);
3729     	sizeUV = pitchUV * ((*h) >> 1);
3730     	if(offsets) {
3731           offsets[0] = 0;
3732           offsets[1] = sizeY;
3733           offsets[2] = sizeY + sizeUV;
3734         }
3735         size = sizeY + (sizeUV << 1);
3736     	break;
3737     case PIXEL_FMT_NV12:
3738     case PIXEL_FMT_NV21:
3739         *w = (*w + 7) & ~7;
3740         *h = (*h + 1) & ~1;
3741 	pitchY = *w;
3742     	pitchUV = *w;
3743     	if(pitches) {
3744       	    pitches[0] = pitchY;
3745             pitches[1] = pitchUV;
3746         }
3747     	sizeY = pitchY * (*h);
3748     	sizeUV = pitchUV * ((*h) >> 1);
3749     	if(offsets) {
3750           offsets[0] = 0;
3751           offsets[1] = sizeY;
3752         }
3753         size = sizeY + (sizeUV << 1);
3754         break;
3755     case PIXEL_FMT_YUY2:
3756     case PIXEL_FMT_UYVY:
3757     case PIXEL_FMT_YVYU:
3758     case PIXEL_FMT_RGB6:
3759     case PIXEL_FMT_RGB5:
3760     default:
3761         *w = (*w + 1) & ~1;
3762         pitchY = *w << 1;
3763     	if(pitches) pitches[0] = pitchY;
3764     	if(offsets) offsets[0] = 0;
3765     	size = pitchY * (*h);
3766     	break;
3767     }
3768 
3769     return size;
3770 }
3771 
3772 
3773 /*********************************
3774  *      OFFSCREEN SURFACES       *
3775  *********************************/
3776 
3777 static int
SISAllocSurface(ScrnInfoPtr pScrn,int id,UShort w,UShort h,XF86SurfacePtr surface)3778 SISAllocSurface (
3779     ScrnInfoPtr pScrn,
3780     int id,
3781     UShort w,
3782     UShort h,
3783     XF86SurfacePtr surface
3784 )
3785 {
3786     SISPtr pSiS = SISPTR(pScrn);
3787     SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
3788     int size;
3789 
3790     if((w < IMAGE_MIN_WIDTH) || (h < IMAGE_MIN_HEIGHT))
3791        return BadValue;
3792 
3793     if((w > DummyEncoding.width) || (h > DummyEncoding.height))
3794        return BadValue;
3795 
3796     if(pPriv->grabbedByV4L)
3797        return BadAlloc;
3798 
3799     w = (w + 1) & ~1;
3800     pPriv->pitch = ((w << 1) + 63) & ~63; /* Only packed pixel modes supported */
3801     size = h * pPriv->pitch;
3802     if(!(pPriv->offset = SISAllocateFBMemory(pScrn, &pPriv->handle, size)))
3803        return BadAlloc;
3804 
3805     surface->width   = w;
3806     surface->height  = h;
3807     surface->pScrn   = pScrn;
3808     surface->id      = id;
3809     surface->pitches = &pPriv->pitch;
3810     surface->offsets = &pPriv->offset;
3811     surface->devPrivate.ptr = (pointer)pPriv;
3812 
3813     close_overlay(pSiS, pPriv);
3814     pPriv->videoStatus = 0;
3815     REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
3816     pSiS->VideoTimerCallback = NULL;
3817     pPriv->grabbedByV4L = TRUE;
3818     return Success;
3819 }
3820 
3821 static int
SISStopSurface(XF86SurfacePtr surface)3822 SISStopSurface (XF86SurfacePtr surface)
3823 {
3824     SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr);
3825     SISPtr pSiS = SISPTR(surface->pScrn);
3826 
3827     if(pPriv->grabbedByV4L && pPriv->videoStatus) {
3828        close_overlay(pSiS, pPriv);
3829        pPriv->mustwait = 1;
3830        pPriv->videoStatus = 0;
3831     }
3832     return Success;
3833 }
3834 
3835 static int
SISFreeSurface(XF86SurfacePtr surface)3836 SISFreeSurface (XF86SurfacePtr surface)
3837 {
3838     SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr);
3839 
3840     if(pPriv->grabbedByV4L) {
3841        SISStopSurface(surface);
3842        SISFreeFBMemory(surface->pScrn, &pPriv->handle);
3843        pPriv->grabbedByV4L = FALSE;
3844     }
3845     return Success;
3846 }
3847 
3848 static int
SISGetSurfaceAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 * value)3849 SISGetSurfaceAttribute (
3850     ScrnInfoPtr pScrn,
3851     Atom attribute,
3852     INT32 *value
3853 )
3854 {
3855     SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
3856 
3857     return SISGetPortAttribute(pScrn, attribute, value, (pointer)pPriv);
3858 }
3859 
3860 static int
SISSetSurfaceAttribute(ScrnInfoPtr pScrn,Atom attribute,INT32 value)3861 SISSetSurfaceAttribute(
3862     ScrnInfoPtr pScrn,
3863     Atom attribute,
3864     INT32 value
3865 )
3866 {
3867     SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);;
3868 
3869     return SISSetPortAttribute(pScrn, attribute, value, (pointer)pPriv);
3870 }
3871 
3872 static int
SISDisplaySurface(XF86SurfacePtr surface,short src_x,short src_y,short drw_x,short drw_y,short src_w,short src_h,short drw_w,short drw_h,RegionPtr clipBoxes)3873 SISDisplaySurface (
3874     XF86SurfacePtr surface,
3875     short src_x, short src_y,
3876     short drw_x, short drw_y,
3877     short src_w, short src_h,
3878     short drw_w, short drw_h,
3879     RegionPtr clipBoxes
3880 )
3881 {
3882    ScrnInfoPtr pScrn = surface->pScrn;
3883    SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr);
3884 #ifdef SIS_USE_XAA
3885    SISPtr pSiS = SISPTR(pScrn);
3886    int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 };
3887 #endif
3888 
3889    if(!pPriv->grabbedByV4L) return Success;
3890 
3891    pPriv->drw_x = drw_x;
3892    pPriv->drw_y = drw_y;
3893    pPriv->drw_w = drw_w;
3894    pPriv->drw_h = drw_h;
3895    pPriv->src_x = src_x;
3896    pPriv->src_y = src_y;
3897    pPriv->src_w = src_w;
3898    pPriv->src_h = src_h;
3899    pPriv->id = surface->id;
3900    pPriv->height = surface->height;
3901    pPriv->bufAddr[0] = surface->offsets[0];
3902    pPriv->currentBuf = 0;
3903    pPriv->srcPitch = surface->pitches[0];
3904 
3905    SISDisplayVideo(pScrn, pPriv);
3906 
3907    if(pPriv->autopaintColorKey) {
3908 #ifdef SIS_USE_XAA
3909       XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr;
3910 
3911       if((pPriv->NoOverlay) && pXAA && pXAA->FillMono8x8PatternRects) {
3912          (*pXAA->FillMono8x8PatternRects)(pScrn,
3913 	  		myreds[(pSiS->CurrentLayout.bitsPerPixel >> 3) - 1],
3914 	 		0x000000, GXcopy, ~0,
3915 			REGION_NUM_RECTS(clipBoxes),
3916 			REGION_RECTS(clipBoxes),
3917 			0x00422418, 0x18244200, 0, 0);
3918 
3919       } else {
3920 #endif
3921 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
3922    	 (*pXAA->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0,
3923                         REGION_NUM_RECTS(clipBoxes),
3924                         REGION_RECTS(clipBoxes));
3925 #else
3926          xf86XVFillKeyHelper(pScrn->pScreen, (pPriv->NoOverlay) ? 0x00ff0000 : pPriv->colorKey, clipBoxes);
3927 #endif
3928 #ifdef SIS_USE_XAA
3929       }
3930 #endif
3931    }
3932 
3933    pPriv->videoStatus = CLIENT_VIDEO_ON;
3934 
3935    return Success;
3936 }
3937 
3938 #define NUMOFFSCRIMAGES_300 4
3939 #define NUMOFFSCRIMAGES_315 5
3940 
3941 static XF86OffscreenImageRec SISOffscreenImages[NUMOFFSCRIMAGES_315] =
3942 {
3943  {
3944    &SISImages[0],  	/* YUV2 */
3945    VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
3946    SISAllocSurface,
3947    SISFreeSurface,
3948    SISDisplaySurface,
3949    SISStopSurface,
3950    SISGetSurfaceAttribute,
3951    SISSetSurfaceAttribute,
3952    0, 0,  			/* Rest will be filled in */
3953    0,
3954    NULL
3955  },
3956  {
3957    &SISImages[2],	/* UYVY */
3958    VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
3959    SISAllocSurface,
3960    SISFreeSurface,
3961    SISDisplaySurface,
3962    SISStopSurface,
3963    SISGetSurfaceAttribute,
3964    SISSetSurfaceAttribute,
3965    0, 0,  			/* Rest will be filled in */
3966    0,
3967    NULL
3968  }
3969  ,
3970  {
3971    &SISImages[4],	/* RV15 */
3972    VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
3973    SISAllocSurface,
3974    SISFreeSurface,
3975    SISDisplaySurface,
3976    SISStopSurface,
3977    SISGetSurfaceAttribute,
3978    SISSetSurfaceAttribute,
3979    0, 0,  			/* Rest will be filled in */
3980    0,
3981    NULL
3982  },
3983  {
3984    &SISImages[5],	/* RV16 */
3985    VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
3986    SISAllocSurface,
3987    SISFreeSurface,
3988    SISDisplaySurface,
3989    SISStopSurface,
3990    SISGetSurfaceAttribute,
3991    SISSetSurfaceAttribute,
3992    0, 0,  			/* Rest will be filled in */
3993    0,
3994    NULL
3995  },
3996  {
3997    &SISImages[6],	/* YVYU */
3998    VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
3999    SISAllocSurface,
4000    SISFreeSurface,
4001    SISDisplaySurface,
4002    SISStopSurface,
4003    SISGetSurfaceAttribute,
4004    SISSetSurfaceAttribute,
4005    0, 0,  			/* Rest will be filled in */
4006    0,
4007    NULL
4008  }
4009 };
4010 
4011 static void
SISInitOffscreenImages(ScreenPtr pScreen)4012 SISInitOffscreenImages(ScreenPtr pScreen)
4013 {
4014     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
4015     SISPtr pSiS = SISPTR(pScrn);
4016     int i, num;
4017 
4018     if(pSiS->VGAEngine == SIS_300_VGA)	num = NUMOFFSCRIMAGES_300;
4019     else 				num = NUMOFFSCRIMAGES_315;
4020 
4021     for(i = 0; i < num; i++) {
4022        SISOffscreenImages[i].max_width  = DummyEncoding.width;
4023        SISOffscreenImages[i].max_height = DummyEncoding.height;
4024        if(pSiS->VGAEngine == SIS_300_VGA) {
4025           SISOffscreenImages[i].attributes = &SISAttributes_300[0];
4026 	  SISOffscreenImages[i].num_attributes = SiSCountAttributes(&SISAttributes_300[0]);
4027        } else {
4028           SISOffscreenImages[i].attributes = &SISAttributes_315[0];
4029 	  SISOffscreenImages[i].num_attributes = SiSCountAttributes(&SISAttributes_315[0]);
4030 	  if((pSiS->hasTwoOverlays) && (!(pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORT760OO))) {
4031 	     SISOffscreenImages[i].num_attributes--;
4032 	  }
4033        }
4034     }
4035     xf86XVRegisterOffscreenImages(pScreen, SISOffscreenImages, num);
4036 }
4037 
4038 /*****************************************************************/
4039 /*                         BLIT ADAPTORS                         */
4040 /*****************************************************************/
4041 #ifdef INCL_YUV_BLIT_ADAPTOR
4042 
4043 static void
SISSetPortDefaultsBlit(ScrnInfoPtr pScrn,SISBPortPrivPtr pPriv)4044 SISSetPortDefaultsBlit(ScrnInfoPtr pScrn, SISBPortPrivPtr pPriv)
4045 {
4046     /* Default: Don't sync. */
4047     pPriv->vsync  = 0;
4048 }
4049 
4050 static void
SISResetVideoBlit(ScrnInfoPtr pScrn)4051 SISResetVideoBlit(ScrnInfoPtr pScrn)
4052 {
4053 }
4054 
4055 static XF86VideoAdaptorPtr
SISSetupBlitVideo(ScreenPtr pScreen)4056 SISSetupBlitVideo(ScreenPtr pScreen)
4057 {
4058    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
4059    SISPtr pSiS = SISPTR(pScrn);
4060    XF86VideoAdaptorPtr adapt;
4061    SISBPortPrivPtr pPriv;
4062    int i;
4063 
4064 #ifdef SIS_USE_XAA
4065    if(!pSiS->useEXA) {
4066       if(!pSiS->AccelInfoPtr) return NULL;
4067    }
4068 #endif
4069 
4070    if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
4071     			   (sizeof(DevUnion) * NUM_BLIT_PORTS) +
4072                            sizeof(SISBPortPrivRec)))) {
4073       return NULL;
4074    }
4075 
4076    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
4077    adapt->flags = 0;
4078    adapt->name = "SIS 315/330 series Video Blitter";
4079    adapt->nEncodings = 1;
4080    adapt->pEncodings = &DummyEncodingBlit;
4081    adapt->nFormats = NUM_FORMATS;
4082    adapt->pFormats = SISFormats;
4083    adapt->nImages = NUM_IMAGES_BLIT;
4084    adapt->pImages = SISImagesBlit;
4085    adapt->pAttributes = SISAttributes_Blit;
4086    adapt->nAttributes = NUM_ATTRIBUTES_BLIT;
4087    adapt->nPorts = NUM_BLIT_PORTS;
4088    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
4089 
4090    pSiS->blitPriv = (void *)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
4091    pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
4092 
4093    for(i = 0; i < NUM_BLIT_PORTS; i++) {
4094       adapt->pPortPrivates[i].uval = (ULong)(i);
4095 #if defined(REGION_NULL)
4096       REGION_NULL(pScreen, &pPriv->blitClip[i]);
4097 #else
4098       REGION_INIT(pScreen, &pPriv->blitClip[i], NullBox, 0);
4099 #endif
4100       pPriv->videoStatus[i] = 0;
4101       pPriv->currentBuf[i]  = 0;
4102       pPriv->handle[i]      = NULL;
4103    }
4104 
4105    /* Scanline trigger not implemented by hardware! */
4106    pPriv->VBlankTriggerCRT1 = 0; /* SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT1; */
4107    pPriv->VBlankTriggerCRT2 = 0; /* SCANLINE_TRIGGER_ENABLE | SCANLINE_TR_CRT2; */
4108    if(pSiS->ChipType >= SIS_330) {
4109       pPriv->AccelCmd = YUVRGB_BLIT_330;
4110    } else {
4111       pPriv->AccelCmd = YUVRGB_BLIT_325;
4112    }
4113 
4114    adapt->PutVideo = NULL;
4115    adapt->PutStill = NULL;
4116    adapt->GetVideo = NULL;
4117    adapt->GetStill = NULL;
4118    adapt->StopVideo = (StopVideoFuncPtr)SISStopVideoBlit;
4119    adapt->SetPortAttribute = (SetPortAttributeFuncPtr)SISSetPortAttributeBlit;
4120    adapt->GetPortAttribute = (GetPortAttributeFuncPtr)SISGetPortAttributeBlit;
4121    adapt->QueryBestSize = (QueryBestSizeFuncPtr)SISQueryBestSizeBlit;
4122    adapt->PutImage = (PutImageFuncPtr)SISPutImageBlit;
4123    adapt->QueryImageAttributes = SISQueryImageAttributesBlit;
4124 
4125    pSiS->blitadaptor = adapt;
4126 
4127    pSiS->xvVSync = MAKE_ATOM(sisxvvsync);
4128    pSiS->xvSetDefaults = MAKE_ATOM(sisxvsetdefaults);
4129 
4130    SISResetVideoBlit(pScrn);
4131 
4132    /* Reset the properties to their defaults */
4133    SISSetPortDefaultsBlit(pScrn, pPriv);
4134 
4135    return adapt;
4136 }
4137 
4138 static int
SISGetPortAttributeBlit(ScrnInfoPtr pScrn,Atom attribute,INT32 * value,ULong index)4139 SISGetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute,
4140   			INT32 *value, ULong index)
4141 {
4142    SISPtr pSiS = SISPTR(pScrn);
4143    SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
4144 
4145    if(attribute == pSiS->xvVSync) {
4146       *value = pPriv->vsync;
4147    } else return BadMatch;
4148    return Success;
4149 }
4150 
4151 static int
SISSetPortAttributeBlit(ScrnInfoPtr pScrn,Atom attribute,INT32 value,ULong index)4152 SISSetPortAttributeBlit(ScrnInfoPtr pScrn, Atom attribute,
4153   		    	INT32 value, ULong index)
4154 {
4155    SISPtr pSiS = SISPTR(pScrn);
4156    SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
4157 
4158    if(attribute == pSiS->xvVSync) {
4159       if((value < 0) || (value > 1)) return BadValue;
4160       pPriv->vsync = value;
4161    } else if(attribute == pSiS->xvSetDefaults) {
4162       SISSetPortDefaultsBlit(pScrn, pPriv);
4163    } else return BadMatch;
4164    return Success;
4165 }
4166 
4167 static void
SISStopVideoBlit(ScrnInfoPtr pScrn,ULong index,Bool shutdown)4168 SISStopVideoBlit(ScrnInfoPtr pScrn, ULong index, Bool shutdown)
4169 {
4170    SISPtr pSiS = SISPTR(pScrn);
4171    SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
4172 
4173    /* This shouldn't be called for blitter adaptors due to
4174     * adapt->flags but we provide it anyway.
4175     */
4176 
4177    if(index >= NUM_BLIT_PORTS) return;
4178 
4179    REGION_EMPTY(pScrn->pScreen, &pPriv->blitClip[index]);
4180 
4181    if(shutdown) {
4182       (*pSiS->SyncAccel)(pScrn);
4183       pPriv->videoStatus[index] = 0;
4184       SISFreeFBMemory(pScrn, &pPriv->handle[(int)index]);
4185    }
4186 }
4187 
4188 static int
SISPutImageBlit(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,UChar * buf,short width,short height,Bool sync,RegionPtr clipBoxes,ULong index,DrawablePtr pDraw)4189 SISPutImageBlit(
4190   ScrnInfoPtr pScrn,
4191   short src_x, short src_y,
4192   short drw_x, short drw_y,
4193   short src_w, short src_h,
4194   short drw_w, short drw_h,
4195   int id, UChar *buf,
4196   short width, short height,
4197   Bool sync,
4198   RegionPtr clipBoxes, ULong index,
4199   DrawablePtr pDraw
4200 ){
4201    SISPtr pSiS = SISPTR(pScrn);
4202    SISBPortPrivPtr pPriv = (SISBPortPrivPtr)(pSiS->blitPriv);
4203 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
4204    XAAInfoRecPtr pXAA = pSiS->AccelInfoPtr;
4205 #endif
4206    BoxPtr pbox = REGION_RECTS(clipBoxes);
4207    int    nbox = REGION_NUM_RECTS(clipBoxes);
4208    CARD32 dstbase = 0, offsety, offsetuv, temp;
4209    int    totalSize, bytesize=0, h, w, wb, srcPitch;
4210    int 	  xoffset = 0, yoffset = 0, left, right, top, bottom;
4211    UChar  *ybases, *ubases = NULL, *vbases = NULL, *myubases, *myvbases;
4212    UChar  *ybased, *uvbased, packed;
4213    CARD16 *myuvbased;
4214    SiS_Packet12_YUV MyPacket;
4215 #if 0
4216 #ifdef SISMERGED
4217    Bool first;
4218 #endif
4219 #endif
4220 
4221    if(index >= NUM_BLIT_PORTS) return BadMatch;
4222 
4223    if(!height || !width) return Success;
4224 
4225    switch(id) {
4226      case PIXEL_FMT_YV12:
4227      case PIXEL_FMT_I420:
4228      case PIXEL_FMT_NV12:
4229      case PIXEL_FMT_NV21:
4230        srcPitch = (width + 7) & ~7;  /* Should come this way anyway */
4231        bytesize = srcPitch * height;
4232        totalSize = (bytesize * 3) >> 1;
4233        break;
4234      case PIXEL_FMT_YUY2:
4235      case PIXEL_FMT_UYVY:
4236      case PIXEL_FMT_YVYU:
4237        srcPitch = ((width << 1) + 3) & ~3;
4238        /* Size = width * 2 * height */
4239        totalSize = srcPitch * height;
4240        bytesize = 0;
4241        break;
4242      default:
4243        return BadMatch;
4244    }
4245 
4246    /* allocate memory (we do doublebuffering) */
4247    if(!(pPriv->bufAddr[index][0] = SISAllocateFBMemory(pScrn, &pPriv->handle[index], totalSize << 1)))
4248       return BadAlloc;
4249 
4250    pPriv->bufAddr[index][1] = pPriv->bufAddr[index][0] + totalSize;
4251 
4252    if(drw_w > width) {
4253       xoffset = (drw_w - width) >> 1;
4254    }
4255    if(drw_h > (height & ~1)) {
4256       yoffset = (drw_h - height) >> 1;
4257    }
4258 
4259    if(xoffset || yoffset) {
4260 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,3,0)
4261       if(!RegionsEqual(&pPriv->blitClip[index], clipBoxes)) {
4262 #else
4263       if(!REGION_EQUAL(pScrn->pScreen, &pPriv->blitClip[index], clipBoxes)) {
4264 #endif
4265 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,1,99,1,0)
4266          (*pXAA->FillSolidRects)(pScrn, 0x00000000, GXcopy, ~0,
4267                               REGION_NUM_RECTS(clipBoxes),
4268                               REGION_RECTS(clipBoxes));
4269 #else
4270          xf86XVFillKeyHelper(pScrn->pScreen, 0x00000000, clipBoxes);
4271 #endif
4272          REGION_COPY(pScrn->pScreen, &pPriv->blitClip[index], clipBoxes);
4273       }
4274    }
4275 
4276    memset(&MyPacket, 0, sizeof(MyPacket));
4277 
4278    ybased = pSiS->FbBase + pPriv->bufAddr[index][pPriv->currentBuf[index]];
4279    uvbased = pSiS->FbBase + pPriv->bufAddr[index][pPriv->currentBuf[index]] + bytesize;
4280 
4281    ybases = buf;
4282    packed = 0;
4283 
4284    switch(id) {
4285      case PIXEL_FMT_YV12:
4286 	vbases = buf + bytesize;
4287 	ubases = buf + bytesize*5/4;
4288 	break;
4289      case PIXEL_FMT_I420:
4290 	ubases = buf + bytesize;
4291 	vbases = buf + bytesize*5/4;
4292 	break;
4293      case PIXEL_FMT_NV12:
4294         MyPacket.P12_Command = YUV_FORMAT_NV12;
4295         break;
4296      case PIXEL_FMT_NV21:
4297         MyPacket.P12_Command = YUV_FORMAT_NV21;
4298         break;
4299      case PIXEL_FMT_YUY2:
4300         MyPacket.P12_Command = YUV_FORMAT_YUY2;
4301 	packed = 1;
4302         break;
4303      case PIXEL_FMT_UYVY:
4304         MyPacket.P12_Command = YUV_FORMAT_UYVY;
4305 	packed = 1;
4306         break;
4307      case PIXEL_FMT_YVYU:
4308         MyPacket.P12_Command = YUV_FORMAT_YVYU;
4309 	packed = 1;
4310         break;
4311      default:
4312         return BadMatch;
4313    }
4314 
4315    switch(id) {
4316    case PIXEL_FMT_YV12:
4317    case PIXEL_FMT_I420:
4318       MyPacket.P12_Command = YUV_FORMAT_NV12;
4319       /* Copy y plane */
4320       SiSMemCopyToVideoRam(pSiS, ybased, ybases, bytesize);
4321       /* Copy u/v planes */
4322       wb = srcPitch >> 1;
4323       h = height >> 1;
4324       while(h--) {
4325          myuvbased = (CARD16*)uvbased;
4326          myubases = ubases;
4327          myvbases = vbases;
4328 	 w = wb;
4329 	 while(w--) {
4330 #if X_BYTE_ORDER == X_BIG_ENDIAN
4331  	    temp =  (*myubases++) << 8;
4332 	    temp |= (*myvbases++);
4333 #else
4334 	    temp =  (*myvbases++) << 8;
4335 	    temp |= (*myubases++);
4336 #endif
4337 	    *myuvbased++ = temp;
4338 	 }
4339 	 uvbased += srcPitch;
4340 	 ubases += wb;
4341 	 vbases += wb;
4342       }
4343       break;
4344    default:
4345       SiSMemCopyToVideoRam(pSiS, ybased, ybases, totalSize);
4346    }
4347 
4348    dstbase += FBOFFSET;
4349 
4350    MyPacket.P12_Header0 = SIS_PACKET12_HEADER0;
4351    MyPacket.P12_Header1 = SIS_PACKET12_HEADER1;
4352    MyPacket.P12_Null1 = SIS_NIL_CMD;
4353    MyPacket.P12_Null2 = SIS_NIL_CMD;
4354    MyPacket.P12_YPitch = MyPacket.P12_UVPitch = srcPitch;
4355    MyPacket.P12_DstAddr = dstbase;
4356    MyPacket.P12_DstPitch = pSiS->scrnOffset;
4357    MyPacket.P12_DstHeight = 0x0fff;
4358 
4359    MyPacket.P12_Command |= pPriv->AccelCmd		|
4360 			   SRCVIDEO			|
4361 			   PATFG			|
4362 			   pSiS->SiS310_AccelDepth	|
4363 			   YUV_CMD_YUV			|
4364 			   DSTVIDEO;
4365 
4366 
4367 #if 0 /* Not implemented by hardware! */
4368    if(pPriv->vsync) {
4369 #ifdef SISMERGED
4370       if(!pSiS->MergedFB) {
4371 #endif
4372 #ifdef SISDUALHEAD
4373          if(pSiS->DualHeadMode) {
4374 	    if(pSiS->SecondHead) {
4375 	       MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1;
4376 	    } else {
4377 	       MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2;
4378 	    }
4379 	 } else {
4380 #endif
4381             Bool IsSlaveMode = SiSBridgeIsInSlaveMode(pScrn);
4382             if((pSiS->VBFlags & DISPTYPE_DISP2) && !IsSlaveMode)
4383 	       MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2;
4384 	    else if((pSiS->VBFlags & DISPTYPE_DISP1) || IsSlaveMode)
4385 	       MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1;
4386 #ifdef SISDUALHEAD
4387          }
4388 #endif
4389 #ifdef SISMERGED
4390       }
4391 #endif
4392    }
4393 #endif
4394 
4395 #if 0
4396 #ifdef SISMERGED
4397    first = TRUE;
4398 #endif
4399 #endif
4400    while(nbox--) {
4401       left = pbox->x1;
4402       if(left >= drw_x + xoffset + width) goto mycont;
4403 
4404       right = pbox->x2;
4405       if(right <= drw_x + xoffset) goto mycont;
4406 
4407       top = pbox->y1;
4408       if(top >= drw_y + yoffset + height) goto mycont;
4409 
4410       bottom = pbox->y2;
4411       if(bottom <= drw_y + yoffset) goto mycont;
4412 
4413       if(left < (drw_x + xoffset)) left = drw_x + xoffset;
4414       if(right > (drw_x + xoffset + width)) right = drw_x + xoffset + width;
4415       if(top < (drw_y + yoffset)) top = drw_y + yoffset;
4416       if(bottom > (drw_y + yoffset + height)) bottom = drw_y + yoffset + height;
4417 
4418       MyPacket.P12_DstX = left;
4419       MyPacket.P12_DstY = top;
4420       MyPacket.P12_RectWidth = right - left;
4421       MyPacket.P12_RectHeight = bottom - top;
4422 
4423 #if 0
4424 #ifdef SISMERGED
4425       if((first) && (pSiS->MergedFB)) {
4426          int scrwidth = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2->HDisplay;
4427 	 int scrheight = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2->VDisplay;
4428 	 if( (right < pSiS->CRT2pScrn->frameX0) ||
4429 	     (left >= pSiS->CRT2pScrn->frameX0 + scrwidth) ||
4430 	     (bottom < pSiS->CRT2pScrn->frameY0) ||
4431 	     (top >= pSiS->CRT2pScrn->frameY0 + scrheight) ) {
4432 	    MyPacket.P12_Command |= pPriv->VBlankTriggerCRT1;
4433 	 } else {
4434 	    MyPacket.P12_Command |= pPriv->VBlankTriggerCRT2;
4435 	 }
4436       }
4437 #endif
4438 #endif
4439 
4440       offsety = offsetuv = 0;
4441       if(packed) {
4442          if(pbox->y1 > drw_y + yoffset) {
4443             offsetuv  = (pbox->y1 - drw_y - yoffset) * srcPitch;
4444          }
4445          if(pbox->x1 > drw_x + xoffset) {
4446             offsetuv += ((pbox->x1 - drw_x - xoffset) << 1);
4447 	    if(offsetuv & 3) {
4448 #if 0	       /* Paint over covering object - no */
4449 	       if(MyPacket.P12_DstX > 0) {
4450 	          offsetuv &= ~3;
4451 	          MyPacket.P12_DstX--;
4452 	          MyPacket.P12_RectWidth++;
4453 	       } else {
4454 #endif
4455 	          offsetuv = (offsetuv + 3) & ~3;
4456 	          MyPacket.P12_DstX++;
4457 	          MyPacket.P12_RectWidth--;
4458 #if 0
4459 	       }
4460 #endif
4461 	    }
4462          }
4463       } else {
4464          if(pbox->y1 > drw_y + yoffset) {
4465             offsety  = (pbox->y1 - drw_y - yoffset) * srcPitch;
4466 	    offsetuv = ((pbox->y1 - drw_y - yoffset) >> 1) * srcPitch;
4467          }
4468          if(pbox->x1 > drw_x + xoffset) {
4469             offsety += (pbox->x1 - drw_x - xoffset);
4470 	    offsetuv += (pbox->x1 - drw_x - xoffset);
4471 	    if(offsetuv & 1) {
4472 	       offsety++;
4473 	       offsetuv++;
4474 	       MyPacket.P12_DstX++;
4475 	       MyPacket.P12_RectWidth--;
4476 	    }
4477          }
4478       }
4479 
4480       if(!MyPacket.P12_RectWidth) continue;
4481 
4482       MyPacket.P12_YSrcAddr  = pPriv->bufAddr[index][pPriv->currentBuf[index]] + offsety + FBOFFSET;
4483       MyPacket.P12_UVSrcAddr = pPriv->bufAddr[index][pPriv->currentBuf[index]] + bytesize + offsetuv + FBOFFSET;
4484       SISWriteBlitPacket(pSiS, (CARD32*)&MyPacket);
4485 #if 0
4486       MyPacket.P12_Command &= ~(pPriv->VBlankTriggerCRT1 | pPriv->VBlankTriggerCRT2);
4487 #endif
4488 #if 0
4489 #ifdef SISMERGED
4490       first = FALSE;
4491 #endif
4492 #endif
4493 mycont:
4494       pbox++;
4495    }
4496 
4497 #if 0
4498    {
4499    int debug = 0;
4500    while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { debug++; };
4501    while( (SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { debug++; };
4502    xf86DrvMsg(0, X_INFO, "vsync %d, debug %d\n", pPriv->vsync, debug);
4503    }
4504 #endif
4505 
4506    pPriv->currentBuf[index] ^= 1;
4507 
4508    UpdateCurrentTime();
4509    pPriv->freeTime[index] = currentTime.milliseconds + FREE_DELAY;
4510    pPriv->videoStatus[index] = FREE_TIMER;
4511 
4512    pSiS->VideoTimerCallback = SISVideoTimerCallback;
4513 
4514    return Success;
4515 }
4516 
4517 static int
4518 SISQueryImageAttributesBlit(
4519   ScrnInfoPtr pScrn,
4520   int id,
4521   UShort *w, UShort *h,
4522   int *pitches, int *offsets
4523 ){
4524     int    pitchY, pitchUV;
4525     int    size, sizeY, sizeUV;
4526 
4527     if(*w > DummyEncodingBlit.width) *w = DummyEncodingBlit.width;
4528     if(*h > DummyEncodingBlit.height) *h = DummyEncodingBlit.height;
4529 
4530     switch(id) {
4531     case PIXEL_FMT_YV12:
4532     case PIXEL_FMT_I420:
4533 	*w = (*w + 7) & ~7;
4534 	*h = (*h + 1) & ~1;
4535 	pitchY = *w;
4536 	pitchUV = *w >> 1;
4537 	if(pitches) {
4538 	   pitches[0] = pitchY;
4539 	   pitches[1] = pitches[2] = pitchUV;
4540 	}
4541 	sizeY = pitchY * (*h);
4542 	sizeUV = pitchUV * ((*h) >> 1);
4543 	if(offsets) {
4544 	   offsets[0] = 0;
4545 	   offsets[1] = sizeY;
4546 	   offsets[2] = sizeY + sizeUV;
4547 	}
4548 	size = sizeY + (sizeUV << 1);
4549 	break;
4550     case PIXEL_FMT_NV12:
4551     case PIXEL_FMT_NV21:
4552 	*w = (*w + 7) & ~7;
4553 	pitchY = *w;
4554 	pitchUV = *w;
4555 	if(pitches) {
4556 	   pitches[0] = pitchY;
4557 	   pitches[1] = pitchUV;
4558 	}
4559 	sizeY = pitchY * (*h);
4560 	sizeUV = pitchUV * ((*h) >> 1);
4561 	if(offsets) {
4562 	   offsets[0] = 0;
4563 	   offsets[1] = sizeY;
4564 	}
4565 	size = sizeY + (sizeUV << 1);
4566 	break;
4567     case PIXEL_FMT_YUY2:
4568     case PIXEL_FMT_UYVY:
4569     case PIXEL_FMT_YVYU:
4570     default:
4571 	*w = (*w + 1) & ~1;
4572 	pitchY = *w << 1;
4573 	if(pitches) pitches[0] = pitchY;
4574 	if(offsets) offsets[0] = 0;
4575 	size = pitchY * (*h);
4576 	break;
4577     }
4578 
4579     return size;
4580 }
4581 
4582 static void
4583 SISQueryBestSizeBlit(
4584   ScrnInfoPtr pScrn,
4585   Bool motion,
4586   short vid_w, short vid_h,
4587   short drw_w, short drw_h,
4588   unsigned int *p_w, unsigned int *p_h,
4589   ULong index
4590 ){
4591   /* We cannot scale */
4592   *p_w = vid_w;
4593   *p_h = vid_h;
4594 }
4595 #endif /* INCL_YUV */
4596 
4597 /*****************************************/
4598 /*            TIMER CALLBACK             */
4599 /*****************************************/
4600 
4601 static void
4602 SISVideoTimerCallback(ScrnInfoPtr pScrn, Time now)
4603 {
4604     SISPtr          pSiS = SISPTR(pScrn);
4605     SISPortPrivPtr  pPriv = NULL;
4606 #ifdef INCL_YUV_BLIT_ADAPTOR
4607     SISBPortPrivPtr pPrivBlit = NULL;
4608 #endif
4609     UChar           sridx, cridx;
4610     Bool	    setcallback = FALSE;
4611 
4612     if(!pScrn->vtSema) return;
4613 
4614     if(pSiS->adaptor) {
4615        pPriv = GET_PORT_PRIVATE(pScrn);
4616        if(!pPriv->videoStatus) pPriv = NULL;
4617     }
4618 
4619     if(pPriv) {
4620        if(pPriv->videoStatus & TIMER_MASK) {
4621           if(pPriv->videoStatus & OFF_TIMER) {
4622 	     setcallback = TRUE;
4623 	     if(pPriv->offTime < now) {
4624                 /* Turn off the overlay */
4625 	        sridx = inSISREG(SISSR); cridx = inSISREG(SISCR);
4626                 close_overlay(pSiS, pPriv);
4627 	        outSISREG(SISSR, sridx); outSISREG(SISCR, cridx);
4628 	        pPriv->mustwait = 1;
4629                 pPriv->videoStatus = FREE_TIMER;
4630                 pPriv->freeTime = now + FREE_DELAY;
4631 	     }
4632           } else if(pPriv->videoStatus & FREE_TIMER) {
4633 	     if(pPriv->freeTime < now) {
4634                 SISFreeFBMemory(pScrn, &pPriv->handle);
4635 	        pPriv->mustwait = 1;
4636                 pPriv->videoStatus = 0;
4637              } else {
4638 	        setcallback = TRUE;
4639 	     }
4640           }
4641        }
4642     }
4643 
4644 #ifdef INCL_YUV_BLIT_ADAPTOR
4645     if(pSiS->blitadaptor) {
4646        int i;
4647        pPrivBlit = (SISBPortPrivPtr)(pSiS->blitPriv);
4648        for(i = 0; i < NUM_BLIT_PORTS; i++) {
4649           if(pPrivBlit->videoStatus[i] & FREE_TIMER) {
4650 	     if(pPrivBlit->freeTime[i] < now) {
4651                 SISFreeFBMemory(pScrn, &pPrivBlit->handle[i]);
4652                 pPrivBlit->videoStatus[i] = 0;
4653 	     } else {
4654 	        setcallback = TRUE;
4655 	     }
4656           }
4657        }
4658     }
4659 #endif
4660 
4661     pSiS->VideoTimerCallback = (setcallback) ? SISVideoTimerCallback : NULL;
4662 }
4663 
4664