readding XFree86's cvs IDs
[xf86-video-sis/mirage.git] / src / sis_video.c
blobec30f3daccf681d783e43e22f9c324f8a8af021b
1 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_video.c,v 1.48 2004/01/23 22:29:06 twini Exp $ */
2 /*
3 * Xv driver for SiS 300, 315 and 330 series.
5 * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1) Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2) Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3) All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: "This product includes
17 * software developed by Thomas Winischhofer, Vienna, Austria."
18 * 4) The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * Author: Thomas Winischhofer <thomas@winischhofer.net>
34 * Formerly based on a mostly non-working code fragment for the 630 by
35 * Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan which is
36 * Copyright (C) 2000 Silicon Integrated Systems Corp, Inc.
38 * Basic structure based on the mga Xv driver by Mark Vojkovich
39 * and i810 Xv driver by Jonathan Bian <jonathan.bian@intel.com>.
41 * All comments in this file are by Thomas Winischhofer.
43 * This supports the following chipsets:
44 * SiS300: No registers >0x65, two overlays (one used for CRT1, one for CRT2)
45 * SiS630/730: No registers >0x6b, two overlays (one used for CRT1, one for CRT2)
46 * SiS550: Full register range, two overlays (one used for CRT1, one for CRT2)
47 * SiS315: Full register range, one overlay (used for both CRT1 and CRT2 alt.)
48 * SiS650/740: Full register range, one overlay (used for both CRT1 and CRT2 alt.)
49 * SiSM650/651: Full register range, two overlays (one used for CRT1, one for CRT2)
50 * SiS330: Full register range, one overlay (used for both CRT1 and CRT2 alt.)
51 * SiS661/741/760: Full register range, two overlays (one used for CRT1, one for CRT2)
53 * Help for reading the code:
54 * 315/550/650/740/M650/651/330/661/741/760 = SIS_315_VGA
55 * 300/630/730 = SIS_300_VGA
56 * For chipsets with 2 overlays, hasTwoOverlays will be true
58 * Notes on display modes:
60 * -) dual head mode:
61 * DISPMODE is either SINGLE1 or SINGLE2, hence you need to check dualHeadMode flag
62 * DISPMODE is _never_ MIRROR.
63 * a) Chipsets with 2 overlays:
64 * 315/330 series: Only half sized overlays available (width 960), 660: 1536
65 * Overlay 1 is used on CRT1, overlay 2 for CRT2.
66 * b) Chipsets with 1 overlay:
67 * Full size overlays available.
68 * Overlay is used for either CRT1 or CRT2
69 * -) merged fb mode:
70 * a) Chipsets with 2 overlays:
71 * 315/330 series: Only half sized overlays available (width 960), 660: 1536
72 * DISPMODE is always MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2.
73 * b) Chipsets with 1 overlay:
74 * Full size overlays available.
75 * DISPMODE is either SINGLE1 or SINGLE2. Overlay is used accordingly on either
76 * CRT1 or CRT2 (automatically, where it is located)
77 * -) mirror mode (without dualhead or mergedfb)
78 * a) Chipsets with 2 overlays:
79 * 315/330 series: Only half sized overlays available (width 960), 660: 1536
80 * DISPMODE is MIRROR. Overlay 1 is used for CRT1, overlay 2 for CRT2.
81 * b) Chipsets with 1 overlay:
82 * Full size overlays available.
83 * DISPMODE is either SINGLE1 or SINGLE2. Overlay is used depending on
84 * XvOnCRT2 flag.
87 #include "xf86.h"
88 #include "xf86_OSproc.h"
89 #include "xf86Resources.h"
90 #include "xf86_ansic.h"
91 #include "compiler.h"
92 #include "xf86PciInfo.h"
93 #include "xf86Pci.h"
94 #include "xf86fbman.h"
95 #include "regionstr.h"
97 #include "sis.h"
98 #include "xf86xv.h"
99 #include "Xv.h"
100 #include "xaa.h"
101 #include "xaalocal.h"
102 #include "dixstruct.h"
103 #include "fourcc.h"
105 #include "sis_regs.h"
107 static XF86VideoAdaptorPtr SISSetupImageVideo(ScreenPtr);
108 static void SISStopVideo(ScrnInfoPtr, pointer, Bool);
109 static int SISSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
110 static int SISGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
111 static void SISQueryBestSize(ScrnInfoPtr, Bool, short, short, short,
112 short, unsigned int *,unsigned int *, pointer);
113 static int SISPutImage( ScrnInfoPtr,
114 short, short, short, short, short, short, short, short,
115 int, unsigned char*, short, short, Bool, RegionPtr, pointer);
116 static int SISQueryImageAttributes(ScrnInfoPtr,
117 int, unsigned short *, unsigned short *, int *, int *);
118 static void SISVideoTimerCallback(ScrnInfoPtr pScrn, Time now);
119 static void SISInitOffscreenImages(ScreenPtr pScrn);
120 extern BOOLEAN SiSBridgeIsInSlaveMode(ScrnInfoPtr pScrn);
122 #define OFF_DELAY 200 /* milliseconds */
123 #define FREE_DELAY 60000
125 #define OFF_TIMER 0x01
126 #define FREE_TIMER 0x02
127 #define CLIENT_VIDEO_ON 0x04
129 #define TIMER_MASK (OFF_TIMER | FREE_TIMER)
131 #define WATCHDOG_DELAY 500000 /* Watchdog counter for Vertical Restrace waiting */
133 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
135 #define IMAGE_MIN_WIDTH 32 /* Minimum and maximum source image sizes */
136 #define IMAGE_MIN_HEIGHT 24
137 #define IMAGE_MAX_WIDTH_300 720
138 #define IMAGE_MAX_HEIGHT_300 576
139 #define IMAGE_MAX_WIDTH_315 1920
140 #define IMAGE_MAX_HEIGHT_315 1080
142 #define OVERLAY_MIN_WIDTH 32 /* Minimum overlay sizes */
143 #define OVERLAY_MIN_HEIGHT 24
145 #define DISPMODE_SINGLE1 0x1 /* CRT1 only */
146 #define DISPMODE_SINGLE2 0x2 /* CRT2 only */
147 #define DISPMODE_MIRROR 0x4 /* CRT1 + CRT2 MIRROR (see note below) */
149 #define LINEBUFLIMIT1 384 /* Limits at which line buffers must be merged */
150 #define LINEBUFLIMIT2 720
151 #define LINEBUFLIMIT3 576
153 #ifdef SISDUALHEAD
154 #define HEADOFFSET (pSiS->dhmOffset)
155 #endif
157 #define GET_PORT_PRIVATE(pScrn) \
158 (SISPortPrivPtr)((SISPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
160 /* Note on "MIRROR":
161 * When using VESA on machines with an enabled video bridge, this means
162 * a real mirror. CRT1 and CRT2 have the exact same resolution and
163 * refresh rate. The same applies to modes which require the bridge to
164 * operate in slave mode.
165 * When not using VESA and the bridge is not in slave mode otherwise,
166 * CRT1 and CRT2 have the same resolution but possibly a different
167 * refresh rate.
170 /* client libraries expect an encoding */
171 static XF86VideoEncodingRec DummyEncoding =
174 "XV_IMAGE",
175 0, 0, /* Will be filled in */
176 {1, 1}
179 #define NUM_FORMATS 3
181 static XF86VideoFormatRec SISFormats[NUM_FORMATS] =
183 { 8, PseudoColor},
184 {16, TrueColor},
185 {24, TrueColor}
188 static char sisxvcolorkey[] = "XV_COLORKEY";
189 static char sisxvbrightness[] = "XV_BRIGHTNESS";
190 static char sisxvcontrast[] = "XV_CONTRAST";
191 static char sisxvsaturation[] = "XV_SATURATION";
192 static char sisxvhue[] = "XV_HUE";
193 static char sisxvautopaintcolorkey[] = "XV_AUTOPAINT_COLORKEY";
194 static char sisxvsetdefaults[] = "XV_SET_DEFAULTS";
195 static char sisxvswitchcrt[] = "XV_SWITCHCRT";
196 static char sisxvtvxposition[] = "XV_TVXPOSITION";
197 static char sisxvtvyposition[] = "XV_TVYPOSITION";
198 static char sisxvgammared[] = "XV_GAMMA_RED";
199 static char sisxvgammagreen[] = "XV_GAMMA_GREEN";
200 static char sisxvgammablue[] = "XV_GAMMA_BLUE";
201 static char sisxvdisablegfx[] = "XV_DISABLE_GRAPHICS";
202 static char sisxvdisablegfxlr[] = "XV_DISABLE_GRAPHICS_LR";
203 static char sisxvdisablecolorkey[] = "XV_DISABLE_COLORKEY";
204 static char sisxvusechromakey[] = "XV_USE_CHROMAKEY";
205 static char sisxvinsidechromakey[] = "XV_INSIDE_CHROMAKEY";
206 static char sisxvyuvchromakey[] = "XV_YUV_CHROMAKEY";
207 static char sisxvchromamin[] = "XV_CHROMAMIN";
208 static char sisxvchromamax[] = "XV_CHROMAMAX";
209 static char sisxvqueryvbflags[] = "XV_QUERYVBFLAGS";
210 static char sisxvsdgetdriverversion[] = "XV_SD_GETDRIVERVERSION";
211 static char sisxvsdgethardwareinfo[] = "XV_SD_GETHARDWAREINFO";
212 static char sisxvsdgetbusid[] = "XV_SD_GETBUSID";
213 static char sisxvsdqueryvbflagsversion[] = "XV_SD_QUERYVBFLAGSVERSION";
214 static char sisxvsdgetsdflags[] = "XV_SD_GETSDFLAGS";
215 static char sisxvsdunlocksisdirect[] = "XV_SD_UNLOCKSISDIRECT";
216 static char sisxvsdsetvbflags[] = "XV_SD_SETVBFLAGS";
217 static char sisxvsdquerydetecteddevices[] = "XV_SD_QUERYDETECTEDDEVICES";
218 static char sisxvsdcrt1status[] = "XV_SD_CRT1STATUS";
219 static char sisxvsdcheckmodeindexforcrt2[] = "XV_SD_CHECKMODEINDEXFORCRT2";
220 static char sisxvsdresultcheckmodeindexforcrt2[] = "XV_SD_RESULTCHECKMODEINDEXFORCRT2";
221 static char sisxvsdsisantiflicker[] = "XV_SD_SISANTIFLICKER";
222 static char sisxvsdsissaturation[] = "XV_SD_SISSATURATION";
223 static char sisxvsdsisedgeenhance[] = "XV_SD_SISEDGEENHANCE";
224 static char sisxvsdsiscolcalibf[] = "XV_SD_SISCOLCALIBF";
225 static char sisxvsdsiscolcalibc[] = "XV_SD_SISCOLCALIBC";
226 static char sisxvsdsiscfilter[] = "XV_SD_SISCFILTER";
227 static char sisxvsdsisyfilter[] = "XV_SD_SISYFILTER";
228 static char sisxvsdchcontrast[] = "XV_SD_CHCONTRAST";
229 static char sisxvsdchtextenhance[] = "XV_SD_CHTEXTENHANCE";
230 static char sisxvsdchchromaflickerfilter[] = "XV_SD_CHCHROMAFLICKERFILTER";
231 static char sisxvsdchlumaflickerfilter[] = "XV_SD_CHLUMAFLICKERFILTER";
232 static char sisxvsdchcvbscolor[] = "XV_SD_CHCVBSCOLOR";
233 static char sisxvsdchoverscan[] = "XV_SD_CHOVERSCAN";
234 static char sisxvsdenablegamma[] = "XV_SD_ENABLEGAMMA";
235 static char sisxvsdtvxscale[] = "XV_SD_TVXSCALE";
236 static char sisxvsdtvyscale[] = "XV_SD_TVYSCALE";
237 static char sisxvsdgetscreensize[] = "XV_SD_GETSCREENSIZE";
238 static char sisxvsdstorebrir[] = "XV_SD_STOREDGAMMABRIR";
239 static char sisxvsdstorebrig[] = "XV_SD_STOREDGAMMABRIG";
240 static char sisxvsdstorebrib[] = "XV_SD_STOREDGAMMABRIB";
241 static char sisxvsdstorepbrir[] = "XV_SD_STOREDGAMMAPBRIR";
242 static char sisxvsdstorepbrig[] = "XV_SD_STOREDGAMMAPBRIG";
243 static char sisxvsdstorepbrib[] = "XV_SD_STOREDGAMMAPBRIB";
244 static char sisxvsdstorebrir2[] = "XV_SD_STOREDGAMMABRIR2";
245 static char sisxvsdstorebrig2[] = "XV_SD_STOREDGAMMABRIG2";
246 static char sisxvsdstorebrib2[] = "XV_SD_STOREDGAMMABRIB2";
247 static char sisxvsdstorepbrir2[] = "XV_SD_STOREDGAMMAPBRIR2";
248 static char sisxvsdstorepbrig2[] = "XV_SD_STOREDGAMMAPBRIG2";
249 static char sisxvsdstorepbrib2[] = "XV_SD_STOREDGAMMAPBRIB2";
250 static char sisxvsdhidehwcursor[] = "XV_SD_HIDEHWCURSOR";
251 #ifdef TWDEBUG
252 static char sisxvsetreg[] = "XV_SD_SETREG";
253 #endif
255 #ifndef SIS_CP
256 #define NUM_ATTRIBUTES_300 56
257 #ifdef TWDEBUG
258 #define NUM_ATTRIBUTES_315 63
259 #else
260 #define NUM_ATTRIBUTES_315 62
261 #endif
262 #endif
264 static XF86AttributeRec SISAttributes_300[NUM_ATTRIBUTES_300] =
266 {XvSettable | XvGettable, 0, (1 << 24) - 1, sisxvcolorkey},
267 {XvSettable | XvGettable, -128, 127, sisxvbrightness},
268 {XvSettable | XvGettable, 0, 7, sisxvcontrast},
269 {XvSettable | XvGettable, 0, 1, sisxvautopaintcolorkey},
270 {XvSettable , 0, 0, sisxvsetdefaults},
271 {XvSettable | XvGettable, -32, 32, sisxvtvxposition},
272 {XvSettable | XvGettable, -32, 32, sisxvtvyposition},
273 {XvSettable | XvGettable, 0, 1, sisxvdisablegfx},
274 {XvSettable | XvGettable, 0, 1, sisxvdisablegfxlr},
275 {XvSettable | XvGettable, 0, 1, sisxvdisablecolorkey},
276 {XvSettable | XvGettable, 0, 1, sisxvusechromakey},
277 {XvSettable | XvGettable, 0, 1, sisxvinsidechromakey},
278 {XvSettable | XvGettable, 0, 1, sisxvyuvchromakey},
279 {XvSettable | XvGettable, 0, (1 << 24) - 1, sisxvchromamin},
280 {XvSettable | XvGettable, 0, (1 << 24) - 1, sisxvchromamax},
281 { XvGettable, 0, 0xffffffff, sisxvqueryvbflags},
282 { XvGettable, 0, 0xffffffff, sisxvsdgetdriverversion},
283 { XvGettable, 0, 0xffffffff, sisxvsdgethardwareinfo},
284 { XvGettable, 0, 0xffffffff, sisxvsdgetbusid},
285 { XvGettable, 0, 0xffffffff, sisxvsdqueryvbflagsversion},
286 { XvGettable, 0, 0xffffffff, sisxvsdgetsdflags},
287 {XvSettable | XvGettable, 0, 0xffffffff, sisxvsdunlocksisdirect},
288 {XvSettable , 0, 0xffffffff, sisxvsdsetvbflags},
289 { XvGettable, 0, 0xffffffff, sisxvsdquerydetecteddevices},
290 {XvSettable | XvGettable, 0, 1, sisxvsdcrt1status},
291 {XvSettable , 0, 0xffffffff, sisxvsdcheckmodeindexforcrt2},
292 { XvGettable, 0, 0xffffffff, sisxvsdresultcheckmodeindexforcrt2},
293 {XvSettable | XvGettable, 0, 4, sisxvsdsisantiflicker},
294 {XvSettable | XvGettable, 0, 15, sisxvsdsissaturation},
295 {XvSettable | XvGettable, 0, 15, sisxvsdsisedgeenhance},
296 {XvSettable | XvGettable, -128, 127, sisxvsdsiscolcalibf},
297 {XvSettable | XvGettable, -120, 120, sisxvsdsiscolcalibc},
298 {XvSettable | XvGettable, 0, 1, sisxvsdsiscfilter},
299 {XvSettable | XvGettable, 0, 8, sisxvsdsisyfilter},
300 {XvSettable | XvGettable, 0, 15, sisxvsdchcontrast},
301 {XvSettable | XvGettable, 0, 15, sisxvsdchtextenhance},
302 {XvSettable | XvGettable, 0, 15, sisxvsdchchromaflickerfilter},
303 {XvSettable | XvGettable, 0, 15, sisxvsdchlumaflickerfilter},
304 {XvSettable | XvGettable, 0, 1, sisxvsdchcvbscolor},
305 {XvSettable | XvGettable, 0, 3, sisxvsdchoverscan},
306 {XvSettable | XvGettable, 0, 3, sisxvsdenablegamma},
307 {XvSettable | XvGettable, -16, 16, sisxvsdtvxscale},
308 {XvSettable | XvGettable, -4, 3, sisxvsdtvyscale},
309 { XvGettable, 0, 0xffffffff, sisxvsdgetscreensize},
310 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrir},
311 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrig},
312 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrib},
313 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrir},
314 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrig},
315 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrib},
316 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrir2},
317 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrig2},
318 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrib2},
319 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrir2},
320 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrig2},
321 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrib2},
322 #ifdef SIS_CP
323 SIS_CP_VIDEO_ATTRIBUTES
324 #endif
327 static XF86AttributeRec SISAttributes_315[NUM_ATTRIBUTES_315] =
329 {XvSettable | XvGettable, 0, (1 << 24) - 1, sisxvcolorkey},
330 {XvSettable | XvGettable, -128, 127, sisxvbrightness},
331 {XvSettable | XvGettable, 0, 7, sisxvcontrast},
332 {XvSettable | XvGettable, -7, 7, sisxvsaturation},
333 {XvSettable | XvGettable, -8, 7, sisxvhue},
334 {XvSettable | XvGettable, 0, 1, sisxvautopaintcolorkey},
335 {XvSettable , 0, 0, sisxvsetdefaults},
336 {XvSettable | XvGettable, -32, 32, sisxvtvxposition},
337 {XvSettable | XvGettable, -32, 32, sisxvtvyposition},
338 {XvSettable | XvGettable, 100, 10000, sisxvgammared},
339 {XvSettable | XvGettable, 100, 10000, sisxvgammagreen},
340 {XvSettable | XvGettable, 100, 10000, sisxvgammablue},
341 {XvSettable | XvGettable, 0, 1, sisxvdisablegfx},
342 {XvSettable | XvGettable, 0, 1, sisxvdisablegfxlr},
343 {XvSettable | XvGettable, 0, 1, sisxvdisablecolorkey},
344 {XvSettable | XvGettable, 0, 1, sisxvusechromakey},
345 {XvSettable | XvGettable, 0, 1, sisxvinsidechromakey},
346 {XvSettable | XvGettable, 0, (1 << 24) - 1, sisxvchromamin},
347 {XvSettable | XvGettable, 0, (1 << 24) - 1, sisxvchromamax},
348 { XvGettable, 0, 0xffffffff, sisxvqueryvbflags},
349 { XvGettable, 0, 0xffffffff, sisxvsdgetdriverversion},
350 { XvGettable, 0, 0xffffffff, sisxvsdgethardwareinfo},
351 { XvGettable, 0, 0xffffffff, sisxvsdgetbusid},
352 { XvGettable, 0, 0xffffffff, sisxvsdqueryvbflagsversion},
353 { XvGettable, 0, 0xffffffff, sisxvsdgetsdflags},
354 {XvSettable | XvGettable, 0, 0xffffffff, sisxvsdunlocksisdirect},
355 {XvSettable , 0, 0xffffffff, sisxvsdsetvbflags},
356 { XvGettable, 0, 0xffffffff, sisxvsdquerydetecteddevices},
357 {XvSettable | XvGettable, 0, 1, sisxvsdcrt1status},
358 {XvSettable , 0, 0xffffffff, sisxvsdcheckmodeindexforcrt2},
359 { XvGettable, 0, 0xffffffff, sisxvsdresultcheckmodeindexforcrt2},
360 {XvSettable | XvGettable, 0, 4, sisxvsdsisantiflicker},
361 {XvSettable | XvGettable, 0, 15, sisxvsdsissaturation},
362 {XvSettable | XvGettable, 0, 15, sisxvsdsisedgeenhance},
363 {XvSettable | XvGettable, -128, 127, sisxvsdsiscolcalibf},
364 {XvSettable | XvGettable, -120, 120, sisxvsdsiscolcalibc},
365 {XvSettable | XvGettable, 0, 1, sisxvsdsiscfilter},
366 {XvSettable | XvGettable, 0, 8, sisxvsdsisyfilter},
367 {XvSettable | XvGettable, 0, 15, sisxvsdchcontrast},
368 {XvSettable | XvGettable, 0, 15, sisxvsdchtextenhance},
369 {XvSettable | XvGettable, 0, 15, sisxvsdchchromaflickerfilter},
370 {XvSettable | XvGettable, 0, 15, sisxvsdchlumaflickerfilter},
371 {XvSettable | XvGettable, 0, 1, sisxvsdchcvbscolor},
372 {XvSettable | XvGettable, 0, 3, sisxvsdchoverscan},
373 {XvSettable | XvGettable, 0, 7, sisxvsdenablegamma},
374 {XvSettable | XvGettable, -16, 16, sisxvsdtvxscale},
375 {XvSettable | XvGettable, -4, 3, sisxvsdtvyscale},
376 { XvGettable, 0, 0xffffffff, sisxvsdgetscreensize},
377 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrir},
378 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrig},
379 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrib},
380 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrir},
381 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrig},
382 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrib},
383 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrir2},
384 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrig2},
385 {XvSettable | XvGettable, 100, 10000, sisxvsdstorebrib2},
386 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrir2},
387 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrig2},
388 {XvSettable | XvGettable, 100, 10000, sisxvsdstorepbrib2},
389 {XvSettable | XvGettable, 0, 1, sisxvsdhidehwcursor},
390 #ifdef TWDEBUG
391 {XvSettable , 0, 0xffffffff, sisxvsetreg},
392 #endif
393 #ifdef SIS_CP
394 SIS_CP_VIDEO_ATTRIBUTES
395 #endif
396 {XvSettable | XvGettable, 0, 1, sisxvswitchcrt},
399 #define NUM_IMAGES_300 6
400 #define NUM_IMAGES_315 7 /* NV12 only - but does not work */
401 #define NUM_IMAGES_330 9 /* NV12 and NV21 */
402 #define PIXEL_FMT_YV12 FOURCC_YV12 /* 0x32315659 */
403 #define PIXEL_FMT_UYVY FOURCC_UYVY /* 0x59565955 */
404 #define PIXEL_FMT_YUY2 FOURCC_YUY2 /* 0x32595559 */
405 #define PIXEL_FMT_I420 FOURCC_I420 /* 0x30323449 */
406 #define PIXEL_FMT_RGB5 0x35315652
407 #define PIXEL_FMT_RGB6 0x36315652
408 #define PIXEL_FMT_YVYU 0x55595659 /* 315/330 only */
409 #define PIXEL_FMT_NV12 0x3231564e /* 330 only */
410 #define PIXEL_FMT_NV21 0x3132564e /* 330 only */
412 /* TODO: */
413 #define PIXEL_FMT_RAW8 0x38574152
415 static XF86ImageRec SISImages[NUM_IMAGES_330] =
417 XVIMAGE_YUY2, /* If order is changed, SISOffscreenImages must be adapted */
418 XVIMAGE_YV12,
419 XVIMAGE_UYVY,
420 XVIMAGE_I420
422 { /* RGB 555 */
423 PIXEL_FMT_RGB5,
424 XvRGB,
425 LSBFirst,
426 {'R','V','1','5',
427 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
429 XvPacked,
431 /* 15, 0x001F, 0x03E0, 0x7C00, - incorrect! */
432 15, 0x7C00, 0x03E0, 0x001F,
433 0, 0, 0,
434 0, 0, 0,
435 0, 0, 0,
436 {'R', 'V', 'B',0,
437 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
438 XvTopToBottom
440 { /* RGB 565 */
441 PIXEL_FMT_RGB6,
442 XvRGB,
443 LSBFirst,
444 {'R','V','1','6',
445 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
447 XvPacked,
449 /* 16, 0x001F, 0x07E0, 0xF800, - incorrect! */
450 16, 0xF800, 0x07E0, 0x001F,
451 0, 0, 0,
452 0, 0, 0,
453 0, 0, 0,
454 {'R', 'V', 'B',0,
455 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
456 XvTopToBottom
458 { /* YVYU */
459 PIXEL_FMT_YVYU, \
460 XvYUV, \
461 LSBFirst, \
462 {'Y','V','Y','U',
463 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71},
465 XvPacked,
467 0, 0, 0, 0,
468 8, 8, 8,
469 1, 2, 2,
470 1, 1, 1,
471 {'Y','V','Y','U',
472 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
473 XvTopToBottom
475 { /* NV12 */
476 PIXEL_FMT_NV12,
477 XvYUV,
478 LSBFirst,
479 {'N','V','1','2',
480 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71},
482 XvPlanar,
484 0, 0, 0, 0,
485 8, 8, 8,
486 1, 2, 2,
487 1, 2, 2,
488 {'Y','U','V',0,
489 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
490 XvTopToBottom
492 { /* NV21 */
493 PIXEL_FMT_NV21,
494 XvYUV,
495 LSBFirst,
496 {'N','V','2','1',
497 0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71},
499 XvPlanar,
501 0, 0, 0, 0,
502 8, 8, 8,
503 1, 2, 2,
504 1, 2, 2,
505 {'Y','V','U',0,
506 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
507 XvTopToBottom
511 typedef struct {
512 FBLinearPtr linear;
513 CARD32 bufAddr[2];
515 unsigned char currentBuf;
517 short drw_x, drw_y, drw_w, drw_h;
518 short src_x, src_y, src_w, src_h;
519 int id;
520 short srcPitch, height;
522 char brightness;
523 unsigned char contrast;
524 char hue;
525 short saturation;
527 RegionRec clip;
528 CARD32 colorKey;
529 Bool autopaintColorKey;
531 Bool disablegfx;
532 Bool disablegfxlr;
534 Bool usechromakey;
535 Bool insidechromakey, yuvchromakey;
536 CARD32 chromamin, chromamax;
538 CARD32 videoStatus;
539 BOOLEAN overlayStatus;
540 Time offTime;
541 Time freeTime;
543 CARD32 displayMode;
544 Bool bridgeIsSlave;
546 Bool hasTwoOverlays; /* Chipset has two overlays */
547 Bool dualHeadMode; /* We're running in DHM */
549 Bool NoOverlay;
550 Bool PrevOverlay;
552 Bool AllowSwitchCRT;
553 int crtnum; /* 0=CRT1, 1=CRT2 */
555 Bool needToScale; /* Need to scale video */
557 int shiftValue; /* 315/330 series need word addr/pitch, 300 series double word */
559 short linebufMergeLimit;
560 CARD8 linebufmask;
562 short oldx1, oldx2, oldy1, oldy2;
563 #ifdef SISMERGED
564 short oldx1_2, oldx2_2, oldy1_2, oldy2_2;
565 #endif
566 int mustwait;
568 Bool grabbedByV4L; /* V4L stuff */
569 int pitch;
570 int offset;
572 int modeflags; /* Flags field of current display mode */
574 int tvxpos, tvypos;
575 Bool updatetvxpos, updatetvypos;
577 } SISPortPrivRec, *SISPortPrivPtr;
579 typedef struct {
580 int pixelFormat;
582 CARD16 pitch;
583 CARD16 origPitch;
585 CARD8 keyOP;
586 CARD16 HUSF;
587 CARD16 VUSF;
588 CARD8 IntBit;
589 CARD8 wHPre;
591 CARD16 srcW;
592 CARD16 srcH;
594 BoxRec dstBox;
596 CARD32 PSY;
597 CARD32 PSV;
598 CARD32 PSU;
600 CARD16 SCREENheight;
602 CARD8 lineBufSize;
604 DisplayModePtr currentmode;
606 #ifdef SISMERGED
607 CARD16 pitch2;
608 CARD16 HUSF2;
609 CARD16 VUSF2;
610 CARD8 IntBit2;
611 CARD8 wHPre2;
613 CARD16 srcW2;
614 CARD16 srcH2;
615 BoxRec dstBox2;
616 CARD32 PSY2;
617 CARD32 PSV2;
618 CARD32 PSU2;
619 CARD16 SCREENheight2;
620 CARD8 lineBufSize2;
622 DisplayModePtr currentmode2;
624 Bool DoFirst, DoSecond;
625 #endif
627 CARD8 bobEnable;
629 CARD8 contrastCtrl;
630 CARD8 contrastFactor;
632 CARD8 (*VBlankActiveFunc)(SISPtr, SISPortPrivPtr);
633 #if 0
634 CARD32 (*GetScanLineFunc)(SISPtr pSiS);
635 #endif
637 #if 0
638 /* The following are not used yet */
639 CARD16 SubPictHUSF; /* Subpicture scaling */
640 CARD16 SubpictVUSF;
641 CARD8 SubpictIntBit;
642 CARD8 SubPictwHPre;
643 CARD16 SubPictsrcW; /* Subpicture source width */
644 CARD16 SubPictsrcH; /* Subpicture source height */
645 BoxRec SubPictdstBox; /* SubPicture destination box */
646 CARD32 SubPictAddr; /* SubPicture address */
647 CARD32 SubPictPitch; /* SubPicture pitch */
648 CARD32 SubPictOrigPitch; /* SubPicture real pitch (needed for scaling twice) */
649 CARD32 SubPictPreset; /* Subpicture Preset */
651 CARD32 MPEG_Y; /* MPEG Y Buffer Addr */
652 CARD32 MPEG_UV; /* MPEG UV Buffer Addr */
653 #endif
655 } SISOverlayRec, *SISOverlayPtr;
659 /****************************************************************************
660 * Raw register access : These routines directly interact with the sis's
661 * control aperature. Must not be called until after
662 * the board's pci memory has been mapped.
663 ****************************************************************************/
665 #if 0
666 static CARD32 _sisread(SISPtr pSiS, CARD32 reg)
668 return *(pSiS->IOBase + reg);
671 static void _siswrite(SISPtr pSiS, CARD32 reg, CARD32 data)
673 *(pSiS->IOBase + reg) = data;
675 #endif
677 static CARD8 getsrreg(SISPtr pSiS, CARD8 reg)
679 CARD8 ret;
680 inSISIDXREG(SISSR, reg, ret);
681 return(ret);
684 static CARD8 getvideoreg(SISPtr pSiS, CARD8 reg)
686 CARD8 ret;
687 inSISIDXREG(SISVID, reg, ret);
688 return(ret);
691 static __inline void setvideoreg(SISPtr pSiS, CARD8 reg, CARD8 data)
693 outSISIDXREG(SISVID, reg, data);
696 static __inline void setvideoregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask)
698 CARD8 old;
699 inSISIDXREG(SISVID, reg, old);
700 data = (data & mask) | (old & (~mask));
701 outSISIDXREG(SISVID, reg, data);
704 static void setsrregmask(SISPtr pSiS, CARD8 reg, CARD8 data, CARD8 mask)
706 CARD8 old;
708 inSISIDXREG(SISSR, reg, old);
709 data = (data & mask) | (old & (~mask));
710 outSISIDXREG(SISSR, reg, data);
713 /* VBlank */
714 static CARD8 vblank_active_CRT1(SISPtr pSiS, SISPortPrivPtr pPriv)
716 return(inSISREG(SISINPSTAT) & 0x08);
719 static CARD8 vblank_active_CRT2(SISPtr pSiS, SISPortPrivPtr pPriv)
721 CARD8 ret;
723 if(pPriv->bridgeIsSlave) return(vblank_active_CRT1(pSiS, pPriv));
725 if(pSiS->VGAEngine == SIS_315_VGA) {
726 inSISIDXREG(SISPART1, 0x30, ret);
727 } else {
728 inSISIDXREG(SISPART1, 0x25, ret);
730 return((ret & 0x02) ^ 0x02);
733 /* Scanline - unused */
734 #if 0
735 static CARD32 get_scanline_CRT1(SISPtr pSiS)
737 CARD32 line;
739 _siswrite (pSiS, REG_PRIM_CRT_COUNTER, 0x00000001);
740 line = _sisread (pSiS, REG_PRIM_CRT_COUNTER);
742 return ((line >> 16) & 0x07FF);
745 static CARD32 get_scanline_CRT2(SISPtr pSiS)
747 CARD32 line;
749 line = (CARD32)(getsisreg(pSiS, SISPART1, Index_CRT2_FC_VCount1) & 0x70) * 16
750 + getsisreg(pSiS, SISPART1, Index_CRT2_FC_VCount);
752 return line;
754 #endif
756 static void
757 SiSComputeXvGamma(SISPtr pSiS)
759 int num = 255, i;
760 double red = 1.0 / (double)((double)pSiS->XvGammaRed / 1000);
761 double green = 1.0 / (double)((double)pSiS->XvGammaGreen / 1000);
762 double blue = 1.0 / (double)((double)pSiS->XvGammaBlue / 1000);
764 for(i = 0; i <= num; i++) {
765 pSiS->XvGammaRampRed[i] =
766 (red == 1.0) ? i : (CARD8)(pow((double)i / (double)num, red) * (double)num + 0.5);
768 pSiS->XvGammaRampGreen[i] =
769 (green == 1.0) ? i : (CARD8)(pow((double)i / (double)num, green) * (double)num + 0.5);
771 pSiS->XvGammaRampBlue[i] =
772 (blue == 1.0) ? i : (CARD8)(pow((double)i / (double)num, blue) * (double)num + 0.5);
776 static void
777 SiSSetXvGamma(SISPtr pSiS)
779 int i;
780 unsigned char backup = getsrreg(pSiS, 0x1f);
781 setsrregmask(pSiS, 0x1f, 0x08, 0x18);
782 for(i = 0; i <= 255; i++) {
783 MMIO_OUT32(pSiS->IOBase, 0x8570,
784 (i << 24) |
785 (pSiS->XvGammaRampBlue[i] << 16) |
786 (pSiS->XvGammaRampGreen[i] << 8) |
787 pSiS->XvGammaRampRed[i]);
789 setsrregmask(pSiS, 0x1f, backup, 0xff);
792 static void
793 SiSUpdateXvGamma(SISPtr pSiS, SISPortPrivPtr pPriv)
795 unsigned char sr7 = getsrreg(pSiS, 0x07);
797 if(!pSiS->XvGamma) return;
798 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAYGAMMA)) return;
800 #ifdef SISDUALHEAD
801 if((pPriv->dualHeadMode) && (!pSiS->SecondHead)) return;
802 #endif
804 if(!(sr7 & 0x04)) return;
806 SiSComputeXvGamma(pSiS);
807 SiSSetXvGamma(pSiS);
810 static void
811 SISResetXvGamma(ScrnInfoPtr pScrn)
813 SISPtr pSiS = SISPTR(pScrn);
814 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
816 SiSUpdateXvGamma(pSiS, pPriv);
819 void SISInitVideo(ScreenPtr pScreen)
821 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
822 XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
823 XF86VideoAdaptorPtr newAdaptor = NULL;
824 int num_adaptors;
826 newAdaptor = SISSetupImageVideo(pScreen);
827 if(newAdaptor)
828 SISInitOffscreenImages(pScreen);
830 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
832 if(newAdaptor) {
833 if(!num_adaptors) {
834 num_adaptors = 1;
835 adaptors = &newAdaptor;
836 } else {
837 /* need to free this someplace */
838 newAdaptors = xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
839 if(newAdaptors) {
840 memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
841 newAdaptors[num_adaptors] = newAdaptor;
842 adaptors = newAdaptors;
843 num_adaptors++;
848 if(num_adaptors)
849 xf86XVScreenInit(pScreen, adaptors, num_adaptors);
851 if(newAdaptors)
852 xfree(newAdaptors);
855 static void
856 SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
858 SISPtr pSiS = SISPTR(pScrn);
859 #ifdef SISDUALHEAD
860 SISEntPtr pSiSEnt = pSiS->entityPrivate;;
861 #endif
863 pPriv->colorKey = pSiS->colorKey = 0x000101fe;
864 pPriv->videoStatus = 0;
865 pPriv->brightness = pSiS->XvDefBri;
866 pPriv->contrast = pSiS->XvDefCon;
867 pPriv->hue = pSiS->XvDefHue;
868 pPriv->saturation = pSiS->XvDefSat;
869 pPriv->autopaintColorKey = TRUE;
870 pPriv->disablegfx = pSiS->XvDefDisableGfx;
871 pPriv->disablegfxlr= pSiS->XvDefDisableGfxLR;
872 pSiS->disablecolorkeycurrent = pSiS->XvDisableColorKey;
873 pPriv->usechromakey = pSiS->XvUseChromaKey;
874 pPriv->insidechromakey = pSiS->XvInsideChromaKey;
875 pPriv->yuvchromakey = pSiS->XvYUVChromaKey;
876 pPriv->chromamin = pSiS->XvChromaMin;
877 pPriv->chromamax = pSiS->XvChromaMax;
878 if(pPriv->dualHeadMode) {
879 #ifdef SISDUALHEAD
880 if(!pSiS->SecondHead) {
881 pPriv->tvxpos = pSiS->tvxpos;
882 pPriv->tvypos = pSiS->tvypos;
883 pPriv->updatetvxpos = TRUE;
884 pPriv->updatetvypos = TRUE;
886 #endif
887 } else {
888 pPriv->tvxpos = pSiS->tvxpos;
889 pPriv->tvypos = pSiS->tvypos;
890 pPriv->updatetvxpos = TRUE;
891 pPriv->updatetvypos = TRUE;
893 #ifdef SIS_CP
894 SIS_CP_VIDEO_DEF
895 #endif
896 if(pPriv->dualHeadMode) {
897 #ifdef SISDUALHEAD
898 pPriv->crtnum =
899 pSiSEnt->curxvcrtnum =
900 pSiSEnt->XvOnCRT2 ? 1 : 0;
901 #endif
902 } else
903 pPriv->crtnum = pSiS->XvOnCRT2 ? 1 : 0;
905 pSiS->XvGammaRed = pSiS->XvGammaRedDef;
906 pSiS->XvGammaGreen = pSiS->XvGammaGreenDef;
907 pSiS->XvGammaBlue = pSiS->XvGammaBlueDef;
908 SiSUpdateXvGamma(pSiS, pPriv);
911 static void
912 SISResetVideo(ScrnInfoPtr pScrn)
914 SISPtr pSiS = SISPTR(pScrn);
915 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
917 /* Unlock registers */
918 #ifdef UNLOCK_ALWAYS
919 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
920 #endif
921 if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1) {
922 setvideoreg (pSiS, Index_VI_Passwd, 0x86);
923 if(getvideoreg (pSiS, Index_VI_Passwd) != 0xa1)
924 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
925 "Xv: Video password could not unlock registers\n");
928 /* Initialize first overlay (CRT1) ------------------------------- */
930 /* This bit has obviously a different meaning on 315 series (linebuffer-related) */
931 if(pSiS->VGAEngine == SIS_300_VGA) {
932 /* Write-enable video registers */
933 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x80, 0x81);
934 } else {
935 /* Select overlay 2, clear all linebuffer related bits */
936 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0xb1);
939 /* Disable overlay */
940 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
942 /* Disable bob de-interlacer and some strange bit */
943 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x82);
945 /* Select RGB chroma key format (300 series only) */
946 if(pSiS->VGAEngine == SIS_300_VGA) {
947 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x40);
950 /* Reset scale control and contrast */
951 /* (Enable DDA (interpolation)) */
952 setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60);
953 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F);
955 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00);
956 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00);
957 setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00);
958 setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00);
959 setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00);
960 setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00);
961 setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00);
963 if(pSiS->Chipset == PCI_CHIP_SIS330) {
964 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
965 } else if(pSiS->Chipset == PCI_CHIP_SIS660) {
966 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0);
968 if(pSiS->sishw_ext.jChipType == SIS_661) {
969 setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x2c, 0x3c);
972 if((pSiS->ChipFlags & SiSCF_Is65x) || (pSiS->Chipset == PCI_CHIP_SIS660)) {
973 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x04);
976 /* Initialize second overlay (CRT2) - only for 300, 630/730, 550, M650/651, 661/741/660/760 */
977 if(pPriv->hasTwoOverlays) {
979 if(pSiS->VGAEngine == SIS_300_VGA) {
980 /* Write-enable video registers */
981 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x81, 0x81);
982 } else {
983 /* Select overlay 2, clear all linebuffer related bits */
984 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0xb1);
987 /* Disable overlay */
988 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
990 /* Disable bob de-interlacer and some strange bit */
991 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x82);
993 /* Select RGB chroma key format */
994 if(pSiS->VGAEngine == SIS_300_VGA) {
995 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x40);
998 /* Reset scale control and contrast */
999 /* (Enable DDA (interpolation)) */
1000 setvideoregmask(pSiS, Index_VI_Scale_Control, 0x60, 0x60);
1001 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F);
1003 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Low, 0x00);
1004 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Preset_Middle, 0x00);
1005 setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Low, 0x00);
1006 setvideoreg(pSiS, Index_VI_UV_Buf_Preset_Middle, 0x00);
1007 setvideoreg(pSiS, Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00);
1008 setvideoreg(pSiS, Index_VI_Play_Threshold_Low, 0x00);
1009 setvideoreg(pSiS, Index_VI_Play_Threshold_High, 0x00);
1011 if(pSiS->Chipset == PCI_CHIP_SIS330) {
1012 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0x10);
1013 } else if(pSiS->Chipset == PCI_CHIP_SIS660) {
1014 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, 0x00, 0xE0);
1016 if(pSiS->sishw_ext.jChipType == SIS_661) {
1017 setvideoregmask(pSiS, Index_VI_V_Buf_Start_Over, 0x24, 0x3c);
1022 /* set default properties for overlay 1 (CRT1) -------------------------- */
1023 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01);
1024 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07);
1025 setvideoreg(pSiS, Index_VI_Brightness, 0x20);
1026 if(pSiS->VGAEngine == SIS_315_VGA) {
1027 setvideoreg(pSiS, Index_VI_Hue, 0x00);
1028 setvideoreg(pSiS, Index_VI_Saturation, 0x00);
1031 /* set default properties for overlay 2(CRT2) -------------------------- */
1032 if(pPriv->hasTwoOverlays) {
1033 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
1034 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07);
1035 setvideoreg(pSiS, Index_VI_Brightness, 0x20);
1036 if(pSiS->VGAEngine == SIS_315_VGA) {
1037 setvideoreg(pSiS, Index_VI_Hue, 0x00);
1038 setvideoreg(pSiS, Index_VI_Saturation, 0x00);
1042 /* Reset Xv gamma correction */
1043 if(pSiS->VGAEngine == SIS_315_VGA) {
1044 SiSUpdateXvGamma(pSiS, pPriv);
1048 /* Set display mode (single CRT1/CRT2, mirror).
1049 * MIRROR mode is only available on chipsets with two overlays.
1050 * On the other chipsets, if only CRT1 or only CRT2 are used,
1051 * the correct display CRT is chosen automatically. If both
1052 * CRT1 and CRT2 are connected, the user can choose between CRT1 and
1053 * CRT2 by using the option XvOnCRT2.
1055 static void
1056 set_dispmode(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
1058 SISPtr pSiS = SISPTR(pScrn);
1060 pPriv->dualHeadMode = pPriv->bridgeIsSlave = FALSE;
1062 if(SiSBridgeIsInSlaveMode(pScrn)) pPriv->bridgeIsSlave = TRUE;
1064 if( (pSiS->VBFlags & VB_DISPMODE_MIRROR) ||
1065 ((pPriv->bridgeIsSlave) && (pSiS->VBFlags & DISPTYPE_DISP2)) ) {
1066 if(pPriv->hasTwoOverlays)
1067 pPriv->displayMode = DISPMODE_MIRROR; /* CRT1+CRT2 (2 overlays) */
1068 else if(pPriv->crtnum)
1069 pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */
1070 else
1071 pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */
1072 } else {
1073 #ifdef SISDUALHEAD
1074 if(pSiS->DualHeadMode) {
1075 pPriv->dualHeadMode = TRUE;
1076 if(pSiS->SecondHead)
1077 pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */
1078 else
1079 pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */
1080 } else
1081 #endif
1082 if(pSiS->VBFlags & DISPTYPE_DISP1) {
1083 pPriv->displayMode = DISPMODE_SINGLE1; /* CRT1 only */
1084 } else {
1085 pPriv->displayMode = DISPMODE_SINGLE2; /* CRT2 only */
1090 static void
1091 set_disptype_regs(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
1093 SISPtr pSiS = SISPTR(pScrn);
1094 #ifdef SISDUALHEAD
1095 SISEntPtr pSiSEnt = pSiS->entityPrivate;
1096 int crtnum = 0;
1098 if(pPriv->dualHeadMode) crtnum = pSiSEnt->curxvcrtnum;
1099 #endif
1102 * SR06[7:6]
1103 * Bit 7: Enable overlay 2 on CRT2
1104 * Bit 6: Enable overlay 1 on CRT2
1105 * SR32[7:6]
1106 * Bit 7: DCLK/TCLK overlay 2
1107 * 0=DCLK (overlay on CRT1)
1108 * 1=TCLK (overlay on CRT2)
1109 * Bit 6: DCLK/TCLK overlay 1
1110 * 0=DCLK (overlay on CRT1)
1111 * 1=TCLK (overlay on CRT2)
1113 * On chipsets with two overlays, we can freely select and also
1114 * have a mirror mode. However, we use overlay 1 for CRT1 and
1115 * overlay 2 for CRT2.
1116 * ATTENTION: CRT2 can only take up to 1 (one) overlay. Setting
1117 * SR06/32 to 0xc0 DOES NOT WORK. THAT'S CONFIRMED.
1118 * Therefore, we use overlay 1 on CRT2 if in SINGLE2 mode.
1120 * For chipsets with only one overlay, user must choose whether
1121 * to display the overlay on CRT1 or CRT2 by setting XvOnCRT2
1122 * to TRUE (CRT2) or FALSE (CRT1). The driver does this auto-
1123 * matically if only CRT1 or only CRT2 is used.
1125 #ifdef UNLOCK_ALWAYS
1126 sisSaveUnlockExtRegisterLock(pSiS, NULL, NULL);
1127 #endif
1129 switch (pPriv->displayMode)
1131 case DISPMODE_SINGLE1: /* CRT1-only mode: */
1132 if(pPriv->hasTwoOverlays) {
1133 if(pPriv->dualHeadMode) {
1134 setsrregmask(pSiS, 0x06, 0x00, 0x40); /* overlay 1 -> CRT1 */
1135 setsrregmask(pSiS, 0x32, 0x00, 0x40);
1136 } else {
1137 setsrregmask(pSiS, 0x06, 0x00, 0xc0); /* both overlays -> CRT1 */
1138 setsrregmask(pSiS, 0x32, 0x00, 0xc0);
1140 } else {
1141 #ifdef SISDUALHEAD
1142 if((!pPriv->dualHeadMode) || (crtnum == 0)) {
1143 #endif
1144 setsrregmask(pSiS, 0x06, 0x00, 0xc0); /* only overlay -> CRT1 */
1145 setsrregmask(pSiS, 0x32, 0x00, 0xc0);
1146 #ifdef SISDUALHEAD
1148 #endif
1150 break;
1152 case DISPMODE_SINGLE2: /* CRT2-only mode: */
1153 if(pPriv->hasTwoOverlays) {
1154 if(pPriv->dualHeadMode) {
1155 setsrregmask(pSiS, 0x06, 0x80, 0x80); /* overlay 2 -> CRT2 */
1156 setsrregmask(pSiS, 0x32, 0x80, 0x80);
1157 } else {
1158 setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* overlay 1 -> CRT2 */
1159 setsrregmask(pSiS, 0x32, 0xc0, 0xc0); /* (although both clocks for CRT2!) */
1161 } else {
1162 #ifdef SISDUALHEAD
1163 if((!pPriv->dualHeadMode) || (crtnum == 1)) {
1164 #endif
1165 setsrregmask(pSiS, 0x06, 0x40, 0xc0); /* only overlay -> CRT2 */
1166 setsrregmask(pSiS, 0x32, 0x40, 0xc0);
1167 #ifdef SISDUALHEAD
1169 #endif
1171 break;
1173 case DISPMODE_MIRROR: /* CRT1+CRT2-mode: (only on chips with 2 overlays) */
1174 default:
1175 setsrregmask(pSiS, 0x06, 0x80, 0xc0); /* overlay 1 -> CRT1, overlay 2 -> CRT2 */
1176 setsrregmask(pSiS, 0x32, 0x80, 0xc0);
1177 break;
1181 static void
1182 set_allowswitchcrt(SISPtr pSiS, SISPortPrivPtr pPriv)
1184 if(pSiS->hasTwoOverlays) {
1185 pPriv->AllowSwitchCRT = FALSE;
1186 } else {
1187 pPriv->AllowSwitchCRT = TRUE;
1188 if(pSiS->XvOnCRT2) {
1189 if(!(pSiS->VBFlags & DISPTYPE_DISP1)) {
1190 pPriv->AllowSwitchCRT = FALSE;
1192 } else {
1193 if(!(pSiS->VBFlags & DISPTYPE_DISP2)) {
1194 pPriv->AllowSwitchCRT = FALSE;
1200 static void
1201 set_maxencoding(SISPtr pSiS, SISPortPrivPtr pPriv)
1203 if(pSiS->VGAEngine == SIS_300_VGA) {
1204 DummyEncoding.width = IMAGE_MAX_WIDTH_300;
1205 DummyEncoding.height = IMAGE_MAX_HEIGHT_300;
1206 } else {
1207 DummyEncoding.width = IMAGE_MAX_WIDTH_315;
1208 DummyEncoding.height = IMAGE_MAX_HEIGHT_315;
1209 if(pPriv->hasTwoOverlays) {
1210 /* Only half width available if both overlays
1211 * are going to be used
1213 #ifdef SISDUALHEAD
1214 if(pSiS->DualHeadMode) {
1215 if(pSiS->Chipset == PCI_CHIP_SIS660) {
1216 DummyEncoding.width = 1536;
1217 } else {
1218 DummyEncoding.width >>= 1;
1220 } else
1221 #endif
1222 #ifdef SISMERGED
1223 if(pSiS->MergedFB) {
1224 if(pSiS->Chipset == PCI_CHIP_SIS660) {
1225 DummyEncoding.width = 1536;
1226 } else {
1227 DummyEncoding.width >>= 1;
1229 } else
1230 #endif
1231 if(pPriv->displayMode == DISPMODE_MIRROR) {
1232 if(pSiS->Chipset == PCI_CHIP_SIS660) {
1233 DummyEncoding.width = 1536;
1234 } else {
1235 DummyEncoding.width >>= 1;
1242 static XF86VideoAdaptorPtr
1243 SISSetupImageVideo(ScreenPtr pScreen)
1245 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1246 SISPtr pSiS = SISPTR(pScrn);
1247 XF86VideoAdaptorPtr adapt;
1248 SISPortPrivPtr pPriv;
1250 if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
1251 sizeof(SISPortPrivRec) +
1252 sizeof(DevUnion))))
1253 return NULL;
1255 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
1256 adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
1257 adapt->name = "SIS 300/315/330 series Video Overlay";
1258 adapt->nEncodings = 1;
1259 adapt->pEncodings = &DummyEncoding;
1261 adapt->nFormats = NUM_FORMATS;
1262 adapt->pFormats = SISFormats;
1263 adapt->nPorts = 1;
1264 adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
1266 pPriv = (SISPortPrivPtr)(&adapt->pPortPrivates[1]);
1268 /* Setup chipset type helpers */
1269 if(pSiS->hasTwoOverlays) {
1270 pPriv->hasTwoOverlays = TRUE;
1271 pPriv->AllowSwitchCRT = FALSE;
1272 } else {
1273 pPriv->hasTwoOverlays = FALSE;
1274 pPriv->AllowSwitchCRT = TRUE;
1275 if(pSiS->XvOnCRT2) {
1276 if(!(pSiS->VBFlags & DISPTYPE_DISP1)) {
1277 pPriv->AllowSwitchCRT = FALSE;
1279 } else {
1280 if(!(pSiS->VBFlags & DISPTYPE_DISP2)) {
1281 pPriv->AllowSwitchCRT = FALSE;
1286 set_allowswitchcrt(pSiS, pPriv);
1288 adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
1289 if(pSiS->VGAEngine == SIS_300_VGA) {
1290 adapt->nImages = NUM_IMAGES_300;
1291 adapt->pAttributes = SISAttributes_300;
1292 adapt->nAttributes = NUM_ATTRIBUTES_300;
1293 } else {
1294 if(pSiS->sishw_ext.jChipType >= SIS_330) {
1295 adapt->nImages = NUM_IMAGES_330;
1296 } else {
1297 adapt->nImages = NUM_IMAGES_315;
1299 adapt->pAttributes = SISAttributes_315;
1300 adapt->nAttributes = NUM_ATTRIBUTES_315;
1301 if(pPriv->hasTwoOverlays) adapt->nAttributes--;
1304 adapt->pImages = SISImages;
1305 adapt->PutVideo = NULL;
1306 adapt->PutStill = NULL;
1307 adapt->GetVideo = NULL;
1308 adapt->GetStill = NULL;
1309 adapt->StopVideo = SISStopVideo;
1310 adapt->SetPortAttribute = SISSetPortAttribute;
1311 adapt->GetPortAttribute = SISGetPortAttribute;
1312 adapt->QueryBestSize = SISQueryBestSize;
1313 adapt->PutImage = SISPutImage;
1314 adapt->QueryImageAttributes = SISQueryImageAttributes;
1316 pPriv->videoStatus = 0;
1317 pPriv->currentBuf = 0;
1318 pPriv->linear = NULL;
1319 pPriv->grabbedByV4L= FALSE;
1320 pPriv->NoOverlay = FALSE;
1321 pPriv->PrevOverlay = FALSE;
1323 /* gotta uninit this someplace */
1324 #if defined(REGION_NULL)
1325 REGION_NULL(pScreen, &pPriv->clip);
1326 #else
1327 REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
1328 #endif
1330 pSiS->adaptor = adapt;
1332 pSiS->xvBrightness = MAKE_ATOM(sisxvbrightness);
1333 pSiS->xvContrast = MAKE_ATOM(sisxvcontrast);
1334 pSiS->xvColorKey = MAKE_ATOM(sisxvcolorkey);
1335 pSiS->xvSaturation = MAKE_ATOM(sisxvsaturation);
1336 pSiS->xvHue = MAKE_ATOM(sisxvhue);
1337 pSiS->xvSwitchCRT = MAKE_ATOM(sisxvswitchcrt);
1338 pSiS->xvAutopaintColorKey = MAKE_ATOM(sisxvautopaintcolorkey);
1339 pSiS->xvSetDefaults = MAKE_ATOM(sisxvsetdefaults);
1340 pSiS->xvDisableGfx = MAKE_ATOM(sisxvdisablegfx);
1341 pSiS->xvDisableGfxLR = MAKE_ATOM(sisxvdisablegfxlr);
1342 pSiS->xvTVXPosition = MAKE_ATOM(sisxvtvxposition);
1343 pSiS->xvTVYPosition = MAKE_ATOM(sisxvtvyposition);
1344 pSiS->xvGammaRed = MAKE_ATOM(sisxvgammared);
1345 pSiS->xvGammaGreen = MAKE_ATOM(sisxvgammagreen);
1346 pSiS->xvGammaBlue = MAKE_ATOM(sisxvgammablue);
1347 pSiS->xvDisableColorkey = MAKE_ATOM(sisxvdisablecolorkey);
1348 pSiS->xvUseChromakey = MAKE_ATOM(sisxvusechromakey);
1349 pSiS->xvInsideChromakey = MAKE_ATOM(sisxvinsidechromakey);
1350 pSiS->xvYUVChromakey = MAKE_ATOM(sisxvyuvchromakey);
1351 pSiS->xvChromaMin = MAKE_ATOM(sisxvchromamin);
1352 pSiS->xvChromaMax = MAKE_ATOM(sisxvchromamax);
1353 pSiS->xv_QVF = MAKE_ATOM(sisxvqueryvbflags);
1354 pSiS->xv_GDV = MAKE_ATOM(sisxvsdgetdriverversion);
1355 pSiS->xv_GHI = MAKE_ATOM(sisxvsdgethardwareinfo);
1356 pSiS->xv_GBI = MAKE_ATOM(sisxvsdgetbusid);
1357 pSiS->xv_QVV = MAKE_ATOM(sisxvsdqueryvbflagsversion);
1358 pSiS->xv_GSF = MAKE_ATOM(sisxvsdgetsdflags);
1359 pSiS->xv_USD = MAKE_ATOM(sisxvsdunlocksisdirect);
1360 pSiS->xv_SVF = MAKE_ATOM(sisxvsdsetvbflags);
1361 pSiS->xv_QDD = MAKE_ATOM(sisxvsdquerydetecteddevices);
1362 pSiS->xv_CT1 = MAKE_ATOM(sisxvsdcrt1status);
1363 pSiS->xv_CMD = MAKE_ATOM(sisxvsdcheckmodeindexforcrt2);
1364 pSiS->xv_CMDR = MAKE_ATOM(sisxvsdresultcheckmodeindexforcrt2);
1365 pSiS->xv_TAF = MAKE_ATOM(sisxvsdsisantiflicker);
1366 pSiS->xv_TSA = MAKE_ATOM(sisxvsdsissaturation);
1367 pSiS->xv_TEE = MAKE_ATOM(sisxvsdsisedgeenhance);
1368 pSiS->xv_COC = MAKE_ATOM(sisxvsdsiscolcalibc);
1369 pSiS->xv_COF = MAKE_ATOM(sisxvsdsiscolcalibf);
1370 pSiS->xv_CFI = MAKE_ATOM(sisxvsdsiscfilter);
1371 pSiS->xv_YFI = MAKE_ATOM(sisxvsdsisyfilter);
1372 pSiS->xv_TCO = MAKE_ATOM(sisxvsdchcontrast);
1373 pSiS->xv_TTE = MAKE_ATOM(sisxvsdchtextenhance);
1374 pSiS->xv_TCF = MAKE_ATOM(sisxvsdchchromaflickerfilter);
1375 pSiS->xv_TLF = MAKE_ATOM(sisxvsdchlumaflickerfilter);
1376 pSiS->xv_TCC = MAKE_ATOM(sisxvsdchcvbscolor);
1377 pSiS->xv_OVR = MAKE_ATOM(sisxvsdchoverscan);
1378 pSiS->xv_SGA = MAKE_ATOM(sisxvsdenablegamma);
1379 pSiS->xv_TXS = MAKE_ATOM(sisxvsdtvxscale);
1380 pSiS->xv_TYS = MAKE_ATOM(sisxvsdtvyscale);
1381 pSiS->xv_GSS = MAKE_ATOM(sisxvsdgetscreensize);
1382 pSiS->xv_BRR = MAKE_ATOM(sisxvsdstorebrir);
1383 pSiS->xv_BRG = MAKE_ATOM(sisxvsdstorebrig);
1384 pSiS->xv_BRB = MAKE_ATOM(sisxvsdstorebrib);
1385 pSiS->xv_PBR = MAKE_ATOM(sisxvsdstorepbrir);
1386 pSiS->xv_PBG = MAKE_ATOM(sisxvsdstorepbrig);
1387 pSiS->xv_PBB = MAKE_ATOM(sisxvsdstorepbrib);
1388 pSiS->xv_BRR2 = MAKE_ATOM(sisxvsdstorebrir2);
1389 pSiS->xv_BRG2 = MAKE_ATOM(sisxvsdstorebrig2);
1390 pSiS->xv_BRB2 = MAKE_ATOM(sisxvsdstorebrib2);
1391 pSiS->xv_PBR2 = MAKE_ATOM(sisxvsdstorepbrir2);
1392 pSiS->xv_PBG2 = MAKE_ATOM(sisxvsdstorepbrig2);
1393 pSiS->xv_PBB2 = MAKE_ATOM(sisxvsdstorepbrib2);
1394 pSiS->xv_SHC = MAKE_ATOM(sisxvsdhidehwcursor);
1395 #ifdef TWDEBUG
1396 pSiS->xv_STR = MAKE_ATOM(sisxvsetreg);
1397 #endif
1398 #ifdef SIS_CP
1399 SIS_CP_VIDEO_ATOMS
1400 #endif
1402 pSiS->xv_sisdirectunlocked = 0;
1403 pSiS->xv_sd_result = 0;
1405 /* 300 series require double words for addresses and pitches,
1406 * 315/330 series require word.
1408 switch (pSiS->VGAEngine) {
1409 case SIS_315_VGA:
1410 pPriv->shiftValue = 1;
1411 break;
1412 case SIS_300_VGA:
1413 default:
1414 pPriv->shiftValue = 2;
1415 break;
1418 /* Set displayMode according to VBFlags */
1419 set_dispmode(pScrn, pPriv);
1421 /* Now for the linebuffer stuff.
1422 * All chipsets have a certain number of linebuffers, each of a certain
1423 * size. The number of buffers is per overlay.
1424 * Chip number size max video size
1425 * 300 2 ? 720x576
1426 * 630/730 2 ? 720x576
1427 * 315 2 960? 1920x1080
1428 * 650/740 2 960 ("120x128") 1920x1080
1429 * M650/651.. 4 480 1920x1080
1430 * 330 2 960 1920x1080
1431 * 661/741/760 4 768 1920x1080
1432 * The unit of size is unknown; I just know that a size of 480 limits
1433 * the video source width to 384. Beyond that, line buffers must be
1434 * merged (otherwise the video output is garbled).
1435 * To use the maximum width (eg 1920x1080 on the 315 series, including
1436 * the M650, 651 and later), *all* line buffers must be merged. Hence,
1437 * we can only use one overlay. This should be set up for modes where
1438 * either only CRT1 or only CRT2 is used.
1439 * If both overlays are going to be used (such as in modes were both
1440 * CRT1 and CRT2 are active), we are limited to the half of the
1441 * maximum width, or 1536 on 661/741/760.
1444 pPriv->linebufMergeLimit = LINEBUFLIMIT1;
1445 if(pSiS->Chipset == PCI_CHIP_SIS660) {
1446 pPriv->linebufMergeLimit = LINEBUFLIMIT3;
1449 set_maxencoding(pSiS, pPriv);
1451 if(pSiS->VGAEngine == SIS_300_VGA) {
1452 pPriv->linebufmask = 0x11;
1453 } else {
1454 pPriv->linebufmask = 0xb1;
1455 if(!(pPriv->hasTwoOverlays)) {
1456 /* On machines with only one overlay, the linebuffers are
1457 * generally larger, so our merging-limit is higher, too.
1459 pPriv->linebufMergeLimit = LINEBUFLIMIT2;
1463 /* Reset the properties to their defaults */
1464 SISSetPortDefaults(pScrn, pPriv);
1466 /* Set SR(06, 32) registers according to DISPMODE */
1467 set_disptype_regs(pScrn, pPriv);
1469 SISResetVideo(pScrn);
1470 pSiS->ResetXv = SISResetVideo;
1471 if(pSiS->VGAEngine == SIS_315_VGA) {
1472 pSiS->ResetXvGamma = SISResetXvGamma;
1475 return adapt;
1478 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0)
1479 static Bool
1480 RegionsEqual(RegionPtr A, RegionPtr B)
1482 int *dataA, *dataB;
1483 int num;
1485 num = REGION_NUM_RECTS(A);
1486 if(num != REGION_NUM_RECTS(B))
1487 return FALSE;
1489 if((A->extents.x1 != B->extents.x1) ||
1490 (A->extents.x2 != B->extents.x2) ||
1491 (A->extents.y1 != B->extents.y1) ||
1492 (A->extents.y2 != B->extents.y2))
1493 return FALSE;
1495 dataA = (int*)REGION_RECTS(A);
1496 dataB = (int*)REGION_RECTS(B);
1498 while(num--) {
1499 if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
1500 return FALSE;
1501 dataA += 2;
1502 dataB += 2;
1505 return TRUE;
1507 #endif
1509 static int
1510 SISSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
1511 INT32 value, pointer data)
1513 SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
1514 SISPtr pSiS = SISPTR(pScrn);
1515 #ifdef SISDUALHEAD
1516 SISEntPtr pSiSEnt = pSiS->entityPrivate;;
1517 #endif
1519 if(attribute == pSiS->xvBrightness) {
1520 if((value < -128) || (value > 127))
1521 return BadValue;
1522 pPriv->brightness = value;
1523 } else if(attribute == pSiS->xvContrast) {
1524 if((value < 0) || (value > 7))
1525 return BadValue;
1526 pPriv->contrast = value;
1527 } else if(attribute == pSiS->xvColorKey) {
1528 pPriv->colorKey = pSiS->colorKey = value;
1529 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
1530 } else if(attribute == pSiS->xvAutopaintColorKey) {
1531 if((value < 0) || (value > 1))
1532 return BadValue;
1533 pPriv->autopaintColorKey = value;
1534 } else if(attribute == pSiS->xvSetDefaults) {
1535 SISSetPortDefaults(pScrn, pPriv);
1536 } else if(attribute == pSiS->xvDisableGfx) {
1537 if((value < 0) || (value > 1))
1538 return BadValue;
1539 pPriv->disablegfx = value;
1540 } else if(attribute == pSiS->xvDisableGfxLR) {
1541 if((value < 0) || (value > 1))
1542 return BadValue;
1543 pPriv->disablegfxlr = value;
1544 } else if(attribute == pSiS->xvTVXPosition) {
1545 if((value < -32) || (value > 32))
1546 return BadValue;
1547 pPriv->tvxpos = value;
1548 if(pSiS->xv_sisdirectunlocked) {
1549 SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
1550 pPriv->updatetvxpos = FALSE;
1551 } else {
1552 pSiS->tvxpos = pPriv->tvxpos;
1553 #ifdef SISDUALHEAD
1554 if(pPriv->dualHeadMode) pSiSEnt->tvxpos = pPriv->tvxpos;
1555 #endif
1556 pPriv->updatetvxpos = TRUE;
1558 } else if(attribute == pSiS->xvTVYPosition) {
1559 if((value < -32) || (value > 32))
1560 return BadValue;
1561 pPriv->tvypos = value;
1562 if(pSiS->xv_sisdirectunlocked) {
1563 SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
1564 pPriv->updatetvypos = FALSE;
1565 } else {
1566 pSiS->tvypos = pPriv->tvypos;
1567 #ifdef SISDUALHEAD
1568 if(pPriv->dualHeadMode) pSiSEnt->tvypos = pPriv->tvypos;
1569 #endif
1570 pPriv->updatetvypos = TRUE;
1572 } else if(attribute == pSiS->xvDisableColorkey) {
1573 if((value < 0) || (value > 1))
1574 return BadValue;
1575 pSiS->disablecolorkeycurrent = value;
1576 } else if(attribute == pSiS->xvUseChromakey) {
1577 if((value < 0) || (value > 1))
1578 return BadValue;
1579 pPriv->usechromakey = value;
1580 } else if(attribute == pSiS->xvInsideChromakey) {
1581 if((value < 0) || (value > 1))
1582 return BadValue;
1583 pPriv->insidechromakey = value;
1584 } else if(attribute == pSiS->xvYUVChromakey) {
1585 if((value < 0) || (value > 1))
1586 return BadValue;
1587 pPriv->yuvchromakey = value;
1588 } else if(attribute == pSiS->xvChromaMin) {
1589 pPriv->chromamin = value;
1590 } else if(attribute == pSiS->xvChromaMax) {
1591 pPriv->chromamax = value;
1592 } else if(attribute == pSiS->xv_USD) {
1593 if(pSiS->enablesisctrl) {
1594 if(value == SIS_DIRECTKEY) {
1595 pSiS->xv_sisdirectunlocked++;
1596 } else if(pSiS->xv_sisdirectunlocked) {
1597 pSiS->xv_sisdirectunlocked--;
1599 } else {
1600 pSiS->xv_sisdirectunlocked = 0;
1602 } else if(attribute == pSiS->xv_SVF) {
1603 #ifdef SISDUALHEAD
1604 if(!pPriv->dualHeadMode)
1605 #endif
1606 if(pSiS->xv_sisdirectunlocked) {
1607 SISSwitchCRT2Type(pScrn, (unsigned long)value);
1608 set_dispmode(pScrn, pPriv);
1609 set_allowswitchcrt(pSiS, pPriv);
1610 set_maxencoding(pSiS, pPriv);
1612 } else if(attribute == pSiS->xv_CT1) {
1613 #ifdef SISDUALHEAD
1614 if(!pPriv->dualHeadMode)
1615 #endif
1616 if(pSiS->xv_sisdirectunlocked) {
1617 SISSwitchCRT1Status(pScrn, (unsigned long)value);
1618 set_dispmode(pScrn, pPriv);
1619 set_allowswitchcrt(pSiS, pPriv);
1620 set_maxencoding(pSiS, pPriv);
1622 } else if(attribute == pSiS->xv_TAF) {
1623 if(pSiS->xv_sisdirectunlocked) {
1624 SiS_SetSISTVantiflicker(pScrn, (int)value);
1626 } else if(attribute == pSiS->xv_TSA) {
1627 if(pSiS->xv_sisdirectunlocked) {
1628 SiS_SetSISTVsaturation(pScrn, (int)value);
1630 } else if(attribute == pSiS->xv_TEE) {
1631 if(pSiS->xv_sisdirectunlocked) {
1632 SiS_SetSISTVedgeenhance(pScrn, (int)value);
1634 } else if(attribute == pSiS->xv_CFI) {
1635 if(pSiS->xv_sisdirectunlocked) {
1636 SiS_SetSISTVcfilter(pScrn, value ? 1 : 0);
1638 } else if(attribute == pSiS->xv_YFI) {
1639 if(pSiS->xv_sisdirectunlocked) {
1640 SiS_SetSISTVyfilter(pScrn, value);
1642 } else if(attribute == pSiS->xv_COC) {
1643 if(pSiS->xv_sisdirectunlocked) {
1644 SiS_SetSISTVcolcalib(pScrn, (int)value, TRUE);
1646 } else if(attribute == pSiS->xv_COF) {
1647 if(pSiS->xv_sisdirectunlocked) {
1648 SiS_SetSISTVcolcalib(pScrn, (int)value, FALSE);
1650 } else if(attribute == pSiS->xv_TCO) {
1651 if(pSiS->xv_sisdirectunlocked) {
1652 SiS_SetCHTVcontrast(pScrn, (int)value);
1654 } else if(attribute == pSiS->xv_TTE) {
1655 if(pSiS->xv_sisdirectunlocked) {
1656 SiS_SetCHTVtextenhance(pScrn, (int)value);
1658 } else if(attribute == pSiS->xv_TCF) {
1659 if(pSiS->xv_sisdirectunlocked) {
1660 SiS_SetCHTVchromaflickerfilter(pScrn, (int)value);
1662 } else if(attribute == pSiS->xv_TLF) {
1663 if(pSiS->xv_sisdirectunlocked) {
1664 SiS_SetCHTVlumaflickerfilter(pScrn, (int)value);
1666 } else if(attribute == pSiS->xv_TCC) {
1667 if(pSiS->xv_sisdirectunlocked) {
1668 SiS_SetCHTVcvbscolor(pScrn, value ? 1 : 0);
1670 } else if(attribute == pSiS->xv_OVR) {
1671 if(pSiS->xv_sisdirectunlocked) {
1672 pSiS->UseCHOverScan = -1;
1673 pSiS->OptTVSOver = FALSE;
1674 if(value == 3) {
1675 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSOVER) {
1676 pSiS->OptTVSOver = TRUE;
1678 pSiS->UseCHOverScan = 1;
1679 } else if(value == 2) pSiS->UseCHOverScan = 1;
1680 else if(value == 1) pSiS->UseCHOverScan = 0;
1682 } else if(attribute == pSiS->xv_CMD) {
1683 if(pSiS->xv_sisdirectunlocked) {
1684 int result = 0;
1685 pSiS->xv_sd_result = (value & 0xffffff00);
1686 result = SISCheckModeIndexForCRT2Type(pScrn, (unsigned short)(value & 0xff),
1687 (unsigned short)((value >> 8) & 0xff),
1688 FALSE);
1689 pSiS->xv_sd_result |= (result & 0xff);
1691 } else if(attribute == pSiS->xv_SGA) {
1692 if(pSiS->xv_sisdirectunlocked) {
1693 Bool backup = pSiS->XvGamma;
1694 pSiS->CRT1gamma = (value & 0x01) ? TRUE : FALSE;
1695 pSiS->CRT2gamma = (value & 0x02) ? TRUE : FALSE;
1696 pSiS->XvGamma = (value & 0x04) ? TRUE : FALSE;
1697 #ifdef SISDUALHEAD
1698 if(pPriv->dualHeadMode) {
1699 pSiSEnt->CRT1gamma = pSiS->CRT1gamma;
1700 pSiSEnt->CRT2gamma = pSiS->CRT2gamma;
1702 #endif
1703 if(pSiS->VGAEngine == SIS_315_VGA) {
1704 if(backup != pSiS->XvGamma) {
1705 SiSUpdateXvGamma(pSiS, pPriv);
1709 } else if(attribute == pSiS->xv_TXS) {
1710 if((value < -16) || (value > 16))
1711 return BadValue;
1712 if(pSiS->xv_sisdirectunlocked) {
1713 SiS_SetTVxscale(pScrn, value);
1715 } else if(attribute == pSiS->xv_TYS) {
1716 if((value < -4) || (value > 3))
1717 return BadValue;
1718 if(pSiS->xv_sisdirectunlocked) {
1719 SiS_SetTVyscale(pScrn, value);
1721 } else if(attribute == pSiS->xv_BRR) {
1722 if((value < 100) || (value > 10000))
1723 return BadValue;
1724 if(pSiS->xv_sisdirectunlocked) {
1725 pSiS->GammaBriR = value;
1727 } else if(attribute == pSiS->xv_BRG) {
1728 if((value < 100) || (value > 10000))
1729 return BadValue;
1730 if(pSiS->xv_sisdirectunlocked) {
1731 pSiS->GammaBriG = value;
1733 } else if(attribute == pSiS->xv_BRB) {
1734 if((value < 100) || (value > 10000))
1735 return BadValue;
1736 if(pSiS->xv_sisdirectunlocked) {
1737 pSiS->GammaBriB = value;
1739 } else if(attribute == pSiS->xv_PBR) {
1740 if((value < 100) || (value > 10000))
1741 return BadValue;
1742 if(pSiS->xv_sisdirectunlocked) {
1743 pSiS->GammaPBriR = value;
1745 } else if(attribute == pSiS->xv_PBG) {
1746 if((value < 100) || (value > 10000))
1747 return BadValue;
1748 if(pSiS->xv_sisdirectunlocked) {
1749 pSiS->GammaPBriG = value;
1751 } else if(attribute == pSiS->xv_PBB) {
1752 if((value < 100) || (value > 10000))
1753 return BadValue;
1754 if(pSiS->xv_sisdirectunlocked) {
1755 pSiS->GammaPBriB = value;
1757 } else if(attribute == pSiS->xv_BRR2) {
1758 if((value < 100) || (value > 10000))
1759 return BadValue;
1760 if(pSiS->xv_sisdirectunlocked) {
1761 #ifdef SISDUALHEAD
1762 if(pPriv->dualHeadMode) pSiSEnt->GammaBriR = value;
1763 #endif
1765 } else if(attribute == pSiS->xv_BRG2) {
1766 if((value < 100) || (value > 10000))
1767 return BadValue;
1768 if(pSiS->xv_sisdirectunlocked) {
1769 #ifdef SISDUALHEAD
1770 if(pPriv->dualHeadMode) pSiSEnt->GammaBriG = value;
1771 #endif
1773 } else if(attribute == pSiS->xv_BRB2) {
1774 if((value < 100) || (value > 10000))
1775 return BadValue;
1776 if(pSiS->xv_sisdirectunlocked) {
1777 #ifdef SISDUALHEAD
1778 if(pPriv->dualHeadMode) pSiSEnt->GammaBriB = value;
1779 #endif
1781 } else if(attribute == pSiS->xv_PBR2) {
1782 if((value < 100) || (value > 10000))
1783 return BadValue;
1784 if(pSiS->xv_sisdirectunlocked) {
1785 #ifdef SISDUALHEAD
1786 if(pPriv->dualHeadMode) pSiSEnt->GammaPBriR = value;
1787 #endif
1789 } else if(attribute == pSiS->xv_PBG2) {
1790 if((value < 100) || (value > 10000))
1791 return BadValue;
1792 if(pSiS->xv_sisdirectunlocked) {
1793 #ifdef SISDUALHEAD
1794 if(pPriv->dualHeadMode) pSiSEnt->GammaPBriG = value;
1795 #endif
1797 } else if(attribute == pSiS->xv_PBB2) {
1798 if((value < 100) || (value > 10000))
1799 return BadValue;
1800 if(pSiS->xv_sisdirectunlocked) {
1801 #ifdef SISDUALHEAD
1802 if(pPriv->dualHeadMode) pSiSEnt->GammaPBriB = value;
1803 #endif
1805 } else if(attribute == pSiS->xv_SHC) {
1806 if(pSiS->xv_sisdirectunlocked) {
1807 Bool VisibleBackup = pSiS->HWCursorIsVisible;
1808 pSiS->HideHWCursor = value ? TRUE : FALSE;
1809 if(pSiS->CursorInfoPtr) {
1810 if(VisibleBackup) {
1811 if(value) {
1812 (pSiS->CursorInfoPtr->HideCursor)(pScrn);
1813 } else {
1814 (pSiS->CursorInfoPtr->ShowCursor)(pScrn);
1817 pSiS->HWCursorIsVisible = VisibleBackup;
1820 #ifdef TWDEBUG
1821 } else if(attribute == pSiS->xv_STR) {
1822 unsigned short port;
1823 switch((value & 0xff000000) >> 24) {
1824 case 0x00: port = SISSR; break;
1825 case 0x01: port = SISPART1; break;
1826 case 0x02: port = SISPART2; break;
1827 case 0x03: port = SISPART3; break;
1828 case 0x04: port = SISPART4; break;
1829 case 0x05: port = SISCR; break;
1830 case 0x06: port = SISVID; break;
1831 default: return BadValue;
1833 outSISIDXREG(port,((value & 0x00ff0000) >> 16), ((value & 0x0000ff00) >> 8));
1834 return Success;
1835 #endif
1836 #ifdef SIS_CP
1837 SIS_CP_VIDEO_SETATTRIBUTE
1838 #endif
1839 } else if(pSiS->VGAEngine == SIS_315_VGA) {
1840 if(attribute == pSiS->xvSwitchCRT) {
1841 if(pPriv->AllowSwitchCRT) {
1842 if((value < 0) || (value > 1))
1843 return BadValue;
1844 pPriv->crtnum = value;
1845 #ifdef SISDUALHEAD
1846 if(pPriv->dualHeadMode) pSiSEnt->curxvcrtnum = value;
1847 #endif
1849 } else if(attribute == pSiS->xvHue) {
1850 if((value < -8) || (value > 7))
1851 return BadValue;
1852 pPriv->hue = value;
1853 } else if(attribute == pSiS->xvSaturation) {
1854 if((value < -7) || (value > 7))
1855 return BadValue;
1856 pPriv->saturation = value;
1857 } else if(attribute == pSiS->xvGammaRed) {
1858 if((value < 100) || (value > 10000))
1859 return BadValue;
1860 pSiS->XvGammaRed = value;
1861 SiSUpdateXvGamma(pSiS, pPriv);
1862 } else if(attribute == pSiS->xvGammaGreen) {
1863 if((value < 100) || (value > 10000))
1864 return BadValue;
1865 pSiS->XvGammaGreen = value;
1866 SiSUpdateXvGamma(pSiS, pPriv);
1867 } else if(attribute == pSiS->xvGammaBlue) {
1868 if((value < 100) || (value > 10000))
1869 return BadValue;
1870 pSiS->XvGammaBlue = value;
1871 SiSUpdateXvGamma(pSiS, pPriv);
1872 } else return BadMatch;
1873 } else return BadMatch;
1874 return Success;
1877 static int
1878 SISGetPortAttribute(
1879 ScrnInfoPtr pScrn,
1880 Atom attribute,
1881 INT32 *value,
1882 pointer data
1884 SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
1885 SISPtr pSiS = SISPTR(pScrn);
1886 #ifdef SISDUALHEAD
1887 SISEntPtr pSiSEnt = pSiS->entityPrivate;;
1888 #endif
1890 if(attribute == pSiS->xvBrightness) {
1891 *value = pPriv->brightness;
1892 } else if(attribute == pSiS->xvContrast) {
1893 *value = pPriv->contrast;
1894 } else if(attribute == pSiS->xvColorKey) {
1895 *value = pPriv->colorKey;
1896 } else if(attribute == pSiS->xvAutopaintColorKey) {
1897 *value = (pPriv->autopaintColorKey) ? 1 : 0;
1898 } else if(attribute == pSiS->xvDisableGfx) {
1899 *value = (pPriv->disablegfx) ? 1 : 0;
1900 } else if(attribute == pSiS->xvDisableGfxLR) {
1901 *value = (pPriv->disablegfxlr) ? 1 : 0;
1902 } else if(attribute == pSiS->xvTVXPosition) {
1903 *value = SiS_GetTVxposoffset(pScrn);
1904 } else if(attribute == pSiS->xvTVYPosition) {
1905 *value = SiS_GetTVyposoffset(pScrn);
1906 } else if(attribute == pSiS->xvDisableColorkey) {
1907 *value = (pSiS->disablecolorkeycurrent) ? 1 : 0;
1908 } else if(attribute == pSiS->xvUseChromakey) {
1909 *value = (pPriv->usechromakey) ? 1 : 0;
1910 } else if(attribute == pSiS->xvInsideChromakey) {
1911 *value = (pPriv->insidechromakey) ? 1 : 0;
1912 } else if(attribute == pSiS->xvYUVChromakey) {
1913 *value = (pPriv->yuvchromakey) ? 1 : 0;
1914 } else if(attribute == pSiS->xvChromaMin) {
1915 *value = pPriv->chromamin;
1916 } else if(attribute == pSiS->xvChromaMax) {
1917 *value = pPriv->chromamax;
1918 } else if(attribute == pSiS->xv_QVF) {
1919 *value = pSiS->VBFlags;
1920 } else if(attribute == pSiS->xv_GDV) {
1921 *value = SISDRIVERIVERSION;
1922 } else if(attribute == pSiS->xv_GHI) {
1923 *value = (pSiS->ChipFlags & 0xffff) | (pSiS->sishw_ext.jChipType << 16) | (pSiS->ChipRev << 24);
1924 } else if(attribute == pSiS->xv_GBI) {
1925 *value = (pSiS->PciInfo->bus << 16) | (pSiS->PciInfo->device << 8) | pSiS->PciInfo->func;
1926 } else if(attribute == pSiS->xv_QVV) {
1927 *value = SIS_VBFlagsVersion;
1928 } else if(attribute == pSiS->xv_QDD) {
1929 *value = pSiS->detectedCRT2Devices;
1930 } else if(attribute == pSiS->xv_CT1) {
1931 *value = pSiS->CRT1isoff ? 0 : 1;
1932 } else if(attribute == pSiS->xv_GSF) {
1933 *value = pSiS->SiS_SD_Flags;
1934 } else if(attribute == pSiS->xv_USD) {
1935 *value = pSiS->xv_sisdirectunlocked;
1936 } else if(attribute == pSiS->xv_TAF) {
1937 *value = SiS_GetSISTVantiflicker(pScrn);
1938 } else if(attribute == pSiS->xv_TSA) {
1939 *value = SiS_GetSISTVsaturation(pScrn);
1940 } else if(attribute == pSiS->xv_TEE) {
1941 *value = SiS_GetSISTVedgeenhance(pScrn);
1942 } else if(attribute == pSiS->xv_CFI) {
1943 *value = SiS_GetSISTVcfilter(pScrn);
1944 } else if(attribute == pSiS->xv_YFI) {
1945 *value = SiS_GetSISTVyfilter(pScrn);
1946 } else if(attribute == pSiS->xv_COC) {
1947 *value = SiS_GetSISTVcolcalib(pScrn, TRUE);
1948 } else if(attribute == pSiS->xv_COF) {
1949 *value = SiS_GetSISTVcolcalib(pScrn, FALSE);
1950 } else if(attribute == pSiS->xv_TCO) {
1951 *value = SiS_GetCHTVcontrast(pScrn);
1952 } else if(attribute == pSiS->xv_TTE) {
1953 *value = SiS_GetCHTVtextenhance(pScrn);
1954 } else if(attribute == pSiS->xv_TCF) {
1955 *value = SiS_GetCHTVchromaflickerfilter(pScrn);
1956 } else if(attribute == pSiS->xv_TLF) {
1957 *value = SiS_GetCHTVlumaflickerfilter(pScrn);
1958 } else if(attribute == pSiS->xv_TCC) {
1959 *value = SiS_GetCHTVcvbscolor(pScrn);
1960 } else if(attribute == pSiS->xv_CMDR) {
1961 *value = pSiS->xv_sd_result;
1962 } else if(attribute == pSiS->xv_OVR) {
1963 *value = 0;
1964 if(pSiS->OptTVSOver == 1) *value = 3;
1965 else if(pSiS->UseCHOverScan == 1) *value = 2;
1966 else if(pSiS->UseCHOverScan == 0) *value = 1;
1967 } else if(attribute == pSiS->xv_SGA) {
1968 *value = 0;
1969 #ifdef SISDUALHEAD
1970 if(pPriv->dualHeadMode) {
1971 if(pSiSEnt->CRT1gamma) *value |= 0x01;
1972 if(pSiSEnt->CRT2gamma) *value |= 0x02;
1973 } else {
1974 #endif
1975 if(pSiS->CRT1gamma) *value |= 0x01;
1976 if(pSiS->CRT2gamma) *value |= 0x02;
1977 #ifdef SISDUALHEAD
1979 if(pSiS->XvGamma) *value |= 0x04;
1980 #endif
1981 } else if(attribute == pSiS->xv_TXS) {
1982 *value = SiS_GetTVxscale(pScrn);
1983 } else if(attribute == pSiS->xv_TYS) {
1984 *value = SiS_GetTVyscale(pScrn);
1985 } else if(attribute == pSiS->xv_GSS) {
1986 *value = (pScrn->virtualX << 16) | pScrn->virtualY;
1987 } else if(attribute == pSiS->xv_BRR) {
1988 *value = pSiS->GammaBriR;
1989 } else if(attribute == pSiS->xv_BRG) {
1990 *value = pSiS->GammaBriG;
1991 } else if(attribute == pSiS->xv_BRB) {
1992 *value = pSiS->GammaBriB;
1993 } else if(attribute == pSiS->xv_PBR) {
1994 *value = pSiS->GammaPBriR;
1995 } else if(attribute == pSiS->xv_PBG) {
1996 *value = pSiS->GammaPBriG;
1997 } else if(attribute == pSiS->xv_PBB) {
1998 *value = pSiS->GammaPBriB;
1999 } else if(attribute == pSiS->xv_BRR2) {
2000 #ifdef SISDUALHEAD
2001 if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriR;
2002 else
2003 #endif
2004 *value = pSiS->GammaBriR;
2005 } else if(attribute == pSiS->xv_BRG2) {
2006 #ifdef SISDUALHEAD
2007 if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriG;
2008 else
2009 #endif
2010 *value = pSiS->GammaBriG;
2011 } else if(attribute == pSiS->xv_BRB2) {
2012 #ifdef SISDUALHEAD
2013 if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriB;
2014 else
2015 #endif
2016 *value = pSiS->GammaBriB;
2017 } else if(attribute == pSiS->xv_PBR2) {
2018 #ifdef SISDUALHEAD
2019 if(pPriv->dualHeadMode) *value = pSiSEnt->GammaPBriR;
2020 else
2021 #endif
2022 *value = pSiS->GammaPBriR;
2023 } else if(attribute == pSiS->xv_PBG2) {
2024 #ifdef SISDUALHEAD
2025 if(pPriv->dualHeadMode) *value = pSiSEnt->GammaPBriG;
2026 else
2027 #endif
2028 *value = pSiS->GammaPBriG;
2029 } else if(attribute == pSiS->xv_PBB2) {
2030 #ifdef SISDUALHEAD
2031 if(pPriv->dualHeadMode) *value = pSiSEnt->GammaPBriB;
2032 else
2033 #endif
2034 *value = pSiS->GammaPBriB;
2035 } else if(attribute == pSiS->xv_SHC) {
2036 *value = pSiS->HideHWCursor ? 1 : 0;
2037 #ifdef SIS_CP
2038 SIS_CP_VIDEO_GETATTRIBUTE
2039 #endif
2040 } else if(pSiS->VGAEngine == SIS_315_VGA) {
2041 if(attribute == pSiS->xvSwitchCRT) {
2042 #ifdef SISDUALHEAD
2043 if(pPriv->dualHeadMode)
2044 *value = pSiSEnt->curxvcrtnum;
2045 else
2046 #endif
2047 *value = pPriv->crtnum;
2048 } else if(attribute == pSiS->xvHue) {
2049 *value = pPriv->hue;
2050 } else if(attribute == pSiS->xvSaturation) {
2051 *value = pPriv->saturation;
2052 } else if(attribute == pSiS->xvGammaRed) {
2053 *value = pSiS->XvGammaRed;
2054 } else if(attribute == pSiS->xvGammaGreen) {
2055 *value = pSiS->XvGammaGreen;
2056 } else if(attribute == pSiS->xvGammaBlue) {
2057 *value = pSiS->XvGammaBlue;
2058 } else return BadMatch;
2059 } else return BadMatch;
2060 return Success;
2063 #if 0 /* For future use */
2064 static int
2065 SiSHandleSiSDirectCommand(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv, sisdirectcommand *sdcbuf)
2067 SISPtr pSiS = SISPTR(pScrn);
2068 int i;
2069 unsigned long j;
2071 if(sdcbuf->sdc_id != SDC_ID) return BadMatch;
2073 j = sdcbuf->sdc_header;
2074 j += sdcbuf->sdc_command;
2075 for(i = 0; i < SDC_NUM_PARM; i++) {
2076 j += sdcbuf->sdc_parm[i];
2078 if(j != sdcbuf->sdc_chksum) {
2079 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "SiS Direct: Bad packet checksum\n");
2080 return BadMatch;
2082 sdcbuf->sdc_header = SDC_RESULT_OK;
2083 switch(sdcbuf->sdc_command) {
2084 case SDC_CMD_GETVERSION:
2085 sdcbuf->sdc_parm[0] = SDC_VERSION;
2086 break;
2087 case SDC_CMD_CHECKMODEFORCRT2:
2088 j = sdcbuf->sdc_parm[0];
2089 sdcbuf->sdc_parm[0] = SISCheckModeIndexForCRT2Type(pScrn,
2090 (unsigned short)(j & 0xff),
2091 (unsigned short)((j >> 8) & 0xff),
2092 FALSE) & 0xff;
2093 break;
2094 default:
2095 sdcbuf->sdc_header = SDC_RESULT_UNDEFCMD;
2098 return Success;
2100 #endif
2102 static void
2103 SISQueryBestSize(
2104 ScrnInfoPtr pScrn,
2105 Bool motion,
2106 short vid_w, short vid_h,
2107 short drw_w, short drw_h,
2108 unsigned int *p_w, unsigned int *p_h,
2109 pointer data
2111 *p_w = drw_w;
2112 *p_h = drw_h;
2115 static void
2116 calc_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn,
2117 SISPortPrivPtr pPriv, int index, int iscrt2)
2119 SISPtr pSiS = SISPTR(pScrn);
2120 CARD32 I=0,mult=0;
2121 int flag=0;
2123 int dstW = pOverlay->dstBox.x2 - pOverlay->dstBox.x1;
2124 int dstH = pOverlay->dstBox.y2 - pOverlay->dstBox.y1;
2125 int srcW = pOverlay->srcW;
2126 int srcH = pOverlay->srcH;
2127 CARD16 LCDheight = pSiS->LCDheight;
2128 int srcPitch = pOverlay->origPitch;
2129 int origdstH = dstH;
2130 int modeflags = pOverlay->currentmode->Flags;
2132 /* Stretch image due to panel link scaling */
2133 if(pSiS->VBFlags & (CRT2_LCD | CRT1_LCDA)) {
2134 if(pPriv->bridgeIsSlave) {
2135 if(pSiS->VBFlags & (VB_LVDS | VB_30xBDH)) {
2136 if(pSiS->MiscFlags & MISC_PANELLINKSCALER) {
2137 dstH = (dstH * LCDheight) / pOverlay->SCREENheight;
2140 } else if((iscrt2 && (pSiS->VBFlags & CRT2_LCD)) ||
2141 (!iscrt2 && (pSiS->VBFlags & CRT1_LCDA))) {
2142 if(pSiS->VBFlags & (VB_LVDS | VB_30xBDH | CRT1_LCDA)) {
2143 if(pSiS->MiscFlags & MISC_PANELLINKSCALER) {
2144 dstH = (dstH * LCDheight) / pOverlay->SCREENheight;
2145 if(pPriv->displayMode == DISPMODE_MIRROR) flag = 1;
2151 /* For double scan modes, we need to double the height
2152 * On 315 and 550 (?), we need to double the width as well.
2153 * Interlace mode vice versa.
2155 if(modeflags & V_DBLSCAN) {
2156 dstH = origdstH << 1;
2157 flag = 0;
2158 if((pSiS->sishw_ext.jChipType >= SIS_315H) &&
2159 (pSiS->sishw_ext.jChipType <= SIS_550)) {
2160 dstW <<= 1;
2163 if(modeflags & V_INTERLACE) {
2164 dstH = origdstH >> 1;
2165 flag = 0;
2168 #if 0
2169 /* TEST @@@ */
2170 if(pOverlay->bobEnable & 0x08) dstH <<= 1;
2171 #endif
2173 if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH;
2174 if(dstW == srcW) {
2175 pOverlay->HUSF = 0x00;
2176 pOverlay->IntBit = 0x05;
2177 pOverlay->wHPre = 0;
2178 } else if(dstW > srcW) {
2179 dstW += 2;
2180 pOverlay->HUSF = (srcW << 16) / dstW;
2181 pOverlay->IntBit = 0x04;
2182 pOverlay->wHPre = 0;
2183 } else {
2184 int tmpW = dstW;
2186 /* It seems, the hardware can't scale below factor .125 (=1/8) if the
2187 pitch isn't a multiple of 256.
2188 TODO: Test this on the 315 series!
2190 if((srcPitch % 256) || (srcPitch < 256)) {
2191 if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1;
2194 I = 0;
2195 pOverlay->IntBit = 0x01;
2196 while(srcW >= tmpW) {
2197 tmpW <<= 1;
2198 I++;
2200 pOverlay->wHPre = (CARD8)(I - 1);
2201 dstW <<= (I - 1);
2202 if((srcW % dstW))
2203 pOverlay->HUSF = ((srcW - dstW) << 16) / dstW;
2204 else
2205 pOverlay->HUSF = 0x00;
2208 if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT;
2209 if(dstH == srcH) {
2210 pOverlay->VUSF = 0x00;
2211 pOverlay->IntBit |= 0x0A;
2212 } else if(dstH > srcH) {
2213 dstH += 0x02;
2214 pOverlay->VUSF = (srcH << 16) / dstH;
2215 pOverlay->IntBit |= 0x08;
2216 } else {
2218 I = srcH / dstH;
2219 pOverlay->IntBit |= 0x02;
2221 if(I < 2) {
2222 pOverlay->VUSF = ((srcH - dstH) << 16) / dstH;
2223 /* TW: Needed for LCD-scaling modes */
2224 if((flag) && (mult = (srcH / origdstH)) >= 2) {
2225 pOverlay->pitch /= mult;
2227 } else {
2228 #if 0
2229 if(((pOverlay->bobEnable & 0x08) == 0x00) &&
2230 (((srcPitch * I)>>2) > 0xFFF)){
2231 pOverlay->bobEnable |= 0x08;
2232 srcPitch >>= 1;
2234 #endif
2235 if(((srcPitch * I)>>2) > 0xFFF) {
2236 I = (0xFFF*2/srcPitch);
2237 pOverlay->VUSF = 0xFFFF;
2238 } else {
2239 dstH = I * dstH;
2240 if(srcH % dstH)
2241 pOverlay->VUSF = ((srcH - dstH) << 16) / dstH;
2242 else
2243 pOverlay->VUSF = 0x00;
2245 /* set video frame buffer offset */
2246 pOverlay->pitch = (CARD16)(srcPitch*I);
2251 #ifdef SISMERGED
2252 static void
2253 calc_scale_factor_2(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn,
2254 SISPortPrivPtr pPriv, int index, int iscrt2)
2256 SISPtr pSiS = SISPTR(pScrn);
2257 CARD32 I=0,mult=0;
2258 int flag=0;
2260 int dstW = pOverlay->dstBox2.x2 - pOverlay->dstBox2.x1;
2261 int dstH = pOverlay->dstBox2.y2 - pOverlay->dstBox2.y1;
2262 int srcW = pOverlay->srcW2;
2263 int srcH = pOverlay->srcH2;
2264 CARD16 LCDheight = pSiS->LCDheight;
2265 int srcPitch = pOverlay->origPitch;
2266 int origdstH = dstH;
2267 int modeflags = pOverlay->currentmode2->Flags;
2269 /* Stretch image due to panel link scaling */
2270 if(pSiS->VBFlags & CRT2_LCD) {
2271 if(pSiS->VBFlags & (VB_LVDS | VB_30xBDH)) {
2272 if(pSiS->MiscFlags & MISC_PANELLINKSCALER) {
2273 dstH = (dstH * LCDheight) / pOverlay->SCREENheight2;
2274 flag = 1;
2278 /* For double scan modes, we need to double the height
2279 * On 315 and 550 (?), we need to double the width as well.
2280 * Interlace mode vice versa.
2282 if(modeflags & V_DBLSCAN) {
2283 dstH = origdstH << 1;
2284 flag = 0;
2285 if((pSiS->sishw_ext.jChipType >= SIS_315H) &&
2286 (pSiS->sishw_ext.jChipType <= SIS_550)) {
2287 dstW <<= 1;
2290 if(modeflags & V_INTERLACE) {
2291 dstH = origdstH >> 1;
2292 flag = 0;
2295 #if 0
2296 /* TEST @@@ */
2297 if(pOverlay->bobEnable & 0x08) dstH <<= 1;
2298 #endif
2300 if(dstW < OVERLAY_MIN_WIDTH) dstW = OVERLAY_MIN_WIDTH;
2301 if(dstW == srcW) {
2302 pOverlay->HUSF2 = 0x00;
2303 pOverlay->IntBit2 = 0x05;
2304 pOverlay->wHPre2 = 0;
2305 } else if(dstW > srcW) {
2306 dstW += 2;
2307 pOverlay->HUSF2 = (srcW << 16) / dstW;
2308 pOverlay->IntBit2 = 0x04;
2309 pOverlay->wHPre2 = 0;
2310 } else {
2311 int tmpW = dstW;
2313 /* It seems, the hardware can't scale below factor .125 (=1/8) if the
2314 pitch isn't a multiple of 256.
2315 TODO: Test this on the 315 series!
2317 if((srcPitch % 256) || (srcPitch < 256)) {
2318 if(((dstW * 1000) / srcW) < 125) dstW = tmpW = ((srcW * 125) / 1000) + 1;
2321 I = 0;
2322 pOverlay->IntBit2 = 0x01;
2323 while(srcW >= tmpW) {
2324 tmpW <<= 1;
2325 I++;
2327 pOverlay->wHPre2 = (CARD8)(I - 1);
2328 dstW <<= (I - 1);
2329 if((srcW % dstW))
2330 pOverlay->HUSF2 = ((srcW - dstW) << 16) / dstW;
2331 else
2332 pOverlay->HUSF2 = 0x00;
2335 if(dstH < OVERLAY_MIN_HEIGHT) dstH = OVERLAY_MIN_HEIGHT;
2336 if(dstH == srcH) {
2337 pOverlay->VUSF2 = 0x00;
2338 pOverlay->IntBit2 |= 0x0A;
2339 } else if(dstH > srcH) {
2340 dstH += 0x02;
2341 pOverlay->VUSF2 = (srcH << 16) / dstH;
2342 pOverlay->IntBit2 |= 0x08;
2343 } else {
2345 I = srcH / dstH;
2346 pOverlay->IntBit2 |= 0x02;
2348 if(I < 2) {
2349 pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH;
2350 /* Needed for LCD-scaling modes */
2351 if(flag && ((mult = (srcH / origdstH)) >= 2)) {
2352 pOverlay->pitch2 /= mult;
2354 } else {
2355 #if 0
2356 if(((pOverlay->bobEnable & 0x08) == 0x00) &&
2357 (((srcPitch * I)>>2) > 0xFFF)){
2358 pOverlay->bobEnable |= 0x08;
2359 srcPitch >>= 1;
2361 #endif
2362 if(((srcPitch * I)>>2) > 0xFFF) {
2363 I = (0xFFF*2/srcPitch);
2364 pOverlay->VUSF2 = 0xFFFF;
2365 } else {
2366 dstH = I * dstH;
2367 if(srcH % dstH)
2368 pOverlay->VUSF2 = ((srcH - dstH) << 16) / dstH;
2369 else
2370 pOverlay->VUSF2 = 0x00;
2372 /* set video frame buffer offset */
2373 pOverlay->pitch2 = (CARD16)(srcPitch*I);
2377 #endif
2379 static CARD8
2380 calc_line_buf_size(CARD32 srcW, CARD8 wHPre, CARD32 pixelFormat)
2382 CARD8 preHIDF;
2383 CARD32 I;
2384 CARD32 line = srcW;
2386 if( (pixelFormat == PIXEL_FMT_YV12) ||
2387 (pixelFormat == PIXEL_FMT_I420) ||
2388 (pixelFormat == PIXEL_FMT_NV12) ||
2389 (pixelFormat == PIXEL_FMT_NV21) )
2391 preHIDF = wHPre & 0x07;
2392 switch (preHIDF)
2394 case 3 :
2395 if((line & 0xffffff00) == line)
2396 I = (line >> 8);
2397 else
2398 I = (line >> 8) + 1;
2399 return((CARD8)(I * 32 - 1));
2400 case 4 :
2401 if((line & 0xfffffe00) == line)
2402 I = (line >> 9);
2403 else
2404 I = (line >> 9) + 1;
2405 return((CARD8)(I * 64 - 1));
2406 case 5 :
2407 if((line & 0xfffffc00) == line)
2408 I = (line >> 10);
2409 else
2410 I = (line >> 10) + 1;
2411 return((CARD8)(I * 128 - 1));
2412 case 6 :
2413 return((CARD8)(255));
2414 default :
2415 if((line & 0xffffff80) == line)
2416 I = (line >> 7);
2417 else
2418 I = (line >> 7) + 1;
2419 return((CARD8)(I * 16 - 1));
2421 } else { /* YUV2, UYVY */
2422 if((line & 0xffffff8) == line)
2423 I = (line >> 3);
2424 else
2425 I = (line >> 3) + 1;
2426 return((CARD8)(I - 1));
2430 static __inline void
2431 set_line_buf_size_1(SISOverlayPtr pOverlay)
2433 pOverlay->lineBufSize = calc_line_buf_size(pOverlay->srcW,pOverlay->wHPre, pOverlay->pixelFormat);
2436 #ifdef SISMERGED
2437 static __inline void
2438 set_line_buf_size_2(SISOverlayPtr pOverlay)
2440 pOverlay->lineBufSize2 = calc_line_buf_size(pOverlay->srcW2,pOverlay->wHPre2, pOverlay->pixelFormat);
2443 static void
2444 merge_line_buf_mfb(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable1, Bool enable2,
2445 short width1, short width2, short limit)
2447 unsigned char misc1, misc2, mask = pPriv->linebufmask;
2449 if(pPriv->hasTwoOverlays) { /* This means we are in MIRROR mode */
2451 misc2 = 0x00;
2452 if(enable1) misc1 = 0x04;
2453 else misc1 = 0x00;
2454 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
2455 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
2457 misc2 = 0x01;
2458 if(enable2) misc1 = 0x04;
2459 else misc1 = 0x00;
2460 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
2461 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
2463 } else { /* This means we are either in SINGLE1 or SINGLE2 mode */
2465 misc2 = 0x00;
2466 if(enable1 || enable2) misc1 = 0x04;
2467 else misc1 = 0x00;
2469 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
2470 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
2474 #endif
2476 /* About linebuffer merging:
2478 * For example the 651:
2479 * Each overlay has 4 line buffers, 384 bytes each (<-- Is that really correct? 1920 / 384 = 5 !!!)
2480 * If the source width is greater than 384, line buffers must be merged.
2481 * Dual merge: Only O1 usable (uses overlay 2's linebuffer), maximum width 384*2
2482 * Individual merge: Both overlays available, maximum width 384*2
2483 * All merge: Only overlay 1 available, maximum width = 384*4 (<--- should be 1920, is 1536...)
2486 * Normally: Dual merge: Individual merge
2487 * Overlay 1 Overlay 2 Overlay 1 only! Both overlays
2488 * ___1___ ___5___ ___1___ ___2___ -\ O1 ___1___ ___2___
2489 * ___2___ ___6___ ___3___ ___4___ \_ O 1 O1 ___3___ ___4___
2490 * ___3___ ___7___ ___5___ ___6___ / O2 ___5___ ___6___
2491 * ___4___ ___8___ ___7___ ___8___ -/ O2 ___7___ ___8___
2494 * All merge: ___1___ ___2___ ___3___ ___4___
2495 * (Overlay 1 only!) ___5___ ___6___ ___7___ ___8___
2497 * Individual merge is supported on all chipsets.
2498 * Dual merge is only supported on the 300 series and M650/651 and later.
2499 * All merge is only supported on the M650/651 and later.
2504 static void
2505 merge_line_buf(SISPtr pSiS, SISPortPrivPtr pPriv, Bool enable, short width, short limit)
2507 unsigned char misc1, misc2, mask = pPriv->linebufmask;
2509 if(enable) { /* ----- enable linebuffer merge */
2511 switch(pPriv->displayMode){
2512 case DISPMODE_SINGLE1:
2513 if(pSiS->VGAEngine == SIS_300_VGA) {
2514 if(pPriv->dualHeadMode) {
2515 misc2 = 0x00;
2516 misc1 = 0x04;
2517 } else {
2518 misc2 = 0x10;
2519 misc1 = 0x00;
2521 } else {
2522 if(pPriv->hasTwoOverlays) {
2523 if(pPriv->dualHeadMode) {
2524 misc2 = 0x00;
2525 misc1 = 0x04;
2526 } else {
2527 if(width > (limit * 2)) {
2528 misc2 = 0x20;
2529 } else {
2530 misc2 = 0x10;
2532 misc1 = 0x00;
2534 } else {
2535 misc2 = 0x00;
2536 misc1 = 0x04;
2539 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
2540 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
2541 break;
2543 case DISPMODE_SINGLE2:
2544 if(pSiS->VGAEngine == SIS_300_VGA) {
2545 if(pPriv->dualHeadMode) {
2546 misc2 = 0x01;
2547 misc1 = 0x04;
2548 } else {
2549 misc2 = 0x10;
2550 misc1 = 0x00;
2552 } else {
2553 if(pPriv->hasTwoOverlays) {
2554 if(pPriv->dualHeadMode) {
2555 misc2 = 0x01;
2556 misc1 = 0x04;
2557 } else {
2558 if(width > (limit * 2)) {
2559 misc2 = 0x20;
2560 } else {
2561 misc2 = 0x10;
2563 misc1 = 0x00;
2565 } else {
2566 misc2 = 0x00;
2567 misc1 = 0x04;
2570 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
2571 setvideoregmask(pSiS, Index_VI_Control_Misc1, misc1, 0x04);
2572 break;
2574 case DISPMODE_MIRROR: /* This can only be on chips with 2 overlays */
2575 default:
2576 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask);
2577 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04);
2578 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask);
2579 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x04, 0x04);
2580 break;
2583 } else { /* ----- disable linebuffer merge */
2585 switch(pPriv->displayMode) {
2587 case DISPMODE_SINGLE1:
2588 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask);
2589 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
2590 break;
2592 case DISPMODE_SINGLE2:
2593 if(pSiS->VGAEngine == SIS_300_VGA) {
2594 if(pPriv->dualHeadMode) misc2 = 0x01;
2595 else misc2 = 0x00;
2596 } else {
2597 if(pPriv->hasTwoOverlays) {
2598 if(pPriv->dualHeadMode) misc2 = 0x01;
2599 else misc2 = 0x00;
2600 } else {
2601 misc2 = 0x00;
2604 setvideoregmask(pSiS, Index_VI_Control_Misc2, misc2, mask);
2605 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
2606 break;
2608 case DISPMODE_MIRROR: /* This can only be on chips with 2 overlays */
2609 default:
2610 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, mask);
2611 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
2612 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, mask);
2613 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x04);
2614 break;
2619 static __inline void
2620 set_format(SISPtr pSiS, SISOverlayPtr pOverlay)
2622 CARD8 fmt;
2624 switch (pOverlay->pixelFormat){
2625 case PIXEL_FMT_YV12:
2626 case PIXEL_FMT_I420:
2627 fmt = 0x0c;
2628 break;
2629 case PIXEL_FMT_YUY2:
2630 fmt = 0x28;
2631 break;
2632 case PIXEL_FMT_UYVY:
2633 fmt = 0x08;
2634 break;
2635 case PIXEL_FMT_YVYU:
2636 fmt = 0x38;
2637 break;
2638 case PIXEL_FMT_NV12:
2639 fmt = 0x4c;
2640 break;
2641 case PIXEL_FMT_NV21:
2642 fmt = 0x5c;
2643 break;
2644 case PIXEL_FMT_RGB5: /* D[5:4] : 00 RGB555, 01 RGB 565 */
2645 fmt = 0x00;
2646 break;
2647 case PIXEL_FMT_RGB6:
2648 fmt = 0x10;
2649 break;
2650 default:
2651 fmt = 0x00;
2652 break;
2654 setvideoregmask(pSiS, Index_VI_Control_Misc0, fmt, 0xfc);
2657 static __inline void
2658 set_colorkey(SISPtr pSiS, CARD32 colorkey)
2660 CARD8 r, g, b;
2662 b = (CARD8)(colorkey & 0xFF);
2663 g = (CARD8)((colorkey>>8) & 0xFF);
2664 r = (CARD8)((colorkey>>16) & 0xFF);
2666 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Min ,(CARD8)b);
2667 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Min ,(CARD8)g);
2668 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Min ,(CARD8)r);
2670 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Blue_Max ,(CARD8)b);
2671 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Green_Max ,(CARD8)g);
2672 setvideoreg(pSiS, Index_VI_Overlay_ColorKey_Red_Max ,(CARD8)r);
2675 static __inline void
2676 set_chromakey(SISPtr pSiS, CARD32 chromamin, CARD32 chromamax)
2678 CARD8 r1, g1, b1;
2679 CARD8 r2, g2, b2;
2681 b1 = (CARD8)(chromamin & 0xFF);
2682 g1 = (CARD8)((chromamin>>8) & 0xFF);
2683 r1 = (CARD8)((chromamin>>16) & 0xFF);
2684 b2 = (CARD8)(chromamax & 0xFF);
2685 g2 = (CARD8)((chromamax>>8) & 0xFF);
2686 r2 = (CARD8)((chromamax>>16) & 0xFF);
2688 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Min ,(CARD8)b1);
2689 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Min ,(CARD8)g1);
2690 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Min ,(CARD8)r1);
2692 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Blue_V_Max ,(CARD8)b2);
2693 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Green_U_Max ,(CARD8)g2);
2694 setvideoreg(pSiS, Index_VI_Overlay_ChromaKey_Red_Y_Max ,(CARD8)r2);
2697 static __inline void
2698 set_brightness(SISPtr pSiS, CARD8 brightness)
2700 setvideoreg(pSiS, Index_VI_Brightness, brightness);
2703 static __inline void
2704 set_contrast(SISPtr pSiS, CARD8 contrast)
2706 setvideoregmask(pSiS, Index_VI_Contrast_Enh_Ctrl, contrast, 0x07);
2709 /* 315 series and later only */
2710 static __inline void
2711 set_saturation(SISPtr pSiS, short saturation)
2713 CARD8 temp = 0;
2715 if(saturation < 0) {
2716 temp |= 0x88;
2717 saturation = -saturation;
2719 temp |= (saturation & 0x07);
2720 temp |= ((saturation & 0x07) << 4);
2722 setvideoreg(pSiS, Index_VI_Saturation, temp);
2725 /* 315 series and later only */
2726 static __inline void
2727 set_hue(SISPtr pSiS, CARD8 hue)
2729 setvideoregmask(pSiS, Index_VI_Hue, (hue & 0x08) ? (hue ^ 0x07) : hue, 0x0F);
2732 static __inline void
2733 set_disablegfx(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay)
2735 /* This is not supported on M65x, 65x (x>0) or later */
2736 /* For CRT1 ONLY!!! */
2737 if((!(pSiS->ChipFlags & SiSCF_Is65x)) && (pSiS->Chipset != PCI_CHIP_SIS660)) {
2738 setvideoregmask(pSiS, Index_VI_Control_Misc2, mybool ? 0x04 : 0x00, 0x04);
2739 if(mybool) pOverlay->keyOP = VI_ROP_Always;
2743 static __inline void
2744 set_disablegfxlr(SISPtr pSiS, Bool mybool, SISOverlayPtr pOverlay)
2746 setvideoregmask(pSiS, Index_VI_Control_Misc1, mybool ? 0x01 : 0x00, 0x01);
2747 if(mybool) pOverlay->keyOP = VI_ROP_Always;
2750 #ifdef SIS_CP
2751 SIS_CP_VIDEO_SUBS
2752 #endif
2754 static void
2755 set_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index, int iscrt2)
2757 ScrnInfoPtr pScrn = pSiS->pScrn;
2759 CARD16 pitch=0;
2760 CARD8 h_over=0, v_over=0;
2761 CARD16 top, bottom, left, right;
2762 CARD16 screenX, screenY;
2763 int modeflags, watchdog;
2764 CARD8 data;
2765 CARD32 PSY;
2767 #ifdef SISMERGED
2768 if(pSiS->MergedFB && iscrt2) {
2769 screenX = pOverlay->currentmode2->HDisplay;
2770 screenY = pOverlay->currentmode2->VDisplay;
2771 modeflags = pOverlay->currentmode2->Flags;
2772 top = pOverlay->dstBox2.y1;
2773 bottom = pOverlay->dstBox2.y2;
2774 left = pOverlay->dstBox2.x1;
2775 right = pOverlay->dstBox2.x2;
2776 pitch = pOverlay->pitch2 >> pPriv->shiftValue;
2777 } else {
2778 #endif
2779 screenX = pOverlay->currentmode->HDisplay;
2780 screenY = pOverlay->currentmode->VDisplay;
2781 modeflags = pOverlay->currentmode->Flags;
2782 top = pOverlay->dstBox.y1;
2783 bottom = pOverlay->dstBox.y2;
2784 left = pOverlay->dstBox.x1;
2785 right = pOverlay->dstBox.x2;
2786 pitch = pOverlay->pitch >> pPriv->shiftValue;
2787 #ifdef SISMERGED
2789 #endif
2791 if(bottom > screenY) {
2792 bottom = screenY;
2794 if(right > screenX) {
2795 right = screenX;
2798 /* DoubleScan modes require Y coordinates * 2 */
2799 if(modeflags & V_DBLSCAN) {
2800 top <<= 1;
2801 bottom <<= 1;
2803 /* Interlace modes require Y coordinates / 2 */
2804 if(modeflags & V_INTERLACE) {
2805 top >>= 1;
2806 bottom >>= 1;
2809 h_over = (((left>>8) & 0x0f) | ((right>>4) & 0xf0));
2810 v_over = (((top>>8) & 0x0f) | ((bottom>>4) & 0xf0));
2812 /* set line buffer size */
2813 #ifdef SISMERGED
2814 if(pSiS->MergedFB && iscrt2)
2815 setvideoreg(pSiS, Index_VI_Line_Buffer_Size, pOverlay->lineBufSize2);
2816 else
2817 #endif
2818 setvideoreg(pSiS, Index_VI_Line_Buffer_Size, pOverlay->lineBufSize);
2820 /* set color key mode */
2821 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, pOverlay->keyOP, 0x0f);
2823 /* We don't have to wait for vertical retrace in all cases */
2824 if(pPriv->mustwait) {
2825 if((pSiS->VGAEngine == SIS_315_VGA) && (index)) {
2826 /* overlay 2 needs special treatment */
2827 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
2829 watchdog = WATCHDOG_DELAY;
2830 while(pOverlay->VBlankActiveFunc(pSiS, pPriv) && --watchdog);
2831 watchdog = WATCHDOG_DELAY;
2832 while((!pOverlay->VBlankActiveFunc(pSiS, pPriv)) && --watchdog);
2833 if(!watchdog) xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2834 "Xv: Waiting for vertical retrace timed-out\n");
2837 /* Unlock address registers */
2838 data = getvideoreg(pSiS, Index_VI_Control_Misc1);
2839 setvideoreg(pSiS, Index_VI_Control_Misc1, data | 0x20);
2840 /* Is this required? */
2841 setvideoreg(pSiS, Index_VI_Control_Misc1, data | 0x20);
2843 /* Is this required? (seems so) */
2844 if((pSiS->Chipset == SIS_315_VGA) && !index)
2845 setvideoregmask(pSiS, Index_VI_Control_Misc3, 0x00, (1 << index));
2847 /* Set Y buf pitch */
2848 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_Low, (CARD8)(pitch));
2849 setvideoregmask(pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(pitch >> 8), 0x0f);
2851 /* Set Y start address */
2852 #ifdef SISMERGED
2853 if(pSiS->MergedFB && iscrt2) {
2854 PSY = pOverlay->PSY2;
2855 } else
2856 #endif
2857 PSY = pOverlay->PSY;
2859 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Low, (CARD8)(PSY));
2860 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_Middle, (CARD8)(PSY >> 8));
2861 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Start_High, (CARD8)(PSY >> 16));
2863 /* set 315 series overflow bits for Y plane */
2864 if(pSiS->VGAEngine == SIS_315_VGA) {
2865 setvideoreg(pSiS, Index_VI_Disp_Y_Buf_Pitch_High, (CARD8)(pitch >> 12));
2866 setvideoreg(pSiS, Index_VI_Y_Buf_Start_Over, ((CARD8)(PSY >> 24) & 0x03));
2869 /* Set U/V data if using planar formats */
2870 if( (pOverlay->pixelFormat == PIXEL_FMT_YV12) ||
2871 (pOverlay->pixelFormat == PIXEL_FMT_I420) ||
2872 (pOverlay->pixelFormat == PIXEL_FMT_NV12) ||
2873 (pOverlay->pixelFormat == PIXEL_FMT_NV21) ) {
2875 CARD32 PSU=0, PSV=0, uvpitch = pitch;
2877 PSU = pOverlay->PSU;
2878 PSV = pOverlay->PSV;
2879 #ifdef SISMERGED
2880 if(pSiS->MergedFB && iscrt2) {
2881 PSU = pOverlay->PSU2;
2882 PSV = pOverlay->PSV2;
2884 #endif
2885 if((pOverlay->pixelFormat == PIXEL_FMT_YV12) ||
2886 (pOverlay->pixelFormat == PIXEL_FMT_I420)) {
2887 uvpitch >>= 1;
2890 /* Set U/V pitch */
2891 setvideoreg (pSiS, Index_VI_Disp_UV_Buf_Pitch_Low, (CARD8)uvpitch);
2892 setvideoregmask (pSiS, Index_VI_Disp_Y_UV_Buf_Pitch_Middle, (CARD8)(uvpitch >> 4), 0xf0);
2894 /* set U/V start address */
2895 setvideoreg (pSiS, Index_VI_U_Buf_Start_Low, (CARD8)PSU);
2896 setvideoreg (pSiS, Index_VI_U_Buf_Start_Middle,(CARD8)(PSU >> 8));
2897 setvideoreg (pSiS, Index_VI_U_Buf_Start_High, (CARD8)(PSU >> 16));
2899 setvideoreg (pSiS, Index_VI_V_Buf_Start_Low, (CARD8)PSV);
2900 setvideoreg (pSiS, Index_VI_V_Buf_Start_Middle,(CARD8)(PSV >> 8));
2901 setvideoreg (pSiS, Index_VI_V_Buf_Start_High, (CARD8)(PSV >> 16));
2903 /* 315 series overflow bits */
2904 if(pSiS->VGAEngine == SIS_315_VGA) {
2905 setvideoreg (pSiS, Index_VI_Disp_UV_Buf_Pitch_High, (CARD8)(uvpitch >> 12));
2906 setvideoreg (pSiS, Index_VI_U_Buf_Start_Over, ((CARD8)(PSU >> 24) & 0x03));
2907 if(pSiS->sishw_ext.jChipType == SIS_661) {
2908 setvideoregmask (pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03), 0xc3);
2909 } else {
2910 setvideoreg (pSiS, Index_VI_V_Buf_Start_Over, ((CARD8)(PSV >> 24) & 0x03));
2915 /* set scale factor */
2916 #ifdef SISMERGED
2917 if(pSiS->MergedFB && iscrt2) {
2918 setvideoreg (pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF2));
2919 setvideoreg (pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF2) >> 8));
2920 setvideoreg (pSiS, Index_VI_Ver_Up_Scale_Low, (CARD8)(pOverlay->VUSF2));
2921 setvideoreg (pSiS, Index_VI_Ver_Up_Scale_High, (CARD8)((pOverlay->VUSF2) >> 8));
2923 setvideoregmask (pSiS, Index_VI_Scale_Control, (pOverlay->IntBit2 << 3)
2924 |(pOverlay->wHPre2), 0x7f);
2925 } else {
2926 #endif
2927 setvideoreg (pSiS, Index_VI_Hor_Post_Up_Scale_Low, (CARD8)(pOverlay->HUSF));
2928 setvideoreg (pSiS, Index_VI_Hor_Post_Up_Scale_High,(CARD8)((pOverlay->HUSF) >> 8));
2929 setvideoreg (pSiS, Index_VI_Ver_Up_Scale_Low, (CARD8)(pOverlay->VUSF));
2930 setvideoreg (pSiS, Index_VI_Ver_Up_Scale_High, (CARD8)((pOverlay->VUSF)>>8));
2932 setvideoregmask (pSiS, Index_VI_Scale_Control, (pOverlay->IntBit << 3)
2933 |(pOverlay->wHPre), 0x7f);
2934 #ifdef SISMERGED
2936 #endif
2938 if((pSiS->VGAEngine == SIS_315_VGA) && (index)){
2939 /* Trigger register copy for 315/330 series */
2940 /* setvideoreg(pSiS, Index_VI_Control_Misc3, (1 << index)); */
2941 setvideoregmask(pSiS, Index_VI_Control_Misc3, (1 << index), (1 << index));
2944 /* set destination window position */
2945 setvideoreg(pSiS, Index_VI_Win_Hor_Disp_Start_Low, (CARD8)left);
2946 setvideoreg(pSiS, Index_VI_Win_Hor_Disp_End_Low, (CARD8)right);
2947 setvideoreg(pSiS, Index_VI_Win_Hor_Over, (CARD8)h_over);
2949 setvideoreg(pSiS, Index_VI_Win_Ver_Disp_Start_Low, (CARD8)top);
2950 setvideoreg(pSiS, Index_VI_Win_Ver_Disp_End_Low, (CARD8)bottom);
2951 setvideoreg(pSiS, Index_VI_Win_Ver_Over, (CARD8)v_over);
2953 setvideoregmask(pSiS, Index_VI_Control_Misc1, pOverlay->bobEnable, 0x1a);
2955 /* Lock the address registers */
2956 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x20);
2959 /* Overlay MUST NOT be switched off while beam is over it */
2960 static void
2961 close_overlay(SISPtr pSiS, SISPortPrivPtr pPriv)
2963 CARD32 watchdog;
2965 if(!(pPriv->overlayStatus)) return;
2966 pPriv->overlayStatus = FALSE;
2968 if(pPriv->displayMode & (DISPMODE_MIRROR | DISPMODE_SINGLE2)) {
2970 /* CRT2: MIRROR or SINGLE2
2971 * 1 overlay: Uses overlay 0
2972 * 2 overlays: Uses Overlay 1 if MIRROR or DUAL HEAD
2973 * Uses Overlay 0 if SINGLE2 and not DUAL HEAD
2976 if(pPriv->hasTwoOverlays) {
2978 if((pPriv->dualHeadMode) || (pPriv->displayMode == DISPMODE_MIRROR)) {
2979 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
2980 } else {
2981 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01);
2984 } else if(pPriv->displayMode == DISPMODE_SINGLE2) {
2986 #ifdef SISDUALHEAD
2987 if(pPriv->dualHeadMode) {
2988 /* Check if overlay already grabbed by other head */
2989 if(!(getsrreg(pSiS, 0x06) & 0x40)) return;
2991 #endif
2992 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x01);
2996 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
2997 watchdog = WATCHDOG_DELAY;
2998 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
2999 watchdog = WATCHDOG_DELAY;
3000 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
3001 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
3002 watchdog = WATCHDOG_DELAY;
3003 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
3004 watchdog = WATCHDOG_DELAY;
3005 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
3007 #ifdef SIS_CP
3008 SIS_CP_RESET_CP
3009 #endif
3013 if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) {
3015 /* CRT1: Always uses overlay 0
3018 #ifdef SISDUALHEAD
3019 if(pPriv->dualHeadMode) {
3020 if(!pPriv->hasTwoOverlays) {
3021 /* Check if overlay already grabbed by other head */
3022 if(getsrreg(pSiS, 0x06) & 0x40) return;
3025 #endif
3026 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05);
3027 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
3028 watchdog = WATCHDOG_DELAY;
3029 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
3030 watchdog = WATCHDOG_DELAY;
3031 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
3032 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
3033 watchdog = WATCHDOG_DELAY;
3034 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
3035 watchdog = WATCHDOG_DELAY;
3036 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
3041 static void
3042 SISDisplayVideo(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv)
3044 SISPtr pSiS = SISPTR(pScrn);
3045 #ifdef SISDUALHEAD
3046 SISEntPtr pSiSEnt = pSiS->entityPrivate;
3047 #endif
3048 short srcPitch = pPriv->srcPitch;
3049 short height = pPriv->height;
3050 unsigned short screenwidth;
3051 SISOverlayRec overlay;
3052 int srcOffsetX=0, srcOffsetY=0;
3053 int sx=0, sy=0;
3054 int index = 0, iscrt2 = 0;
3055 #ifdef SISMERGED
3056 unsigned char temp;
3057 unsigned short screen2width=0;
3058 int srcOffsetX2=0, srcOffsetY2=0;
3059 int sx2=0, sy2=0, watchdog;
3060 #endif
3062 pPriv->NoOverlay = FALSE;
3063 #ifdef SISDUALHEAD
3064 if(pPriv->dualHeadMode) {
3065 if(!pPriv->hasTwoOverlays) {
3066 if(pSiS->SecondHead) {
3067 if(pSiSEnt->curxvcrtnum != 0) {
3068 if(pPriv->overlayStatus) {
3069 close_overlay(pSiS, pPriv);
3071 pPriv->NoOverlay = TRUE;
3072 return;
3074 } else {
3075 if(pSiSEnt->curxvcrtnum != 1) {
3076 if(pPriv->overlayStatus) {
3077 close_overlay(pSiS, pPriv);
3079 pPriv->NoOverlay = TRUE;
3080 return;
3085 #endif
3087 /* setup dispmode (MIRROR, SINGLEx) */
3088 set_dispmode(pScrn, pPriv);
3090 /* Check if overlay is supported with current mode */
3091 #ifdef SISMERGED
3092 if(!pSiS->MergedFB) {
3093 #endif
3094 if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) {
3095 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) {
3096 if(pPriv->overlayStatus) {
3097 close_overlay(pSiS, pPriv);
3099 pPriv->NoOverlay = TRUE;
3100 return;
3103 #ifdef SISMERGED
3105 #endif
3107 memset(&overlay, 0, sizeof(overlay));
3109 overlay.pixelFormat = pPriv->id;
3110 overlay.pitch = overlay.origPitch = srcPitch;
3111 if(pPriv->usechromakey) {
3112 overlay.keyOP = (pPriv->insidechromakey) ? VI_ROP_ChromaKey : VI_ROP_NotChromaKey;
3113 } else {
3114 overlay.keyOP = VI_ROP_DestKey;
3116 /* overlay.bobEnable = 0x02; */
3117 overlay.bobEnable = 0x00; /* Disable BOB de-interlacer */
3119 #ifdef SISMERGED
3120 if(pSiS->MergedFB) {
3121 overlay.DoFirst = TRUE;
3122 overlay.DoSecond = TRUE;
3123 overlay.pitch2 = overlay.origPitch;
3124 overlay.currentmode = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT1;
3125 overlay.currentmode2 = ((SiSMergedDisplayModePtr)pSiS->CurrentLayout.mode->Private)->CRT2;
3126 overlay.SCREENheight = overlay.currentmode->VDisplay;
3127 overlay.SCREENheight2 = overlay.currentmode2->VDisplay;
3128 screenwidth = overlay.currentmode->HDisplay;
3129 screen2width = overlay.currentmode2->HDisplay;
3130 overlay.dstBox.x1 = pPriv->drw_x - pSiS->CRT1frameX0;
3131 overlay.dstBox.x2 = overlay.dstBox.x1 + pPriv->drw_w;
3132 overlay.dstBox.y1 = pPriv->drw_y - pSiS->CRT1frameY0;
3133 overlay.dstBox.y2 = overlay.dstBox.y1 + pPriv->drw_h;
3134 overlay.dstBox2.x1 = pPriv->drw_x - pSiS->CRT2pScrn->frameX0;
3135 overlay.dstBox2.x2 = overlay.dstBox2.x1 + pPriv->drw_w;
3136 overlay.dstBox2.y1 = pPriv->drw_y - pSiS->CRT2pScrn->frameY0;
3137 overlay.dstBox2.y2 = overlay.dstBox2.y1 + pPriv->drw_h;
3138 /* xf86DrvMsg(0, X_INFO, "DV(1): %d %d %d %d | %d %d %d %d\n",
3139 overlay.dstBox.x1,overlay.dstBox.x2,overlay.dstBox.y1,overlay.dstBox.y2,
3140 overlay.dstBox2.x1,overlay.dstBox2.x2,overlay.dstBox2.y1,overlay.dstBox2.y2); */
3141 } else {
3142 #endif
3143 overlay.currentmode = pSiS->CurrentLayout.mode;
3144 overlay.SCREENheight = overlay.currentmode->VDisplay;
3145 screenwidth = overlay.currentmode->HDisplay;
3146 overlay.dstBox.x1 = pPriv->drw_x - pScrn->frameX0;
3147 overlay.dstBox.x2 = pPriv->drw_x + pPriv->drw_w - pScrn->frameX0;
3148 overlay.dstBox.y1 = pPriv->drw_y - pScrn->frameY0;
3149 overlay.dstBox.y2 = pPriv->drw_y + pPriv->drw_h - pScrn->frameY0;
3150 /* xf86DrvMsg(0, X_INFO, "DV(1): %d %d %d %d\n",
3151 overlay.dstBox.x1,overlay.dstBox.x2,overlay.dstBox.y1,overlay.dstBox.y2); */
3152 #ifdef SISMERGED
3154 #endif
3156 /* Note: x2/y2 is actually real coordinate + 1 */
3158 if((overlay.dstBox.x1 >= overlay.dstBox.x2) ||
3159 (overlay.dstBox.y1 >= overlay.dstBox.y2)) {
3160 #ifdef SISMERGED
3161 if(pSiS->MergedFB) overlay.DoFirst = FALSE;
3162 else
3163 #endif
3164 return;
3167 if((overlay.dstBox.x2 <= 0) || (overlay.dstBox.y2 <= 0)) {
3168 #ifdef SISMERGED
3169 if(pSiS->MergedFB) overlay.DoFirst = FALSE;
3170 else
3171 #endif
3172 return;
3175 if((overlay.dstBox.x1 >= screenwidth) || (overlay.dstBox.y1 >= overlay.SCREENheight)) {
3176 #ifdef SISMERGED
3177 if(pSiS->MergedFB) overlay.DoFirst = FALSE;
3178 else
3179 #endif
3180 return;
3183 #ifdef SISMERGED
3184 if(pSiS->MergedFB) {
3185 /* Check if dotclock is within limits for CRT1 */
3186 if(pPriv->displayMode & (DISPMODE_SINGLE1 | DISPMODE_MIRROR)) {
3187 if(!(pSiS->MiscFlags & MISC_CRT1OVERLAY)) {
3188 overlay.DoFirst = FALSE;
3192 #endif
3194 if(overlay.dstBox.x1 < 0) {
3195 srcOffsetX = pPriv->src_w * (-overlay.dstBox.x1) / pPriv->drw_w;
3196 overlay.dstBox.x1 = 0;
3198 if(overlay.dstBox.y1 < 0) {
3199 srcOffsetY = pPriv->src_h * (-overlay.dstBox.y1) / pPriv->drw_h;
3200 overlay.dstBox.y1 = 0;
3203 #ifdef SISMERGED
3204 if(pSiS->MergedFB) {
3205 if((overlay.dstBox2.x1 >= overlay.dstBox2.x2) ||
3206 (overlay.dstBox2.y1 >= overlay.dstBox2.y2))
3207 overlay.DoSecond = FALSE;
3209 if((overlay.dstBox2.x2 <= 0) || (overlay.dstBox2.y2 <= 0))
3210 overlay.DoSecond = FALSE;
3212 if((overlay.dstBox2.x1 >= screen2width) || (overlay.dstBox2.y1 >= overlay.SCREENheight2))
3213 overlay.DoSecond = FALSE;
3215 if(overlay.dstBox2.x1 < 0) {
3216 srcOffsetX2 = pPriv->src_w * (-overlay.dstBox2.x1) / pPriv->drw_w;
3217 overlay.dstBox2.x1 = 0;
3219 if(overlay.dstBox2.y1 < 0) {
3220 srcOffsetY2 = pPriv->src_h * (-overlay.dstBox2.y1) / pPriv->drw_h;
3221 overlay.dstBox2.y1 = 0;
3224 /* If neither overlay is to be displayed, disable them if they are currently enabled */
3225 if((!overlay.DoFirst) && (!overlay.DoSecond)) {
3226 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05);
3227 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
3228 temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
3229 if(temp & 0x02) {
3230 watchdog = WATCHDOG_DELAY;
3231 if(pPriv->hasTwoOverlays) {
3232 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
3233 watchdog = WATCHDOG_DELAY;
3234 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
3235 } else {
3236 temp = getsrreg(pSiS, 0x06);
3237 if(!(temp & 0x40)) {
3238 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
3239 watchdog = WATCHDOG_DELAY;
3240 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
3241 } else {
3242 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
3243 watchdog = WATCHDOG_DELAY;
3244 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
3247 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
3249 if(pPriv->hasTwoOverlays) {
3250 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
3251 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
3252 temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
3253 if(temp & 0x02) {
3254 watchdog = WATCHDOG_DELAY;
3255 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
3256 watchdog = WATCHDOG_DELAY;
3257 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
3258 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
3261 pPriv->overlayStatus = FALSE;
3262 return;
3265 #endif
3267 switch(pPriv->id) {
3269 case PIXEL_FMT_YV12:
3270 #ifdef SISMERGED
3271 if((!pSiS->MergedFB) || (overlay.DoFirst)) {
3272 #endif
3273 sx = (pPriv->src_x + srcOffsetX) & ~7;
3274 sy = (pPriv->src_y + srcOffsetY) & ~1;
3275 overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch;
3276 overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1);
3277 overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1);
3278 #ifdef SISDUALHEAD
3279 overlay.PSY += HEADOFFSET;
3280 overlay.PSV += HEADOFFSET;
3281 overlay.PSU += HEADOFFSET;
3282 #endif
3283 overlay.PSY >>= pPriv->shiftValue;
3284 overlay.PSV >>= pPriv->shiftValue;
3285 overlay.PSU >>= pPriv->shiftValue;
3286 #ifdef SISMERGED
3288 if((pSiS->MergedFB) && (overlay.DoSecond)) {
3289 sx2 = (pPriv->src_x + srcOffsetX2) & ~7;
3290 sy2 = (pPriv->src_y + srcOffsetY2) & ~1;
3291 overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch;
3292 overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1);
3293 overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1);
3294 overlay.PSY2 >>= pPriv->shiftValue;
3295 overlay.PSV2 >>= pPriv->shiftValue;
3296 overlay.PSU2 >>= pPriv->shiftValue;
3298 #endif
3299 break;
3301 case PIXEL_FMT_I420:
3302 #ifdef SISMERGED
3303 if((!pSiS->MergedFB) || (overlay.DoFirst)) {
3304 #endif
3305 sx = (pPriv->src_x + srcOffsetX) & ~7;
3306 sy = (pPriv->src_y + srcOffsetY) & ~1;
3307 overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch;
3308 overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx + sy*srcPitch/2) >> 1);
3309 overlay.PSU = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1);
3310 #ifdef SISDUALHEAD
3311 overlay.PSY += HEADOFFSET;
3312 overlay.PSV += HEADOFFSET;
3313 overlay.PSU += HEADOFFSET;
3314 #endif
3315 overlay.PSY >>= pPriv->shiftValue;
3316 overlay.PSV >>= pPriv->shiftValue;
3317 overlay.PSU >>= pPriv->shiftValue;
3318 #ifdef SISMERGED
3320 if((pSiS->MergedFB) && (overlay.DoSecond)) {
3321 sx2 = (pPriv->src_x + srcOffsetX2) & ~7;
3322 sy2 = (pPriv->src_y + srcOffsetY2) & ~1;
3323 overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch;
3324 overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch*5/4 + ((sx2 + sy2*srcPitch/2) >> 1);
3325 overlay.PSU2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1);
3326 overlay.PSY2 >>= pPriv->shiftValue;
3327 overlay.PSV2 >>= pPriv->shiftValue;
3328 overlay.PSU2 >>= pPriv->shiftValue;
3330 #endif
3331 break;
3333 case PIXEL_FMT_NV12:
3334 case PIXEL_FMT_NV21:
3335 #ifdef SISMERGED
3336 if((!pSiS->MergedFB) || (overlay.DoFirst)) {
3337 #endif
3338 sx = (pPriv->src_x + srcOffsetX) & ~7;
3339 sy = (pPriv->src_y + srcOffsetY) & ~1;
3340 overlay.PSY = pPriv->bufAddr[pPriv->currentBuf] + sx + sy*srcPitch;
3341 overlay.PSV = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx + sy*srcPitch/2) >> 1);
3342 #ifdef SISDUALHEAD
3343 overlay.PSY += HEADOFFSET;
3344 overlay.PSV += HEADOFFSET;
3345 #endif
3346 overlay.PSY >>= pPriv->shiftValue;
3347 overlay.PSV >>= pPriv->shiftValue;
3348 overlay.PSU = overlay.PSV;
3349 #ifdef SISMERGED
3351 if((pSiS->MergedFB) && (overlay.DoSecond)) {
3352 sx2 = (pPriv->src_x + srcOffsetX2) & ~7;
3353 sy2 = (pPriv->src_y + srcOffsetY2) & ~1;
3354 overlay.PSY2 = pPriv->bufAddr[pPriv->currentBuf] + sx2 + sy2*srcPitch;
3355 overlay.PSV2 = pPriv->bufAddr[pPriv->currentBuf] + height*srcPitch + ((sx2 + sy2*srcPitch/2) >> 1);
3356 overlay.PSY2 >>= pPriv->shiftValue;
3357 overlay.PSV2 >>= pPriv->shiftValue;
3358 overlay.PSU2 = overlay.PSV2;
3360 #endif
3361 break;
3363 case PIXEL_FMT_YUY2:
3364 case PIXEL_FMT_UYVY:
3365 case PIXEL_FMT_YVYU:
3366 case PIXEL_FMT_RGB6:
3367 case PIXEL_FMT_RGB5:
3368 default:
3369 #ifdef SISMERGED
3370 if((!pSiS->MergedFB) || (overlay.DoFirst)) {
3371 #endif
3372 sx = (pPriv->src_x + srcOffsetX) & ~1;
3373 sy = (pPriv->src_y + srcOffsetY);
3374 overlay.PSY = (pPriv->bufAddr[pPriv->currentBuf] + sx*2 + sy*srcPitch);
3375 #ifdef SISDUALHEAD
3376 overlay.PSY += HEADOFFSET;
3377 #endif
3378 overlay.PSY >>= pPriv->shiftValue;
3379 #ifdef SISMERGED
3381 if((pSiS->MergedFB) && (overlay.DoSecond)) {
3382 sx2 = (pPriv->src_x + srcOffsetX2) & ~1;
3383 sy2 = (pPriv->src_y + srcOffsetY2);
3384 overlay.PSY2 = (pPriv->bufAddr[pPriv->currentBuf] + sx2*2 + sy2*srcPitch);
3385 overlay.PSY2 >>= pPriv->shiftValue;
3387 #endif
3388 break;
3391 /* Some clipping checks */
3392 #ifdef SISMERGED
3393 if((!pSiS->MergedFB) || (overlay.DoFirst)) {
3394 #endif
3395 overlay.srcW = pPriv->src_w - (sx - pPriv->src_x);
3396 overlay.srcH = pPriv->src_h - (sy - pPriv->src_y);
3397 if( (pPriv->oldx1 != overlay.dstBox.x1) ||
3398 (pPriv->oldx2 != overlay.dstBox.x2) ||
3399 (pPriv->oldy1 != overlay.dstBox.y1) ||
3400 (pPriv->oldy2 != overlay.dstBox.y2) ) {
3401 pPriv->mustwait = 1;
3402 pPriv->oldx1 = overlay.dstBox.x1; pPriv->oldx2 = overlay.dstBox.x2;
3403 pPriv->oldy1 = overlay.dstBox.y1; pPriv->oldy2 = overlay.dstBox.y2;
3406 #ifdef SISMERGED
3408 if((pSiS->MergedFB) && (overlay.DoSecond)) {
3409 overlay.srcW2 = pPriv->src_w - (sx2 - pPriv->src_x);
3410 overlay.srcH2 = pPriv->src_h - (sy2 - pPriv->src_y);
3411 if( (pPriv->oldx1_2 != overlay.dstBox2.x1) ||
3412 (pPriv->oldx2_2 != overlay.dstBox2.x2) ||
3413 (pPriv->oldy1_2 != overlay.dstBox2.y1) ||
3414 (pPriv->oldy2_2 != overlay.dstBox2.y2) ) {
3415 pPriv->mustwait = 1;
3416 pPriv->oldx1_2 = overlay.dstBox2.x1; pPriv->oldx2_2 = overlay.dstBox2.x2;
3417 pPriv->oldy1_2 = overlay.dstBox2.y1; pPriv->oldy2_2 = overlay.dstBox2.y2;
3420 #endif
3422 #ifdef SISMERGED
3423 /* Disable an overlay if it is not to be displayed (but enabled currently) */
3424 if((pSiS->MergedFB) && (pPriv->hasTwoOverlays)) {
3425 if(!overlay.DoFirst) {
3426 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x00, 0x05);
3427 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
3428 temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
3429 if(temp & 0x02) {
3430 watchdog = WATCHDOG_DELAY;
3431 while(vblank_active_CRT1(pSiS, pPriv) && --watchdog);
3432 watchdog = WATCHDOG_DELAY;
3433 while((!vblank_active_CRT1(pSiS, pPriv)) && --watchdog);
3434 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
3436 } else if(!overlay.DoSecond) {
3437 setvideoregmask(pSiS, Index_VI_Control_Misc2, 0x01, 0x01);
3438 setvideoregmask(pSiS, Index_VI_Control_Misc1, 0x00, 0x01);
3439 temp = getvideoreg(pSiS,Index_VI_Control_Misc0);
3440 if(temp & 0x02) {
3441 watchdog = WATCHDOG_DELAY;
3442 while(vblank_active_CRT2(pSiS, pPriv) && --watchdog);
3443 watchdog = WATCHDOG_DELAY;
3444 while((!vblank_active_CRT2(pSiS, pPriv)) && --watchdog);
3445 setvideoregmask(pSiS, Index_VI_Control_Misc0, 0x00, 0x02);
3449 #endif
3451 /* Loop head */
3452 if(pPriv->displayMode & DISPMODE_SINGLE2) {
3453 if(pPriv->hasTwoOverlays) { /* We have 2 overlays: */
3454 if(pPriv->dualHeadMode) {
3455 /* Dual head: We use overlay 2 for CRT2 */
3456 index = 1; iscrt2 = 1;
3457 } else {
3458 /* Single head: We use overlay 1 for CRT2 */
3459 index = 0; iscrt2 = 1;
3461 } else { /* We have 1 overlay */
3462 /* We use that only overlay for CRT2 */
3463 index = 0; iscrt2 = 1;
3465 overlay.VBlankActiveFunc = vblank_active_CRT2;
3466 #ifdef SISMERGED
3467 if(!pPriv->hasTwoOverlays) {
3468 if((pSiS->MergedFB) && (!overlay.DoSecond)) {
3469 index = 0; iscrt2 = 0;
3470 overlay.VBlankActiveFunc = vblank_active_CRT1;
3471 pPriv->displayMode = DISPMODE_SINGLE1;
3474 #endif
3475 } else {
3476 index = 0; iscrt2 = 0;
3477 overlay.VBlankActiveFunc = vblank_active_CRT1;
3478 #ifdef SISMERGED
3479 if((pSiS->MergedFB) && (!overlay.DoFirst)) {
3480 if(pPriv->hasTwoOverlays) index = 1;
3481 iscrt2 = 1;
3482 overlay.VBlankActiveFunc = vblank_active_CRT2;
3483 if(!pPriv->hasTwoOverlays) {
3484 pPriv->displayMode = DISPMODE_SINGLE2;
3487 #endif
3490 /* set display mode SR06,32 (CRT1, CRT2 or mirror) */
3491 set_disptype_regs(pScrn, pPriv);
3493 /* set (not only calc) merge line buffer */
3494 #ifdef SISMERGED
3495 if(!pSiS->MergedFB) {
3496 #endif
3497 merge_line_buf(pSiS, pPriv, (overlay.srcW > pPriv->linebufMergeLimit), overlay.srcW,
3498 pPriv->linebufMergeLimit);
3499 #ifdef SISMERGED
3500 } else {
3501 Bool temp1 = FALSE, temp2 = FALSE;
3502 if(overlay.DoFirst) {
3503 if(overlay.srcW > pPriv->linebufMergeLimit) temp1 = TRUE;
3505 if(overlay.DoSecond) {
3506 if(overlay.srcW2 > pPriv->linebufMergeLimit) temp2 = TRUE;
3508 merge_line_buf_mfb(pSiS, pPriv, temp1, temp2, overlay.srcW, overlay.srcW2, pPriv->linebufMergeLimit);
3510 #endif
3512 /* calculate (not set!) line buffer length */
3513 #ifdef SISMERGED
3514 if((!pSiS->MergedFB) || (overlay.DoFirst))
3515 #endif
3516 set_line_buf_size_1(&overlay);
3517 #ifdef SISMERGED
3518 if((pSiS->MergedFB) && (overlay.DoSecond))
3519 set_line_buf_size_2(&overlay);
3520 #endif
3522 /* Do the following in a loop for CRT1 and CRT2 ----------------- */
3523 MIRROR:
3525 /* calculate (not set!) scale factor */
3526 #ifdef SISMERGED
3527 if(pSiS->MergedFB && iscrt2)
3528 calc_scale_factor_2(&overlay, pScrn, pPriv, index, iscrt2);
3529 else
3530 #endif
3531 calc_scale_factor(&overlay, pScrn, pPriv, index, iscrt2);
3533 /* Select overlay 1 (used for CRT1/or CRT2) or overlay 2 (used for CRT2) */
3534 setvideoregmask(pSiS, Index_VI_Control_Misc2, index, 0x01);
3536 /* set format */
3537 set_format(pSiS, &overlay);
3539 /* set color key */
3540 set_colorkey(pSiS, pPriv->colorKey);
3542 if(pPriv->usechromakey) {
3543 /* Select chroma key format (300 series only) */
3544 if(pSiS->VGAEngine == SIS_300_VGA) {
3545 setvideoregmask(pSiS, Index_VI_Control_Misc0,
3546 (pPriv->yuvchromakey ? 0x40 : 0x00), 0x40);
3548 set_chromakey(pSiS, pPriv->chromamin, pPriv->chromamax);
3551 /* set brightness, contrast, hue, saturation */
3552 set_brightness(pSiS, pPriv->brightness);
3553 set_contrast(pSiS, pPriv->contrast);
3554 if(pSiS->VGAEngine == SIS_315_VGA) {
3555 set_hue(pSiS, pPriv->hue);
3556 set_saturation(pSiS, pPriv->saturation);
3559 if(pPriv->dualHeadMode) {
3560 #ifdef SISDUALHEAD
3561 if(!pSiS->SecondHead) {
3562 if(pPriv->updatetvxpos) {
3563 SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
3564 pPriv->updatetvxpos = FALSE;
3566 if(pPriv->updatetvypos) {
3567 SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
3568 pPriv->updatetvypos = FALSE;
3571 #endif
3572 } else {
3573 if(pPriv->updatetvxpos) {
3574 SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
3575 pPriv->updatetvxpos = FALSE;
3577 if(pPriv->updatetvypos) {
3578 SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
3579 pPriv->updatetvypos = FALSE;
3583 /* enable/disable graphics display around overlay
3584 * (Since disabled overlays don't get treated in this
3585 * loop, we omit respective checks here)
3588 if(!iscrt2) set_disablegfx(pSiS, pPriv->disablegfx, &overlay);
3589 else if(!pPriv->hasTwoOverlays) {
3590 set_disablegfx(pSiS, FALSE, &overlay);
3592 set_disablegfxlr(pSiS, pPriv->disablegfxlr, &overlay);
3594 #ifdef SIS_CP
3595 SIS_CP_VIDEO_SET_CP
3596 #endif
3598 /* set overlay parameters */
3599 set_overlay(pSiS, &overlay, pPriv, index, iscrt2);
3601 if((pSiS->VGAEngine == SIS_315_VGA) && !index) {
3602 /* Trigger register copy for 315 series */
3603 setvideoregmask(pSiS, Index_VI_Control_Misc3, (1 << index), (1 << index));
3606 /* enable overlay */
3607 setvideoregmask (pSiS, Index_VI_Control_Misc0, 0x02, 0x02);
3609 /* loop foot */
3610 if(pPriv->displayMode & DISPMODE_MIRROR &&
3611 index == 0 &&
3612 pPriv->hasTwoOverlays) {
3613 #ifdef SISMERGED
3614 if((!pSiS->MergedFB) || overlay.DoSecond) {
3615 #endif
3616 index = 1; iscrt2 = 1;
3617 overlay.VBlankActiveFunc = vblank_active_CRT2;
3618 goto MIRROR;
3619 #ifdef SISMERGED
3621 #endif
3624 pPriv->mustwait = 0;
3625 pPriv->overlayStatus = TRUE;
3628 static FBLinearPtr
3629 SISAllocateOverlayMemory(
3630 ScrnInfoPtr pScrn,
3631 FBLinearPtr linear,
3632 int size
3634 ScreenPtr pScreen;
3635 FBLinearPtr new_linear;
3637 if(linear) {
3638 if(linear->size >= size)
3639 return linear;
3641 if(xf86ResizeOffscreenLinear(linear, size))
3642 return linear;
3644 xf86FreeOffscreenLinear(linear);
3647 pScreen = screenInfo.screens[pScrn->scrnIndex];
3649 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8,
3650 NULL, NULL, NULL);
3652 if(!new_linear) {
3653 int max_size;
3655 xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8,
3656 PRIORITY_EXTREME);
3658 if(max_size < size) return NULL;
3660 xf86PurgeUnlockedOffscreenAreas(pScreen);
3661 new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8,
3662 NULL, NULL, NULL);
3664 if(!new_linear)
3665 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3666 "Xv: Failed to allocate %dK of video memory\n", size/1024);
3667 #ifdef TWDEBUG
3668 else
3669 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3670 "Xv: Allocated %dK of video memory\n", size/1024);
3671 #endif
3673 return new_linear;
3676 static void
3677 SISFreeOverlayMemory(ScrnInfoPtr pScrn)
3679 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
3681 if(pPriv->linear) {
3682 xf86FreeOffscreenLinear(pPriv->linear);
3683 pPriv->linear = NULL;
3687 static void
3688 SISStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
3690 SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
3691 SISPtr pSiS = SISPTR(pScrn);
3693 if(pPriv->grabbedByV4L) return;
3695 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
3697 if(shutdown) {
3698 if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
3699 close_overlay(pSiS, pPriv);
3700 pPriv->mustwait = 1;
3702 SISFreeOverlayMemory(pScrn);
3703 pPriv->videoStatus = 0;
3704 pSiS->VideoTimerCallback = NULL;
3705 } else {
3706 if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
3707 pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
3708 pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
3709 pSiS->VideoTimerCallback = SISVideoTimerCallback;
3714 static int
3715 SISPutImage(
3716 ScrnInfoPtr pScrn,
3717 short src_x, short src_y,
3718 short drw_x, short drw_y,
3719 short src_w, short src_h,
3720 short drw_w, short drw_h,
3721 int id, unsigned char* buf,
3722 short width, short height,
3723 Bool sync,
3724 RegionPtr clipBoxes, pointer data
3726 SISPtr pSiS = SISPTR(pScrn);
3727 SISPortPrivPtr pPriv = (SISPortPrivPtr)data;
3729 int totalSize=0;
3730 int depth = pSiS->CurrentLayout.bitsPerPixel >> 3;
3731 int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 };
3733 #if 0
3734 if(id == SDC_ID) {
3735 return(SiSHandleSiSDirectCommand(pScrn, pPriv, (sisdirectcommand *)buf));
3737 #endif
3739 if(pPriv->grabbedByV4L) return Success;
3741 pPriv->drw_x = drw_x;
3742 pPriv->drw_y = drw_y;
3743 pPriv->drw_w = drw_w;
3744 pPriv->drw_h = drw_h;
3745 pPriv->src_x = src_x;
3746 pPriv->src_y = src_y;
3747 pPriv->src_w = src_w;
3748 pPriv->src_h = src_h;
3749 pPriv->id = id;
3750 pPriv->height = height;
3752 /* Pixel formats:
3753 1. YU12: 3 planes: H V
3754 Y sample period 1 1 (8 bit per pixel)
3755 V sample period 2 2 (8 bit per pixel, subsampled)
3756 U sample period 2 2 (8 bit per pixel, subsampled)
3758 Y plane is fully sampled (width*height), U and V planes
3759 are sampled in 2x2 blocks, hence a group of 4 pixels requires
3760 4 + 1 + 1 = 6 bytes. The data is planar, ie in single planes
3761 for Y, U and V.
3762 2. UYVY: 3 planes: H V
3763 Y sample period 1 1 (8 bit per pixel)
3764 V sample period 2 1 (8 bit per pixel, subsampled)
3765 U sample period 2 1 (8 bit per pixel, subsampled)
3766 Y plane is fully sampled (width*height), U and V planes
3767 are sampled in 2x1 blocks, hence a group of 4 pixels requires
3768 4 + 2 + 2 = 8 bytes. The data is bit packed, there are no separate
3769 Y, U or V planes.
3770 Bit order: U0 Y0 V0 Y1 U2 Y2 V2 Y3 ...
3771 3. I420: Like YU12, but planes U and V are in reverse order.
3772 4. YUY2: Like UYVY, but order is
3773 Y0 U0 Y1 V0 Y2 U2 Y3 V2 ...
3774 5. YVYU: Like YUY2, but order is
3775 Y0 V0 Y1 U0 Y2 V2 Y3 U2 ...
3778 switch(id){
3779 case PIXEL_FMT_YV12:
3780 case PIXEL_FMT_I420:
3781 case PIXEL_FMT_NV12:
3782 case PIXEL_FMT_NV21:
3783 pPriv->srcPitch = (width + 7) & ~7;
3784 /* Size = width * height * 3 / 2 */
3785 totalSize = (pPriv->srcPitch * height * 3) >> 1; /* Verified */
3786 break;
3787 case PIXEL_FMT_YUY2:
3788 case PIXEL_FMT_UYVY:
3789 case PIXEL_FMT_YVYU:
3790 case PIXEL_FMT_RGB6:
3791 case PIXEL_FMT_RGB5:
3792 default:
3793 pPriv->srcPitch = ((width << 1) + 3) & ~3; /* Verified */
3794 /* Size = width * 2 * height */
3795 totalSize = pPriv->srcPitch * height;
3798 /* make it a multiple of 16 to simplify to copy loop */
3799 totalSize += 15;
3800 totalSize &= ~15;
3802 /* allocate memory (we do doublebuffering) */
3803 if(!(pPriv->linear = SISAllocateOverlayMemory(pScrn, pPriv->linear,
3804 totalSize<<1)))
3805 return BadAlloc;
3807 /* fixup pointers */
3808 pPriv->bufAddr[0] = (pPriv->linear->offset * depth);
3809 pPriv->bufAddr[1] = pPriv->bufAddr[0] + totalSize;
3811 /* copy data */
3812 if((pSiS->XvUseMemcpy) || (totalSize < 16)) {
3813 memcpy(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf], buf, totalSize);
3814 } else {
3815 unsigned long i;
3816 CARD32 *src = (CARD32 *)buf;
3817 CARD32 *dest = (CARD32 *)(pSiS->FbBase + pPriv->bufAddr[pPriv->currentBuf]);
3818 for(i = 0; i < (totalSize/16); i++) {
3819 *dest++ = *src++;
3820 *dest++ = *src++;
3821 *dest++ = *src++;
3822 *dest++ = *src++;
3826 SISDisplayVideo(pScrn, pPriv);
3828 /* update cliplist */
3829 if(pPriv->autopaintColorKey &&
3830 (pPriv->grabbedByV4L ||
3831 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0)
3832 (!RegionsEqual(&pPriv->clip, clipBoxes)) ||
3833 #else
3834 (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) ||
3835 #endif
3836 (pPriv->PrevOverlay != pPriv->NoOverlay))) {
3837 /* We always paint the colorkey for V4L */
3838 if(!pPriv->grabbedByV4L) {
3839 REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
3841 /* draw these */
3842 pPriv->PrevOverlay = pPriv->NoOverlay;
3843 if((pPriv->NoOverlay) && (!pSiS->NoAccel)) {
3844 XAAFillMono8x8PatternRects(pScrn, myreds[depth-1], 0x000000, GXcopy, ~0,
3845 REGION_NUM_RECTS(clipBoxes),
3846 REGION_RECTS(clipBoxes),
3847 0x00422418, 0x18244200, 0, 0);
3848 } else {
3849 if(!pSiS->disablecolorkeycurrent) {
3850 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
3851 XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0,
3852 REGION_NUM_RECTS(clipBoxes),
3853 REGION_RECTS(clipBoxes));
3854 #else
3855 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
3856 #endif
3862 pPriv->currentBuf ^= 1;
3864 pPriv->videoStatus = CLIENT_VIDEO_ON;
3866 pSiS->VideoTimerCallback = SISVideoTimerCallback;
3868 return Success;
3871 static int
3872 SISQueryImageAttributes(
3873 ScrnInfoPtr pScrn,
3874 int id,
3875 unsigned short *w, unsigned short *h,
3876 int *pitches, int *offsets
3878 int pitchY, pitchUV;
3879 int size, sizeY, sizeUV;
3881 if(*w < IMAGE_MIN_WIDTH) *w = IMAGE_MIN_WIDTH;
3882 if(*h < IMAGE_MIN_HEIGHT) *h = IMAGE_MIN_HEIGHT;
3884 if(*w > DummyEncoding.width) *w = DummyEncoding.width;
3885 if(*h > DummyEncoding.height) *h = DummyEncoding.height;
3887 switch(id) {
3888 case PIXEL_FMT_YV12:
3889 case PIXEL_FMT_I420:
3890 *w = (*w + 7) & ~7;
3891 *h = (*h + 1) & ~1;
3892 pitchY = *w;
3893 pitchUV = *w >> 1;
3894 if(pitches) {
3895 pitches[0] = pitchY;
3896 pitches[1] = pitches[2] = pitchUV;
3898 sizeY = pitchY * (*h);
3899 sizeUV = pitchUV * ((*h) >> 1);
3900 if(offsets) {
3901 offsets[0] = 0;
3902 offsets[1] = sizeY;
3903 offsets[2] = sizeY + sizeUV;
3905 size = sizeY + (sizeUV << 1);
3906 break;
3907 case PIXEL_FMT_NV12:
3908 case PIXEL_FMT_NV21:
3909 *w = (*w + 7) & ~7;
3910 *h = (*h + 1) & ~1;
3911 pitchY = *w;
3912 pitchUV = *w;
3913 if(pitches) {
3914 pitches[0] = pitchY;
3915 pitches[1] = pitchUV;
3917 sizeY = pitchY * (*h);
3918 sizeUV = pitchUV * ((*h) >> 1);
3919 if(offsets) {
3920 offsets[0] = 0;
3921 offsets[1] = sizeY;
3923 size = sizeY + (sizeUV << 1);
3924 break;
3925 case PIXEL_FMT_YUY2:
3926 case PIXEL_FMT_UYVY:
3927 case PIXEL_FMT_YVYU:
3928 case PIXEL_FMT_RGB6:
3929 case PIXEL_FMT_RGB5:
3930 default:
3931 *w = (*w + 1) & ~1;
3932 pitchY = *w << 1;
3933 if(pitches) pitches[0] = pitchY;
3934 if(offsets) offsets[0] = 0;
3935 size = pitchY * (*h);
3936 break;
3939 return size;
3942 static void
3943 SISVideoTimerCallback(ScrnInfoPtr pScrn, Time now)
3945 SISPtr pSiS = SISPTR(pScrn);
3946 SISPortPrivPtr pPriv = NULL;
3947 unsigned char sridx, cridx;
3949 pSiS->VideoTimerCallback = NULL;
3951 if(!pScrn->vtSema) return;
3953 if(pSiS->adaptor) {
3954 pPriv = GET_PORT_PRIVATE(pScrn);
3955 if(!pPriv->videoStatus)
3956 pPriv = NULL;
3959 if(pPriv) {
3960 if(pPriv->videoStatus & TIMER_MASK) {
3961 UpdateCurrentTime();
3962 if(pPriv->offTime < currentTime.milliseconds) {
3963 if(pPriv->videoStatus & OFF_TIMER) {
3964 /* Turn off the overlay */
3965 sridx = inSISREG(SISSR); cridx = inSISREG(SISCR);
3966 close_overlay(pSiS, pPriv);
3967 outSISREG(SISSR, sridx); outSISREG(SISCR, cridx);
3968 pPriv->mustwait = 1;
3969 pPriv->videoStatus = FREE_TIMER;
3970 pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
3971 pSiS->VideoTimerCallback = SISVideoTimerCallback;
3972 } else if(pPriv->videoStatus & FREE_TIMER) {
3973 SISFreeOverlayMemory(pScrn);
3974 pPriv->mustwait = 1;
3975 pPriv->videoStatus = 0;
3977 } else
3978 pSiS->VideoTimerCallback = SISVideoTimerCallback;
3983 /* Offscreen surface stuff */
3985 static int
3986 SISAllocSurface (
3987 ScrnInfoPtr pScrn,
3988 int id,
3989 unsigned short w,
3990 unsigned short h,
3991 XF86SurfacePtr surface
3994 SISPtr pSiS = SISPTR(pScrn);
3995 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
3996 int size, depth;
3998 #ifdef TWDEBUG
3999 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv: SISAllocSurface called\n");
4000 #endif
4002 if((w < IMAGE_MIN_WIDTH) || (h < IMAGE_MIN_HEIGHT))
4003 return BadValue;
4004 if((w > DummyEncoding.width) || (h > DummyEncoding.height))
4005 return BadValue;
4007 if(pPriv->grabbedByV4L)
4008 return BadAlloc;
4010 depth = pSiS->CurrentLayout.bitsPerPixel >> 3;
4011 w = (w + 1) & ~1;
4012 pPriv->pitch = ((w << 1) + 63) & ~63; /* Only packed pixel modes supported */
4013 size = h * pPriv->pitch; /* / depth; - Why? */
4014 pPriv->linear = SISAllocateOverlayMemory(pScrn, pPriv->linear, size);
4015 if(!pPriv->linear)
4016 return BadAlloc;
4018 pPriv->offset = pPriv->linear->offset * depth;
4020 surface->width = w;
4021 surface->height = h;
4022 surface->pScrn = pScrn;
4023 surface->id = id;
4024 surface->pitches = &pPriv->pitch;
4025 surface->offsets = &pPriv->offset;
4026 surface->devPrivate.ptr = (pointer)pPriv;
4028 close_overlay(pSiS, pPriv);
4029 pPriv->videoStatus = 0;
4030 REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
4031 pSiS->VideoTimerCallback = NULL;
4032 pPriv->grabbedByV4L = TRUE;
4033 return Success;
4036 static int
4037 SISStopSurface (XF86SurfacePtr surface)
4039 SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr);
4040 SISPtr pSiS = SISPTR(surface->pScrn);
4042 if(pPriv->grabbedByV4L && pPriv->videoStatus) {
4043 close_overlay(pSiS, pPriv);
4044 pPriv->mustwait = 1;
4045 pPriv->videoStatus = 0;
4047 return Success;
4050 static int
4051 SISFreeSurface (XF86SurfacePtr surface)
4053 SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr);
4055 if(pPriv->grabbedByV4L) {
4056 SISStopSurface(surface);
4057 SISFreeOverlayMemory(surface->pScrn);
4058 pPriv->grabbedByV4L = FALSE;
4060 return Success;
4063 static int
4064 SISGetSurfaceAttribute (
4065 ScrnInfoPtr pScrn,
4066 Atom attribute,
4067 INT32 *value
4070 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
4072 return SISGetPortAttribute(pScrn, attribute, value, (pointer)pPriv);
4075 static int
4076 SISSetSurfaceAttribute(
4077 ScrnInfoPtr pScrn,
4078 Atom attribute,
4079 INT32 value
4082 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);;
4084 return SISSetPortAttribute(pScrn, attribute, value, (pointer)pPriv);
4087 static int
4088 SISDisplaySurface (
4089 XF86SurfacePtr surface,
4090 short src_x, short src_y,
4091 short drw_x, short drw_y,
4092 short src_w, short src_h,
4093 short drw_w, short drw_h,
4094 RegionPtr clipBoxes
4097 ScrnInfoPtr pScrn = surface->pScrn;
4098 SISPtr pSiS = SISPTR(pScrn);
4099 SISPortPrivPtr pPriv = (SISPortPrivPtr)(surface->devPrivate.ptr);
4100 int myreds[] = { 0x000000ff, 0x0000f800, 0, 0x00ff0000 };
4102 #ifdef TWDEBUG
4103 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv: DisplaySurface called\n");
4104 #endif
4106 if(!pPriv->grabbedByV4L) return Success;
4108 pPriv->drw_x = drw_x;
4109 pPriv->drw_y = drw_y;
4110 pPriv->drw_w = drw_w;
4111 pPriv->drw_h = drw_h;
4112 pPriv->src_x = src_x;
4113 pPriv->src_y = src_y;
4114 pPriv->src_w = src_w;
4115 pPriv->src_h = src_h;
4116 pPriv->id = surface->id;
4117 pPriv->height = surface->height;
4118 pPriv->bufAddr[0] = surface->offsets[0];
4119 pPriv->currentBuf = 0;
4120 pPriv->srcPitch = surface->pitches[0];
4122 SISDisplayVideo(pScrn, pPriv);
4124 if(pPriv->autopaintColorKey) {
4125 if((pPriv->NoOverlay) && (!(pSiS->NoAccel))) {
4126 XAAFillMono8x8PatternRects(pScrn,
4127 myreds[(pSiS->CurrentLayout.bitsPerPixel >> 3) - 1],
4128 0x000000, GXcopy, ~0,
4129 REGION_NUM_RECTS(clipBoxes),
4130 REGION_RECTS(clipBoxes),
4131 0x00422418, 0x18244200, 0, 0);
4133 } else {
4134 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,0,0)
4135 XAAFillSolidRects(pScrn, pPriv->colorKey, GXcopy, ~0,
4136 REGION_NUM_RECTS(clipBoxes),
4137 REGION_RECTS(clipBoxes));
4138 #else
4139 xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
4140 #endif
4144 pPriv->videoStatus = CLIENT_VIDEO_ON;
4146 return Success;
4149 #define NUMOFFSCRIMAGES_300 4
4150 #define NUMOFFSCRIMAGES_315 5
4152 static XF86OffscreenImageRec SISOffscreenImages[NUMOFFSCRIMAGES_315] =
4155 &SISImages[0], /* YUV2 */
4156 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
4157 SISAllocSurface,
4158 SISFreeSurface,
4159 SISDisplaySurface,
4160 SISStopSurface,
4161 SISGetSurfaceAttribute,
4162 SISSetSurfaceAttribute,
4163 0, 0, /* Rest will be filled in */
4165 NULL
4168 &SISImages[2], /* UYVY */
4169 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
4170 SISAllocSurface,
4171 SISFreeSurface,
4172 SISDisplaySurface,
4173 SISStopSurface,
4174 SISGetSurfaceAttribute,
4175 SISSetSurfaceAttribute,
4176 0, 0, /* Rest will be filled in */
4178 NULL
4182 &SISImages[4], /* RV15 */
4183 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
4184 SISAllocSurface,
4185 SISFreeSurface,
4186 SISDisplaySurface,
4187 SISStopSurface,
4188 SISGetSurfaceAttribute,
4189 SISSetSurfaceAttribute,
4190 0, 0, /* Rest will be filled in */
4192 NULL
4195 &SISImages[5], /* RV16 */
4196 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
4197 SISAllocSurface,
4198 SISFreeSurface,
4199 SISDisplaySurface,
4200 SISStopSurface,
4201 SISGetSurfaceAttribute,
4202 SISSetSurfaceAttribute,
4203 0, 0, /* Rest will be filled in */
4205 NULL
4208 &SISImages[6], /* YVYU */
4209 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
4210 SISAllocSurface,
4211 SISFreeSurface,
4212 SISDisplaySurface,
4213 SISStopSurface,
4214 SISGetSurfaceAttribute,
4215 SISSetSurfaceAttribute,
4216 0, 0, /* Rest will be filled in */
4218 NULL
4222 static void
4223 SISInitOffscreenImages(ScreenPtr pScreen)
4225 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
4226 SISPtr pSiS = SISPTR(pScrn);
4227 SISPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);
4228 int i, num;
4230 if(pSiS->VGAEngine == SIS_300_VGA) num = NUMOFFSCRIMAGES_300;
4231 else num = NUMOFFSCRIMAGES_315;
4233 for(i = 0; i <= num; i++) {
4234 SISOffscreenImages[i].max_width = DummyEncoding.width;
4235 SISOffscreenImages[i].max_height = DummyEncoding.height;
4236 if(pSiS->VGAEngine == SIS_300_VGA) {
4237 SISOffscreenImages[i].num_attributes = NUM_ATTRIBUTES_300;
4238 SISOffscreenImages[i].attributes = &SISAttributes_300[0];
4239 } else {
4240 if(pPriv->hasTwoOverlays) {
4241 SISOffscreenImages[i].num_attributes = NUM_ATTRIBUTES_315;
4242 } else {
4243 SISOffscreenImages[i].num_attributes = NUM_ATTRIBUTES_315 - 1;
4245 SISOffscreenImages[i].attributes = &SISAttributes_315[0];
4248 xf86XVRegisterOffscreenImages(pScreen, SISOffscreenImages, num);
4251 #ifdef NOT_YET_IMPLEMENTED /* ----------- TW: FOR FUTURE USE -------------------- */
4253 /* Set alpha - does not work */
4254 static void
4255 set_alpha(SISPtr pSiS, CARD8 alpha)
4257 setvideoregmask(pSiS, Index_VI_Key_Overlay_OP, ((alpha & 0x0f) << 4), 0xf0);
4260 /* Set SubPicture Start Address (yet unused) */
4261 static void
4262 set_subpict_start_offset(SISPtr pSiS, SISOverlayPtr pOverlay, int index)
4264 CARD32 temp;
4265 CARD8 data;
4267 temp = pOverlay->SubPictAddr >> 4; /* 630 <-> 315 shiftValue? */
4269 setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_Low, temp & 0xFF);
4270 setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_Middle, (temp>>8) & 0xFF);
4271 setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_High, (temp>>16) & 0x3F);
4272 if(pSiS->VGAEngine == SIS_315_VGA) {
4273 setvideoreg(pSiS,Index_VI_SubPict_Start_Over, (temp>>22) & 0x01);
4274 /* Submit SubPict offset ? */
4275 /* data=getvideoreg(pSiS,Index_VI_Control_Misc3); */
4276 setvideoreg(pSiS,Index_VI_Control_Misc3, (1 << index) | 0x04);
4280 /* Set SubPicture Pitch (yet unused) */
4281 static void
4282 set_subpict_pitch(SISPtr pSiS, SISOverlayPtr pOverlay, int index)
4284 CARD32 temp;
4285 CARD8 data;
4287 temp = pOverlay->SubPictPitch >> 4; /* 630 <-> 315 shiftValue? */
4289 setvideoreg(pSiS,Index_VI_SubPict_Buf_Pitch, temp & 0xFF);
4290 if(pSiS->VGAEngine == SIS_315_VGA) {
4291 setvideoreg(pSiS,Index_VI_SubPict_Buf_Pitch_High, (temp>>8) & 0xFF);
4292 /* Submit SubPict pitch ? */
4293 /* data=getvideoreg(pSiS,Index_VI_Control_Misc3); */
4294 setvideoreg(pSiS,Index_VI_Control_Misc3, (1 << index) | 0x04);
4298 /* Calculate and set SubPicture scaling (untested, unused yet) */
4299 static void
4300 set_subpict_scale_factor(SISOverlayPtr pOverlay, ScrnInfoPtr pScrn,
4301 SISPortPrivPtr pPriv, int index, int iscrt2)
4303 SISPtr pSiS = SISPTR(pScrn);
4304 CARD32 I=0,mult=0;
4305 int flag=0;
4307 int dstW = pOverlay->SubPictdstBox.x2 - pOverlay->SubPictdstBox.x1;
4308 int dstH = pOverlay->SubPictdstBox.y2 - pOverlay->SubPictdstBox.y1;
4309 int srcW = pOverlay->SubPictsrcW;
4310 int srcH = pOverlay->SubPictsrcH;
4311 CARD16 LCDheight = pSiS->LCDheight;
4312 int srcPitch = pOverlay->SubPictOrigPitch;
4313 int origdstH = dstH;
4315 /* Stretch image due to idiotic LCD "auto"-scaling */
4316 /* INCOMPLETE and INCORRECT - See set_scale_factor() */
4317 if( (pPriv->bridgeIsSlave) && (pSiS->VBFlags & CRT2_LCD) ) {
4318 dstH = (dstH * LCDheight) / pOverlay->SCREENheight;
4319 } else if((index) && (pSiS->VBFlags & CRT2_LCD)) {
4320 dstH = (dstH * LCDheight) / pOverlay->SCREENheight;
4321 if(pPriv->displayMode == DISPMODE_MIRROR) flag = 1;
4324 if(dstW == srcW) {
4325 pOverlay->SubPictHUSF = 0x00;
4326 pOverlay->SubPictIntBit = 0x01;
4327 } else if(dstW > srcW) {
4328 pOverlay->SubPictHUSF = (srcW << 16) / dstW;
4329 pOverlay->SubPictIntBit = 0x00;
4330 } else {
4331 int tmpW = dstW;
4333 I = 0x00;
4334 while (srcW >= tmpW) {
4335 tmpW <<= 1;
4336 I++;
4338 pOverlay->SubPictwHPre = (CARD8)(I - 1);
4339 dstW <<= (I - 1);
4340 if((srcW % dstW))
4341 pOverlay->SubPictHUSF = ((srcW - dstW) << 16) / dstW;
4342 else
4343 pOverlay->SubPictHUSF = 0x00;
4345 pOverlay->SubPictIntBit = 0x01;
4348 if(dstH == srcH) {
4349 pOverlay->SubPictVUSF = 0x00;
4350 pOverlay->SubPictIntBit |= 0x02;
4351 } else if(dstH > srcH) {
4352 dstH += 0x02;
4353 pOverlay->SubPictVUSF = (srcH << 16) / dstH;
4354 /* pOverlay->SubPictIntBit |= 0x00; */
4355 } else {
4357 I = srcH / dstH;
4358 pOverlay->SubPictIntBit |= 0x02;
4360 if(I < 2) {
4361 pOverlay->SubPictVUSF = ((srcH - dstH) << 16) / dstH;
4362 /* TW: Needed for LCD-scaling modes */
4363 if((flag) && (mult = (srcH / origdstH)) >= 2)
4364 pOverlay->SubPictPitch /= mult;
4365 } else {
4366 if(((srcPitch * I)>>2) > 0xFFF) {
4367 I = (0xFFF*2/srcPitch);
4368 pOverlay->SubPictVUSF = 0xFFFF;
4369 } else {
4370 dstH = I * dstH;
4371 if(srcH % dstH)
4372 pOverlay->SubPictVUSF = ((srcH - dstH) << 16) / dstH;
4373 else
4374 pOverlay->SubPictVUSF = 0x00;
4376 /* set video frame buffer offset */
4377 pOverlay->SubPictPitch = (CARD16)(srcPitch*I);
4380 /* set SubPicture scale factor */
4381 setvideoreg (pSiS, Index_VI_SubPict_Hor_Scale_Low, (CARD8)(pOverlay->SubPictHUSF));
4382 setvideoreg (pSiS, Index_VI_SubPict_Hor_Scale_High, (CARD8)((pOverlay->SubPictHUSF)>>8));
4383 setvideoreg (pSiS, Index_VI_SubPict_Vert_Scale_Low, (CARD8)(pOverlay->SubPictVUSF));
4384 setvideoreg (pSiS, Index_VI_SubPict_Vert_Scale_High,(CARD8)((pOverlay->SubPictVUSF)>>8));
4386 setvideoregmask (pSiS, Index_VI_SubPict_Scale_Control,
4387 (pOverlay->SubPictIntBit << 3) |
4388 (pOverlay->SubPictwHPre), 0x7f);
4391 /* Set SubPicture Preset (yet unused) */
4392 static void
4393 set_subpict_preset(SISPtr pSiS, SISOverlayPtr pOverlay)
4395 CARD32 temp;
4396 CARD8 data;
4398 temp = pOverlay->SubPictPreset >> 4; /* TW: 630 <-> 315 ? */
4400 setvideoreg(pSiS,Index_VI_SubPict_Buf_Preset_Low, temp & 0xFF);
4401 setvideoreg(pSiS,Index_VI_SubPict_Buf_Preset_Middle, (temp>>8) & 0xFF);
4402 data = getvideoreg(pSiS,Index_VI_SubPict_Buf_Start_High);
4403 if(temp > 0xFFFF)
4404 data |= 0x40;
4405 else
4406 data &= ~0x40;
4407 setvideoreg(pSiS,Index_VI_SubPict_Buf_Start_High, data);
4410 static void
4411 enable_subpict_overlay(SISPtr pSiS, Bool enable)
4413 setvideoregmask(pSiS, Index_VI_SubPict_Scale_Control,
4414 enable ? 0x40 : 0x00,
4415 0x40);
4418 /* Set overlay for subpicture */
4419 static void
4420 set_subpict_overlay(SISPtr pSiS, SISOverlayPtr pOverlay, SISPortPrivPtr pPriv, int index)
4422 ScrnInfoPtr pScrn = pSiS->pScrn;
4424 set_subpict_pitch(pSiS, &overlay, index);
4425 set_subpict_start_offset(pSiS, &overlay, index);
4426 set_subpict_scale_factor(&overlay, pScrn, pPriv, index);
4427 /* set_subpict_preset(pSiS, &overlay); */
4428 /* enable_subpict_overlay(pSiS, 1); */
4432 /* Set MPEG Field Preset (yet unused) */
4433 static void
4434 set_mpegfield_preset(SISPtr pSiS, SISOverlayPtr pOverlay)
4436 setvideoreg(pSiS,Index_MPEG_Y_Buf_Preset_Low, pOverlay->MPEG_Y & 0xFF);
4437 setvideoreg(pSiS,Index_MPEG_Y_Buf_Preset_Middle, (pOverlay->MPEG_Y>>8) & 0xFF);
4439 setvideoreg(pSiS,Index_MPEG_UV_Buf_Preset_Low, pOverlay->MPEG_UV & 0xFF);
4440 setvideoreg(pSiS,Index_MPEG_UV_Buf_Preset_Middle, (pOverlay->MPEG_UV>>8) & 0xFF);
4442 setvideoreg(pSiS,Index_MPEG_Y_UV_Buf_Preset_High,
4443 ((pOverlay->MPEG_Y>>16) & 0x0F) | ((pOverlay->MPEG_UV>>12) & 0xF0));
4446 static void
4447 set_mpegfield_scale(SISPtr pSiS, SISOverlayPtr pOverlay)
4449 /* Empty for now */
4452 #endif /* ------------------------------------------------------------------- */