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