sis_utility.c revision 7edd284e
1/*
2 * SiS driver utility interface & routines
3 *
4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1) Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2) Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3) The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Author: Thomas Winischhofer <thomas@winischhofer.net>
29 *
30 */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include "sis.h"
37#include <X11/X.h>
38#include "dixstruct.h"
39
40#include "sis_videostr.h"
41
42#ifdef TWDEBUG
43#define SIS_NEED_orSISIDXREG
44#include "sis_regs.h"
45#endif
46
47/* Definitions for SISCTRL extension */
48
49#define SISCTRL_PROTOCOL_NAME	"SISCTRL"
50
51#define SISCTRL_MAJOR_VERSION		0	/* current version numbers */
52#define SISCTRL_MINOR_VERSION		1
53
54#define SISCTRL_MAX_SCREENS		32	/* number of screens the ext can handle */
55
56#define X_SiSCtrlQueryVersion		0
57#define X_SiSCtrlCommand		1
58
59#define SDC_ID				0x53495321
60
61#define SDC_VERSION			1
62
63#define SDC_NUM_PARM_RESULT		20
64
65/* sdc_command */
66#define SDC_CMD_GETVERSION 		0x98980001
67#define SDC_CMD_GETHWINFO		0x98980002
68#define SDC_CMD_GETALLFLAGS		0x98980003
69#define SDC_CMD_GETVBFLAGSVERSION	0x98980004
70#define SDC_CMD_GETVBFLAGS		0x98980005
71#define SDC_CMD_CHECKMODEFORCRT2	0x98980006
72#define SDC_CMD_SETVBFLAGS		0x98980007
73#define SDC_CMD_GETDETECTEDDEVICES	0x98980008
74#define SDC_CMD_REDETECTCRT2DEVICES	0x98980009
75#define SDC_CMD_GETCRT1STATUS		0x9898000a
76#define SDC_CMD_SETCRT1STATUS		0x9898000b
77#define SDC_CMD_GETSDFLAGS		0x9898000c
78#define SDC_CMD_GETSD2FLAGS		0x9898000d
79#define SDC_CMD_GETLOCKSTATUS		0x9898000e
80#define SDC_CMD_SETLOCKSTATUS		0x9898000f
81#define SDC_CMD_GETTVANTIFLICKER	0x98980010
82#define SDC_CMD_SETTVANTIFLICKER	0x98980011
83#define SDC_CMD_GETTVSATURATION		0x98980012
84#define SDC_CMD_SETTVSATURATION		0x98980013
85#define SDC_CMD_GETTVEDGEENHANCE	0x98980014
86#define SDC_CMD_SETTVEDGEENHANCE	0x98980015
87#define SDC_CMD_GETTVCFILTER		0x98980016
88#define SDC_CMD_SETTVCFILTER		0x98980017
89#define SDC_CMD_GETTVYFILTER		0x98980018
90#define SDC_CMD_SETTVYFILTER		0x98980019
91#define SDC_CMD_GETTVCOLORCALIB		0x9898001a
92#define SDC_CMD_SETTVCOLORCALIB		0x9898001b
93#define SDC_CMD_GETTVCHCONTRAST		0x9898001c
94#define SDC_CMD_SETTVCHCONTRAST		0x9898001d
95#define SDC_CMD_GETTVCHTEXTENHANCE	0x9898001e
96#define SDC_CMD_SETTVCHTEXTENHANCE	0x9898001f
97#define SDC_CMD_GETTVCHCHROMAFLICKERFILTER 0x98980020
98#define SDC_CMD_SETTVCHCHROMAFLICKERFILTER 0x98980021
99#define SDC_CMD_GETTVCHLUMAFLICKERFILTER 0x98980022
100#define SDC_CMD_SETTVCHLUMAFLICKERFILTER 0x98980023
101#define SDC_CMD_GETTVCHCVBSCOLOR	0x98980024
102#define SDC_CMD_SETTVCHCVBSCOLOR	0x98980025
103#define SDC_CMD_GETCHTVOVERSCAN		0x98980026
104#define SDC_CMD_SETCHTVOVERSCAN		0x98980027
105#define SDC_CMD_GETGAMMASTATUS		0x98980028
106#define SDC_CMD_SETGAMMASTATUS		0x98980029
107#define SDC_CMD_GETTVXSCALE		0x9898002a
108#define SDC_CMD_SETTVXSCALE		0x9898002b
109#define SDC_CMD_GETTVYSCALE		0x9898002c
110#define SDC_CMD_SETTVYSCALE		0x9898002d
111#define SDC_CMD_GETSCREENSIZE		0x9898002e
112#define SDC_CMD_GETGAMMABRIGHTNESS	0x9898002f
113#define SDC_CMD_SETGAMMABRIGHTNESS	0x98980030
114#define SDC_CMD_GETGAMMABRIGHTNESS2	0x98980031
115#define SDC_CMD_SETGAMMABRIGHTNESS2	0x98980032
116#define SDC_CMD_GETGETGAMMACRT2		0x98980033
117#define SDC_CMD_SETGETGAMMACRT2		0x98980034
118#define SDC_CMD_GETHWCURSORSTATUS	0x98980035
119#define SDC_CMD_SETHWCURSORSTATUS	0x98980036
120#define SDC_CMD_GETPANELMODE		0x98980037
121#define SDC_CMD_SETPANELMODE		0x98980038
122#define SDC_CMD_GETMERGEDMODEDETAILS	0x98980039
123#define SDC_CMD_GETDEVICENAME		0x9898003a
124#define SDC_CMD_GETMONITORNAME		0x9898003b
125#define SDC_CMD_GETDEVICENAME2		0x9898003c
126#define SDC_CMD_GETMONITORNAME2		0x9898003d
127#define SDC_CMD_SETXVBRIGHTNESS		0x9898003e
128#define SDC_CMD_GETXVBRIGHTNESS		0x9898003f
129#define SDC_CMD_SETXVCONTRAST		0x98980040
130#define SDC_CMD_GETXVCONTRAST		0x98980041
131#define SDC_CMD_SETXVHUE		0x98980042
132#define SDC_CMD_GETXVHUE		0x98980043
133#define SDC_CMD_SETXVSATURATION		0x98980044
134#define SDC_CMD_GETXVSATURATION		0x98980045
135#define SDC_CMD_SETXVGAMMA		0x98980046
136#define SDC_CMD_GETXVGAMMA		0x98980047
137#define SDC_CMD_SETXVCOLORKEY		0x98980048
138#define SDC_CMD_GETXVCOLORKEY		0x98980049
139#define SDC_CMD_SETXVAUTOPAINTCOLORKEY	0x9898004a
140#define SDC_CMD_GETXVAUTOPAINTCOLORKEY	0x9898004b
141#define SDC_CMD_SETXVDEFAULTS		0x9898004c
142#define SDC_CMD_SETXVDISABLEGFX		0x9898004d
143#define SDC_CMD_GETXVDISABLEGFX		0x9898004e
144#define SDC_CMD_SETXVDISABLEGFXLR	0x9898004f
145#define SDC_CMD_GETXVDISABLEGFXLR	0x98980050
146#define SDC_CMD_SETXVSWITCHCRT		0x98980051
147#define SDC_CMD_GETXVSWITCHCRT		0x98980052
148#define SDC_CMD_GETTVXPOS		0x98980053
149#define SDC_CMD_SETTVXPOS		0x98980054
150#define SDC_CMD_GETTVYPOS		0x98980055
151#define SDC_CMD_SETTVYPOS		0x98980056
152#define SDC_CMD_SETXVDEINT		0x98980057
153#define SDC_CMD_GETXVDEINT		0x98980058
154#define SDC_CMD_GETMONGAMMACRT1		0x98980059
155#define SDC_CMD_GETMONGAMMACRT2		0x9898005a
156#define SDC_CMD_LOGQUIET		0x9898005b
157#define SDC_CMD_GETNEWGAMMABRICON	0x9898005c
158#define SDC_CMD_SETNEWGAMMABRICON	0x9898005d
159#define SDC_CMD_GETNEWGAMMABRICON2	0x9898005e
160#define SDC_CMD_SETNEWGAMMABRICON2	0x9898005f
161#define SDC_CMD_GETGETNEWGAMMACRT2	0x98980060
162#define SDC_CMD_SETGETNEWGAMMACRT2	0x98980061
163#define SDC_CMD_NEWSETVBFLAGS		0x98980062
164#define SDC_CMD_GETCRT1SATGAIN		0x98980063
165#define SDC_CMD_SETCRT1SATGAIN		0x98980064
166#define SDC_CMD_GETCRT2SATGAIN		0x98980065
167#define SDC_CMD_SETCRT2SATGAIN		0x98980066
168/* more to come, adapt MAXCOMMAND! */
169#define SDC_MAXCOMMAND			SDC_CMD_SETCRT2SATGAIN
170
171/* in result_header */
172#define SDC_RESULT_OK  			0x66670000
173#define SDC_RESULT_UNDEFCMD		0x66670001
174#define SDC_RESULT_NOPERM		0x66670002
175#define SDC_RESULT_INVAL		0x66670003
176#define SDC_RESULT_MESSAGEERROR		0x66670004  /* Client side only */
177#define SDC_RESULT_NOEXTENSION		0x66670005  /* Client side only */
178
179/* For SDC_CMD_GETHWINFO */
180#define SDC_BUS_TYPE_PCI		0
181#define SDC_BUS_TYPE_AGP		1
182#define SDC_BUS_TYPE_PCIE		2
183#define SDC_BUS_TYPE_USB		3
184
185/* For SDC_CMD_GETMERGEDMODEDETAILS */
186#define SDC_MMODE_POS_ERROR		0
187#define SDC_MMODE_POS_LEFTOF		1
188#define SDC_MMODE_POS_RIGHTOF		2
189#define SDC_MMODE_POS_ABOVE		3
190#define SDC_MMODE_POS_BELOW		4
191#define SDC_MMODE_POS_CLONE		5
192
193typedef struct _SiSCtrlQueryVersion {
194    CARD8	reqType;		/* always SiSCtrlReqCode */
195    CARD8	SiSCtrlReqType;		/* always X_SiSCtrlQueryVersion */
196    CARD16	length;
197} xSiSCtrlQueryVersionReq;
198#define sz_xSiSCtrlQueryVersionReq	4
199
200typedef struct {
201    BYTE	type;			/* X_Reply */
202    BOOL	pad1;
203    CARD16	sequenceNumber;
204    CARD32	length;
205    CARD16	majorVersion;		/* major version of SISCTRL */
206    CARD16	minorVersion;		/* minor version of SISCTRL */
207    CARD32	pad2;
208    CARD32	pad3;
209    CARD32	pad4;
210    CARD32	pad5;
211    CARD32	pad6;
212} xSiSCtrlQueryVersionReply;
213#define sz_xSiSCtrlQueryVersionReply	32
214
215typedef struct {
216    CARD8	reqType;		/* always SiSCtrlReqCode */
217    CARD8	SiSCtrlReqType;		/* always SiSCtrl_SiSCtrlCommand */
218    CARD16	length;
219    CARD32	pad1;
220    CARD32	screen;
221    CARD32 	sdc_id;
222    CARD32 	sdc_chksum;
223    CARD32	sdc_command;
224    CARD32	sdc_parm[SDC_NUM_PARM_RESULT];
225    CARD32	sdc_result_header;
226    CARD32	sdc_result[SDC_NUM_PARM_RESULT];
227    char	sdc_buffer[32];
228} xSiSCtrlCommandReq;
229#define sz_xSiSCtrlCommandReq		(28 + (SDC_NUM_PARM_RESULT * 4 * 2) + 32)
230
231typedef struct {
232    BYTE	type;			/* X_Reply */
233    BOOL	pad1;
234    CARD16	sequenceNumber;
235    CARD32	length;
236    CARD32	screen;
237    CARD32 	sdc_id;
238    CARD32 	sdc_chksum;
239    CARD32	sdc_command;
240    CARD32	sdc_parm[SDC_NUM_PARM_RESULT];
241    CARD32	sdc_result_header;
242    CARD32	sdc_result[SDC_NUM_PARM_RESULT];
243    char	sdc_buffer[32];
244} xSiSCtrlCommandReply;
245#define sz_xSiSCtrlCommandReply		(28 + (SDC_NUM_PARM_RESULT * 4 * 2) + 32)
246
247typedef struct {
248    unsigned int maxscreens;		/* Max number of entries = SISCTRL_MAX_SCREENS*/
249    unsigned int version_major;		/* Extension major version */
250    unsigned int version_minor; 	/* Extension minor version */
251    int		 (*HandleSiSDirectCommand[SISCTRL_MAX_SCREENS])(xSiSCtrlCommandReply *);
252} xSiSCtrlScreenTable;
253
254void		SiSCtrlExtInit(ScrnInfoPtr pScrn);
255void		SiSCtrlExtUnregister(SISPtr pSiS, int index);
256
257#ifdef XV_SD_DEPRECATED
258int		SISSetPortUtilAttribute(ScrnInfoPtr pScrn, Atom attribute,
259					INT32 value, SISPortPrivPtr pPriv);
260int		SISGetPortUtilAttribute(ScrnInfoPtr pScrn,  Atom attribute,
261					INT32 *value, SISPortPrivPtr pPriv);
262#endif
263
264extern Bool 	SISRedetectCRT2Type(ScrnInfoPtr pScrn);
265extern UShort	SiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode,
266				 unsigned int VBFlags, Bool hcm);
267extern UShort	SiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode,
268				 unsigned int VBFlags, Bool hcm);
269extern void	SISAdjustFrame(ADJUST_FRAME_ARGS_DECL);
270extern float	SiSCalcVRate(DisplayModePtr mode);
271extern void	SiS_UpdateGammaCRT2(ScrnInfoPtr pScrn);
272#ifdef SISGAMMARAMP
273extern void	SISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn);
274#endif
275
276extern void	SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv);
277extern void	SISUpdateVideoParms(SISPtr pSiS, SISPortPrivPtr pPriv);
278extern void	SiSUpdateXvGamma(SISPtr pSiS, SISPortPrivPtr pPriv);
279
280/***********************************
281 *        Low-level routines       *
282 ***********************************/
283
284static Bool
285SISSwitchCRT1Status(ScrnInfoPtr pScrn, int onoff, Bool quiet)
286{
287    SISPtr pSiS = SISPTR(pScrn);
288    DisplayModePtr mode = pScrn->currentMode;
289    ULong vbflags = pSiS->VBFlags;
290    ULong vbflags3 = pSiS->VBFlags3;
291    int crt1off;
292
293    /* onoff: 0=OFF, 1=ON(VGA), 2=ON(LCDA) */
294
295    /* Switching to LCDA will disable CRT2 if previously LCD or VGA,
296     * unless on a dual-vb setup
297     */
298
299    /* For usability reasons, the user should not simply "lose" one
300     * of his output devices in MergedFB mode. Therefore, a switch
301     * which might lead to this situation will not be performed in
302     * MergedFB mode. (For example: If CRT2 is either LCD or VGA,
303     * don't let the user switch to LCD-via-CRT1 mode, because he
304     * would lose one output device since LCD-via-CRT1 is only
305     * supported together with TV, not any other CRT2 type.)
306     * In Non-MergedFB mode, losing one output device is not
307     * considered that harmful.
308     * Update: We let the user switch off a device if currently
309     * a "clone" mode is active. Same for switching CRT1 to LCD
310     * while CRT2 is LCD or VGA.
311     */
312
313    /* Do NOT use this to switch from CRT1_LCDA to CRT2_LCD */
314
315    /* Only on 300 and 315/330/340 series */
316    if(pSiS->VGAEngine != SIS_300_VGA &&
317       pSiS->VGAEngine != SIS_315_VGA) return FALSE;
318
319    /* Off only if at least one CRT2 device is active */
320    if((!onoff) && (!(vbflags & CRT2_ENABLE))) return FALSE;
321
322#ifdef SISDUALHEAD
323    if(pSiS->DualHeadMode) return FALSE;
324#endif
325
326    /* Can't switch to LCDA if not supported (duh!) */
327    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA)) {
328       if(onoff == 2) {
329          if(!quiet) {
330             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
331	        "LCD-via-CRT1 not supported by hardware or no panel detected\n");
332	  }
333          return FALSE;
334       }
335    }
336
337#ifdef SISMERGED
338    if(pSiS->MergedFB) {
339       if(((SiSMergedDisplayModePtr)mode->Private)->CRT2Position != sisClone) {
340          if(!onoff) {
341             if(!quiet) {
342                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
343	           "CRT1 can't be switched off in MergedFB mode unless a clone mode is active\n");
344	     }
345             return FALSE;
346          } else if(onoff == 2) {
347             if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
348                if(vbflags & (CRT2_LCD|CRT2_VGA)) {
349	           if(!quiet) {
350	              xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
351	   	         "CRT1 type can only be VGA while CRT2 is LCD or VGA\n");
352	           }
353                   return FALSE;
354                }
355	     }
356          }
357       }
358       if(mode->Private) {
359	  mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
360       }
361    }
362#endif
363
364    vbflags &= ~(DISPTYPE_CRT1 | SINGLE_MODE | MIRROR_MODE | CRT1_LCDA);
365    vbflags3 &= ~(VB3_CRT1_TV | VB3_CRT1_LCD | VB3_CRT1_VGA);
366    crt1off = 1;
367    if(onoff > 0) {
368       vbflags |= DISPTYPE_CRT1;
369       crt1off = 0;
370       if(onoff == 2) {
371	  vbflags |= CRT1_LCDA;
372	  vbflags3 |= VB3_CRT1_LCD;
373	  if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
374	     vbflags &= ~(CRT2_LCD|CRT2_VGA);
375	  }
376       } else {
377          vbflags3 |= VB3_CRT1_VGA;
378       }
379       /* Remember: Dualhead not supported */
380       if(vbflags & CRT2_ENABLE) vbflags |= MIRROR_MODE;
381       else vbflags |= SINGLE_MODE;
382    } else {
383       vbflags |= SINGLE_MODE;
384    }
385
386    if(vbflags & CRT1_LCDA) {
387       if(SiS_CheckModeCRT1(pScrn, mode, vbflags, pSiS->HaveCustomModes) < 0x14) {
388          if(!quiet) {
389             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
390		"Current mode not suitable for LCD-via-CRT1\n");
391	  }
392          return FALSE;
393       }
394    }
395
396    pSiS->CRT1off = crt1off;
397    pSiS->VBFlags = pSiS->VBFlags_backup = vbflags;
398    pSiS->VBFlags3 = pSiS->VBFlags_backup3 = vbflags3;
399
400    /* Sync the accelerators */
401    (*pSiS->SyncAccel)(pScrn);
402
403    pSiS->skipswitchcheck = TRUE;
404    if(!(pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)))) {
405       pSiS->skipswitchcheck = FALSE;
406       return FALSE;
407    }
408    pSiS->skipswitchcheck = FALSE;
409    SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
410    return TRUE;
411}
412
413static Bool
414SISRedetectCRT2Devices(ScrnInfoPtr pScrn)
415{
416    SISPtr pSiS = SISPTR(pScrn);
417
418    if((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) {
419       return FALSE;
420    }
421
422#ifdef SISDUALHEAD
423    if(pSiS->DualHeadMode) return FALSE;
424#endif
425
426    /* Sync the accelerators */
427    (*pSiS->SyncAccel)(pScrn);
428
429    if(SISRedetectCRT2Type(pScrn)) {
430       /* If this returns TRUE, we need to reset the display mode */
431       /* Sync the accelerators */
432       (*pSiS->SyncAccel)(pScrn);
433       pSiS->skipswitchcheck = TRUE;
434       if(!(pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)))) {
435          pSiS->skipswitchcheck = FALSE;
436          return FALSE;
437       }
438       pSiS->skipswitchcheck = FALSE;
439       SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
440    }
441    return TRUE;
442}
443
444static Bool
445SISSwitchCRT2Type(ScrnInfoPtr pScrn, ULong newvbflags, Bool quiet)
446{
447    SISPtr pSiS = SISPTR(pScrn);
448    Bool hcm = pSiS->HaveCustomModes;
449    DisplayModePtr mode = pScrn->currentMode;
450
451    /* Do NOT use this to switch from CRT2_LCD to CRT1_LCDA */
452
453    /* Switching CRT2 to LCD or VGA will switch CRT1 to VGA if
454     * previously LCD-via-CRT1
455     */
456
457    /* For usability reasons, the user should not simply "lose" one
458     * of his output devices in MergedFB mode. Therefore, a switch
459     * which might lead to this situation will not be performed in
460     * MergedFB mode. (For example: If CRT1 is LCD-via-CRT1, don't
461     * let the user switch CRT2 to LCD or VGA mode, because he
462     * would lose one output device since LCD-via-CRT1 is only
463     * supported together with TV, not any other CRT2 type.)
464     * In Non-MergedFB mode, losing one output device is not
465     * considered that harmful.
466     * Update: We allow this if currently a "clone" display mode
467     * is active.
468     */
469
470    /* Only on 300 and 315/330/340 series */
471    if(pSiS->VGAEngine != SIS_300_VGA &&
472       pSiS->VGAEngine != SIS_315_VGA) return FALSE;
473
474    /* Only if there is a video bridge */
475    if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE;
476
477#ifdef SISDUALHEAD
478    if(pSiS->DualHeadMode) return FALSE;
479#endif
480
481#define SiS_NewVBMask (CRT2_ENABLE|CRT1_LCDA|TV_PAL|TV_NTSC|TV_PALM|TV_PALN|TV_NTSCJ| \
482		       TV_AVIDEO|TV_SVIDEO|TV_SCART|TV_HIVISION|TV_YPBPR|TV_YPBPRALL|\
483		       TV_YPBPRAR)
484
485    newvbflags &= SiS_NewVBMask;
486    newvbflags |= pSiS->VBFlags & ~SiS_NewVBMask;
487
488    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA)) {
489       newvbflags &= ~CRT1_LCDA;
490    }
491    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) {
492       newvbflags &= ~TV_HIVISION;
493    }
494    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) {
495       newvbflags &= ~TV_YPBPR;
496    }
497
498#ifdef SISMERGED
499    if(pSiS->MergedFB) {
500       if((mode->Private) &&
501          ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position != sisClone) {
502          if(!(newvbflags & CRT2_ENABLE)) {
503             if(!quiet) {
504	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
505	           "CRT2 can't be switched off in MergedFB mode unless a clone mode is active\n");
506	     }
507	     return FALSE;
508          }
509          if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
510             if((newvbflags & (CRT2_LCD|CRT2_VGA)) && (newvbflags & CRT1_LCDA)) {
511                if(!quiet) {
512	           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
513	              "CRT2 type can only be TV while in LCD-via-CRT1 mode\n");
514	        }
515	        return FALSE;
516	     }
517          }
518       }
519       hcm = pSiS->HaveCustomModes2;
520       if(mode->Private) {
521	  mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2;
522       }
523    }
524#endif
525
526    if((!(newvbflags & CRT2_ENABLE)) && (!(newvbflags & DISPTYPE_CRT1))) {
527       if(!quiet) {
528          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
529             "CRT2 can't be switched off while CRT1 is off\n");
530       }
531       return FALSE;
532    }
533
534    /* CRT2_LCD and CRT2_VGA overrule LCDA (in non-MergedFB mode) */
535    if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
536       if(newvbflags & (CRT2_LCD|CRT2_VGA)) {
537          newvbflags &= ~CRT1_LCDA;
538       }
539    }
540
541    /* Check if the current mode is suitable for desired output device (if any) */
542    if(SiS_CheckModeCRT2(pScrn, mode, newvbflags, hcm) < 0x14) {
543       if(!quiet) {
544          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
545	     "Current mode not suitable for desired CRT2 output device\n");
546       }
547       return FALSE;
548    }
549
550    /* Remember: Dualhead not supported */
551    newvbflags &= ~(SINGLE_MODE | MIRROR_MODE);
552    if((newvbflags & DISPTYPE_CRT1) && (newvbflags & CRT2_ENABLE)) {
553       newvbflags |= MIRROR_MODE;
554    } else {
555       newvbflags |= SINGLE_MODE;
556    }
557
558    /* Sync the accelerators */
559    (*pSiS->SyncAccel)(pScrn);
560
561    pSiS->VBFlags = pSiS->VBFlags_backup = newvbflags;
562
563    pSiS->skipswitchcheck = TRUE;
564    if(!(pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)))) {
565       pSiS->skipswitchcheck = FALSE;
566       return FALSE;
567    }
568    pSiS->skipswitchcheck = FALSE;
569    SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
570    return TRUE;
571}
572
573static Bool
574SISSwitchOutputType(ScrnInfoPtr pScrn, ULong newvbflags, ULong newvbflags3,
575		ULong newvbflags4, Bool quiet)
576{
577    /* For future use */
578
579    return FALSE;
580}
581
582static ULong
583SiSCondToVBFlags(UShort cond, ULong GivenVBFlags)
584{
585    ULong vbflags = GivenVBFlags;
586
587    /* No special treatment for NTSC-J here; conditions equal NTSC */
588    if(cond) {
589       vbflags &= ~(CRT2_ENABLE | CRT1_LCDA | TV_STANDARD | TV_INTERFACE);
590       if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_LCD) {
591	  vbflags |= CRT2_LCD;
592       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_TV) {
593	  vbflags |= (CRT2_TV | TV_SVIDEO);
594	  if(cond & SiS_CF2_TVPAL)  	  vbflags |= TV_PAL;
595	  else if(cond & SiS_CF2_TVPALM)  vbflags |= (TV_PAL | TV_PALM);
596	  else if(cond & SiS_CF2_TVPALN)  vbflags |= (TV_PAL | TV_PALN);
597	  else if(cond & SiS_CF2_TVNTSC)  vbflags |= TV_NTSC;
598       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_TVSPECIAL) {
599          vbflags |= CRT2_TV;
600	  if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVHIVISION)
601		vbflags |= TV_HIVISION;
602	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR525I)
603		vbflags |= (TV_YPBPR | TV_YPBPR525I);
604	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR525P)
605		vbflags |= (TV_YPBPR | TV_YPBPR525P);
606	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR625I)
607		vbflags |= (TV_YPBPR | TV_YPBPR625I);
608	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR625P)
609		vbflags |= (TV_YPBPR | TV_YPBPR625P);
610	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR750P)
611		vbflags |= (TV_YPBPR | TV_YPBPR750P);
612	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR1080I)
613		vbflags |= (TV_YPBPR | TV_YPBPR1080I);
614       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_VGA2) {
615	  vbflags |= CRT2_VGA;
616       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_CRT1LCDA) {
617	  vbflags |= CRT1_LCDA;
618       }
619    }
620    return(vbflags);
621}
622
623static int
624SISCheckModeForCRT2Type(ScrnInfoPtr pScrn, DisplayModePtr mode, ULong vbflags, UShort cond, Bool quiet)
625{
626    SISPtr pSiS = SISPTR(pScrn);
627    DisplayModePtr mastermode;
628    Bool hcm = pSiS->HaveCustomModes;
629    int result = 0;
630
631    mastermode = mode;
632
633#ifdef SISDUALHEAD
634    if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) {
635#endif
636
637       if(vbflags & CRT2_ENABLE) {
638
639#ifdef SISMERGED
640          if(pSiS->MergedFB) {
641             hcm = pSiS->HaveCustomModes2;
642             if(mode->Private) {
643	        mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2;
644             }
645          }
646#endif
647
648          /* For RandR */
649          if((mode->HDisplay > pScrn->virtualX) || (mode->VDisplay > pScrn->virtualY)) {
650             if(!quiet) {
651                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
652		    "Desired mode too large for current screen size\n");
653             }
654             result |= 0x02;
655          }
656
657          /* Check if the desired mode is suitable for current CRT2 output device */
658          if(SiS_CheckModeCRT2(pScrn, mode, vbflags, hcm) < 0x14) {
659             if((!cond) && (!quiet)) {
660                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
661		    "Desired mode not suitable for current CRT2 output device\n");
662             }
663             result |= 0x01;
664          }
665
666       }
667
668#ifdef SISDUALHEAD
669    }
670#endif
671
672    mode = mastermode;
673
674#ifdef SISDUALHEAD
675    if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) {
676#endif
677
678       if(vbflags & CRT1_LCDA) {
679
680#ifdef SISMERGED
681          if(pSiS->MergedFB) {
682             hcm = pSiS->HaveCustomModes;
683             if(mode->Private) {
684	        mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
685	     }
686          }
687#endif
688
689	  /* For RandR */
690	  if((mode->HDisplay > pScrn->virtualX) || (mode->VDisplay > pScrn->virtualY)) {
691	     if(!quiet) {
692		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
693			"Desired mode too large for current screen size\n");
694	     }
695	     result |= 0x02;
696	  }
697
698	  /* Check if the desired mode is suitable for current CRT1 output device */
699	  if(SiS_CheckModeCRT1(pScrn, mode, vbflags, hcm) < 0x14) {
700	     if((!cond) && (!quiet)) {
701		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
702		      "Desired mode not suitable for current CRT1 output device\n");
703	     }
704	     result |= 0x01;
705	  }
706
707       }
708
709#ifdef SISDUALHEAD
710    }
711#endif
712
713    return result;
714}
715
716#ifdef XV_SD_DEPRECATED
717static int
718SISCheckModeIndexForCRT2Type(ScrnInfoPtr pScrn, UShort cond, UShort index, Bool quiet)
719{
720    SISPtr pSiS = SISPTR(pScrn);
721    DisplayModePtr mode = pScrn->modes;
722    ULong vbflags;
723    int i;
724
725    /* Not only CRT2, but also LCDA */
726
727    /* returns 0 if mode ok,
728     *         0x01 if mode not ok for CRT2 device,
729     *         0x02 if mode too large for current root window
730     *         or combinations thereof
731     */
732
733    vbflags = SiSCondToVBFlags(cond, pSiS->VBFlags);
734
735    /* Find mode of given index */
736    if(index) {
737       for(i = 0; i < index; i++) {
738          if(!mode) return 0x03;
739          mode = mode->next;
740       }
741    }
742
743    return(SISCheckModeForCRT2Type(pScrn, mode, vbflags, cond, quiet));
744}
745#endif
746
747static DisplayModePtr
748sisFindModeFromTiming(ScrnInfoPtr pScrn, UShort hdisplay,
749			      UShort vdisplay, UShort htotal, UShort vtotal,
750			      UShort hsyncstart, UShort hsyncend, UShort vsyncstart,
751			      UShort vsyncend, int clock)
752{
753   DisplayModePtr mode = pScrn->modes, pmode = pScrn->modes;
754   Bool found = FALSE;
755
756   do {
757       if( (mode->HDisplay == hdisplay) &&
758           (mode->VDisplay == vdisplay) &&
759	   (mode->HTotal == htotal) &&
760	   (mode->VTotal == vtotal) &&
761	   (mode->HSyncStart == hsyncstart) &&
762	   (mode->VSyncStart == vsyncstart) &&
763	   (mode->HSyncEnd == hsyncend) &&
764	   (mode->VSyncEnd == vsyncend) &&
765	   (mode->Clock == clock) ) {
766	  found = TRUE;
767	  break;
768       }
769       mode = mode->next;
770    } while((mode) && (mode != pmode));
771
772    if(found) return mode;
773    else      return NULL;
774}
775
776static int
777SISCheckModeTimingForCRT2Type(ScrnInfoPtr pScrn, UShort cond, UShort hdisplay,
778			      UShort vdisplay, UShort htotal, UShort vtotal,
779			      UShort hsyncstart, UShort hsyncend, UShort vsyncstart,
780			      UShort vsyncend, int clock, Bool quiet)
781{
782    SISPtr pSiS = SISPTR(pScrn);
783    DisplayModePtr mode;
784    ULong vbflags;
785
786    /* Not only CRT2, but also LCDA */
787
788    /* returns 0 if mode ok,
789     *         0x01 if mode not ok for CRT2 device,
790     *         0x02 if mode too large for current root window
791     *         or combinations thereof
792     */
793
794    vbflags = SiSCondToVBFlags(cond, pSiS->VBFlags);
795
796    /* Find mode with given timing */
797    mode = sisFindModeFromTiming(pScrn, hdisplay, vdisplay, htotal, vtotal,
798				hsyncstart, hsyncend, vsyncstart, vsyncend,
799				clock);
800    if(!mode) return 0x03;
801
802    return(SISCheckModeForCRT2Type(pScrn, mode, vbflags, cond, quiet));
803}
804
805#ifdef SISMERGED
806static void
807SISGetMergedModeDetails(ScrnInfoPtr pScrn,
808	   int hd, int vd, int ht, int vt, int hss, int hse, int vss, int vse, int clk,
809	   unsigned int *pos, unsigned int *crt1x, unsigned int *crt1y,
810	   unsigned int *crt1clk, unsigned int *crt2x, unsigned int *crt2y,
811	   unsigned int *crt2clk)
812{
813    SISPtr pSiS = SISPTR(pScrn);
814    DisplayModePtr mode, tmode;
815
816    if(!pSiS->MergedFB) {
817       *pos = SDC_MMODE_POS_ERROR;
818       return;
819    }
820
821    /* Find mode with given timing */
822    mode = sisFindModeFromTiming(pScrn, hd, vd, ht, vt, hss, hse, vss, vse, clk);
823    if(!mode) {
824       *pos = SDC_MMODE_POS_ERROR;
825       return;
826    }
827
828    switch(((SiSMergedDisplayModePtr)mode->Private)->CRT2Position) {
829       case sisLeftOf:  *pos = SDC_MMODE_POS_LEFTOF;  break;
830       case sisRightOf: *pos = SDC_MMODE_POS_RIGHTOF; break;
831       case sisAbove:   *pos = SDC_MMODE_POS_ABOVE;   break;
832       case sisBelow:   *pos = SDC_MMODE_POS_BELOW;   break;
833       default:         *pos = SDC_MMODE_POS_CLONE;
834    }
835
836    tmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
837    *crt1x = tmode->HDisplay;
838    *crt1y = tmode->VDisplay;
839    *crt1clk = (unsigned int)SiSCalcVRate(tmode);
840
841    tmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2;
842    *crt2x = tmode->HDisplay;
843    *crt2y = tmode->VDisplay;
844    *crt2clk = (unsigned int)SiSCalcVRate(tmode);
845}
846#endif
847
848/***********************************
849 *   SiSCtrl extension interface   *
850 ***********************************/
851
852static void
853sisutil_prepare_string(xSiSCtrlCommandReply *sdcbuf, const char *mystring)
854{
855   int slen = 0;
856   sdcbuf->sdc_buffer[0] = 0;
857   if(mystring) {
858      slen = strlen(mystring);
859      if(slen > 31) slen = 31;
860      strncpy(&sdcbuf->sdc_buffer[0], mystring, slen);
861      sdcbuf->sdc_buffer[slen] = 0;
862   }
863   sdcbuf->sdc_result[0] = slen;
864}
865
866static int
867SiSHandleSiSDirectCommand(xSiSCtrlCommandReply *sdcbuf)
868{
869   ScrnInfoPtr pScrn = xf86ScreenToScrn(screenInfo.screens[sdcbuf->screen]);
870   SISPtr pSiS = SISPTR(pScrn);
871#ifdef SISDUALHEAD
872   SISEntPtr pSiSEnt = pSiS->entityPrivate;
873#endif
874   SISPortPrivPtr pPriv = NULL;
875   int i;
876   ULong j;
877
878   if(sdcbuf->sdc_id != SDC_ID) return BadMatch;
879
880   if(pSiS->adaptor) {
881      pPriv = GET_PORT_PRIVATE(pScrn);
882   }
883
884   j = sdcbuf->sdc_command;
885   for(i = 0; i < SDC_NUM_PARM_RESULT; i++) {
886      j += sdcbuf->sdc_parm[i];
887   }
888
889   if(j != sdcbuf->sdc_chksum) return BadMatch;
890
891   sdcbuf->sdc_result_header = SDC_RESULT_OK;
892
893   switch(sdcbuf->sdc_command) {
894
895   case SDC_CMD_GETVERSION:
896      sdcbuf->sdc_result[0] = SDC_VERSION;
897      sdcbuf->sdc_result[1] = SDC_MAXCOMMAND;
898      break;
899
900   case SDC_CMD_GETHWINFO:
901      {
902	 UShort romptr = 0;
903	 char *biosvers = NULL;
904	 int slen = 0;
905
906	 if(pSiS->BIOS) {
907	    romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8);
908	    if(romptr < 65530) {
909	       biosvers = (char *)&pSiS->BIOS[romptr];
910	       slen = strlen(biosvers);
911	       if(slen > 10) slen = 10;
912	    }
913	 }
914	 sdcbuf->sdc_result[0]  = pSiS->IsAGPCard ? SDC_BUS_TYPE_AGP : SDC_BUS_TYPE_PCI;
915	 if(pSiS->IsPCIExpress) sdcbuf->sdc_result[0] = SDC_BUS_TYPE_PCIE;
916	 sdcbuf->sdc_result[1]  = pSiS->PciBus;
917	 sdcbuf->sdc_result[2]  = pSiS->PciDevice;
918	 sdcbuf->sdc_result[3]  = pSiS->PciFunc;
919	 sdcbuf->sdc_result[4]  = pSiS->ROM661New ? 1 : (pSiS->HaveXGIBIOS ? 2 : 0),
920	 sdcbuf->sdc_result[5]  = pSiS->ChipFlags;
921	 sdcbuf->sdc_result[6]  = pSiS->ChipType;
922	 sdcbuf->sdc_result[7]  = pSiS->ChipRev;
923	 sdcbuf->sdc_result[8]  = SISDRIVERVERSIONYEAR;
924	 sdcbuf->sdc_result[9]  = SISDRIVERVERSIONMONTH;
925	 sdcbuf->sdc_result[10] = SISDRIVERVERSIONDAY;
926	 sdcbuf->sdc_result[11] = SISDRIVERREVISION;
927	 sdcbuf->sdc_result[12] = pScrn->videoRam;
928	 sdcbuf->sdc_result[13] = pSiS->UMAsize;
929	 sdcbuf->sdc_result[14] = pSiS->LFBsize;
930	 if(slen) strncpy(&sdcbuf->sdc_buffer[0], biosvers, slen);
931	 sdcbuf->sdc_buffer[slen] = 0;
932      }
933      break;
934
935   case SDC_CMD_GETALLFLAGS:
936      sdcbuf->sdc_result[0] = SIS_VBFlagsVersion;
937      sdcbuf->sdc_result[1] = pSiS->VBFlags;
938      sdcbuf->sdc_result[2] = pSiS->SiS_SD_Flags;
939      sdcbuf->sdc_result[3] = pSiS->SiS_SD2_Flags;
940      sdcbuf->sdc_result[4] = pSiS->detectedCRT2Devices;
941      sdcbuf->sdc_result[5] = pSiS->VBFlags2;
942      sdcbuf->sdc_result[6] = pSiS->SiS_SD3_Flags;
943      sdcbuf->sdc_result[7] = pSiS->SiS_SD4_Flags;
944      sdcbuf->sdc_result[8] = pSiS->VBFlags3;
945      sdcbuf->sdc_result[9] = pSiS->VBFlags4;
946      break;
947
948   case SDC_CMD_GETVBFLAGSVERSION:
949      sdcbuf->sdc_result[0] = SIS_VBFlagsVersion;
950      break;
951
952   case SDC_CMD_GETVBFLAGS:
953      sdcbuf->sdc_result[0] = pSiS->VBFlags;
954      sdcbuf->sdc_result[1] = pSiS->VBFlags2;
955      sdcbuf->sdc_result[2] = pSiS->VBFlags3;
956      sdcbuf->sdc_result[3] = pSiS->VBFlags4;
957      break;
958
959   case SDC_CMD_CHECKMODEFORCRT2:
960      {
961	 int clk, hd, hss, hse, ht, vd, vss, vse, vt, result;
962	 ULong flags;
963
964	 flags = sdcbuf->sdc_parm[0];
965	 clk   = sdcbuf->sdc_parm[1];
966	 hd    = sdcbuf->sdc_parm[2];
967	 hss   = sdcbuf->sdc_parm[3];
968	 hse   = sdcbuf->sdc_parm[4];
969	 ht    = sdcbuf->sdc_parm[5];
970	 vd    = sdcbuf->sdc_parm[6];
971	 vss   = sdcbuf->sdc_parm[7];
972	 vse   = sdcbuf->sdc_parm[8];
973	 vt    = sdcbuf->sdc_parm[9];
974
975	 result = SISCheckModeTimingForCRT2Type(pScrn, (UShort)(flags & 0xff),
976			hd, vd, ht, vt, hss, hse, vss, vse, clk, pSiS->SCLogQuiet) & 0xff;
977	 sdcbuf->sdc_result[0] = result;
978      }
979      break;
980
981   case SDC_CMD_SETVBFLAGS:
982#ifdef SISDUALHEAD
983      if(!pSiS->DualHeadMode) {
984#endif
985	 if(pSiS->xv_sisdirectunlocked) {
986	    SISSwitchCRT2Type(pScrn, (ULong)sdcbuf->sdc_parm[0], pSiS->SCLogQuiet);
987	    if(pPriv) SISUpdateVideoParms(pSiS, pPriv);
988	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
989#ifdef SISDUALHEAD
990      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
991#endif
992      break;
993
994   case SDC_CMD_NEWSETVBFLAGS:
995#ifdef SISDUALHEAD
996      if(!pSiS->DualHeadMode) {
997#endif
998	 if(pSiS->xv_sisdirectunlocked) {
999	    SISSwitchOutputType(pScrn, (ULong)sdcbuf->sdc_parm[0], (ULong)sdcbuf->sdc_parm[1],
1000	    		(ULong)sdcbuf->sdc_parm[2], pSiS->SCLogQuiet);
1001	    if(pPriv) SISUpdateVideoParms(pSiS, pPriv);
1002	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1003#ifdef SISDUALHEAD
1004      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1005#endif
1006      break;
1007
1008   case SDC_CMD_GETDETECTEDDEVICES:
1009      sdcbuf->sdc_result[0] = pSiS->detectedCRT2Devices;
1010      break;
1011
1012   case SDC_CMD_REDETECTCRT2DEVICES:
1013#ifdef SISDUALHEAD
1014      if(!pSiS->DualHeadMode) {
1015#endif
1016	 if(pSiS->xv_sisdirectunlocked) {
1017	    SISRedetectCRT2Devices(pScrn);
1018	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1019#ifdef SISDUALHEAD
1020      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1021#endif
1022      break;
1023
1024   case SDC_CMD_GETCRT1STATUS:
1025      sdcbuf->sdc_result[0] = pSiS->CRT1isoff ? 0 : 1;
1026      break;
1027
1028   case SDC_CMD_SETCRT1STATUS:
1029#ifdef SISDUALHEAD
1030      if(!pSiS->DualHeadMode) {
1031#endif
1032	 if(pSiS->xv_sisdirectunlocked) {
1033	    SISSwitchCRT1Status(pScrn, (ULong)sdcbuf->sdc_parm[0], pSiS->SCLogQuiet);
1034	    if(pPriv) SISUpdateVideoParms(pSiS, pPriv);
1035	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1036#ifdef SISDUALHEAD
1037      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1038#endif
1039      break;
1040
1041   case SDC_CMD_GETSDFLAGS:
1042      sdcbuf->sdc_result[0] = pSiS->SiS_SD_Flags;
1043      break;
1044
1045   case SDC_CMD_GETSD2FLAGS:
1046      sdcbuf->sdc_result[0] = pSiS->SiS_SD2_Flags;
1047      break;
1048
1049   case SDC_CMD_GETLOCKSTATUS:
1050      sdcbuf->sdc_result[0] = pSiS->xv_sisdirectunlocked;
1051      break;
1052
1053   case SDC_CMD_SETLOCKSTATUS:
1054      if(pSiS->enablesisctrl) {
1055	 if(sdcbuf->sdc_parm[0] == SIS_DIRECTKEY) {
1056	    pSiS->xv_sisdirectunlocked++;
1057	 } else if(pSiS->xv_sisdirectunlocked) {
1058	    pSiS->xv_sisdirectunlocked--;
1059	 }
1060      } else {
1061	 pSiS->xv_sisdirectunlocked = 0;
1062	 sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1063      }
1064      break;
1065
1066   case SDC_CMD_GETTVANTIFLICKER:
1067      sdcbuf->sdc_result[0] = SiS_GetSISTVantiflicker(pScrn);
1068      break;
1069
1070   case SDC_CMD_SETTVANTIFLICKER:
1071      if(pSiS->xv_sisdirectunlocked) {
1072	 SiS_SetSISTVantiflicker(pScrn, (int)sdcbuf->sdc_parm[0]);
1073      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1074      break;
1075
1076   case SDC_CMD_GETTVSATURATION:
1077      sdcbuf->sdc_result[0] = SiS_GetSISTVsaturation(pScrn);
1078      break;
1079
1080   case SDC_CMD_SETTVSATURATION:
1081      if(pSiS->xv_sisdirectunlocked) {
1082	 SiS_SetSISTVsaturation(pScrn, (int)sdcbuf->sdc_parm[0]);
1083      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1084      break;
1085
1086   case SDC_CMD_GETTVEDGEENHANCE:
1087      sdcbuf->sdc_result[0] = SiS_GetSISTVedgeenhance(pScrn);;
1088      break;
1089
1090   case SDC_CMD_SETTVEDGEENHANCE:
1091      if(pSiS->xv_sisdirectunlocked) {
1092	 SiS_SetSISTVedgeenhance(pScrn, (int)sdcbuf->sdc_parm[0]);
1093      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1094      break;
1095
1096   case SDC_CMD_GETTVCFILTER:
1097      sdcbuf->sdc_result[0] = SiS_GetSISTVcfilter(pScrn);
1098      break;
1099
1100   case SDC_CMD_SETTVCFILTER:
1101      if(pSiS->xv_sisdirectunlocked) {
1102	 SiS_SetSISTVcfilter(pScrn, sdcbuf->sdc_parm[0] ? 1 : 0);
1103      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1104      break;
1105
1106   case SDC_CMD_GETTVYFILTER:
1107      sdcbuf->sdc_result[0] = SiS_GetSISTVyfilter(pScrn);
1108      break;
1109
1110   case SDC_CMD_SETTVYFILTER:
1111      if(pSiS->xv_sisdirectunlocked) {
1112	 SiS_SetSISTVyfilter(pScrn, sdcbuf->sdc_parm[0]);
1113      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1114      break;
1115
1116   case SDC_CMD_GETTVCOLORCALIB:
1117      sdcbuf->sdc_result[0] = SiS_GetSISTVcolcalib(pScrn, TRUE) + 32768;
1118      sdcbuf->sdc_result[1] = SiS_GetSISTVcolcalib(pScrn, FALSE) + 32768;
1119      break;
1120
1121   case SDC_CMD_SETTVCOLORCALIB:
1122      if(pSiS->xv_sisdirectunlocked) {
1123         SiS_SetSISTVcolcalib(pScrn, (int)sdcbuf->sdc_parm[0] - 32768, TRUE);
1124	 SiS_SetSISTVcolcalib(pScrn, (int)sdcbuf->sdc_parm[1] - 32768, FALSE);
1125      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1126      break;
1127
1128   case SDC_CMD_GETTVCHCONTRAST:
1129      sdcbuf->sdc_result[0] = SiS_GetCHTVcontrast(pScrn);
1130      break;
1131
1132   case SDC_CMD_SETTVCHCONTRAST:
1133      if(pSiS->xv_sisdirectunlocked) {
1134	 SiS_SetCHTVcontrast(pScrn, (int)sdcbuf->sdc_parm[0]);
1135      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1136      break;
1137
1138   case SDC_CMD_GETTVCHTEXTENHANCE:
1139      sdcbuf->sdc_result[0] = SiS_GetCHTVtextenhance(pScrn);
1140      break;
1141
1142   case SDC_CMD_SETTVCHTEXTENHANCE:
1143      if(pSiS->xv_sisdirectunlocked) {
1144	 SiS_SetCHTVtextenhance(pScrn, (int)sdcbuf->sdc_parm[0]);
1145      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1146      break;
1147
1148   case SDC_CMD_GETTVCHCHROMAFLICKERFILTER:
1149      sdcbuf->sdc_result[0] = SiS_GetCHTVchromaflickerfilter(pScrn);
1150      break;
1151
1152   case SDC_CMD_SETTVCHCHROMAFLICKERFILTER:
1153      if(pSiS->xv_sisdirectunlocked) {
1154	 SiS_SetCHTVchromaflickerfilter(pScrn, (int)sdcbuf->sdc_parm[0]);
1155      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1156      break;
1157
1158   case SDC_CMD_GETTVCHLUMAFLICKERFILTER:
1159      sdcbuf->sdc_result[0] = SiS_GetCHTVlumaflickerfilter(pScrn);
1160      break;
1161
1162   case SDC_CMD_SETTVCHLUMAFLICKERFILTER:
1163      if(pSiS->xv_sisdirectunlocked) {
1164	 SiS_SetCHTVlumaflickerfilter(pScrn, (int)sdcbuf->sdc_parm[0]);
1165      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1166      break;
1167
1168   case SDC_CMD_GETTVCHCVBSCOLOR:
1169      sdcbuf->sdc_result[0] = SiS_GetCHTVcvbscolor(pScrn);
1170      break;
1171
1172   case SDC_CMD_SETTVCHCVBSCOLOR:
1173      if(pSiS->xv_sisdirectunlocked) {
1174	 SiS_SetCHTVcvbscolor(pScrn, sdcbuf->sdc_parm[0] ? 1 : 0);
1175      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1176      break;
1177
1178   case SDC_CMD_GETCHTVOVERSCAN:
1179      {  /* Changing of CRT2 settings not supported in DHM! */
1180	 int i = 0;
1181	 if(pSiS->OptTVSOver == 1)         i = 3;
1182	 else if(pSiS->UseCHOverScan == 1) i = 2;
1183	 else if(pSiS->UseCHOverScan == 0) i = 1;
1184	 sdcbuf->sdc_result[0] = i;
1185      }
1186      break;
1187
1188   case SDC_CMD_SETCHTVOVERSCAN:
1189      if(pSiS->xv_sisdirectunlocked) {
1190	 pSiS->UseCHOverScan = -1;
1191	 pSiS->OptTVSOver = FALSE;
1192	 if(sdcbuf->sdc_parm[0] == 3) {
1193	    if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSOVER) {
1194	       pSiS->OptTVSOver = TRUE;
1195	    }
1196	    pSiS->UseCHOverScan = 1;
1197	 } else if(sdcbuf->sdc_parm[0] == 2) pSiS->UseCHOverScan = 1;
1198	 else if(sdcbuf->sdc_parm[0] == 1)   pSiS->UseCHOverScan = 0;
1199      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1200      break;
1201
1202   case SDC_CMD_GETGAMMASTATUS:
1203      {
1204         int i = 0;
1205#ifdef SISDUALHEAD
1206	 if(pSiS->DualHeadMode) {
1207	    if(pSiSEnt->CRT1gamma) i |= 0x01;
1208	    if(pSiSEnt->CRT2gamma) i |= 0x02;
1209	 } else {
1210#endif
1211	    if(pSiS->CRT1gamma)    i |= 0x01;
1212	    if(pSiS->CRT2gamma)    i |= 0x02;
1213	    if(pSiS->CRT2SepGamma) i |= 0x08;
1214#ifdef SISDUALHEAD
1215	 }
1216#endif
1217	 if(pSiS->XvGamma) i |= 0x04;
1218         sdcbuf->sdc_result[0] = i;
1219      }
1220      break;
1221
1222   case SDC_CMD_SETGAMMASTATUS:
1223      if(pSiS->xv_sisdirectunlocked) {
1224         int value = sdcbuf->sdc_parm[0];
1225	 Bool backup = pSiS->XvGamma;
1226	 Bool backup2 = pSiS->CRT2SepGamma;
1227	 pSiS->CRT1gamma = (value & 0x01) ? TRUE : FALSE;
1228	 pSiS->CRT2gamma = (value & 0x02) ? TRUE : FALSE;
1229#ifdef SISDUALHEAD
1230	 if(pSiS->DualHeadMode) {
1231	    pSiSEnt->CRT1gamma = pSiS->CRT1gamma;
1232	    pSiSEnt->CRT2gamma = pSiS->CRT2gamma;
1233	 }
1234#endif
1235	 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSGRCRT2) {
1236	    pSiS->CRT2SepGamma = (value & 0x08) ? TRUE : FALSE;
1237	    if(pSiS->CRT2SepGamma != backup2) {
1238	       if(pSiS->CRT2SepGamma) {
1239		  SiS_UpdateGammaCRT2(pScrn);
1240	       }
1241#ifdef SISGAMMARAMP
1242	       else {
1243		  SISCalculateGammaRamp(pScrn->pScreen, pScrn);
1244	       }
1245#endif
1246	      /* ATTN: When disabling CRT2 sep gamma,
1247	       * as long as SISGAMMARAMP is not defined,
1248	       * application needs to reset palette using
1249	       * vidmodextension! (See SiS_SD_CANSETGAMMA)
1250	       *
1251	       * Note: Difference between setting gamma values
1252	       * for CRT1 and CRT2: For CRT1, driver only
1253	       * stores the values, but does nothing with them;
1254	       * App needs to calc gamma ramp itself for CRT1,
1255	       * and set it using the VidModExtention.
1256	       * For CRT2, the driver will IMMEDIATELY recalc
1257	       * the palette.
1258	       */
1259	    }
1260	 } else pSiS->CRT2SepGamma = FALSE;
1261
1262	 pSiS->XvGamma = (value & 0x04) ? TRUE : FALSE;
1263	 if(pSiS->VGAEngine == SIS_315_VGA) {
1264	    if(backup != pSiS->XvGamma) {
1265	       if(pPriv) SiSUpdateXvGamma(pSiS, pPriv);
1266	    }
1267	 }
1268      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1269      break;
1270
1271   case SDC_CMD_GETTVXSCALE:
1272      sdcbuf->sdc_result[0] = SiS_GetTVxscale(pScrn) + 32768;
1273      break;
1274
1275   case SDC_CMD_SETTVXSCALE:
1276      {
1277         int value = sdcbuf->sdc_parm[0] - 32768;
1278         if((value < -16) || (value > 16)) {
1279	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1280         } else if(pSiS->xv_sisdirectunlocked) {
1281	    SiS_SetTVxscale(pScrn, value);
1282         } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1283      }
1284      break;
1285
1286   case SDC_CMD_GETTVYSCALE:
1287      sdcbuf->sdc_result[0] = SiS_GetTVyscale(pScrn) + 32768;
1288      break;
1289
1290   case SDC_CMD_SETTVYSCALE:
1291      {
1292         int value = sdcbuf->sdc_parm[0] - 32768;
1293         if((value < -4) || (value > 3)) {
1294	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1295         } else if(pSiS->xv_sisdirectunlocked) {
1296	    SiS_SetTVyscale(pScrn, value);
1297         } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1298      }
1299      break;
1300
1301   case SDC_CMD_GETSCREENSIZE:
1302      sdcbuf->sdc_result[0] = (pScrn->virtualX << 16) | pScrn->virtualY;
1303      break;
1304
1305   case SDC_CMD_GETGAMMABRIGHTNESS:  /* xv_BRx, xv_PBx */
1306      sdcbuf->sdc_result[0] = pSiS->GammaBriR;
1307      sdcbuf->sdc_result[1] = pSiS->GammaBriG;
1308      sdcbuf->sdc_result[2] = pSiS->GammaBriB;
1309      break;
1310
1311   case SDC_CMD_GETNEWGAMMABRICON:  /* no xv pendant */
1312      sdcbuf->sdc_result[0] = (CARD32)(((int)(pSiS->NewGammaBriR * 1000.0)) + 1000);
1313      sdcbuf->sdc_result[1] = (CARD32)(((int)(pSiS->NewGammaBriG * 1000.0)) + 1000);
1314      sdcbuf->sdc_result[2] = (CARD32)(((int)(pSiS->NewGammaBriB * 1000.0)) + 1000);
1315      sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiS->NewGammaConR * 1000.0)) + 1000);
1316      sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiS->NewGammaConG * 1000.0)) + 1000);
1317      sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiS->NewGammaConB * 1000.0)) + 1000);
1318      break;
1319
1320   case SDC_CMD_SETGAMMABRIGHTNESS:  /* xv_BRx, xv_PBx */
1321      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1322	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1323	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000) {
1324	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1325      } else if(pSiS->xv_sisdirectunlocked) {
1326	 pSiS->GammaBriR = sdcbuf->sdc_parm[0];
1327	 pSiS->GammaBriG = sdcbuf->sdc_parm[1];
1328	 pSiS->GammaBriB = sdcbuf->sdc_parm[2];
1329	 pSiS->NewGammaBriR = pSiS->NewGammaBriG = pSiS->NewGammaBriB = 0.0;
1330	 pSiS->NewGammaConR = pSiS->NewGammaConG = pSiS->NewGammaConB = 0.0;
1331	 pSiS->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
1332      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1333      break;
1334
1335   case SDC_CMD_SETNEWGAMMABRICON:  /* no xv pendant */
1336      if(sdcbuf->sdc_parm[0] > 2000 || sdcbuf->sdc_parm[1] > 2000 ||
1337	 sdcbuf->sdc_parm[2] > 2000 || sdcbuf->sdc_parm[3] > 2000 ||
1338	 sdcbuf->sdc_parm[4] > 2000 || sdcbuf->sdc_parm[5] > 2000) {
1339	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1340      } else if(pSiS->xv_sisdirectunlocked) {
1341	 pSiS->NewGammaBriR = ((float)((int)sdcbuf->sdc_parm[0] - 1000)) / 1000.0;
1342	 pSiS->NewGammaBriG = ((float)((int)sdcbuf->sdc_parm[1] - 1000)) / 1000.0;
1343	 pSiS->NewGammaBriB = ((float)((int)sdcbuf->sdc_parm[2] - 1000)) / 1000.0;
1344	 pSiS->NewGammaConR = ((float)((int)sdcbuf->sdc_parm[3] - 1000)) / 1000.0;
1345	 pSiS->NewGammaConG = ((float)((int)sdcbuf->sdc_parm[4] - 1000)) / 1000.0;
1346	 pSiS->NewGammaConB = ((float)((int)sdcbuf->sdc_parm[5] - 1000)) / 1000.0;
1347	 pSiS->GammaBriR = pSiS->GammaBriG = pSiS->GammaBriB = 1000;
1348	 pSiS->SiS_SD3_Flags &= ~SiS_SD3_OLDGAMMAINUSE;
1349      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1350      break;
1351
1352   case SDC_CMD_GETGAMMABRIGHTNESS2: /* xv_BRx2, xv_PBx2 */
1353#ifdef SISDUALHEAD
1354      if(pSiS->DualHeadMode) {
1355         sdcbuf->sdc_result[0] = pSiSEnt->GammaBriR;
1356	 sdcbuf->sdc_result[1] = pSiSEnt->GammaBriG;
1357	 sdcbuf->sdc_result[2] = pSiSEnt->GammaBriB;
1358	 break;
1359      }
1360#endif
1361      sdcbuf->sdc_result[0] = pSiS->GammaBriR;
1362      sdcbuf->sdc_result[1] = pSiS->GammaBriG;
1363      sdcbuf->sdc_result[2] = pSiS->GammaBriB;
1364      break;
1365
1366   case SDC_CMD_GETNEWGAMMABRICON2: /* no xv pendant */
1367#ifdef SISDUALHEAD
1368      if(pSiS->DualHeadMode) {
1369         sdcbuf->sdc_result[0] = (CARD32)(((int)(pSiSEnt->NewGammaBriR * 1000.0)) + 1000);
1370	 sdcbuf->sdc_result[1] = (CARD32)(((int)(pSiSEnt->NewGammaBriG * 1000.0)) + 1000);
1371	 sdcbuf->sdc_result[2] = (CARD32)(((int)(pSiSEnt->NewGammaBriB * 1000.0)) + 1000);
1372	 sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiSEnt->NewGammaConR * 1000.0)) + 1000);
1373	 sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiSEnt->NewGammaConG * 1000.0)) + 1000);
1374	 sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiSEnt->NewGammaConB * 1000.0)) + 1000);
1375	 break;
1376      }
1377#endif
1378      sdcbuf->sdc_result[0] = (CARD32)(((int)(pSiS->NewGammaBriR * 1000.0)) + 1000);
1379      sdcbuf->sdc_result[1] = (CARD32)(((int)(pSiS->NewGammaBriG * 1000.0)) + 1000);
1380      sdcbuf->sdc_result[2] = (CARD32)(((int)(pSiS->NewGammaBriB * 1000.0)) + 1000);
1381      sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiS->NewGammaConR * 1000.0)) + 1000);
1382      sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiS->NewGammaConG * 1000.0)) + 1000);
1383      sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiS->NewGammaConB * 1000.0)) + 1000);
1384      break;
1385
1386   case SDC_CMD_SETGAMMABRIGHTNESS2: /* xv_BRx2, xv_PBx2 */
1387      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1388	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1389	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000) {
1390	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1391      } else if(pSiS->xv_sisdirectunlocked) {
1392         pSiS->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
1393#ifdef SISDUALHEAD
1394	 if(pSiS->DualHeadMode) {
1395	    pSiSEnt->GammaBriR = sdcbuf->sdc_parm[0];
1396	    pSiSEnt->GammaBriG = sdcbuf->sdc_parm[1];
1397	    pSiSEnt->GammaBriB = sdcbuf->sdc_parm[2];
1398	    pSiSEnt->NewGammaBriR = pSiSEnt->NewGammaBriG = pSiSEnt->NewGammaBriB = 0.0;
1399	    pSiSEnt->NewGammaConR = pSiSEnt->NewGammaConG = pSiSEnt->NewGammaConB = 0.0;
1400	 }
1401#endif
1402      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1403      break;
1404
1405   case SDC_CMD_SETNEWGAMMABRICON2: /* no xv pendant */
1406      if(sdcbuf->sdc_parm[0] > 2000 || sdcbuf->sdc_parm[1] > 2000 ||
1407	 sdcbuf->sdc_parm[2] > 2000 || sdcbuf->sdc_parm[3] > 2000 ||
1408	 sdcbuf->sdc_parm[4] > 2000 || sdcbuf->sdc_parm[5] > 2000) {
1409	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1410      } else if(pSiS->xv_sisdirectunlocked) {
1411         pSiS->SiS_SD3_Flags &= ~SiS_SD3_OLDGAMMAINUSE;
1412#ifdef SISDUALHEAD
1413	 if(pSiS->DualHeadMode) {
1414	    pSiSEnt->NewGammaBriR = ((float)((int)sdcbuf->sdc_parm[0] - 1000)) / 1000.0;
1415	    pSiSEnt->NewGammaBriG = ((float)((int)sdcbuf->sdc_parm[1] - 1000)) / 1000.0;
1416	    pSiSEnt->NewGammaBriB = ((float)((int)sdcbuf->sdc_parm[2] - 1000)) / 1000.0;
1417	    pSiSEnt->NewGammaConR = ((float)((int)sdcbuf->sdc_parm[3] - 1000)) / 1000.0;
1418	    pSiSEnt->NewGammaConG = ((float)((int)sdcbuf->sdc_parm[4] - 1000)) / 1000.0;
1419	    pSiSEnt->NewGammaConB = ((float)((int)sdcbuf->sdc_parm[5] - 1000)) / 1000.0;
1420	    pSiSEnt->GammaBriR = pSiSEnt->GammaBriG = pSiSEnt->GammaBriB = 1000;
1421	 }
1422#endif
1423      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1424      break;
1425
1426   case SDC_CMD_GETGETGAMMACRT2:
1427      sdcbuf->sdc_result[0] = (ULong)(pSiS->GammaR2 * 1000);
1428      sdcbuf->sdc_result[1] = (ULong)(pSiS->GammaG2 * 1000);
1429      sdcbuf->sdc_result[2] = (ULong)(pSiS->GammaB2 * 1000);
1430      sdcbuf->sdc_result[3] = pSiS->GammaBriR2;
1431      sdcbuf->sdc_result[4] = pSiS->GammaBriG2;
1432      sdcbuf->sdc_result[5] = pSiS->GammaBriB2;
1433      break;
1434
1435   case SDC_CMD_GETGETNEWGAMMACRT2:
1436      sdcbuf->sdc_result[0] = (ULong)(pSiS->GammaR2 * 1000);
1437      sdcbuf->sdc_result[1] = (ULong)(pSiS->GammaG2 * 1000);
1438      sdcbuf->sdc_result[2] = (ULong)(pSiS->GammaB2 * 1000);
1439      sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiS->NewGammaBriR2 * 1000.0)) + 1000);
1440      sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiS->NewGammaBriG2 * 1000.0)) + 1000);
1441      sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiS->NewGammaBriB2 * 1000.0)) + 1000);
1442      sdcbuf->sdc_result[6] = (CARD32)(((int)(pSiS->NewGammaConR2 * 1000.0)) + 1000);
1443      sdcbuf->sdc_result[7] = (CARD32)(((int)(pSiS->NewGammaConG2 * 1000.0)) + 1000);
1444      sdcbuf->sdc_result[8] = (CARD32)(((int)(pSiS->NewGammaConB2 * 1000.0)) + 1000);
1445      break;
1446
1447   case SDC_CMD_SETGETGAMMACRT2:
1448      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1449	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1450	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000 ||
1451	 sdcbuf->sdc_parm[3] < 100 || sdcbuf->sdc_parm[3] > 10000 ||
1452	 sdcbuf->sdc_parm[4] < 100 || sdcbuf->sdc_parm[4] > 10000 ||
1453	 sdcbuf->sdc_parm[5] < 100 || sdcbuf->sdc_parm[5] > 10000) {
1454	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1455      } else if(pSiS->xv_sisdirectunlocked) {
1456         pSiS->GammaR2 = (float)sdcbuf->sdc_parm[0] / (float)1000;
1457	 pSiS->GammaG2 = (float)sdcbuf->sdc_parm[1] / (float)1000;
1458	 pSiS->GammaB2 = (float)sdcbuf->sdc_parm[2] / (float)1000;
1459	 pSiS->GammaBriR2 = sdcbuf->sdc_parm[3];
1460	 pSiS->GammaBriG2 = sdcbuf->sdc_parm[4];
1461	 pSiS->GammaBriB2 = sdcbuf->sdc_parm[5];
1462	 pSiS->NewGammaBriR2 = pSiS->NewGammaBriG2 = pSiS->NewGammaBriB2 = 0.0;
1463	 pSiS->NewGammaConR2 = pSiS->NewGammaConG2 = pSiS->NewGammaConB2 = 0.0;
1464	 pSiS->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
1465	 SiS_UpdateGammaCRT2(pScrn);
1466      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1467      break;
1468
1469   case SDC_CMD_SETGETNEWGAMMACRT2:
1470      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1471	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1472	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000 ||
1473	 sdcbuf->sdc_parm[3] > 2000 || sdcbuf->sdc_parm[4] > 2000 ||
1474	 sdcbuf->sdc_parm[5] > 2000 || sdcbuf->sdc_parm[6] > 2000 ||
1475	 sdcbuf->sdc_parm[7] > 2000 || sdcbuf->sdc_parm[8] > 2000) {
1476	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1477      } else if(pSiS->xv_sisdirectunlocked) {
1478         pSiS->GammaR2 = (float)sdcbuf->sdc_parm[0] / (float)1000;
1479	 pSiS->GammaG2 = (float)sdcbuf->sdc_parm[1] / (float)1000;
1480	 pSiS->GammaB2 = (float)sdcbuf->sdc_parm[2] / (float)1000;
1481	 pSiS->NewGammaBriR2 = ((float)((int)sdcbuf->sdc_parm[3] - 1000)) / 1000.0;
1482	 pSiS->NewGammaBriG2 = ((float)((int)sdcbuf->sdc_parm[4] - 1000)) / 1000.0;
1483	 pSiS->NewGammaBriB2 = ((float)((int)sdcbuf->sdc_parm[5] - 1000)) / 1000.0;
1484	 pSiS->NewGammaConR2 = ((float)((int)sdcbuf->sdc_parm[6] - 1000)) / 1000.0;
1485	 pSiS->NewGammaConG2 = ((float)((int)sdcbuf->sdc_parm[7] - 1000)) / 1000.0;
1486	 pSiS->NewGammaConB2 = ((float)((int)sdcbuf->sdc_parm[8] - 1000)) / 1000.0;
1487	 pSiS->GammaBriR2 = pSiS->GammaBriG2 = pSiS->GammaBriB2 = 1000;
1488	 pSiS->SiS_SD3_Flags &= ~SiS_SD3_OLDGAMMAINUSE;
1489	 SiS_UpdateGammaCRT2(pScrn);
1490      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1491      break;
1492
1493   case SDC_CMD_GETHWCURSORSTATUS:
1494      sdcbuf->sdc_result[0] = pSiS->HideHWCursor ? 1 : 0;
1495      break;
1496
1497   case SDC_CMD_SETHWCURSORSTATUS:
1498      if(pSiS->xv_sisdirectunlocked) {
1499	 Bool VisibleBackup = pSiS->HWCursorIsVisible;
1500	 pSiS->HideHWCursor = sdcbuf->sdc_parm[0] ? TRUE : FALSE;
1501	 if(pSiS->CursorInfoPtr) {
1502	    if(VisibleBackup) {
1503	       if(sdcbuf->sdc_parm[0]) {
1504	 	  (pSiS->CursorInfoPtr->HideCursor)(pScrn);
1505	       } else {
1506		  (pSiS->CursorInfoPtr->ShowCursor)(pScrn);
1507	       }
1508	    }
1509	    pSiS->HWCursorIsVisible = VisibleBackup;
1510	 }
1511      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1512      break;
1513
1514   case SDC_CMD_GETPANELMODE:
1515      {
1516	 int i = 0;
1517	 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
1518	    switch(pSiS->SiS_Pr->UsePanelScaler) {
1519	    case -1: i |= 0x01; break;
1520	    case 1:  i |= 0x02; break;
1521	    }
1522	    if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
1523	       switch(pSiS->SiS_Pr->CenterScreen) {
1524	       case -1: i |= 0x04; break;
1525	       case 1:  i |= 0x08; break;
1526	       }
1527	    }
1528	 }
1529	 sdcbuf->sdc_result[0] = i;
1530      }
1531      break;
1532
1533   case SDC_CMD_SETPANELMODE:
1534      if(pSiS->xv_sisdirectunlocked) {
1535         int value = sdcbuf->sdc_parm[0];
1536         if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
1537	    if(value & 0x01)      pSiS->SiS_Pr->UsePanelScaler = -1;
1538	    else if(value & 0x02) pSiS->SiS_Pr->UsePanelScaler = 1;
1539	    else		  pSiS->SiS_Pr->UsePanelScaler = 0;
1540	    if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
1541	       if(value & 0x04)      pSiS->SiS_Pr->CenterScreen = -1;
1542	       else if(value & 0x08) pSiS->SiS_Pr->CenterScreen = 1;
1543	       else		     pSiS->SiS_Pr->CenterScreen = 0;
1544	    }
1545         }
1546      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1547      break;
1548
1549   case SDC_CMD_GETMERGEDMODEDETAILS:
1550#ifdef SISMERGED
1551      if(pSiS->MergedFB) {
1552         int clk, hd, hss, hse, ht, vd, vss, vse, vt;
1553	 unsigned int pos, crt1x, crt1y, crt1clk, crt2x, crt2y, crt2clk;
1554
1555	 clk   = sdcbuf->sdc_parm[0];
1556	 hd    = sdcbuf->sdc_parm[1];
1557	 hss   = sdcbuf->sdc_parm[2];
1558	 hse   = sdcbuf->sdc_parm[3];
1559	 ht    = sdcbuf->sdc_parm[4];
1560	 vd    = sdcbuf->sdc_parm[5];
1561	 vss   = sdcbuf->sdc_parm[6];
1562	 vse   = sdcbuf->sdc_parm[7];
1563	 vt    = sdcbuf->sdc_parm[8];
1564
1565	 SISGetMergedModeDetails(pScrn,
1566		hd, vd, ht, vt, hss, hse, vss, vse, clk,
1567		&pos, &crt1x, &crt1y, &crt1clk, &crt2x, &crt2y, &crt2clk);
1568
1569	 sdcbuf->sdc_result[0] = pos;
1570	 sdcbuf->sdc_result[1] = crt1x;
1571	 sdcbuf->sdc_result[2] = crt1y;
1572	 sdcbuf->sdc_result[3] = crt1clk;
1573	 sdcbuf->sdc_result[4] = crt2x;
1574	 sdcbuf->sdc_result[5] = crt2y;
1575	 sdcbuf->sdc_result[6] = crt2clk;
1576
1577	 switch(pSiS->CRT2Position) {
1578	 case sisLeftOf:  sdcbuf->sdc_result[7] = SDC_MMODE_POS_LEFTOF; break;
1579	 case sisRightOf: sdcbuf->sdc_result[7] = SDC_MMODE_POS_RIGHTOF; break;
1580	 case sisAbove:   sdcbuf->sdc_result[7] = SDC_MMODE_POS_ABOVE; break;
1581	 case sisBelow:   sdcbuf->sdc_result[7] = SDC_MMODE_POS_BELOW; break;
1582	 default:         sdcbuf->sdc_result[7] = SDC_MMODE_POS_CLONE;
1583	 }
1584
1585      } else
1586#endif
1587         sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1588      break;
1589
1590   case SDC_CMD_GETDEVICENAME:		/* In DualHead mode, this returns CRT1 data */
1591      {
1592         SISPtr	mypSiS = pSiS;
1593	 sdcbuf->sdc_result[0] = 0;
1594#ifdef SISDUALHEAD
1595	 if(pSiS->DualHeadMode) {
1596	    if(pSiSEnt->pScrn_2) mypSiS = SISPTR(pSiSEnt->pScrn_2);
1597	 }
1598#endif
1599	 sisutil_prepare_string(sdcbuf, mypSiS->devsectname);
1600      }
1601      break;
1602
1603   case SDC_CMD_GETMONITORNAME:		/* In DualHead mode, this returns CRT1 data */
1604      {
1605         ScrnInfoPtr mypScrn = pScrn;
1606         sdcbuf->sdc_result[0] = 0;
1607#ifdef SISDUALHEAD
1608	 if(pSiS->DualHeadMode) {
1609	    if(pSiSEnt->pScrn_2) mypScrn = pSiSEnt->pScrn_2;
1610	 }
1611#endif
1612         if(mypScrn->monitor) {
1613            sisutil_prepare_string(sdcbuf, mypScrn->monitor->id);
1614         }
1615      }
1616      break;
1617
1618   case SDC_CMD_GETDEVICENAME2:		/* In DualHead mode, this returns CRT2 data */
1619      sdcbuf->sdc_result[0] = 0;
1620#ifdef SISDUALHEAD
1621      if(pSiS->DualHeadMode) {
1622         if(pSiSEnt->pScrn_1) {
1623	    sisutil_prepare_string(sdcbuf, SISPTR(pSiSEnt->pScrn_1)->devsectname);
1624	 }
1625      } else
1626#endif
1627	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1628      break;
1629
1630   case SDC_CMD_GETMONITORNAME2:	/* In DualHead mode, this returns CRT2 data */
1631      sdcbuf->sdc_result[0] = 0;
1632#ifdef SISDUALHEAD
1633      if(pSiS->DualHeadMode) {
1634         if(pSiSEnt->pScrn_1) {
1635	    if(pSiSEnt->pScrn_1->monitor) {
1636               sisutil_prepare_string(sdcbuf, pSiSEnt->pScrn_1->monitor->id);
1637            }
1638	 }
1639      } else
1640#endif
1641	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1642      break;
1643
1644   case SDC_CMD_SETXVBRIGHTNESS:
1645      if(pPriv) {
1646         int val = sdcbuf->sdc_parm[0] - 32768;
1647         if(val >= -128 && val <= 127) pPriv->brightness = val;
1648	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1649      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1650      break;
1651
1652   case SDC_CMD_GETXVBRIGHTNESS:
1653      if(pPriv) {
1654         sdcbuf->sdc_result[0] = pPriv->brightness + 32768;
1655      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1656      break;
1657
1658   case SDC_CMD_SETXVCONTRAST:
1659      if(pPriv) {
1660         int val = sdcbuf->sdc_parm[0] - 32768;
1661         if(val >= 0 && val <= 7) pPriv->contrast = val;
1662	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1663      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1664      break;
1665
1666   case SDC_CMD_GETXVCONTRAST:
1667      if(pPriv) {
1668         sdcbuf->sdc_result[0] = pPriv->contrast + 32768;
1669      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1670      break;
1671
1672   case SDC_CMD_SETXVHUE:
1673      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
1674         int val = sdcbuf->sdc_parm[0] - 32768;
1675         if(val >= -8 && val <= 7) pPriv->hue = val;
1676	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1677      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1678      break;
1679
1680   case SDC_CMD_GETXVHUE:
1681      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
1682         sdcbuf->sdc_result[0] = pPriv->hue + 32768;
1683      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1684      break;
1685
1686   case SDC_CMD_SETXVSATURATION:
1687      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
1688         int val = sdcbuf->sdc_parm[0] - 32768;
1689         if(val >= -7 && val <= 7) pPriv->saturation = val;
1690	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1691      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1692      break;
1693
1694   case SDC_CMD_GETXVSATURATION:
1695      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
1696         sdcbuf->sdc_result[0] = pPriv->saturation + 32768;
1697      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1698      break;
1699
1700   case SDC_CMD_SETXVGAMMA:
1701      if((pPriv) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTXVGAMMA1)) {
1702         if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1703	    sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1704	    sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000) {
1705	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1706	 } else {
1707	    pSiS->XvGammaRed = sdcbuf->sdc_parm[0];
1708	    pSiS->XvGammaGreen = sdcbuf->sdc_parm[1];
1709	    pSiS->XvGammaBlue = sdcbuf->sdc_parm[2];
1710	    SiSUpdateXvGamma(pSiS, pPriv);
1711	 }
1712      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1713      break;
1714
1715   case SDC_CMD_GETXVGAMMA:
1716      if((pPriv) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTXVGAMMA1)) {
1717         sdcbuf->sdc_result[0] = pSiS->XvGammaRed;
1718	 sdcbuf->sdc_result[1] = pSiS->XvGammaGreen;
1719	 sdcbuf->sdc_result[2] = pSiS->XvGammaBlue;
1720      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1721      break;
1722
1723   case SDC_CMD_SETXVCOLORKEY:
1724      if(pPriv) {
1725         pPriv->colorKey = pSiS->colorKey = sdcbuf->sdc_parm[0];
1726      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1727      break;
1728
1729   case SDC_CMD_GETXVCOLORKEY:
1730      if(pPriv) {
1731         sdcbuf->sdc_result[0] = pPriv->colorKey;
1732      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1733      break;
1734
1735   case SDC_CMD_SETXVAUTOPAINTCOLORKEY:
1736      if(pPriv) {
1737         pPriv->autopaintColorKey = sdcbuf->sdc_parm[0] ? 1 : 0;
1738      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1739      break;
1740
1741   case SDC_CMD_GETXVAUTOPAINTCOLORKEY:
1742      if(pPriv) {
1743         sdcbuf->sdc_result[0] = pPriv->autopaintColorKey ? 1 : 0;
1744      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1745      break;
1746
1747   case SDC_CMD_SETXVDEFAULTS:
1748      if(pPriv) {
1749         SISSetPortDefaults(pScrn, pPriv);
1750      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1751      break;
1752
1753   case SDC_CMD_SETXVDISABLEGFX:
1754      if(pPriv) {
1755         pPriv->disablegfx = sdcbuf->sdc_parm[0] ? 1 : 0;
1756      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1757      break;
1758
1759   case SDC_CMD_GETXVDISABLEGFX:
1760      if(pPriv) {
1761         sdcbuf->sdc_result[0] = pPriv->disablegfx ? 1 : 0;
1762      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1763      break;
1764
1765   case SDC_CMD_SETXVDISABLEGFXLR:
1766      if(pPriv) {
1767         pPriv->disablegfxlr = sdcbuf->sdc_parm[0] ? 1 : 0;
1768      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1769      break;
1770
1771   case SDC_CMD_GETXVDISABLEGFXLR:
1772      if(pPriv) {
1773         sdcbuf->sdc_result[0] = pPriv->disablegfxlr ? 1 : 0;
1774      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1775      break;
1776
1777   case SDC_CMD_SETXVSWITCHCRT:
1778      if((pPriv) && (pSiS->VGAEngine == SIS_315_VGA)) {
1779         if(pPriv->AllowSwitchCRT) {
1780	    pPriv->crtnum = sdcbuf->sdc_parm[0] ? 1 : 0;
1781#ifdef SISDUALHEAD
1782            if(pPriv->dualHeadMode) pSiSEnt->curxvcrtnum = pPriv->crtnum;
1783#endif
1784	 }
1785      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1786      break;
1787
1788   case SDC_CMD_GETXVSWITCHCRT:
1789      if((pPriv) && (pSiS->VGAEngine == SIS_315_VGA)) {
1790#ifdef SISDUALHEAD
1791         if(pPriv->dualHeadMode)
1792            sdcbuf->sdc_result[0] = pSiSEnt->curxvcrtnum;
1793         else
1794#endif
1795            sdcbuf->sdc_result[0] = pPriv->crtnum;
1796      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1797      break;
1798
1799
1800   case SDC_CMD_SETTVXPOS:
1801      {
1802	 int value = sdcbuf->sdc_parm[0] - 32768;
1803	 if((value < -32) || (value > 32)) {
1804	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1805	 } else if(pSiS->xv_sisdirectunlocked) {
1806	    pPriv->tvxpos = value;
1807	    SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
1808	    pPriv->updatetvxpos = FALSE;
1809         } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1810      }
1811      break;
1812
1813   case SDC_CMD_GETTVXPOS:
1814      sdcbuf->sdc_result[0] = SiS_GetTVxposoffset(pScrn) + 32768;
1815      break;
1816
1817   case SDC_CMD_SETTVYPOS:
1818      {
1819	 int value = sdcbuf->sdc_parm[0] - 32768;
1820	 if((value < -32) || (value > 32)) {
1821	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1822	 } else if(pSiS->xv_sisdirectunlocked) {
1823	    pPriv->tvypos = value;
1824	    SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
1825	    pPriv->updatetvypos = FALSE;
1826	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1827      }
1828      break;
1829
1830   case SDC_CMD_GETTVYPOS:
1831      sdcbuf->sdc_result[0] = SiS_GetTVyposoffset(pScrn) + 32768;
1832      break;
1833
1834   case SDC_CMD_SETXVDEINT:
1835   case SDC_CMD_GETXVDEINT:
1836      sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1837      break;
1838
1839   case SDC_CMD_GETMONGAMMACRT1:
1840      sdcbuf->sdc_result[0] = pSiS->CRT1MonGamma;
1841      break;
1842
1843   case SDC_CMD_GETMONGAMMACRT2:
1844      sdcbuf->sdc_result[0] = pSiS->CRT2MonGamma;
1845      break;
1846
1847   case SDC_CMD_LOGQUIET:
1848      pSiS->SCLogQuiet = sdcbuf->sdc_parm[0] ? TRUE : FALSE;
1849      break;
1850
1851   case SDC_CMD_GETCRT1SATGAIN:
1852      sdcbuf->sdc_result[0] = SiS_GetSISCRT1SaturationGain(pScrn);
1853      break;
1854
1855   case SDC_CMD_SETCRT1SATGAIN:
1856      if(pSiS->xv_sisdirectunlocked) {
1857	 SiS_SetSISCRT1SaturationGain(pScrn, (int)sdcbuf->sdc_parm[0]);
1858      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1859      break;
1860
1861   default:
1862      sdcbuf->sdc_result_header = SDC_RESULT_UNDEFCMD;
1863   }
1864
1865   return Success;
1866}
1867
1868/* Proc */
1869
1870static int
1871SiSProcSiSCtrlQueryVersion(ClientPtr client)
1872{
1873    xSiSCtrlQueryVersionReply	  rep;
1874#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
1875    register int		  n;
1876#endif
1877
1878    REQUEST_SIZE_MATCH(xSiSCtrlQueryVersionReq);
1879    rep.type = X_Reply;
1880    rep.length = 0;
1881    rep.sequenceNumber = client->sequence;
1882    rep.majorVersion = SISCTRL_MAJOR_VERSION;
1883    rep.minorVersion = SISCTRL_MINOR_VERSION;
1884    if(client->swapped) {
1885        _swaps(&rep.sequenceNumber, n);
1886        _swapl(&rep.length, n);
1887        _swaps(&rep.majorVersion, n);
1888        _swaps(&rep.minorVersion, n);
1889    }
1890    WriteToClient(client, sizeof(xSiSCtrlQueryVersionReply), (char *)&rep);
1891    return (client->noClientException);
1892}
1893
1894static int
1895SiSProcSiSCtrlCommand(ClientPtr client)
1896{
1897    REQUEST(xSiSCtrlCommandReq);
1898    xSiSCtrlCommandReply rep;
1899    ExtensionEntry 	 *myext;
1900    xSiSCtrlScreenTable  *myctrl;
1901#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
1902    register int	 n;
1903#endif
1904    int 		 i, ret;
1905
1906    REQUEST_SIZE_MATCH(xSiSCtrlCommandReq);
1907
1908    memcpy(&rep, stuff, sizeof(xSiSCtrlCommandReply));
1909
1910    /* Get pointer to ExtensionEntry */
1911    if(!(myext = CheckExtension(SISCTRL_PROTOCOL_NAME))) return BadMatch;
1912
1913    /* Get pointer to our private */
1914    if(!(myctrl = (xSiSCtrlScreenTable *)myext->extPrivate)) return BadMatch;
1915
1916    /* Check if screen index is within out limits */
1917    if(rep.screen > myctrl->maxscreens) return BadMatch;
1918
1919    /* Check if this screen has added itself */
1920    if(!(myctrl->HandleSiSDirectCommand[rep.screen])) return BadMatch;
1921
1922    /* Finally, execute the command */
1923    if((ret = (myctrl->HandleSiSDirectCommand[rep.screen])(&rep)) != Success)
1924       return ret;
1925
1926    rep.type = X_Reply;
1927    rep.length = (sizeof(xSiSCtrlCommandReply) - sizeof(xGenericReply)) >> 2;
1928    rep.sequenceNumber = client->sequence;
1929
1930    if(client->swapped) {
1931       _swaps(&rep.sequenceNumber, n);
1932       _swapl(&rep.length, n);
1933       _swapl(&rep.screen, n);
1934       _swapl(&rep.sdc_id, n);
1935       _swapl(&rep.sdc_command, n);
1936       _swapl(&rep.sdc_result_header, n);
1937       for(i = 0; i < SDC_NUM_PARM_RESULT; i++) {
1938	  _swapl(&rep.sdc_parm[i], n);
1939	  _swapl(&rep.sdc_result[i], n);
1940       }
1941    }
1942    WriteToClient(client, sizeof(xSiSCtrlCommandReply), (char *)&rep);
1943    return client->noClientException;
1944}
1945
1946static int
1947SiSProcSiSCtrlDispatch(ClientPtr client)
1948{
1949    REQUEST(xReq);
1950    switch(stuff->data) {
1951	case X_SiSCtrlQueryVersion:
1952	     return SiSProcSiSCtrlQueryVersion(client);
1953	case X_SiSCtrlCommand:
1954	     return SiSProcSiSCtrlCommand(client);
1955    }
1956    return BadRequest;
1957}
1958
1959/* SProc */
1960
1961static int
1962SiSSProcSiSCtrlQueryVersion(ClientPtr client)
1963{
1964    REQUEST(xSiSCtrlQueryVersionReq);
1965#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
1966    register int n;
1967#endif
1968    _swaps(&stuff->length, n);
1969    REQUEST_SIZE_MATCH(xSiSCtrlQueryVersionReq);
1970    return SiSProcSiSCtrlQueryVersion(client);
1971}
1972
1973static int
1974SiSSProcSiSCtrlCommand(ClientPtr client)
1975{
1976    REQUEST(xSiSCtrlCommandReq);
1977#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
1978    register int n;
1979#endif
1980    int i;
1981    _swaps(&stuff->length, n);
1982    _swapl(&stuff->screen, n);
1983    _swapl(&stuff->sdc_id, n);
1984    _swapl(&stuff->sdc_command, n);
1985    _swapl(&stuff->sdc_result_header, n);
1986    for(i = 0; i < SDC_NUM_PARM_RESULT; i++) {
1987       _swapl(&stuff->sdc_parm[i], n);
1988       _swapl(&stuff->sdc_result[i], n);
1989    }
1990    REQUEST_SIZE_MATCH(xSiSCtrlCommandReq);
1991    return SiSProcSiSCtrlCommand(client);
1992}
1993
1994static int
1995SiSSProcSiSCtrlDispatch(ClientPtr client)
1996{
1997    REQUEST(xReq);
1998    switch(stuff->data) {
1999       case X_SiSCtrlQueryVersion:
2000	  return SiSSProcSiSCtrlQueryVersion(client);
2001       case X_SiSCtrlCommand:
2002	  return SiSSProcSiSCtrlCommand(client);
2003    }
2004    return BadRequest;
2005}
2006
2007static void
2008SiSCtrlResetProc(ExtensionEntry* extEntry)
2009{
2010    /* Called by CloseDownExtensions() */
2011    /* (CloseDownExtensions() is called BEFORE CloseScreen,
2012     * which is why we must not use pSiS->SiSCtrlExtEntry
2013     * in SiSCtrlExtUnregister())
2014     */
2015    if(extEntry->extPrivate) {
2016       free(extEntry->extPrivate);
2017       extEntry->extPrivate = NULL;
2018    }
2019}
2020
2021void
2022SiSCtrlExtInit(ScrnInfoPtr pScrn)
2023{
2024   SISPtr pSiS = SISPTR(pScrn);
2025   ExtensionEntry  *myext;
2026   xSiSCtrlScreenTable *myctrl;
2027   unsigned int version, revision;
2028
2029   if((pSiS->VGAEngine != SIS_300_VGA) &&
2030      (pSiS->VGAEngine != SIS_315_VGA))
2031      return;
2032
2033   pSiS->SCLogQuiet = FALSE;
2034
2035   if(!(myext = CheckExtension(SISCTRL_PROTOCOL_NAME))) {
2036
2037      if(!(myctrl = calloc(sizeof(xSiSCtrlScreenTable), 1)))
2038         return;
2039
2040      if(!(myext = AddExtension(SISCTRL_PROTOCOL_NAME, 0, 0,
2041				SiSProcSiSCtrlDispatch,
2042				SiSSProcSiSCtrlDispatch,
2043				SiSCtrlResetProc,
2044				StandardMinorOpcode))) {
2045         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2046	 		"Failed to add SISCTRL extension\n");
2047	 free(myctrl);
2048	 return;
2049      }
2050
2051      myext->extPrivate = (pointer)myctrl;
2052
2053      myctrl->maxscreens = SISCTRL_MAX_SCREENS;
2054      myctrl->version_major = version = SISCTRL_MAJOR_VERSION;
2055      myctrl->version_minor = revision = SISCTRL_MINOR_VERSION;
2056
2057      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2058		"Initialized SISCTRL extension version %d.%d\n",
2059		version, revision);
2060
2061   } else {
2062
2063      if(!(myctrl = (xSiSCtrlScreenTable *)myext->extPrivate)) {
2064         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2065		"Internal error: Found SISCTRL extension with NULL-private!\n");
2066	 return;
2067      }
2068
2069      version = myctrl->version_major;
2070      revision = myctrl->version_minor;
2071   }
2072
2073   if(pScrn->scrnIndex < myctrl->maxscreens) {
2074
2075      myctrl->HandleSiSDirectCommand[pScrn->scrnIndex] = SiSHandleSiSDirectCommand;
2076
2077      pSiS->SiSCtrlExtEntry = myext;
2078
2079      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2080		"Registered screen %d with SISCTRL extension version %d.%d\n",
2081		pScrn->scrnIndex, version, revision);
2082   } else {
2083
2084      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2085		"Screen number (%d) too high for SISCTRL extension %d.%d\n",
2086		pScrn->scrnIndex, version, revision);
2087
2088   }
2089
2090}
2091
2092void
2093SiSCtrlExtUnregister(SISPtr pSiS, int index)
2094{
2095   ExtensionEntry  *myext;
2096   xSiSCtrlScreenTable *myctrl;
2097
2098   if(!pSiS->SiSCtrlExtEntry) return;
2099
2100   /* Since CloseDownExtensions() is called before
2101    * our CloseScreen(), we must not use the saved
2102    * ptr here, but instead check for the extension.
2103    */
2104
2105   if((myext = CheckExtension(SISCTRL_PROTOCOL_NAME))) {
2106      if((myctrl = (xSiSCtrlScreenTable *)myext->extPrivate)) {
2107         myctrl->HandleSiSDirectCommand[index] = NULL;
2108      }
2109   }
2110}
2111
2112/***********************************
2113 *     Xv attribute interface      *
2114 ***********************************/
2115
2116#ifdef XV_SD_DEPRECATED
2117
2118int
2119SISSetPortUtilAttribute(ScrnInfoPtr pScrn, Atom attribute,
2120			INT32 value, SISPortPrivPtr pPriv)
2121{
2122  SISPtr pSiS = SISPTR(pScrn);
2123#ifdef SISDUALHEAD
2124  SISEntPtr pSiSEnt = pSiS->entityPrivate;;
2125#endif
2126
2127  if(attribute == pSiS->xv_USD) {
2128     if(pSiS->enablesisctrl) {
2129	 if(value == SIS_DIRECTKEY) {
2130	   pSiS->xv_sisdirectunlocked++;
2131	} else if(pSiS->xv_sisdirectunlocked) {
2132	   pSiS->xv_sisdirectunlocked--;
2133	}
2134     } else {
2135	pSiS->xv_sisdirectunlocked = 0;
2136     }
2137  } else if(attribute == pSiS->xv_SVF) {
2138#ifdef SISDUALHEAD
2139     if(!pPriv->dualHeadMode)
2140#endif
2141	if(pSiS->xv_sisdirectunlocked) {
2142	   SISSwitchCRT2Type(pScrn, (ULong)value, FALSE);
2143	   SISUpdateVideoParms(pSiS, pPriv);
2144	}
2145  } else if(attribute == pSiS->xv_CT1) {
2146#ifdef SISDUALHEAD
2147     if(!pPriv->dualHeadMode)
2148#endif
2149	if(pSiS->xv_sisdirectunlocked) {
2150	   SISSwitchCRT1Status(pScrn, (ULong)value, FALSE);
2151	   SISUpdateVideoParms(pSiS, pPriv);
2152        }
2153  } else if(attribute == pSiS->xv_RDT) {
2154#ifdef SISDUALHEAD
2155     if(!pPriv->dualHeadMode)
2156#endif
2157	if(pSiS->xv_sisdirectunlocked) {
2158	   SISRedetectCRT2Devices(pScrn);
2159	}
2160  } else if(attribute == pSiS->xv_TAF) {
2161     if(pSiS->xv_sisdirectunlocked) {
2162	SiS_SetSISTVantiflicker(pScrn, (int)value);
2163     }
2164  } else if(attribute == pSiS->xv_TSA) {
2165     if(pSiS->xv_sisdirectunlocked) {
2166	SiS_SetSISTVsaturation(pScrn, (int)value);
2167     }
2168  } else if(attribute == pSiS->xv_TEE) {
2169     if(pSiS->xv_sisdirectunlocked) {
2170	SiS_SetSISTVedgeenhance(pScrn, (int)value);
2171     }
2172  } else if(attribute == pSiS->xv_CFI) {
2173     if(pSiS->xv_sisdirectunlocked) {
2174	SiS_SetSISTVcfilter(pScrn, value ? 1 : 0);
2175     }
2176  } else if(attribute == pSiS->xv_YFI) {
2177     if(pSiS->xv_sisdirectunlocked) {
2178	SiS_SetSISTVyfilter(pScrn, value);
2179     }
2180  } else if(attribute == pSiS->xv_COC) {
2181     if(pSiS->xv_sisdirectunlocked) {
2182	SiS_SetSISTVcolcalib(pScrn, (int)value, TRUE);
2183     }
2184  } else if(attribute == pSiS->xv_COF) {
2185     if(pSiS->xv_sisdirectunlocked) {
2186	SiS_SetSISTVcolcalib(pScrn, (int)value, FALSE);
2187     }
2188  } else if(attribute == pSiS->xv_TCO) {
2189     if(pSiS->xv_sisdirectunlocked) {
2190	SiS_SetCHTVcontrast(pScrn, (int)value);
2191     }
2192  } else if(attribute == pSiS->xv_TTE) {
2193     if(pSiS->xv_sisdirectunlocked) {
2194	SiS_SetCHTVtextenhance(pScrn, (int)value);
2195     }
2196  } else if(attribute == pSiS->xv_TCF) {
2197     if(pSiS->xv_sisdirectunlocked) {
2198	SiS_SetCHTVchromaflickerfilter(pScrn, (int)value);
2199     }
2200  } else if(attribute == pSiS->xv_TLF) {
2201     if(pSiS->xv_sisdirectunlocked) {
2202	SiS_SetCHTVlumaflickerfilter(pScrn, (int)value);
2203     }
2204  } else if(attribute == pSiS->xv_TCC) {
2205     if(pSiS->xv_sisdirectunlocked) {
2206	SiS_SetCHTVcvbscolor(pScrn, value ? 1 : 0);
2207     }
2208  } else if(attribute == pSiS->xv_OVR) {
2209     if(pSiS->xv_sisdirectunlocked) {
2210	pSiS->UseCHOverScan = -1;
2211	pSiS->OptTVSOver = FALSE;
2212	if(value == 3) {
2213	   if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSOVER) {
2214	      pSiS->OptTVSOver = TRUE;
2215	   }
2216	   pSiS->UseCHOverScan = 1;
2217	} else if(value == 2) pSiS->UseCHOverScan = 1;
2218	else if(value == 1)   pSiS->UseCHOverScan = 0;
2219     }
2220  } else if(attribute == pSiS->xv_CMD) {
2221     if(pSiS->xv_sisdirectunlocked) {
2222	int result = 0;
2223	pSiS->xv_sd_result = (value & 0xffffff00);
2224	result = SISCheckModeIndexForCRT2Type(pScrn, (UShort)(value & 0xff),
2225					      (UShort)((value >> 8) & 0xff),
2226					      FALSE);
2227	pSiS->xv_sd_result |= (result & 0xff);
2228     }
2229  } else if(attribute == pSiS->xv_SGA) {
2230     if(pSiS->xv_sisdirectunlocked) {
2231	Bool backup = pSiS->XvGamma;
2232	Bool backup2 = pSiS->CRT2SepGamma;
2233	pSiS->CRT1gamma = (value & 0x01) ? TRUE : FALSE;
2234	pSiS->CRT2gamma = (value & 0x02) ? TRUE : FALSE;
2235#ifdef SISDUALHEAD
2236	if(pPriv->dualHeadMode) {
2237	   pSiSEnt->CRT1gamma = pSiS->CRT1gamma;
2238	   pSiSEnt->CRT2gamma = pSiS->CRT2gamma;
2239	}
2240#endif
2241	if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSGRCRT2) {
2242	   pSiS->CRT2SepGamma = (value & 0x08) ? TRUE : FALSE;
2243	   if(pSiS->CRT2SepGamma != backup2) {
2244	      if(pSiS->CRT2SepGamma) {
2245		 SiS_UpdateGammaCRT2(pScrn);
2246	      }
2247#ifdef SISGAMMARAMP
2248	      else {
2249		 SISCalculateGammaRamp(pScrn->pScreen, pScrn);
2250	      }
2251#endif
2252	      /* ATTN: When disabling CRT2 sep gamma,
2253	       * as long as SISGAMMARAMP is not defined,
2254	       * application needs to reset palette using
2255	       * vidmodextension! (See SiS_SD_CANSETGAMMA)
2256	       *
2257	       * Note: Difference between setting gamma values
2258	       * for CRT1 and CRT2: For CRT1, driver only
2259	       * stores the values, but does nothing with them.
2260	       * For CRT2, the driver will IMMEDIATELY recalc
2261	       * the palette. App needs to calc gamma ramp
2262	       * itself for CRT1, and set it using the
2263	       * VidModExtention.
2264	       */
2265	   }
2266	} else pSiS->CRT2SepGamma = FALSE;
2267	pSiS->XvGamma = (value & 0x04) ? TRUE : FALSE;
2268	if(pSiS->VGAEngine == SIS_315_VGA) {
2269	   if(backup != pSiS->XvGamma) {
2270	      SiSUpdateXvGamma(pSiS, pPriv);
2271	   }
2272	}
2273     }
2274  } else if(attribute == pSiS->xv_TXS) {
2275     if((value < -16) || (value > 16)) return BadValue;
2276     if(pSiS->xv_sisdirectunlocked) {
2277	SiS_SetTVxscale(pScrn, value);
2278     }
2279  } else if(attribute == pSiS->xv_TYS) {
2280     if((value < -4) || (value > 3)) return BadValue;
2281     if(pSiS->xv_sisdirectunlocked) {
2282	SiS_SetTVyscale(pScrn, value);
2283     }
2284  } else if(attribute == pSiS->xv_BRR) {
2285     if((value < 100) || (value > 10000)) return BadValue;
2286     if(pSiS->xv_sisdirectunlocked) {
2287	pSiS->GammaBriR = value;
2288     }
2289  } else if(attribute == pSiS->xv_BRG) {
2290     if((value < 100) || (value > 10000)) return BadValue;
2291     if(pSiS->xv_sisdirectunlocked) {
2292	pSiS->GammaBriG = value;
2293     }
2294  } else if(attribute == pSiS->xv_BRB) {
2295     if((value < 100) || (value > 10000)) return BadValue;
2296     if(pSiS->xv_sisdirectunlocked) {
2297	pSiS->GammaBriB = value;
2298     }
2299  } else if(attribute == pSiS->xv_PBR) {
2300     /* Nop */
2301  } else if(attribute == pSiS->xv_PBG) {
2302     /* Nop */
2303  } else if(attribute == pSiS->xv_PBB) {
2304     /* Nop */
2305  } else if(attribute == pSiS->xv_BRR2) {
2306     if((value < 100) || (value > 10000)) return BadValue;
2307     if(pSiS->xv_sisdirectunlocked) {
2308#ifdef SISDUALHEAD
2309	if(pPriv->dualHeadMode) pSiSEnt->GammaBriR = value;
2310#endif
2311     }
2312  } else if(attribute == pSiS->xv_BRG2) {
2313     if((value < 100) || (value > 10000)) return BadValue;
2314     if(pSiS->xv_sisdirectunlocked) {
2315#ifdef SISDUALHEAD
2316	if(pPriv->dualHeadMode) pSiSEnt->GammaBriG = value;
2317#endif
2318     }
2319  } else if(attribute == pSiS->xv_BRB2) {
2320     if((value < 100) || (value > 10000)) return BadValue;
2321     if(pSiS->xv_sisdirectunlocked) {
2322#ifdef SISDUALHEAD
2323	if(pPriv->dualHeadMode) pSiSEnt->GammaBriB = value;
2324#endif
2325     }
2326  } else if(attribute == pSiS->xv_PBR2) {
2327     /* Nop */
2328  } else if(attribute == pSiS->xv_PBG2) {
2329     /* Nop */
2330  } else if(attribute == pSiS->xv_PBB2) {
2331     /* Nop */
2332  } else if(attribute == pSiS->xv_GARC2) {
2333     if((value < 100) || (value > 10000)) return BadValue;
2334     if(pSiS->xv_sisdirectunlocked) {
2335	pSiS->GammaR2 = (float)value / (float)1000;
2336	SiS_UpdateGammaCRT2(pScrn);
2337     }
2338  } else if(attribute == pSiS->xv_GAGC2) {
2339     if((value < 100) || (value > 10000)) return BadValue;
2340     if(pSiS->xv_sisdirectunlocked) {
2341	pSiS->GammaG2 = (float)value / (float)1000;
2342	SiS_UpdateGammaCRT2(pScrn);
2343     }
2344  } else if(attribute == pSiS->xv_GABC2) {
2345     if((value < 100) || (value > 10000)) return BadValue;
2346     if(pSiS->xv_sisdirectunlocked) {
2347	pSiS->GammaB2 = (float)value / (float)1000;
2348	SiS_UpdateGammaCRT2(pScrn);
2349     }
2350  } else if(attribute == pSiS->xv_BRRC2) {
2351     if((value < 100) || (value > 10000)) return BadValue;
2352     if(pSiS->xv_sisdirectunlocked) {
2353	pSiS->GammaBriR2 = value;
2354	SiS_UpdateGammaCRT2(pScrn);
2355     }
2356  } else if(attribute == pSiS->xv_BRGC2) {
2357     if((value < 100) || (value > 10000)) return BadValue;
2358     if(pSiS->xv_sisdirectunlocked) {
2359	pSiS->GammaBriG2 = value;
2360	SiS_UpdateGammaCRT2(pScrn);
2361     }
2362  } else if(attribute == pSiS->xv_BRBC2) {
2363     if((value < 100) || (value > 10000)) return BadValue;
2364     if(pSiS->xv_sisdirectunlocked) {
2365	pSiS->GammaBriB2 = value;
2366	SiS_UpdateGammaCRT2(pScrn);
2367     }
2368  } else if(attribute == pSiS->xv_PBRC2) {
2369     /* Nop */
2370  } else if(attribute == pSiS->xv_PBGC2) {
2371     /* Nop */
2372  } else if(attribute == pSiS->xv_PBBC2) {
2373     /* Nop */
2374  } else if(attribute == pSiS->xv_SHC) {
2375     if(pSiS->xv_sisdirectunlocked) {
2376	Bool VisibleBackup = pSiS->HWCursorIsVisible;
2377	pSiS->HideHWCursor = value ? TRUE : FALSE;
2378	if(pSiS->CursorInfoPtr) {
2379	   if(VisibleBackup) {
2380	      if(value) {
2381		 (pSiS->CursorInfoPtr->HideCursor)(pScrn);
2382	      } else {
2383		 (pSiS->CursorInfoPtr->ShowCursor)(pScrn);
2384	      }
2385	   }
2386	   pSiS->HWCursorIsVisible = VisibleBackup;
2387	}
2388     }
2389  } else if(attribute == pSiS->xv_PMD) {
2390     if(pSiS->xv_sisdirectunlocked) {
2391        if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
2392	   if(value & 0x01)      pSiS->SiS_Pr->UsePanelScaler = -1;
2393	   else if(value & 0x02) pSiS->SiS_Pr->UsePanelScaler = 1;
2394	   else			 pSiS->SiS_Pr->UsePanelScaler = 0;
2395	   if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
2396	      if(value & 0x04)      pSiS->SiS_Pr->CenterScreen = -1;
2397	      else if(value & 0x08) pSiS->SiS_Pr->CenterScreen = 1;
2398	      else		    pSiS->SiS_Pr->CenterScreen = 0;
2399	   }
2400        }
2401     }
2402#ifdef TWDEBUG
2403  } else if(attribute == pSiS->xv_STR) {
2404     ULong port;
2405     CARD8 reg;
2406     switch((value & 0xff000000) >> 24) {
2407     case 0x00: port = SISSR;    break;
2408     case 0x01: port = SISPART1; break;
2409     case 0x02: port = SISPART2; break;
2410     case 0x03: port = SISPART3; break;
2411     case 0x04: port = SISPART4; break;
2412     case 0x05: port = SISCR;    break;
2413     case 0x06: port = SISVID;   break;
2414     default:   return BadValue;
2415     }
2416     outSISIDXREG(port,((value & 0x00ff0000) >> 16), ((value & 0x0000ff00) >> 8));
2417     inSISIDXREG(port, ((value & 0x00ff0000) >> 16), reg);
2418     xf86DrvMsg(0, 0, "SetREG %x -> %x -> %x\n", ((value & 0x00ff0000) >> 16), ((value & 0x0000ff00) >> 8), reg);
2419#endif
2420  } else {
2421     return BadMatch;
2422  }
2423
2424  return Success;
2425}
2426
2427int
2428SISGetPortUtilAttribute(ScrnInfoPtr pScrn,  Atom attribute,
2429			INT32 *value, SISPortPrivPtr pPriv)
2430{
2431  SISPtr pSiS = SISPTR(pScrn);
2432#ifdef SISDUALHEAD
2433  SISEntPtr pSiSEnt = pSiS->entityPrivate;;
2434#endif
2435
2436  if(attribute == pSiS->xv_QVF) {
2437     *value = pSiS->VBFlags;
2438  } else if(attribute == pSiS->xv_GDV) {
2439     *value = SISDRIVERIVERSION;
2440  } else if(attribute == pSiS->xv_GHI) {
2441     *value = (pSiS->ChipFlags & 0xffff) | (pSiS->ChipType << 16) | (pSiS->ChipRev << 24);
2442  } else if(attribute == pSiS->xv_GBI) {
2443     *value = (pSiS->PciBus << 16) | (pSiS->PciDevice << 8) | pSiS->PciFunc;
2444  } else if(attribute == pSiS->xv_QVV) {
2445     *value = SIS_VBFlagsVersion;
2446  } else if(attribute == pSiS->xv_QDD) {
2447     *value = pSiS->detectedCRT2Devices;
2448  } else if(attribute == pSiS->xv_CT1) {
2449     *value = pSiS->CRT1isoff ? 0 : 1;
2450  } else if(attribute == pSiS->xv_GSF) {
2451     *value = pSiS->SiS_SD_Flags;
2452  } else if(attribute == pSiS->xv_GSF2) {
2453     *value = pSiS->SiS_SD2_Flags;
2454  } else if(attribute == pSiS->xv_USD) {
2455     *value = pSiS->xv_sisdirectunlocked;
2456  } else if(attribute == pSiS->xv_TAF) {
2457     *value = SiS_GetSISTVantiflicker(pScrn);
2458  } else if(attribute == pSiS->xv_TSA) {
2459     *value = SiS_GetSISTVsaturation(pScrn);
2460  } else if(attribute == pSiS->xv_TEE) {
2461     *value = SiS_GetSISTVedgeenhance(pScrn);
2462  } else if(attribute == pSiS->xv_CFI) {
2463     *value = SiS_GetSISTVcfilter(pScrn);
2464  } else if(attribute == pSiS->xv_YFI) {
2465     *value = SiS_GetSISTVyfilter(pScrn);
2466  } else if(attribute == pSiS->xv_COC) {
2467     *value = SiS_GetSISTVcolcalib(pScrn, TRUE);
2468  } else if(attribute == pSiS->xv_COF) {
2469     *value = SiS_GetSISTVcolcalib(pScrn, FALSE);
2470  } else if(attribute == pSiS->xv_TCO) {
2471     *value = SiS_GetCHTVcontrast(pScrn);
2472  } else if(attribute == pSiS->xv_TTE) {
2473     *value = SiS_GetCHTVtextenhance(pScrn);
2474  } else if(attribute == pSiS->xv_TCF) {
2475     *value = SiS_GetCHTVchromaflickerfilter(pScrn);
2476  } else if(attribute == pSiS->xv_TLF) {
2477     *value = SiS_GetCHTVlumaflickerfilter(pScrn);
2478  } else if(attribute == pSiS->xv_TCC) {
2479     *value = SiS_GetCHTVcvbscolor(pScrn);
2480  } else if(attribute == pSiS->xv_CMDR) {
2481     *value = pSiS->xv_sd_result;
2482  } else if(attribute == pSiS->xv_OVR) {
2483     /* Changing of CRT2 settings not supported in DHM! */
2484     *value = 0;
2485     if(pSiS->OptTVSOver == 1)         *value = 3;
2486     else if(pSiS->UseCHOverScan == 1) *value = 2;
2487     else if(pSiS->UseCHOverScan == 0) *value = 1;
2488  } else if(attribute == pSiS->xv_SGA) {
2489     *value = 0;
2490#ifdef SISDUALHEAD
2491     if(pPriv->dualHeadMode) {
2492        if(pSiSEnt->CRT1gamma) *value |= 0x01;
2493	if(pSiSEnt->CRT2gamma) *value |= 0x02;
2494     } else {
2495#endif
2496	if(pSiS->CRT1gamma)    *value |= 0x01;
2497	if(pSiS->CRT2gamma)    *value |= 0x02;
2498	if(pSiS->CRT2SepGamma) *value |= 0x08;
2499#ifdef SISDUALHEAD
2500     }
2501#endif
2502     if(pSiS->XvGamma) *value |= 0x04;
2503  } else if(attribute == pSiS->xv_TXS) {
2504     *value = SiS_GetTVxscale(pScrn);
2505  } else if(attribute == pSiS->xv_TYS) {
2506     *value = SiS_GetTVyscale(pScrn);
2507  } else if(attribute == pSiS->xv_GSS) {
2508     *value = (pScrn->virtualX << 16) | pScrn->virtualY;
2509  } else if(attribute == pSiS->xv_BRR) {
2510     *value = pSiS->GammaBriR;
2511  } else if(attribute == pSiS->xv_BRG) {
2512     *value = pSiS->GammaBriG;
2513  } else if(attribute == pSiS->xv_BRB) {
2514     *value = pSiS->GammaBriB;
2515  } else if(attribute == pSiS->xv_PBR) {
2516     *value = 1000;
2517  } else if(attribute == pSiS->xv_PBG) {
2518     *value = 1000;
2519  } else if(attribute == pSiS->xv_PBB) {
2520     *value = 1000;
2521  } else if(attribute == pSiS->xv_BRR2) {
2522#ifdef SISDUALHEAD
2523     if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriR;
2524     else
2525#endif
2526          *value = pSiS->GammaBriR;
2527  } else if(attribute == pSiS->xv_BRG2) {
2528#ifdef SISDUALHEAD
2529     if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriG;
2530     else
2531#endif
2532          *value = pSiS->GammaBriG;
2533  } else if(attribute == pSiS->xv_BRB2) {
2534#ifdef SISDUALHEAD
2535     if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriB;
2536     else
2537#endif
2538          *value = pSiS->GammaBriB;
2539  } else if(attribute == pSiS->xv_PBR2) {
2540     *value = 1000;
2541  } else if(attribute == pSiS->xv_PBG2) {
2542     *value = 1000;
2543  } else if(attribute == pSiS->xv_PBB2) {
2544     *value = 1000;
2545  } else if(attribute == pSiS->xv_GARC2) {
2546     *value = (int)(pSiS->GammaR2 * 1000);
2547  } else if(attribute == pSiS->xv_GAGC2) {
2548     *value = (int)(pSiS->GammaG2 * 1000);
2549  } else if(attribute == pSiS->xv_GABC2) {
2550     *value = (int)(pSiS->GammaB2 * 1000);
2551  } else if(attribute == pSiS->xv_BRRC2) {
2552     *value = pSiS->GammaBriR2;
2553  } else if(attribute == pSiS->xv_BRGC2) {
2554     *value = pSiS->GammaBriG2;
2555  } else if(attribute == pSiS->xv_BRBC2) {
2556     *value = pSiS->GammaBriB2;
2557  } else if(attribute == pSiS->xv_PBRC2) {
2558     *value = 1000;
2559  } else if(attribute == pSiS->xv_PBGC2) {
2560     *value = 1000;
2561  } else if(attribute == pSiS->xv_PBBC2) {
2562     *value = 1000;
2563  } else if(attribute == pSiS->xv_SHC) {
2564     *value = pSiS->HideHWCursor ? 1 : 0;
2565  } else if(attribute == pSiS->xv_PMD) {
2566     *value = 0;
2567     if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
2568        switch(pSiS->SiS_Pr->UsePanelScaler) {
2569           case -1: *value |= 0x01; break;
2570           case 1:  *value |= 0x02; break;
2571        }
2572	if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
2573           switch(pSiS->SiS_Pr->CenterScreen) {
2574              case -1: *value |= 0x04; break;
2575              case 1:  *value |= 0x08; break;
2576           }
2577	}
2578     }
2579  } else {
2580     return BadMatch;
2581  }
2582
2583  return Success;
2584}
2585
2586#endif /* XV_SD_DEPRECATED */
2587
2588