sis_utility.c revision 72b676d7
172b676d7Smrg/* $XFree86$ */
272b676d7Smrg/* $XdotOrg$ */
372b676d7Smrg/*
472b676d7Smrg * SiS driver utility interface & routines
572b676d7Smrg *
672b676d7Smrg * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
772b676d7Smrg *
872b676d7Smrg * Redistribution and use in source and binary forms, with or without
972b676d7Smrg * modification, are permitted provided that the following conditions
1072b676d7Smrg * are met:
1172b676d7Smrg * 1) Redistributions of source code must retain the above copyright
1272b676d7Smrg *    notice, this list of conditions and the following disclaimer.
1372b676d7Smrg * 2) Redistributions in binary form must reproduce the above copyright
1472b676d7Smrg *    notice, this list of conditions and the following disclaimer in the
1572b676d7Smrg *    documentation and/or other materials provided with the distribution.
1672b676d7Smrg * 3) The name of the author may not be used to endorse or promote products
1772b676d7Smrg *    derived from this software without specific prior written permission.
1872b676d7Smrg *
1972b676d7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2072b676d7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2172b676d7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2272b676d7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2372b676d7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2472b676d7Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2572b676d7Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2672b676d7Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2772b676d7Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2872b676d7Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2972b676d7Smrg *
3072b676d7Smrg * Author: Thomas Winischhofer <thomas@winischhofer.net>
3172b676d7Smrg *
3272b676d7Smrg */
3372b676d7Smrg
3472b676d7Smrg#ifdef HAVE_CONFIG_H
3572b676d7Smrg#include "config.h"
3672b676d7Smrg#endif
3772b676d7Smrg
3872b676d7Smrg#include "sis.h"
3972b676d7Smrg#define NEED_REPLIES
4072b676d7Smrg#define NEED_EVENTS
4172b676d7Smrg#include <X11/X.h>
4272b676d7Smrg#include "dixstruct.h"
4372b676d7Smrg#define _XF86MISC_SERVER_
4472b676d7Smrg#include <X11/extensions/xf86misc.h>
4572b676d7Smrg
4672b676d7Smrg#include "sis_videostr.h"
4772b676d7Smrg
4872b676d7Smrg#ifdef TWDEBUG
4972b676d7Smrg#define SIS_NEED_orSISIDXREG
5072b676d7Smrg#include "sis_regs.h"
5172b676d7Smrg#endif
5272b676d7Smrg
5372b676d7Smrg/* Definitions for SISCTRL extension */
5472b676d7Smrg
5572b676d7Smrg#define SISCTRL_PROTOCOL_NAME	"SISCTRL"
5672b676d7Smrg
5772b676d7Smrg#define SISCTRL_MAJOR_VERSION		0	/* current version numbers */
5872b676d7Smrg#define SISCTRL_MINOR_VERSION		1
5972b676d7Smrg
6072b676d7Smrg#define SISCTRL_MAX_SCREENS		32	/* number of screens the ext can handle */
6172b676d7Smrg
6272b676d7Smrg#define X_SiSCtrlQueryVersion		0
6372b676d7Smrg#define X_SiSCtrlCommand		1
6472b676d7Smrg
6572b676d7Smrg#define SDC_ID				0x53495321
6672b676d7Smrg
6772b676d7Smrg#define SDC_VERSION			1
6872b676d7Smrg
6972b676d7Smrg#define SDC_NUM_PARM_RESULT		20
7072b676d7Smrg
7172b676d7Smrg/* sdc_command */
7272b676d7Smrg#define SDC_CMD_GETVERSION 		0x98980001
7372b676d7Smrg#define SDC_CMD_GETHWINFO		0x98980002
7472b676d7Smrg#define SDC_CMD_GETALLFLAGS		0x98980003
7572b676d7Smrg#define SDC_CMD_GETVBFLAGSVERSION	0x98980004
7672b676d7Smrg#define SDC_CMD_GETVBFLAGS		0x98980005
7772b676d7Smrg#define SDC_CMD_CHECKMODEFORCRT2	0x98980006
7872b676d7Smrg#define SDC_CMD_SETVBFLAGS		0x98980007
7972b676d7Smrg#define SDC_CMD_GETDETECTEDDEVICES	0x98980008
8072b676d7Smrg#define SDC_CMD_REDETECTCRT2DEVICES	0x98980009
8172b676d7Smrg#define SDC_CMD_GETCRT1STATUS		0x9898000a
8272b676d7Smrg#define SDC_CMD_SETCRT1STATUS		0x9898000b
8372b676d7Smrg#define SDC_CMD_GETSDFLAGS		0x9898000c
8472b676d7Smrg#define SDC_CMD_GETSD2FLAGS		0x9898000d
8572b676d7Smrg#define SDC_CMD_GETLOCKSTATUS		0x9898000e
8672b676d7Smrg#define SDC_CMD_SETLOCKSTATUS		0x9898000f
8772b676d7Smrg#define SDC_CMD_GETTVANTIFLICKER	0x98980010
8872b676d7Smrg#define SDC_CMD_SETTVANTIFLICKER	0x98980011
8972b676d7Smrg#define SDC_CMD_GETTVSATURATION		0x98980012
9072b676d7Smrg#define SDC_CMD_SETTVSATURATION		0x98980013
9172b676d7Smrg#define SDC_CMD_GETTVEDGEENHANCE	0x98980014
9272b676d7Smrg#define SDC_CMD_SETTVEDGEENHANCE	0x98980015
9372b676d7Smrg#define SDC_CMD_GETTVCFILTER		0x98980016
9472b676d7Smrg#define SDC_CMD_SETTVCFILTER		0x98980017
9572b676d7Smrg#define SDC_CMD_GETTVYFILTER		0x98980018
9672b676d7Smrg#define SDC_CMD_SETTVYFILTER		0x98980019
9772b676d7Smrg#define SDC_CMD_GETTVCOLORCALIB		0x9898001a
9872b676d7Smrg#define SDC_CMD_SETTVCOLORCALIB		0x9898001b
9972b676d7Smrg#define SDC_CMD_GETTVCHCONTRAST		0x9898001c
10072b676d7Smrg#define SDC_CMD_SETTVCHCONTRAST		0x9898001d
10172b676d7Smrg#define SDC_CMD_GETTVCHTEXTENHANCE	0x9898001e
10272b676d7Smrg#define SDC_CMD_SETTVCHTEXTENHANCE	0x9898001f
10372b676d7Smrg#define SDC_CMD_GETTVCHCHROMAFLICKERFILTER 0x98980020
10472b676d7Smrg#define SDC_CMD_SETTVCHCHROMAFLICKERFILTER 0x98980021
10572b676d7Smrg#define SDC_CMD_GETTVCHLUMAFLICKERFILTER 0x98980022
10672b676d7Smrg#define SDC_CMD_SETTVCHLUMAFLICKERFILTER 0x98980023
10772b676d7Smrg#define SDC_CMD_GETTVCHCVBSCOLOR	0x98980024
10872b676d7Smrg#define SDC_CMD_SETTVCHCVBSCOLOR	0x98980025
10972b676d7Smrg#define SDC_CMD_GETCHTVOVERSCAN		0x98980026
11072b676d7Smrg#define SDC_CMD_SETCHTVOVERSCAN		0x98980027
11172b676d7Smrg#define SDC_CMD_GETGAMMASTATUS		0x98980028
11272b676d7Smrg#define SDC_CMD_SETGAMMASTATUS		0x98980029
11372b676d7Smrg#define SDC_CMD_GETTVXSCALE		0x9898002a
11472b676d7Smrg#define SDC_CMD_SETTVXSCALE		0x9898002b
11572b676d7Smrg#define SDC_CMD_GETTVYSCALE		0x9898002c
11672b676d7Smrg#define SDC_CMD_SETTVYSCALE		0x9898002d
11772b676d7Smrg#define SDC_CMD_GETSCREENSIZE		0x9898002e
11872b676d7Smrg#define SDC_CMD_GETGAMMABRIGHTNESS	0x9898002f
11972b676d7Smrg#define SDC_CMD_SETGAMMABRIGHTNESS	0x98980030
12072b676d7Smrg#define SDC_CMD_GETGAMMABRIGHTNESS2	0x98980031
12172b676d7Smrg#define SDC_CMD_SETGAMMABRIGHTNESS2	0x98980032
12272b676d7Smrg#define SDC_CMD_GETGETGAMMACRT2		0x98980033
12372b676d7Smrg#define SDC_CMD_SETGETGAMMACRT2		0x98980034
12472b676d7Smrg#define SDC_CMD_GETHWCURSORSTATUS	0x98980035
12572b676d7Smrg#define SDC_CMD_SETHWCURSORSTATUS	0x98980036
12672b676d7Smrg#define SDC_CMD_GETPANELMODE		0x98980037
12772b676d7Smrg#define SDC_CMD_SETPANELMODE		0x98980038
12872b676d7Smrg#define SDC_CMD_GETMERGEDMODEDETAILS	0x98980039
12972b676d7Smrg#define SDC_CMD_GETDEVICENAME		0x9898003a
13072b676d7Smrg#define SDC_CMD_GETMONITORNAME		0x9898003b
13172b676d7Smrg#define SDC_CMD_GETDEVICENAME2		0x9898003c
13272b676d7Smrg#define SDC_CMD_GETMONITORNAME2		0x9898003d
13372b676d7Smrg#define SDC_CMD_SETXVBRIGHTNESS		0x9898003e
13472b676d7Smrg#define SDC_CMD_GETXVBRIGHTNESS		0x9898003f
13572b676d7Smrg#define SDC_CMD_SETXVCONTRAST		0x98980040
13672b676d7Smrg#define SDC_CMD_GETXVCONTRAST		0x98980041
13772b676d7Smrg#define SDC_CMD_SETXVHUE		0x98980042
13872b676d7Smrg#define SDC_CMD_GETXVHUE		0x98980043
13972b676d7Smrg#define SDC_CMD_SETXVSATURATION		0x98980044
14072b676d7Smrg#define SDC_CMD_GETXVSATURATION		0x98980045
14172b676d7Smrg#define SDC_CMD_SETXVGAMMA		0x98980046
14272b676d7Smrg#define SDC_CMD_GETXVGAMMA		0x98980047
14372b676d7Smrg#define SDC_CMD_SETXVCOLORKEY		0x98980048
14472b676d7Smrg#define SDC_CMD_GETXVCOLORKEY		0x98980049
14572b676d7Smrg#define SDC_CMD_SETXVAUTOPAINTCOLORKEY	0x9898004a
14672b676d7Smrg#define SDC_CMD_GETXVAUTOPAINTCOLORKEY	0x9898004b
14772b676d7Smrg#define SDC_CMD_SETXVDEFAULTS		0x9898004c
14872b676d7Smrg#define SDC_CMD_SETXVDISABLEGFX		0x9898004d
14972b676d7Smrg#define SDC_CMD_GETXVDISABLEGFX		0x9898004e
15072b676d7Smrg#define SDC_CMD_SETXVDISABLEGFXLR	0x9898004f
15172b676d7Smrg#define SDC_CMD_GETXVDISABLEGFXLR	0x98980050
15272b676d7Smrg#define SDC_CMD_SETXVSWITCHCRT		0x98980051
15372b676d7Smrg#define SDC_CMD_GETXVSWITCHCRT		0x98980052
15472b676d7Smrg#define SDC_CMD_GETTVXPOS		0x98980053
15572b676d7Smrg#define SDC_CMD_SETTVXPOS		0x98980054
15672b676d7Smrg#define SDC_CMD_GETTVYPOS		0x98980055
15772b676d7Smrg#define SDC_CMD_SETTVYPOS		0x98980056
15872b676d7Smrg#define SDC_CMD_SETXVDEINT		0x98980057
15972b676d7Smrg#define SDC_CMD_GETXVDEINT		0x98980058
16072b676d7Smrg#define SDC_CMD_GETMONGAMMACRT1		0x98980059
16172b676d7Smrg#define SDC_CMD_GETMONGAMMACRT2		0x9898005a
16272b676d7Smrg#define SDC_CMD_LOGQUIET		0x9898005b
16372b676d7Smrg#define SDC_CMD_GETNEWGAMMABRICON	0x9898005c
16472b676d7Smrg#define SDC_CMD_SETNEWGAMMABRICON	0x9898005d
16572b676d7Smrg#define SDC_CMD_GETNEWGAMMABRICON2	0x9898005e
16672b676d7Smrg#define SDC_CMD_SETNEWGAMMABRICON2	0x9898005f
16772b676d7Smrg#define SDC_CMD_GETGETNEWGAMMACRT2	0x98980060
16872b676d7Smrg#define SDC_CMD_SETGETNEWGAMMACRT2	0x98980061
16972b676d7Smrg#define SDC_CMD_NEWSETVBFLAGS		0x98980062
17072b676d7Smrg#define SDC_CMD_GETCRT1SATGAIN		0x98980063
17172b676d7Smrg#define SDC_CMD_SETCRT1SATGAIN		0x98980064
17272b676d7Smrg#define SDC_CMD_GETCRT2SATGAIN		0x98980065
17372b676d7Smrg#define SDC_CMD_SETCRT2SATGAIN		0x98980066
17472b676d7Smrg/* more to come, adapt MAXCOMMAND! */
17572b676d7Smrg#define SDC_MAXCOMMAND			SDC_CMD_SETCRT2SATGAIN
17672b676d7Smrg
17772b676d7Smrg/* in result_header */
17872b676d7Smrg#define SDC_RESULT_OK  			0x66670000
17972b676d7Smrg#define SDC_RESULT_UNDEFCMD		0x66670001
18072b676d7Smrg#define SDC_RESULT_NOPERM		0x66670002
18172b676d7Smrg#define SDC_RESULT_INVAL		0x66670003
18272b676d7Smrg#define SDC_RESULT_MESSAGEERROR		0x66670004  /* Client side only */
18372b676d7Smrg#define SDC_RESULT_NOEXTENSION		0x66670005  /* Client side only */
18472b676d7Smrg
18572b676d7Smrg/* For SDC_CMD_GETHWINFO */
18672b676d7Smrg#define SDC_BUS_TYPE_PCI		0
18772b676d7Smrg#define SDC_BUS_TYPE_AGP		1
18872b676d7Smrg#define SDC_BUS_TYPE_PCIE		2
18972b676d7Smrg#define SDC_BUS_TYPE_USB		3
19072b676d7Smrg
19172b676d7Smrg/* For SDC_CMD_GETMERGEDMODEDETAILS */
19272b676d7Smrg#define SDC_MMODE_POS_ERROR		0
19372b676d7Smrg#define SDC_MMODE_POS_LEFTOF		1
19472b676d7Smrg#define SDC_MMODE_POS_RIGHTOF		2
19572b676d7Smrg#define SDC_MMODE_POS_ABOVE		3
19672b676d7Smrg#define SDC_MMODE_POS_BELOW		4
19772b676d7Smrg#define SDC_MMODE_POS_CLONE		5
19872b676d7Smrg
19972b676d7Smrgtypedef struct _SiSCtrlQueryVersion {
20072b676d7Smrg    CARD8	reqType;		/* always SiSCtrlReqCode */
20172b676d7Smrg    CARD8	SiSCtrlReqType;		/* always X_SiSCtrlQueryVersion */
20272b676d7Smrg    CARD16	length B16;
20372b676d7Smrg} xSiSCtrlQueryVersionReq;
20472b676d7Smrg#define sz_xSiSCtrlQueryVersionReq	4
20572b676d7Smrg
20672b676d7Smrgtypedef struct {
20772b676d7Smrg    BYTE	type;			/* X_Reply */
20872b676d7Smrg    BOOL	pad1;
20972b676d7Smrg    CARD16	sequenceNumber B16;
21072b676d7Smrg    CARD32	length B32;
21172b676d7Smrg    CARD16	majorVersion B16;	/* major version of SISCTRL */
21272b676d7Smrg    CARD16	minorVersion B16;	/* minor version of SISCTRL */
21372b676d7Smrg    CARD32	pad2 B32;
21472b676d7Smrg    CARD32	pad3 B32;
21572b676d7Smrg    CARD32	pad4 B32;
21672b676d7Smrg    CARD32	pad5 B32;
21772b676d7Smrg    CARD32	pad6 B32;
21872b676d7Smrg} xSiSCtrlQueryVersionReply;
21972b676d7Smrg#define sz_xSiSCtrlQueryVersionReply	32
22072b676d7Smrg
22172b676d7Smrgtypedef struct {
22272b676d7Smrg    CARD8	reqType;		/* always SiSCtrlReqCode */
22372b676d7Smrg    CARD8	SiSCtrlReqType;		/* always SiSCtrl_SiSCtrlCommand */
22472b676d7Smrg    CARD16	length B16;
22572b676d7Smrg    CARD32	pad1 B32;
22672b676d7Smrg    CARD32	screen;
22772b676d7Smrg    CARD32 	sdc_id;
22872b676d7Smrg    CARD32 	sdc_chksum;
22972b676d7Smrg    CARD32	sdc_command;
23072b676d7Smrg    CARD32	sdc_parm[SDC_NUM_PARM_RESULT];
23172b676d7Smrg    CARD32	sdc_result_header;
23272b676d7Smrg    CARD32	sdc_result[SDC_NUM_PARM_RESULT];
23372b676d7Smrg    char	sdc_buffer[32];
23472b676d7Smrg} xSiSCtrlCommandReq;
23572b676d7Smrg#define sz_xSiSCtrlCommandReq		(28 + (SDC_NUM_PARM_RESULT * 4 * 2) + 32)
23672b676d7Smrg
23772b676d7Smrgtypedef struct {
23872b676d7Smrg    BYTE	type;			/* X_Reply */
23972b676d7Smrg    BOOL	pad1;
24072b676d7Smrg    CARD16	sequenceNumber B16;
24172b676d7Smrg    CARD32	length B32;
24272b676d7Smrg    CARD32	screen;
24372b676d7Smrg    CARD32 	sdc_id;
24472b676d7Smrg    CARD32 	sdc_chksum;
24572b676d7Smrg    CARD32	sdc_command;
24672b676d7Smrg    CARD32	sdc_parm[SDC_NUM_PARM_RESULT];
24772b676d7Smrg    CARD32	sdc_result_header;
24872b676d7Smrg    CARD32	sdc_result[SDC_NUM_PARM_RESULT];
24972b676d7Smrg    char	sdc_buffer[32];
25072b676d7Smrg} xSiSCtrlCommandReply;
25172b676d7Smrg#define sz_xSiSCtrlCommandReply		(28 + (SDC_NUM_PARM_RESULT * 4 * 2) + 32)
25272b676d7Smrg
25372b676d7Smrgtypedef struct {
25472b676d7Smrg    unsigned int maxscreens;		/* Max number of entries = SISCTRL_MAX_SCREENS*/
25572b676d7Smrg    unsigned int version_major;		/* Extension major version */
25672b676d7Smrg    unsigned int version_minor; 	/* Extension minor version */
25772b676d7Smrg    int		 (*HandleSiSDirectCommand[SISCTRL_MAX_SCREENS])(xSiSCtrlCommandReply *);
25872b676d7Smrg} xSiSCtrlScreenTable;
25972b676d7Smrg
26072b676d7Smrg#ifdef X_XF86MiscPassMessage
26172b676d7Smrgint		SISHandleMessage(int scrnIndex, const char *msgtype, const char *msgval, char **retmsg);
26272b676d7Smrg#endif
26372b676d7Smrgvoid		SiSCtrlExtInit(ScrnInfoPtr pScrn);
26472b676d7Smrgvoid		SiSCtrlExtUnregister(SISPtr pSiS, int index);
26572b676d7Smrg
26672b676d7Smrg#ifdef XV_SD_DEPRECATED
26772b676d7Smrgint		SISSetPortUtilAttribute(ScrnInfoPtr pScrn, Atom attribute,
26872b676d7Smrg					INT32 value, SISPortPrivPtr pPriv);
26972b676d7Smrgint		SISGetPortUtilAttribute(ScrnInfoPtr pScrn,  Atom attribute,
27072b676d7Smrg					INT32 *value, SISPortPrivPtr pPriv);
27172b676d7Smrg#endif
27272b676d7Smrg
27372b676d7Smrgextern Bool 	SISRedetectCRT2Type(ScrnInfoPtr pScrn);
27472b676d7Smrgextern UShort	SiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode,
27572b676d7Smrg				 unsigned int VBFlags, Bool hcm);
27672b676d7Smrgextern UShort	SiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode,
27772b676d7Smrg				 unsigned int VBFlags, Bool hcm);
27872b676d7Smrgextern void	SISAdjustFrame(int scrnIndex, int x, int y, int flags);
27972b676d7Smrgextern float	SiSCalcVRate(DisplayModePtr mode);
28072b676d7Smrgextern void	SiS_UpdateGammaCRT2(ScrnInfoPtr pScrn);
28172b676d7Smrg#ifdef SISGAMMARAMP
28272b676d7Smrgextern void	SISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn);
28372b676d7Smrg#endif
28472b676d7Smrg
28572b676d7Smrgextern void	SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv);
28672b676d7Smrgextern void	SISUpdateVideoParms(SISPtr pSiS, SISPortPrivPtr pPriv);
28772b676d7Smrgextern void	SiSUpdateXvGamma(SISPtr pSiS, SISPortPrivPtr pPriv);
28872b676d7Smrg
28972b676d7Smrg/***********************************
29072b676d7Smrg *        Low-level routines       *
29172b676d7Smrg ***********************************/
29272b676d7Smrg
29372b676d7Smrgstatic Bool
29472b676d7SmrgSISSwitchCRT1Status(ScrnInfoPtr pScrn, int onoff, Bool quiet)
29572b676d7Smrg{
29672b676d7Smrg    SISPtr pSiS = SISPTR(pScrn);
29772b676d7Smrg    DisplayModePtr mode = pScrn->currentMode;
29872b676d7Smrg    ULong vbflags = pSiS->VBFlags;
29972b676d7Smrg    ULong vbflags3 = pSiS->VBFlags3;
30072b676d7Smrg    int crt1off;
30172b676d7Smrg
30272b676d7Smrg    /* onoff: 0=OFF, 1=ON(VGA), 2=ON(LCDA) */
30372b676d7Smrg
30472b676d7Smrg    /* Switching to LCDA will disable CRT2 if previously LCD or VGA,
30572b676d7Smrg     * unless on a dual-vb setup
30672b676d7Smrg     */
30772b676d7Smrg
30872b676d7Smrg    /* For usability reasons, the user should not simply "lose" one
30972b676d7Smrg     * of his output devices in MergedFB mode. Therefore, a switch
31072b676d7Smrg     * which might lead to this situation will not be performed in
31172b676d7Smrg     * MergedFB mode. (For example: If CRT2 is either LCD or VGA,
31272b676d7Smrg     * don't let the user switch to LCD-via-CRT1 mode, because he
31372b676d7Smrg     * would lose one output device since LCD-via-CRT1 is only
31472b676d7Smrg     * supported together with TV, not any other CRT2 type.)
31572b676d7Smrg     * In Non-MergedFB mode, losing one output device is not
31672b676d7Smrg     * considered that harmful.
31772b676d7Smrg     * Update: We let the user switch off a device if currently
31872b676d7Smrg     * a "clone" mode is active. Same for switching CRT1 to LCD
31972b676d7Smrg     * while CRT2 is LCD or VGA.
32072b676d7Smrg     */
32172b676d7Smrg
32272b676d7Smrg    /* Do NOT use this to switch from CRT1_LCDA to CRT2_LCD */
32372b676d7Smrg
32472b676d7Smrg    /* Only on 300 and 315/330/340 series */
32572b676d7Smrg    if(pSiS->VGAEngine != SIS_300_VGA &&
32672b676d7Smrg       pSiS->VGAEngine != SIS_315_VGA) return FALSE;
32772b676d7Smrg
32872b676d7Smrg    /* Off only if at least one CRT2 device is active */
32972b676d7Smrg    if((!onoff) && (!(vbflags & CRT2_ENABLE))) return FALSE;
33072b676d7Smrg
33172b676d7Smrg#ifdef SISDUALHEAD
33272b676d7Smrg    if(pSiS->DualHeadMode) return FALSE;
33372b676d7Smrg#endif
33472b676d7Smrg
33572b676d7Smrg    /* Can't switch to LCDA if not supported (duh!) */
33672b676d7Smrg    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA)) {
33772b676d7Smrg       if(onoff == 2) {
33872b676d7Smrg          if(!quiet) {
33972b676d7Smrg             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
34072b676d7Smrg	        "LCD-via-CRT1 not supported by hardware or no panel detected\n");
34172b676d7Smrg	  }
34272b676d7Smrg          return FALSE;
34372b676d7Smrg       }
34472b676d7Smrg    }
34572b676d7Smrg
34672b676d7Smrg#ifdef SISMERGED
34772b676d7Smrg    if(pSiS->MergedFB) {
34872b676d7Smrg       if(((SiSMergedDisplayModePtr)mode->Private)->CRT2Position != sisClone) {
34972b676d7Smrg          if(!onoff) {
35072b676d7Smrg             if(!quiet) {
35172b676d7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
35272b676d7Smrg	           "CRT1 can't be switched off in MergedFB mode unless a clone mode is active\n");
35372b676d7Smrg	     }
35472b676d7Smrg             return FALSE;
35572b676d7Smrg          } else if(onoff == 2) {
35672b676d7Smrg             if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
35772b676d7Smrg                if(vbflags & (CRT2_LCD|CRT2_VGA)) {
35872b676d7Smrg	           if(!quiet) {
35972b676d7Smrg	              xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
36072b676d7Smrg	   	         "CRT1 type can only be VGA while CRT2 is LCD or VGA\n");
36172b676d7Smrg	           }
36272b676d7Smrg                   return FALSE;
36372b676d7Smrg                }
36472b676d7Smrg	     }
36572b676d7Smrg          }
36672b676d7Smrg       }
36772b676d7Smrg       if(mode->Private) {
36872b676d7Smrg	  mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
36972b676d7Smrg       }
37072b676d7Smrg    }
37172b676d7Smrg#endif
37272b676d7Smrg
37372b676d7Smrg    vbflags &= ~(DISPTYPE_CRT1 | SINGLE_MODE | MIRROR_MODE | CRT1_LCDA);
37472b676d7Smrg    vbflags3 &= ~(VB3_CRT1_TV | VB3_CRT1_LCD | VB3_CRT1_VGA);
37572b676d7Smrg    crt1off = 1;
37672b676d7Smrg    if(onoff > 0) {
37772b676d7Smrg       vbflags |= DISPTYPE_CRT1;
37872b676d7Smrg       crt1off = 0;
37972b676d7Smrg       if(onoff == 2) {
38072b676d7Smrg	  vbflags |= CRT1_LCDA;
38172b676d7Smrg	  vbflags3 |= VB3_CRT1_LCD;
38272b676d7Smrg	  if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
38372b676d7Smrg	     vbflags &= ~(CRT2_LCD|CRT2_VGA);
38472b676d7Smrg	  }
38572b676d7Smrg       } else {
38672b676d7Smrg          vbflags3 |= VB3_CRT1_VGA;
38772b676d7Smrg       }
38872b676d7Smrg       /* Remember: Dualhead not supported */
38972b676d7Smrg       if(vbflags & CRT2_ENABLE) vbflags |= MIRROR_MODE;
39072b676d7Smrg       else vbflags |= SINGLE_MODE;
39172b676d7Smrg    } else {
39272b676d7Smrg       vbflags |= SINGLE_MODE;
39372b676d7Smrg    }
39472b676d7Smrg
39572b676d7Smrg    if(vbflags & CRT1_LCDA) {
39672b676d7Smrg       if(SiS_CheckModeCRT1(pScrn, mode, vbflags, pSiS->HaveCustomModes) < 0x14) {
39772b676d7Smrg          if(!quiet) {
39872b676d7Smrg             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
39972b676d7Smrg		"Current mode not suitable for LCD-via-CRT1\n");
40072b676d7Smrg	  }
40172b676d7Smrg          return FALSE;
40272b676d7Smrg       }
40372b676d7Smrg    }
40472b676d7Smrg
40572b676d7Smrg    pSiS->CRT1off = crt1off;
40672b676d7Smrg    pSiS->VBFlags = pSiS->VBFlags_backup = vbflags;
40772b676d7Smrg    pSiS->VBFlags3 = pSiS->VBFlags_backup3 = vbflags3;
40872b676d7Smrg
40972b676d7Smrg    /* Sync the accelerators */
41072b676d7Smrg    (*pSiS->SyncAccel)(pScrn);
41172b676d7Smrg
41272b676d7Smrg    pSiS->skipswitchcheck = TRUE;
41372b676d7Smrg    if(!(pScrn->SwitchMode(pScrn->scrnIndex, pScrn->currentMode, 0))) {
41472b676d7Smrg       pSiS->skipswitchcheck = FALSE;
41572b676d7Smrg       return FALSE;
41672b676d7Smrg    }
41772b676d7Smrg    pSiS->skipswitchcheck = FALSE;
41872b676d7Smrg    SISAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
41972b676d7Smrg    return TRUE;
42072b676d7Smrg}
42172b676d7Smrg
42272b676d7Smrgstatic Bool
42372b676d7SmrgSISRedetectCRT2Devices(ScrnInfoPtr pScrn)
42472b676d7Smrg{
42572b676d7Smrg    SISPtr pSiS = SISPTR(pScrn);
42672b676d7Smrg
42772b676d7Smrg    if((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) {
42872b676d7Smrg       return FALSE;
42972b676d7Smrg    }
43072b676d7Smrg
43172b676d7Smrg#ifdef SISDUALHEAD
43272b676d7Smrg    if(pSiS->DualHeadMode) return FALSE;
43372b676d7Smrg#endif
43472b676d7Smrg
43572b676d7Smrg    /* Sync the accelerators */
43672b676d7Smrg    (*pSiS->SyncAccel)(pScrn);
43772b676d7Smrg
43872b676d7Smrg    if(SISRedetectCRT2Type(pScrn)) {
43972b676d7Smrg       /* If this returns TRUE, we need to reset the display mode */
44072b676d7Smrg       /* Sync the accelerators */
44172b676d7Smrg       (*pSiS->SyncAccel)(pScrn);
44272b676d7Smrg       pSiS->skipswitchcheck = TRUE;
44372b676d7Smrg       if(!(pScrn->SwitchMode(pScrn->scrnIndex, pScrn->currentMode, 0))) {
44472b676d7Smrg          pSiS->skipswitchcheck = FALSE;
44572b676d7Smrg          return FALSE;
44672b676d7Smrg       }
44772b676d7Smrg       pSiS->skipswitchcheck = FALSE;
44872b676d7Smrg       SISAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
44972b676d7Smrg    }
45072b676d7Smrg    return TRUE;
45172b676d7Smrg}
45272b676d7Smrg
45372b676d7Smrgstatic Bool
45472b676d7SmrgSISSwitchCRT2Type(ScrnInfoPtr pScrn, ULong newvbflags, Bool quiet)
45572b676d7Smrg{
45672b676d7Smrg    SISPtr pSiS = SISPTR(pScrn);
45772b676d7Smrg    Bool hcm = pSiS->HaveCustomModes;
45872b676d7Smrg    DisplayModePtr mode = pScrn->currentMode;
45972b676d7Smrg
46072b676d7Smrg    /* Do NOT use this to switch from CRT2_LCD to CRT1_LCDA */
46172b676d7Smrg
46272b676d7Smrg    /* Switching CRT2 to LCD or VGA will switch CRT1 to VGA if
46372b676d7Smrg     * previously LCD-via-CRT1
46472b676d7Smrg     */
46572b676d7Smrg
46672b676d7Smrg    /* For usability reasons, the user should not simply "lose" one
46772b676d7Smrg     * of his output devices in MergedFB mode. Therefore, a switch
46872b676d7Smrg     * which might lead to this situation will not be performed in
46972b676d7Smrg     * MergedFB mode. (For example: If CRT1 is LCD-via-CRT1, don't
47072b676d7Smrg     * let the user switch CRT2 to LCD or VGA mode, because he
47172b676d7Smrg     * would lose one output device since LCD-via-CRT1 is only
47272b676d7Smrg     * supported together with TV, not any other CRT2 type.)
47372b676d7Smrg     * In Non-MergedFB mode, losing one output device is not
47472b676d7Smrg     * considered that harmful.
47572b676d7Smrg     * Update: We allow this if currently a "clone" display mode
47672b676d7Smrg     * is active.
47772b676d7Smrg     */
47872b676d7Smrg
47972b676d7Smrg    /* Only on 300 and 315/330/340 series */
48072b676d7Smrg    if(pSiS->VGAEngine != SIS_300_VGA &&
48172b676d7Smrg       pSiS->VGAEngine != SIS_315_VGA) return FALSE;
48272b676d7Smrg
48372b676d7Smrg    /* Only if there is a video bridge */
48472b676d7Smrg    if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE;
48572b676d7Smrg
48672b676d7Smrg#ifdef SISDUALHEAD
48772b676d7Smrg    if(pSiS->DualHeadMode) return FALSE;
48872b676d7Smrg#endif
48972b676d7Smrg
49072b676d7Smrg#define SiS_NewVBMask (CRT2_ENABLE|CRT1_LCDA|TV_PAL|TV_NTSC|TV_PALM|TV_PALN|TV_NTSCJ| \
49172b676d7Smrg		       TV_AVIDEO|TV_SVIDEO|TV_SCART|TV_HIVISION|TV_YPBPR|TV_YPBPRALL|\
49272b676d7Smrg		       TV_YPBPRAR)
49372b676d7Smrg
49472b676d7Smrg    newvbflags &= SiS_NewVBMask;
49572b676d7Smrg    newvbflags |= pSiS->VBFlags & ~SiS_NewVBMask;
49672b676d7Smrg
49772b676d7Smrg    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA)) {
49872b676d7Smrg       newvbflags &= ~CRT1_LCDA;
49972b676d7Smrg    }
50072b676d7Smrg    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) {
50172b676d7Smrg       newvbflags &= ~TV_HIVISION;
50272b676d7Smrg    }
50372b676d7Smrg    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) {
50472b676d7Smrg       newvbflags &= ~TV_YPBPR;
50572b676d7Smrg    }
50672b676d7Smrg
50772b676d7Smrg#ifdef SISMERGED
50872b676d7Smrg    if(pSiS->MergedFB) {
50972b676d7Smrg       if((mode->Private) &&
51072b676d7Smrg          ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position != sisClone) {
51172b676d7Smrg          if(!(newvbflags & CRT2_ENABLE)) {
51272b676d7Smrg             if(!quiet) {
51372b676d7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
51472b676d7Smrg	           "CRT2 can't be switched off in MergedFB mode unless a clone mode is active\n");
51572b676d7Smrg	     }
51672b676d7Smrg	     return FALSE;
51772b676d7Smrg          }
51872b676d7Smrg          if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
51972b676d7Smrg             if((newvbflags & (CRT2_LCD|CRT2_VGA)) && (newvbflags & CRT1_LCDA)) {
52072b676d7Smrg                if(!quiet) {
52172b676d7Smrg	           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
52272b676d7Smrg	              "CRT2 type can only be TV while in LCD-via-CRT1 mode\n");
52372b676d7Smrg	        }
52472b676d7Smrg	        return FALSE;
52572b676d7Smrg	     }
52672b676d7Smrg          }
52772b676d7Smrg       }
52872b676d7Smrg       hcm = pSiS->HaveCustomModes2;
52972b676d7Smrg       if(mode->Private) {
53072b676d7Smrg	  mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2;
53172b676d7Smrg       }
53272b676d7Smrg    }
53372b676d7Smrg#endif
53472b676d7Smrg
53572b676d7Smrg    if((!(newvbflags & CRT2_ENABLE)) && (!newvbflags & DISPTYPE_CRT1)) {
53672b676d7Smrg       if(!quiet) {
53772b676d7Smrg          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
53872b676d7Smrg             "CRT2 can't be switched off while CRT1 is off\n");
53972b676d7Smrg       }
54072b676d7Smrg       return FALSE;
54172b676d7Smrg    }
54272b676d7Smrg
54372b676d7Smrg    /* CRT2_LCD and CRT2_VGA overrule LCDA (in non-MergedFB mode) */
54472b676d7Smrg    if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
54572b676d7Smrg       if(newvbflags & (CRT2_LCD|CRT2_VGA)) {
54672b676d7Smrg          newvbflags &= ~CRT1_LCDA;
54772b676d7Smrg       }
54872b676d7Smrg    }
54972b676d7Smrg
55072b676d7Smrg    /* Check if the current mode is suitable for desired output device (if any) */
55172b676d7Smrg    if(SiS_CheckModeCRT2(pScrn, mode, newvbflags, hcm) < 0x14) {
55272b676d7Smrg       if(!quiet) {
55372b676d7Smrg          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
55472b676d7Smrg	     "Current mode not suitable for desired CRT2 output device\n");
55572b676d7Smrg       }
55672b676d7Smrg       return FALSE;
55772b676d7Smrg    }
55872b676d7Smrg
55972b676d7Smrg    /* Remember: Dualhead not supported */
56072b676d7Smrg    newvbflags &= ~(SINGLE_MODE | MIRROR_MODE);
56172b676d7Smrg    if((newvbflags & DISPTYPE_CRT1) && (newvbflags & CRT2_ENABLE)) {
56272b676d7Smrg       newvbflags |= MIRROR_MODE;
56372b676d7Smrg    } else {
56472b676d7Smrg       newvbflags |= SINGLE_MODE;
56572b676d7Smrg    }
56672b676d7Smrg
56772b676d7Smrg    /* Sync the accelerators */
56872b676d7Smrg    (*pSiS->SyncAccel)(pScrn);
56972b676d7Smrg
57072b676d7Smrg    pSiS->VBFlags = pSiS->VBFlags_backup = newvbflags;
57172b676d7Smrg
57272b676d7Smrg    pSiS->skipswitchcheck = TRUE;
57372b676d7Smrg    if(!(pScrn->SwitchMode(pScrn->scrnIndex, pScrn->currentMode, 0))) {
57472b676d7Smrg       pSiS->skipswitchcheck = FALSE;
57572b676d7Smrg       return FALSE;
57672b676d7Smrg    }
57772b676d7Smrg    pSiS->skipswitchcheck = FALSE;
57872b676d7Smrg    SISAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
57972b676d7Smrg    return TRUE;
58072b676d7Smrg}
58172b676d7Smrg
58272b676d7Smrgstatic Bool
58372b676d7SmrgSISSwitchOutputType(ScrnInfoPtr pScrn, ULong newvbflags, ULong newvbflags3,
58472b676d7Smrg		ULong newvbflags4, Bool quiet)
58572b676d7Smrg{
58672b676d7Smrg    /* For future use */
58772b676d7Smrg
58872b676d7Smrg    return FALSE;
58972b676d7Smrg}
59072b676d7Smrg
59172b676d7Smrgstatic ULong
59272b676d7SmrgSiSCondToVBFlags(UShort cond, ULong GivenVBFlags)
59372b676d7Smrg{
59472b676d7Smrg    ULong vbflags = GivenVBFlags;
59572b676d7Smrg
59672b676d7Smrg    /* No special treatment for NTSC-J here; conditions equal NTSC */
59772b676d7Smrg    if(cond) {
59872b676d7Smrg       vbflags &= ~(CRT2_ENABLE | CRT1_LCDA | TV_STANDARD | TV_INTERFACE);
59972b676d7Smrg       if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_LCD) {
60072b676d7Smrg	  vbflags |= CRT2_LCD;
60172b676d7Smrg       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_TV) {
60272b676d7Smrg	  vbflags |= (CRT2_TV | TV_SVIDEO);
60372b676d7Smrg	  if(cond & SiS_CF2_TVPAL)  	  vbflags |= TV_PAL;
60472b676d7Smrg	  else if(cond & SiS_CF2_TVPALM)  vbflags |= (TV_PAL | TV_PALM);
60572b676d7Smrg	  else if(cond & SiS_CF2_TVPALN)  vbflags |= (TV_PAL | TV_PALN);
60672b676d7Smrg	  else if(cond & SiS_CF2_TVNTSC)  vbflags |= TV_NTSC;
60772b676d7Smrg       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_TVSPECIAL) {
60872b676d7Smrg          vbflags |= CRT2_TV;
60972b676d7Smrg	  if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVHIVISION)
61072b676d7Smrg		vbflags |= TV_HIVISION;
61172b676d7Smrg	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR525I)
61272b676d7Smrg		vbflags |= (TV_YPBPR | TV_YPBPR525I);
61372b676d7Smrg	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR525P)
61472b676d7Smrg		vbflags |= (TV_YPBPR | TV_YPBPR525P);
61572b676d7Smrg	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR625I)
61672b676d7Smrg		vbflags |= (TV_YPBPR | TV_YPBPR625I);
61772b676d7Smrg	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR625P)
61872b676d7Smrg		vbflags |= (TV_YPBPR | TV_YPBPR625P);
61972b676d7Smrg	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR750P)
62072b676d7Smrg		vbflags |= (TV_YPBPR | TV_YPBPR750P);
62172b676d7Smrg	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR1080I)
62272b676d7Smrg		vbflags |= (TV_YPBPR | TV_YPBPR1080I);
62372b676d7Smrg       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_VGA2) {
62472b676d7Smrg	  vbflags |= CRT2_VGA;
62572b676d7Smrg       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_CRT1LCDA) {
62672b676d7Smrg	  vbflags |= CRT1_LCDA;
62772b676d7Smrg       }
62872b676d7Smrg    }
62972b676d7Smrg    return(vbflags);
63072b676d7Smrg}
63172b676d7Smrg
63272b676d7Smrgstatic int
63372b676d7SmrgSISCheckModeForCRT2Type(ScrnInfoPtr pScrn, DisplayModePtr mode, ULong vbflags, UShort cond, Bool quiet)
63472b676d7Smrg{
63572b676d7Smrg    SISPtr pSiS = SISPTR(pScrn);
63672b676d7Smrg    DisplayModePtr mastermode;
63772b676d7Smrg    Bool hcm = pSiS->HaveCustomModes;
63872b676d7Smrg    int result = 0;
63972b676d7Smrg
64072b676d7Smrg    mastermode = mode;
64172b676d7Smrg
64272b676d7Smrg#ifdef SISDUALHEAD
64372b676d7Smrg    if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) {
64472b676d7Smrg#endif
64572b676d7Smrg
64672b676d7Smrg       if(vbflags & CRT2_ENABLE) {
64772b676d7Smrg
64872b676d7Smrg#ifdef SISMERGED
64972b676d7Smrg          if(pSiS->MergedFB) {
65072b676d7Smrg             hcm = pSiS->HaveCustomModes2;
65172b676d7Smrg             if(mode->Private) {
65272b676d7Smrg	        mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2;
65372b676d7Smrg             }
65472b676d7Smrg          }
65572b676d7Smrg#endif
65672b676d7Smrg
65772b676d7Smrg          /* For RandR */
65872b676d7Smrg          if((mode->HDisplay > pScrn->virtualX) || (mode->VDisplay > pScrn->virtualY)) {
65972b676d7Smrg             if(!quiet) {
66072b676d7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
66172b676d7Smrg		    "Desired mode too large for current screen size\n");
66272b676d7Smrg             }
66372b676d7Smrg             result |= 0x02;
66472b676d7Smrg          }
66572b676d7Smrg
66672b676d7Smrg          /* Check if the desired mode is suitable for current CRT2 output device */
66772b676d7Smrg          if(SiS_CheckModeCRT2(pScrn, mode, vbflags, hcm) < 0x14) {
66872b676d7Smrg             if((!cond) && (!quiet)) {
66972b676d7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
67072b676d7Smrg		    "Desired mode not suitable for current CRT2 output device\n");
67172b676d7Smrg             }
67272b676d7Smrg             result |= 0x01;
67372b676d7Smrg          }
67472b676d7Smrg
67572b676d7Smrg       }
67672b676d7Smrg
67772b676d7Smrg#ifdef SISDUALHEAD
67872b676d7Smrg    }
67972b676d7Smrg#endif
68072b676d7Smrg
68172b676d7Smrg    mode = mastermode;
68272b676d7Smrg
68372b676d7Smrg#ifdef SISDUALHEAD
68472b676d7Smrg    if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) {
68572b676d7Smrg#endif
68672b676d7Smrg
68772b676d7Smrg       if(vbflags & CRT1_LCDA) {
68872b676d7Smrg
68972b676d7Smrg#ifdef SISMERGED
69072b676d7Smrg          if(pSiS->MergedFB) {
69172b676d7Smrg             hcm = pSiS->HaveCustomModes;
69272b676d7Smrg             if(mode->Private) {
69372b676d7Smrg	        mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
69472b676d7Smrg	     }
69572b676d7Smrg          }
69672b676d7Smrg#endif
69772b676d7Smrg
69872b676d7Smrg	  /* For RandR */
69972b676d7Smrg	  if((mode->HDisplay > pScrn->virtualX) || (mode->VDisplay > pScrn->virtualY)) {
70072b676d7Smrg	     if(!quiet) {
70172b676d7Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
70272b676d7Smrg			"Desired mode too large for current screen size\n");
70372b676d7Smrg	     }
70472b676d7Smrg	     result |= 0x02;
70572b676d7Smrg	  }
70672b676d7Smrg
70772b676d7Smrg	  /* Check if the desired mode is suitable for current CRT1 output device */
70872b676d7Smrg	  if(SiS_CheckModeCRT1(pScrn, mode, vbflags, hcm) < 0x14) {
70972b676d7Smrg	     if((!cond) && (!quiet)) {
71072b676d7Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
71172b676d7Smrg		      "Desired mode not suitable for current CRT1 output device\n");
71272b676d7Smrg	     }
71372b676d7Smrg	     result |= 0x01;
71472b676d7Smrg	  }
71572b676d7Smrg
71672b676d7Smrg       }
71772b676d7Smrg
71872b676d7Smrg#ifdef SISDUALHEAD
71972b676d7Smrg    }
72072b676d7Smrg#endif
72172b676d7Smrg
72272b676d7Smrg    return result;
72372b676d7Smrg}
72472b676d7Smrg
72572b676d7Smrg#ifdef XV_SD_DEPRECATED
72672b676d7Smrgstatic int
72772b676d7SmrgSISCheckModeIndexForCRT2Type(ScrnInfoPtr pScrn, UShort cond, UShort index, Bool quiet)
72872b676d7Smrg{
72972b676d7Smrg    SISPtr pSiS = SISPTR(pScrn);
73072b676d7Smrg    DisplayModePtr mode = pScrn->modes;
73172b676d7Smrg    ULong vbflags;
73272b676d7Smrg    int i;
73372b676d7Smrg
73472b676d7Smrg    /* Not only CRT2, but also LCDA */
73572b676d7Smrg
73672b676d7Smrg    /* returns 0 if mode ok,
73772b676d7Smrg     *         0x01 if mode not ok for CRT2 device,
73872b676d7Smrg     *         0x02 if mode too large for current root window
73972b676d7Smrg     *         or combinations thereof
74072b676d7Smrg     */
74172b676d7Smrg
74272b676d7Smrg    vbflags = SiSCondToVBFlags(cond, pSiS->VBFlags);
74372b676d7Smrg
74472b676d7Smrg    /* Find mode of given index */
74572b676d7Smrg    if(index) {
74672b676d7Smrg       for(i = 0; i < index; i++) {
74772b676d7Smrg          if(!mode) return 0x03;
74872b676d7Smrg          mode = mode->next;
74972b676d7Smrg       }
75072b676d7Smrg    }
75172b676d7Smrg
75272b676d7Smrg    return(SISCheckModeForCRT2Type(pScrn, mode, vbflags, cond, quiet));
75372b676d7Smrg}
75472b676d7Smrg#endif
75572b676d7Smrg
75672b676d7Smrgstatic DisplayModePtr
75772b676d7SmrgsisFindModeFromTiming(ScrnInfoPtr pScrn, UShort hdisplay,
75872b676d7Smrg			      UShort vdisplay, UShort htotal, UShort vtotal,
75972b676d7Smrg			      UShort hsyncstart, UShort hsyncend, UShort vsyncstart,
76072b676d7Smrg			      UShort vsyncend, int clock)
76172b676d7Smrg{
76272b676d7Smrg   DisplayModePtr mode = pScrn->modes, pmode = pScrn->modes;
76372b676d7Smrg   Bool found = FALSE;
76472b676d7Smrg
76572b676d7Smrg   do {
76672b676d7Smrg       if( (mode->HDisplay == hdisplay) &&
76772b676d7Smrg           (mode->VDisplay == vdisplay) &&
76872b676d7Smrg	   (mode->HTotal == htotal) &&
76972b676d7Smrg	   (mode->VTotal == vtotal) &&
77072b676d7Smrg	   (mode->HSyncStart == hsyncstart) &&
77172b676d7Smrg	   (mode->VSyncStart == vsyncstart) &&
77272b676d7Smrg	   (mode->HSyncEnd == hsyncend) &&
77372b676d7Smrg	   (mode->VSyncEnd == vsyncend) &&
77472b676d7Smrg	   (mode->Clock == clock) ) {
77572b676d7Smrg	  found = TRUE;
77672b676d7Smrg	  break;
77772b676d7Smrg       }
77872b676d7Smrg       mode = mode->next;
77972b676d7Smrg    } while((mode) && (mode != pmode));
78072b676d7Smrg
78172b676d7Smrg    if(found) return mode;
78272b676d7Smrg    else      return NULL;
78372b676d7Smrg}
78472b676d7Smrg
78572b676d7Smrgstatic int
78672b676d7SmrgSISCheckModeTimingForCRT2Type(ScrnInfoPtr pScrn, UShort cond, UShort hdisplay,
78772b676d7Smrg			      UShort vdisplay, UShort htotal, UShort vtotal,
78872b676d7Smrg			      UShort hsyncstart, UShort hsyncend, UShort vsyncstart,
78972b676d7Smrg			      UShort vsyncend, int clock, Bool quiet)
79072b676d7Smrg{
79172b676d7Smrg    SISPtr pSiS = SISPTR(pScrn);
79272b676d7Smrg    DisplayModePtr mode;
79372b676d7Smrg    ULong vbflags;
79472b676d7Smrg
79572b676d7Smrg    /* Not only CRT2, but also LCDA */
79672b676d7Smrg
79772b676d7Smrg    /* returns 0 if mode ok,
79872b676d7Smrg     *         0x01 if mode not ok for CRT2 device,
79972b676d7Smrg     *         0x02 if mode too large for current root window
80072b676d7Smrg     *         or combinations thereof
80172b676d7Smrg     */
80272b676d7Smrg
80372b676d7Smrg    vbflags = SiSCondToVBFlags(cond, pSiS->VBFlags);
80472b676d7Smrg
80572b676d7Smrg    /* Find mode with given timing */
80672b676d7Smrg    mode = sisFindModeFromTiming(pScrn, hdisplay, vdisplay, htotal, vtotal,
80772b676d7Smrg				hsyncstart, hsyncend, vsyncstart, vsyncend,
80872b676d7Smrg				clock);
80972b676d7Smrg    if(!mode) return 0x03;
81072b676d7Smrg
81172b676d7Smrg    return(SISCheckModeForCRT2Type(pScrn, mode, vbflags, cond, quiet));
81272b676d7Smrg}
81372b676d7Smrg
81472b676d7Smrg#ifdef SISMERGED
81572b676d7Smrgstatic void
81672b676d7SmrgSISGetMergedModeDetails(ScrnInfoPtr pScrn,
81772b676d7Smrg	   int hd, int vd, int ht, int vt, int hss, int hse, int vss, int vse, int clk,
81872b676d7Smrg	   unsigned int *pos, unsigned int *crt1x, unsigned int *crt1y,
81972b676d7Smrg	   unsigned int *crt1clk, unsigned int *crt2x, unsigned int *crt2y,
82072b676d7Smrg	   unsigned int *crt2clk)
82172b676d7Smrg{
82272b676d7Smrg    SISPtr pSiS = SISPTR(pScrn);
82372b676d7Smrg    DisplayModePtr mode, tmode;
82472b676d7Smrg
82572b676d7Smrg    if(!pSiS->MergedFB) {
82672b676d7Smrg       *pos = SDC_MMODE_POS_ERROR;
82772b676d7Smrg       return;
82872b676d7Smrg    }
82972b676d7Smrg
83072b676d7Smrg    /* Find mode with given timing */
83172b676d7Smrg    mode = sisFindModeFromTiming(pScrn, hd, vd, ht, vt, hss, hse, vss, vse, clk);
83272b676d7Smrg    if(!mode) {
83372b676d7Smrg       *pos = SDC_MMODE_POS_ERROR;
83472b676d7Smrg       return;
83572b676d7Smrg    }
83672b676d7Smrg
83772b676d7Smrg    switch(((SiSMergedDisplayModePtr)mode->Private)->CRT2Position) {
83872b676d7Smrg       case sisLeftOf:  *pos = SDC_MMODE_POS_LEFTOF;  break;
83972b676d7Smrg       case sisRightOf: *pos = SDC_MMODE_POS_RIGHTOF; break;
84072b676d7Smrg       case sisAbove:   *pos = SDC_MMODE_POS_ABOVE;   break;
84172b676d7Smrg       case sisBelow:   *pos = SDC_MMODE_POS_BELOW;   break;
84272b676d7Smrg       default:         *pos = SDC_MMODE_POS_CLONE;
84372b676d7Smrg    }
84472b676d7Smrg
84572b676d7Smrg    tmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
84672b676d7Smrg    *crt1x = tmode->HDisplay;
84772b676d7Smrg    *crt1y = tmode->VDisplay;
84872b676d7Smrg    *crt1clk = (unsigned int)SiSCalcVRate(tmode);
84972b676d7Smrg
85072b676d7Smrg    tmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2;
85172b676d7Smrg    *crt2x = tmode->HDisplay;
85272b676d7Smrg    *crt2y = tmode->VDisplay;
85372b676d7Smrg    *crt2clk = (unsigned int)SiSCalcVRate(tmode);
85472b676d7Smrg}
85572b676d7Smrg#endif
85672b676d7Smrg
85772b676d7Smrg/***********************************
85872b676d7Smrg *     MessageHandler interface    *
85972b676d7Smrg *   (unused now; use extension)   *
86072b676d7Smrg ***********************************/
86172b676d7Smrg
86272b676d7Smrg#ifdef X_XF86MiscPassMessage
86372b676d7Smrgint
86472b676d7SmrgSISHandleMessage(int scrnIndex, const char *msgtype, const char *msgval, char **retmsg)
86572b676d7Smrg{
86672b676d7Smrg    return BadMatch;
86772b676d7Smrg}
86872b676d7Smrg#endif
86972b676d7Smrg
87072b676d7Smrg/***********************************
87172b676d7Smrg *   SiSCtrl extension interface   *
87272b676d7Smrg ***********************************/
87372b676d7Smrg
87472b676d7Smrgstatic void
87572b676d7Smrgsisutil_prepare_string(xSiSCtrlCommandReply *sdcbuf, char *mystring)
87672b676d7Smrg{
87772b676d7Smrg   int slen = 0;
87872b676d7Smrg   sdcbuf->sdc_buffer[0] = 0;
87972b676d7Smrg   if(mystring) {
88072b676d7Smrg      slen = strlen(mystring);
88172b676d7Smrg      if(slen > 31) slen = 31;
88272b676d7Smrg      strncpy(&sdcbuf->sdc_buffer[0], mystring, slen);
88372b676d7Smrg      sdcbuf->sdc_buffer[slen] = 0;
88472b676d7Smrg   }
88572b676d7Smrg   sdcbuf->sdc_result[0] = slen;
88672b676d7Smrg}
88772b676d7Smrg
88872b676d7Smrgstatic int
88972b676d7SmrgSiSHandleSiSDirectCommand(xSiSCtrlCommandReply *sdcbuf)
89072b676d7Smrg{
89172b676d7Smrg   ScrnInfoPtr pScrn = xf86Screens[sdcbuf->screen];
89272b676d7Smrg   SISPtr pSiS = SISPTR(pScrn);
89372b676d7Smrg#ifdef SISDUALHEAD
89472b676d7Smrg   SISEntPtr pSiSEnt = pSiS->entityPrivate;
89572b676d7Smrg#endif
89672b676d7Smrg   SISPortPrivPtr pPriv = NULL;
89772b676d7Smrg   int i;
89872b676d7Smrg   ULong j;
89972b676d7Smrg
90072b676d7Smrg   if(sdcbuf->sdc_id != SDC_ID) return BadMatch;
90172b676d7Smrg
90272b676d7Smrg   if(pSiS->adaptor) {
90372b676d7Smrg      pPriv = GET_PORT_PRIVATE(pScrn);
90472b676d7Smrg   }
90572b676d7Smrg
90672b676d7Smrg   j = sdcbuf->sdc_command;
90772b676d7Smrg   for(i = 0; i < SDC_NUM_PARM_RESULT; i++) {
90872b676d7Smrg      j += sdcbuf->sdc_parm[i];
90972b676d7Smrg   }
91072b676d7Smrg
91172b676d7Smrg   if(j != sdcbuf->sdc_chksum) return BadMatch;
91272b676d7Smrg
91372b676d7Smrg   sdcbuf->sdc_result_header = SDC_RESULT_OK;
91472b676d7Smrg
91572b676d7Smrg   switch(sdcbuf->sdc_command) {
91672b676d7Smrg
91772b676d7Smrg   case SDC_CMD_GETVERSION:
91872b676d7Smrg      sdcbuf->sdc_result[0] = SDC_VERSION;
91972b676d7Smrg      sdcbuf->sdc_result[1] = SDC_MAXCOMMAND;
92072b676d7Smrg      break;
92172b676d7Smrg
92272b676d7Smrg   case SDC_CMD_GETHWINFO:
92372b676d7Smrg      {
92472b676d7Smrg	 UShort romptr = 0;
92572b676d7Smrg	 char *biosvers = NULL;
92672b676d7Smrg	 int slen = 0;
92772b676d7Smrg
92872b676d7Smrg	 if(pSiS->BIOS) {
92972b676d7Smrg	    romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8);
93072b676d7Smrg	    if(romptr < 65530) {
93172b676d7Smrg	       biosvers = (char *)&pSiS->BIOS[romptr];
93272b676d7Smrg	       slen = strlen(biosvers);
93372b676d7Smrg	       if(slen > 10) slen = 10;
93472b676d7Smrg	    }
93572b676d7Smrg	 }
93672b676d7Smrg	 sdcbuf->sdc_result[0]  = pSiS->IsAGPCard ? SDC_BUS_TYPE_AGP : SDC_BUS_TYPE_PCI;
93772b676d7Smrg	 if(pSiS->IsPCIExpress) sdcbuf->sdc_result[0] = SDC_BUS_TYPE_PCIE;
93872b676d7Smrg	 sdcbuf->sdc_result[1]  = pSiS->PciBus;
93972b676d7Smrg	 sdcbuf->sdc_result[2]  = pSiS->PciDevice;
94072b676d7Smrg	 sdcbuf->sdc_result[3]  = pSiS->PciFunc;
94172b676d7Smrg	 sdcbuf->sdc_result[4]  = pSiS->ROM661New ? 1 : (pSiS->HaveXGIBIOS ? 2 : 0),
94272b676d7Smrg	 sdcbuf->sdc_result[5]  = pSiS->ChipFlags;
94372b676d7Smrg	 sdcbuf->sdc_result[6]  = pSiS->ChipType;
94472b676d7Smrg	 sdcbuf->sdc_result[7]  = pSiS->ChipRev;
94572b676d7Smrg	 sdcbuf->sdc_result[8]  = SISDRIVERVERSIONYEAR;
94672b676d7Smrg	 sdcbuf->sdc_result[9]  = SISDRIVERVERSIONMONTH;
94772b676d7Smrg	 sdcbuf->sdc_result[10] = SISDRIVERVERSIONDAY;
94872b676d7Smrg	 sdcbuf->sdc_result[11] = SISDRIVERREVISION;
94972b676d7Smrg	 sdcbuf->sdc_result[12] = pScrn->videoRam;
95072b676d7Smrg	 sdcbuf->sdc_result[13] = pSiS->UMAsize;
95172b676d7Smrg	 sdcbuf->sdc_result[14] = pSiS->LFBsize;
95272b676d7Smrg	 if(slen) strncpy(&sdcbuf->sdc_buffer[0], biosvers, slen);
95372b676d7Smrg	 sdcbuf->sdc_buffer[slen] = 0;
95472b676d7Smrg      }
95572b676d7Smrg      break;
95672b676d7Smrg
95772b676d7Smrg   case SDC_CMD_GETALLFLAGS:
95872b676d7Smrg      sdcbuf->sdc_result[0] = SIS_VBFlagsVersion;
95972b676d7Smrg      sdcbuf->sdc_result[1] = pSiS->VBFlags;
96072b676d7Smrg      sdcbuf->sdc_result[2] = pSiS->SiS_SD_Flags;
96172b676d7Smrg      sdcbuf->sdc_result[3] = pSiS->SiS_SD2_Flags;
96272b676d7Smrg      sdcbuf->sdc_result[4] = pSiS->detectedCRT2Devices;
96372b676d7Smrg      sdcbuf->sdc_result[5] = pSiS->VBFlags2;
96472b676d7Smrg      sdcbuf->sdc_result[6] = pSiS->SiS_SD3_Flags;
96572b676d7Smrg      sdcbuf->sdc_result[7] = pSiS->SiS_SD4_Flags;
96672b676d7Smrg      sdcbuf->sdc_result[8] = pSiS->VBFlags3;
96772b676d7Smrg      sdcbuf->sdc_result[9] = pSiS->VBFlags4;
96872b676d7Smrg      break;
96972b676d7Smrg
97072b676d7Smrg   case SDC_CMD_GETVBFLAGSVERSION:
97172b676d7Smrg      sdcbuf->sdc_result[0] = SIS_VBFlagsVersion;
97272b676d7Smrg      break;
97372b676d7Smrg
97472b676d7Smrg   case SDC_CMD_GETVBFLAGS:
97572b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->VBFlags;
97672b676d7Smrg      sdcbuf->sdc_result[1] = pSiS->VBFlags2;
97772b676d7Smrg      sdcbuf->sdc_result[2] = pSiS->VBFlags3;
97872b676d7Smrg      sdcbuf->sdc_result[3] = pSiS->VBFlags4;
97972b676d7Smrg      break;
98072b676d7Smrg
98172b676d7Smrg   case SDC_CMD_CHECKMODEFORCRT2:
98272b676d7Smrg      {
98372b676d7Smrg	 int clk, hd, hss, hse, ht, vd, vss, vse, vt, result;
98472b676d7Smrg	 ULong flags;
98572b676d7Smrg
98672b676d7Smrg	 flags = sdcbuf->sdc_parm[0];
98772b676d7Smrg	 clk   = sdcbuf->sdc_parm[1];
98872b676d7Smrg	 hd    = sdcbuf->sdc_parm[2];
98972b676d7Smrg	 hss   = sdcbuf->sdc_parm[3];
99072b676d7Smrg	 hse   = sdcbuf->sdc_parm[4];
99172b676d7Smrg	 ht    = sdcbuf->sdc_parm[5];
99272b676d7Smrg	 vd    = sdcbuf->sdc_parm[6];
99372b676d7Smrg	 vss   = sdcbuf->sdc_parm[7];
99472b676d7Smrg	 vse   = sdcbuf->sdc_parm[8];
99572b676d7Smrg	 vt    = sdcbuf->sdc_parm[9];
99672b676d7Smrg
99772b676d7Smrg	 result = SISCheckModeTimingForCRT2Type(pScrn, (UShort)(flags & 0xff),
99872b676d7Smrg			hd, vd, ht, vt, hss, hse, vss, vse, clk, pSiS->SCLogQuiet) & 0xff;
99972b676d7Smrg	 sdcbuf->sdc_result[0] = result;
100072b676d7Smrg      }
100172b676d7Smrg      break;
100272b676d7Smrg
100372b676d7Smrg   case SDC_CMD_SETVBFLAGS:
100472b676d7Smrg#ifdef SISDUALHEAD
100572b676d7Smrg      if(!pSiS->DualHeadMode) {
100672b676d7Smrg#endif
100772b676d7Smrg	 if(pSiS->xv_sisdirectunlocked) {
100872b676d7Smrg	    SISSwitchCRT2Type(pScrn, (ULong)sdcbuf->sdc_parm[0], pSiS->SCLogQuiet);
100972b676d7Smrg	    if(pPriv) SISUpdateVideoParms(pSiS, pPriv);
101072b676d7Smrg	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
101172b676d7Smrg#ifdef SISDUALHEAD
101272b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
101372b676d7Smrg#endif
101472b676d7Smrg      break;
101572b676d7Smrg
101672b676d7Smrg   case SDC_CMD_NEWSETVBFLAGS:
101772b676d7Smrg#ifdef SISDUALHEAD
101872b676d7Smrg      if(!pSiS->DualHeadMode) {
101972b676d7Smrg#endif
102072b676d7Smrg	 if(pSiS->xv_sisdirectunlocked) {
102172b676d7Smrg	    SISSwitchOutputType(pScrn, (ULong)sdcbuf->sdc_parm[0], (ULong)sdcbuf->sdc_parm[1],
102272b676d7Smrg	    		(ULong)sdcbuf->sdc_parm[2], pSiS->SCLogQuiet);
102372b676d7Smrg	    if(pPriv) SISUpdateVideoParms(pSiS, pPriv);
102472b676d7Smrg	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
102572b676d7Smrg#ifdef SISDUALHEAD
102672b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
102772b676d7Smrg#endif
102872b676d7Smrg      break;
102972b676d7Smrg
103072b676d7Smrg   case SDC_CMD_GETDETECTEDDEVICES:
103172b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->detectedCRT2Devices;
103272b676d7Smrg      break;
103372b676d7Smrg
103472b676d7Smrg   case SDC_CMD_REDETECTCRT2DEVICES:
103572b676d7Smrg#ifdef SISDUALHEAD
103672b676d7Smrg      if(!pSiS->DualHeadMode) {
103772b676d7Smrg#endif
103872b676d7Smrg	 if(pSiS->xv_sisdirectunlocked) {
103972b676d7Smrg	    SISRedetectCRT2Devices(pScrn);
104072b676d7Smrg	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
104172b676d7Smrg#ifdef SISDUALHEAD
104272b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
104372b676d7Smrg#endif
104472b676d7Smrg      break;
104572b676d7Smrg
104672b676d7Smrg   case SDC_CMD_GETCRT1STATUS:
104772b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->CRT1isoff ? 0 : 1;
104872b676d7Smrg      break;
104972b676d7Smrg
105072b676d7Smrg   case SDC_CMD_SETCRT1STATUS:
105172b676d7Smrg#ifdef SISDUALHEAD
105272b676d7Smrg      if(!pSiS->DualHeadMode) {
105372b676d7Smrg#endif
105472b676d7Smrg	 if(pSiS->xv_sisdirectunlocked) {
105572b676d7Smrg	    SISSwitchCRT1Status(pScrn, (ULong)sdcbuf->sdc_parm[0], pSiS->SCLogQuiet);
105672b676d7Smrg	    if(pPriv) SISUpdateVideoParms(pSiS, pPriv);
105772b676d7Smrg	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
105872b676d7Smrg#ifdef SISDUALHEAD
105972b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
106072b676d7Smrg#endif
106172b676d7Smrg      break;
106272b676d7Smrg
106372b676d7Smrg   case SDC_CMD_GETSDFLAGS:
106472b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->SiS_SD_Flags;
106572b676d7Smrg      break;
106672b676d7Smrg
106772b676d7Smrg   case SDC_CMD_GETSD2FLAGS:
106872b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->SiS_SD2_Flags;
106972b676d7Smrg      break;
107072b676d7Smrg
107172b676d7Smrg   case SDC_CMD_GETLOCKSTATUS:
107272b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->xv_sisdirectunlocked;
107372b676d7Smrg      break;
107472b676d7Smrg
107572b676d7Smrg   case SDC_CMD_SETLOCKSTATUS:
107672b676d7Smrg      if(pSiS->enablesisctrl) {
107772b676d7Smrg	 if(sdcbuf->sdc_parm[0] == SIS_DIRECTKEY) {
107872b676d7Smrg	    pSiS->xv_sisdirectunlocked++;
107972b676d7Smrg	 } else if(pSiS->xv_sisdirectunlocked) {
108072b676d7Smrg	    pSiS->xv_sisdirectunlocked--;
108172b676d7Smrg	 }
108272b676d7Smrg      } else {
108372b676d7Smrg	 pSiS->xv_sisdirectunlocked = 0;
108472b676d7Smrg	 sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
108572b676d7Smrg      }
108672b676d7Smrg      break;
108772b676d7Smrg
108872b676d7Smrg   case SDC_CMD_GETTVANTIFLICKER:
108972b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetSISTVantiflicker(pScrn);
109072b676d7Smrg      break;
109172b676d7Smrg
109272b676d7Smrg   case SDC_CMD_SETTVANTIFLICKER:
109372b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
109472b676d7Smrg	 SiS_SetSISTVantiflicker(pScrn, (int)sdcbuf->sdc_parm[0]);
109572b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
109672b676d7Smrg      break;
109772b676d7Smrg
109872b676d7Smrg   case SDC_CMD_GETTVSATURATION:
109972b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetSISTVsaturation(pScrn);
110072b676d7Smrg      break;
110172b676d7Smrg
110272b676d7Smrg   case SDC_CMD_SETTVSATURATION:
110372b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
110472b676d7Smrg	 SiS_SetSISTVsaturation(pScrn, (int)sdcbuf->sdc_parm[0]);
110572b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
110672b676d7Smrg      break;
110772b676d7Smrg
110872b676d7Smrg   case SDC_CMD_GETTVEDGEENHANCE:
110972b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetSISTVedgeenhance(pScrn);;
111072b676d7Smrg      break;
111172b676d7Smrg
111272b676d7Smrg   case SDC_CMD_SETTVEDGEENHANCE:
111372b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
111472b676d7Smrg	 SiS_SetSISTVedgeenhance(pScrn, (int)sdcbuf->sdc_parm[0]);
111572b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
111672b676d7Smrg      break;
111772b676d7Smrg
111872b676d7Smrg   case SDC_CMD_GETTVCFILTER:
111972b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetSISTVcfilter(pScrn);
112072b676d7Smrg      break;
112172b676d7Smrg
112272b676d7Smrg   case SDC_CMD_SETTVCFILTER:
112372b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
112472b676d7Smrg	 SiS_SetSISTVcfilter(pScrn, sdcbuf->sdc_parm[0] ? 1 : 0);
112572b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
112672b676d7Smrg      break;
112772b676d7Smrg
112872b676d7Smrg   case SDC_CMD_GETTVYFILTER:
112972b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetSISTVyfilter(pScrn);
113072b676d7Smrg      break;
113172b676d7Smrg
113272b676d7Smrg   case SDC_CMD_SETTVYFILTER:
113372b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
113472b676d7Smrg	 SiS_SetSISTVyfilter(pScrn, sdcbuf->sdc_parm[0]);
113572b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
113672b676d7Smrg      break;
113772b676d7Smrg
113872b676d7Smrg   case SDC_CMD_GETTVCOLORCALIB:
113972b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetSISTVcolcalib(pScrn, TRUE) + 32768;
114072b676d7Smrg      sdcbuf->sdc_result[1] = SiS_GetSISTVcolcalib(pScrn, FALSE) + 32768;
114172b676d7Smrg      break;
114272b676d7Smrg
114372b676d7Smrg   case SDC_CMD_SETTVCOLORCALIB:
114472b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
114572b676d7Smrg         SiS_SetSISTVcolcalib(pScrn, (int)sdcbuf->sdc_parm[0] - 32768, TRUE);
114672b676d7Smrg	 SiS_SetSISTVcolcalib(pScrn, (int)sdcbuf->sdc_parm[1] - 32768, FALSE);
114772b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
114872b676d7Smrg      break;
114972b676d7Smrg
115072b676d7Smrg   case SDC_CMD_GETTVCHCONTRAST:
115172b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetCHTVcontrast(pScrn);
115272b676d7Smrg      break;
115372b676d7Smrg
115472b676d7Smrg   case SDC_CMD_SETTVCHCONTRAST:
115572b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
115672b676d7Smrg	 SiS_SetCHTVcontrast(pScrn, (int)sdcbuf->sdc_parm[0]);
115772b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
115872b676d7Smrg      break;
115972b676d7Smrg
116072b676d7Smrg   case SDC_CMD_GETTVCHTEXTENHANCE:
116172b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetCHTVtextenhance(pScrn);
116272b676d7Smrg      break;
116372b676d7Smrg
116472b676d7Smrg   case SDC_CMD_SETTVCHTEXTENHANCE:
116572b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
116672b676d7Smrg	 SiS_SetCHTVtextenhance(pScrn, (int)sdcbuf->sdc_parm[0]);
116772b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
116872b676d7Smrg      break;
116972b676d7Smrg
117072b676d7Smrg   case SDC_CMD_GETTVCHCHROMAFLICKERFILTER:
117172b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetCHTVchromaflickerfilter(pScrn);
117272b676d7Smrg      break;
117372b676d7Smrg
117472b676d7Smrg   case SDC_CMD_SETTVCHCHROMAFLICKERFILTER:
117572b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
117672b676d7Smrg	 SiS_SetCHTVchromaflickerfilter(pScrn, (int)sdcbuf->sdc_parm[0]);
117772b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
117872b676d7Smrg      break;
117972b676d7Smrg
118072b676d7Smrg   case SDC_CMD_GETTVCHLUMAFLICKERFILTER:
118172b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetCHTVlumaflickerfilter(pScrn);
118272b676d7Smrg      break;
118372b676d7Smrg
118472b676d7Smrg   case SDC_CMD_SETTVCHLUMAFLICKERFILTER:
118572b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
118672b676d7Smrg	 SiS_SetCHTVlumaflickerfilter(pScrn, (int)sdcbuf->sdc_parm[0]);
118772b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
118872b676d7Smrg      break;
118972b676d7Smrg
119072b676d7Smrg   case SDC_CMD_GETTVCHCVBSCOLOR:
119172b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetCHTVcvbscolor(pScrn);
119272b676d7Smrg      break;
119372b676d7Smrg
119472b676d7Smrg   case SDC_CMD_SETTVCHCVBSCOLOR:
119572b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
119672b676d7Smrg	 SiS_SetCHTVcvbscolor(pScrn, sdcbuf->sdc_parm[0] ? 1 : 0);
119772b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
119872b676d7Smrg      break;
119972b676d7Smrg
120072b676d7Smrg   case SDC_CMD_GETCHTVOVERSCAN:
120172b676d7Smrg      {  /* Changing of CRT2 settings not supported in DHM! */
120272b676d7Smrg	 int i = 0;
120372b676d7Smrg	 if(pSiS->OptTVSOver == 1)         i = 3;
120472b676d7Smrg	 else if(pSiS->UseCHOverScan == 1) i = 2;
120572b676d7Smrg	 else if(pSiS->UseCHOverScan == 0) i = 1;
120672b676d7Smrg	 sdcbuf->sdc_result[0] = i;
120772b676d7Smrg      }
120872b676d7Smrg      break;
120972b676d7Smrg
121072b676d7Smrg   case SDC_CMD_SETCHTVOVERSCAN:
121172b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
121272b676d7Smrg	 pSiS->UseCHOverScan = -1;
121372b676d7Smrg	 pSiS->OptTVSOver = FALSE;
121472b676d7Smrg	 if(sdcbuf->sdc_parm[0] == 3) {
121572b676d7Smrg	    if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSOVER) {
121672b676d7Smrg	       pSiS->OptTVSOver = TRUE;
121772b676d7Smrg	    }
121872b676d7Smrg	    pSiS->UseCHOverScan = 1;
121972b676d7Smrg	 } else if(sdcbuf->sdc_parm[0] == 2) pSiS->UseCHOverScan = 1;
122072b676d7Smrg	 else if(sdcbuf->sdc_parm[0] == 1)   pSiS->UseCHOverScan = 0;
122172b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
122272b676d7Smrg      break;
122372b676d7Smrg
122472b676d7Smrg   case SDC_CMD_GETGAMMASTATUS:
122572b676d7Smrg      {
122672b676d7Smrg         int i = 0;
122772b676d7Smrg#ifdef SISDUALHEAD
122872b676d7Smrg	 if(pSiS->DualHeadMode) {
122972b676d7Smrg	    if(pSiSEnt->CRT1gamma) i |= 0x01;
123072b676d7Smrg	    if(pSiSEnt->CRT2gamma) i |= 0x02;
123172b676d7Smrg	 } else {
123272b676d7Smrg#endif
123372b676d7Smrg	    if(pSiS->CRT1gamma)    i |= 0x01;
123472b676d7Smrg	    if(pSiS->CRT2gamma)    i |= 0x02;
123572b676d7Smrg	    if(pSiS->CRT2SepGamma) i |= 0x08;
123672b676d7Smrg#ifdef SISDUALHEAD
123772b676d7Smrg	 }
123872b676d7Smrg#endif
123972b676d7Smrg	 if(pSiS->XvGamma) i |= 0x04;
124072b676d7Smrg         sdcbuf->sdc_result[0] = i;
124172b676d7Smrg      }
124272b676d7Smrg      break;
124372b676d7Smrg
124472b676d7Smrg   case SDC_CMD_SETGAMMASTATUS:
124572b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
124672b676d7Smrg         int value = sdcbuf->sdc_parm[0];
124772b676d7Smrg	 Bool backup = pSiS->XvGamma;
124872b676d7Smrg	 Bool backup2 = pSiS->CRT2SepGamma;
124972b676d7Smrg	 pSiS->CRT1gamma = (value & 0x01) ? TRUE : FALSE;
125072b676d7Smrg	 pSiS->CRT2gamma = (value & 0x02) ? TRUE : FALSE;
125172b676d7Smrg#ifdef SISDUALHEAD
125272b676d7Smrg	 if(pSiS->DualHeadMode) {
125372b676d7Smrg	    pSiSEnt->CRT1gamma = pSiS->CRT1gamma;
125472b676d7Smrg	    pSiSEnt->CRT2gamma = pSiS->CRT2gamma;
125572b676d7Smrg	 }
125672b676d7Smrg#endif
125772b676d7Smrg	 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSGRCRT2) {
125872b676d7Smrg	    pSiS->CRT2SepGamma = (value & 0x08) ? TRUE : FALSE;
125972b676d7Smrg	    if(pSiS->CRT2SepGamma != backup2) {
126072b676d7Smrg	       if(pSiS->CRT2SepGamma) {
126172b676d7Smrg		  SiS_UpdateGammaCRT2(pScrn);
126272b676d7Smrg	       }
126372b676d7Smrg#ifdef SISGAMMARAMP
126472b676d7Smrg	       else {
126572b676d7Smrg		  SISCalculateGammaRamp(pScrn->pScreen, pScrn);
126672b676d7Smrg	       }
126772b676d7Smrg#endif
126872b676d7Smrg	      /* ATTN: When disabling CRT2 sep gamma,
126972b676d7Smrg	       * as long as SISGAMMARAMP is not defined,
127072b676d7Smrg	       * application needs to reset palette using
127172b676d7Smrg	       * vidmodextension! (See SiS_SD_CANSETGAMMA)
127272b676d7Smrg	       *
127372b676d7Smrg	       * Note: Difference between setting gamma values
127472b676d7Smrg	       * for CRT1 and CRT2: For CRT1, driver only
127572b676d7Smrg	       * stores the values, but does nothing with them;
127672b676d7Smrg	       * App needs to calc gamma ramp itself for CRT1,
127772b676d7Smrg	       * and set it using the VidModExtention.
127872b676d7Smrg	       * For CRT2, the driver will IMMEDIATELY recalc
127972b676d7Smrg	       * the palette.
128072b676d7Smrg	       */
128172b676d7Smrg	    }
128272b676d7Smrg	 } else pSiS->CRT2SepGamma = FALSE;
128372b676d7Smrg
128472b676d7Smrg	 pSiS->XvGamma = (value & 0x04) ? TRUE : FALSE;
128572b676d7Smrg	 if(pSiS->VGAEngine == SIS_315_VGA) {
128672b676d7Smrg	    if(backup != pSiS->XvGamma) {
128772b676d7Smrg	       if(pPriv) SiSUpdateXvGamma(pSiS, pPriv);
128872b676d7Smrg	    }
128972b676d7Smrg	 }
129072b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
129172b676d7Smrg      break;
129272b676d7Smrg
129372b676d7Smrg   case SDC_CMD_GETTVXSCALE:
129472b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetTVxscale(pScrn) + 32768;
129572b676d7Smrg      break;
129672b676d7Smrg
129772b676d7Smrg   case SDC_CMD_SETTVXSCALE:
129872b676d7Smrg      {
129972b676d7Smrg         int value = sdcbuf->sdc_parm[0] - 32768;
130072b676d7Smrg         if((value < -16) || (value > 16)) {
130172b676d7Smrg	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
130272b676d7Smrg         } else if(pSiS->xv_sisdirectunlocked) {
130372b676d7Smrg	    SiS_SetTVxscale(pScrn, value);
130472b676d7Smrg         } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
130572b676d7Smrg      }
130672b676d7Smrg      break;
130772b676d7Smrg
130872b676d7Smrg   case SDC_CMD_GETTVYSCALE:
130972b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetTVyscale(pScrn) + 32768;
131072b676d7Smrg      break;
131172b676d7Smrg
131272b676d7Smrg   case SDC_CMD_SETTVYSCALE:
131372b676d7Smrg      {
131472b676d7Smrg         int value = sdcbuf->sdc_parm[0] - 32768;
131572b676d7Smrg         if((value < -4) || (value > 3)) {
131672b676d7Smrg	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
131772b676d7Smrg         } else if(pSiS->xv_sisdirectunlocked) {
131872b676d7Smrg	    SiS_SetTVyscale(pScrn, value);
131972b676d7Smrg         } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
132072b676d7Smrg      }
132172b676d7Smrg      break;
132272b676d7Smrg
132372b676d7Smrg   case SDC_CMD_GETSCREENSIZE:
132472b676d7Smrg      sdcbuf->sdc_result[0] = (pScrn->virtualX << 16) | pScrn->virtualY;
132572b676d7Smrg      break;
132672b676d7Smrg
132772b676d7Smrg   case SDC_CMD_GETGAMMABRIGHTNESS:  /* xv_BRx, xv_PBx */
132872b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->GammaBriR;
132972b676d7Smrg      sdcbuf->sdc_result[1] = pSiS->GammaBriG;
133072b676d7Smrg      sdcbuf->sdc_result[2] = pSiS->GammaBriB;
133172b676d7Smrg      break;
133272b676d7Smrg
133372b676d7Smrg   case SDC_CMD_GETNEWGAMMABRICON:  /* no xv pendant */
133472b676d7Smrg      sdcbuf->sdc_result[0] = (CARD32)(((int)(pSiS->NewGammaBriR * 1000.0)) + 1000);
133572b676d7Smrg      sdcbuf->sdc_result[1] = (CARD32)(((int)(pSiS->NewGammaBriG * 1000.0)) + 1000);
133672b676d7Smrg      sdcbuf->sdc_result[2] = (CARD32)(((int)(pSiS->NewGammaBriB * 1000.0)) + 1000);
133772b676d7Smrg      sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiS->NewGammaConR * 1000.0)) + 1000);
133872b676d7Smrg      sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiS->NewGammaConG * 1000.0)) + 1000);
133972b676d7Smrg      sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiS->NewGammaConB * 1000.0)) + 1000);
134072b676d7Smrg      break;
134172b676d7Smrg
134272b676d7Smrg   case SDC_CMD_SETGAMMABRIGHTNESS:  /* xv_BRx, xv_PBx */
134372b676d7Smrg      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
134472b676d7Smrg	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
134572b676d7Smrg	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000) {
134672b676d7Smrg	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
134772b676d7Smrg      } else if(pSiS->xv_sisdirectunlocked) {
134872b676d7Smrg	 pSiS->GammaBriR = sdcbuf->sdc_parm[0];
134972b676d7Smrg	 pSiS->GammaBriG = sdcbuf->sdc_parm[1];
135072b676d7Smrg	 pSiS->GammaBriB = sdcbuf->sdc_parm[2];
135172b676d7Smrg	 pSiS->NewGammaBriR = pSiS->NewGammaBriG = pSiS->NewGammaBriB = 0.0;
135272b676d7Smrg	 pSiS->NewGammaConR = pSiS->NewGammaConG = pSiS->NewGammaConB = 0.0;
135372b676d7Smrg	 pSiS->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
135472b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
135572b676d7Smrg      break;
135672b676d7Smrg
135772b676d7Smrg   case SDC_CMD_SETNEWGAMMABRICON:  /* no xv pendant */
135872b676d7Smrg      if(sdcbuf->sdc_parm[0] > 2000 || sdcbuf->sdc_parm[1] > 2000 ||
135972b676d7Smrg	 sdcbuf->sdc_parm[2] > 2000 || sdcbuf->sdc_parm[3] > 2000 ||
136072b676d7Smrg	 sdcbuf->sdc_parm[4] > 2000 || sdcbuf->sdc_parm[5] > 2000) {
136172b676d7Smrg	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
136272b676d7Smrg      } else if(pSiS->xv_sisdirectunlocked) {
136372b676d7Smrg	 pSiS->NewGammaBriR = ((float)((int)sdcbuf->sdc_parm[0] - 1000)) / 1000.0;
136472b676d7Smrg	 pSiS->NewGammaBriG = ((float)((int)sdcbuf->sdc_parm[1] - 1000)) / 1000.0;
136572b676d7Smrg	 pSiS->NewGammaBriB = ((float)((int)sdcbuf->sdc_parm[2] - 1000)) / 1000.0;
136672b676d7Smrg	 pSiS->NewGammaConR = ((float)((int)sdcbuf->sdc_parm[3] - 1000)) / 1000.0;
136772b676d7Smrg	 pSiS->NewGammaConG = ((float)((int)sdcbuf->sdc_parm[4] - 1000)) / 1000.0;
136872b676d7Smrg	 pSiS->NewGammaConB = ((float)((int)sdcbuf->sdc_parm[5] - 1000)) / 1000.0;
136972b676d7Smrg	 pSiS->GammaBriR = pSiS->GammaBriG = pSiS->GammaBriB = 1000;
137072b676d7Smrg	 pSiS->SiS_SD3_Flags &= ~SiS_SD3_OLDGAMMAINUSE;
137172b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
137272b676d7Smrg      break;
137372b676d7Smrg
137472b676d7Smrg   case SDC_CMD_GETGAMMABRIGHTNESS2: /* xv_BRx2, xv_PBx2 */
137572b676d7Smrg#ifdef SISDUALHEAD
137672b676d7Smrg      if(pSiS->DualHeadMode) {
137772b676d7Smrg         sdcbuf->sdc_result[0] = pSiSEnt->GammaBriR;
137872b676d7Smrg	 sdcbuf->sdc_result[1] = pSiSEnt->GammaBriG;
137972b676d7Smrg	 sdcbuf->sdc_result[2] = pSiSEnt->GammaBriB;
138072b676d7Smrg	 break;
138172b676d7Smrg      }
138272b676d7Smrg#endif
138372b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->GammaBriR;
138472b676d7Smrg      sdcbuf->sdc_result[1] = pSiS->GammaBriG;
138572b676d7Smrg      sdcbuf->sdc_result[2] = pSiS->GammaBriB;
138672b676d7Smrg      break;
138772b676d7Smrg
138872b676d7Smrg   case SDC_CMD_GETNEWGAMMABRICON2: /* no xv pendant */
138972b676d7Smrg#ifdef SISDUALHEAD
139072b676d7Smrg      if(pSiS->DualHeadMode) {
139172b676d7Smrg         sdcbuf->sdc_result[0] = (CARD32)(((int)(pSiSEnt->NewGammaBriR * 1000.0)) + 1000);
139272b676d7Smrg	 sdcbuf->sdc_result[1] = (CARD32)(((int)(pSiSEnt->NewGammaBriG * 1000.0)) + 1000);
139372b676d7Smrg	 sdcbuf->sdc_result[2] = (CARD32)(((int)(pSiSEnt->NewGammaBriB * 1000.0)) + 1000);
139472b676d7Smrg	 sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiSEnt->NewGammaConR * 1000.0)) + 1000);
139572b676d7Smrg	 sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiSEnt->NewGammaConG * 1000.0)) + 1000);
139672b676d7Smrg	 sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiSEnt->NewGammaConB * 1000.0)) + 1000);
139772b676d7Smrg	 break;
139872b676d7Smrg      }
139972b676d7Smrg#endif
140072b676d7Smrg      sdcbuf->sdc_result[0] = (CARD32)(((int)(pSiS->NewGammaBriR * 1000.0)) + 1000);
140172b676d7Smrg      sdcbuf->sdc_result[1] = (CARD32)(((int)(pSiS->NewGammaBriG * 1000.0)) + 1000);
140272b676d7Smrg      sdcbuf->sdc_result[2] = (CARD32)(((int)(pSiS->NewGammaBriB * 1000.0)) + 1000);
140372b676d7Smrg      sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiS->NewGammaConR * 1000.0)) + 1000);
140472b676d7Smrg      sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiS->NewGammaConG * 1000.0)) + 1000);
140572b676d7Smrg      sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiS->NewGammaConB * 1000.0)) + 1000);
140672b676d7Smrg      break;
140772b676d7Smrg
140872b676d7Smrg   case SDC_CMD_SETGAMMABRIGHTNESS2: /* xv_BRx2, xv_PBx2 */
140972b676d7Smrg      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
141072b676d7Smrg	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
141172b676d7Smrg	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000) {
141272b676d7Smrg	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
141372b676d7Smrg      } else if(pSiS->xv_sisdirectunlocked) {
141472b676d7Smrg         pSiS->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
141572b676d7Smrg#ifdef SISDUALHEAD
141672b676d7Smrg	 if(pSiS->DualHeadMode) {
141772b676d7Smrg	    pSiSEnt->GammaBriR = sdcbuf->sdc_parm[0];
141872b676d7Smrg	    pSiSEnt->GammaBriG = sdcbuf->sdc_parm[1];
141972b676d7Smrg	    pSiSEnt->GammaBriB = sdcbuf->sdc_parm[2];
142072b676d7Smrg	    pSiSEnt->NewGammaBriR = pSiSEnt->NewGammaBriG = pSiSEnt->NewGammaBriB = 0.0;
142172b676d7Smrg	    pSiSEnt->NewGammaConR = pSiSEnt->NewGammaConG = pSiSEnt->NewGammaConB = 0.0;
142272b676d7Smrg	 }
142372b676d7Smrg#endif
142472b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
142572b676d7Smrg      break;
142672b676d7Smrg
142772b676d7Smrg   case SDC_CMD_SETNEWGAMMABRICON2: /* no xv pendant */
142872b676d7Smrg      if(sdcbuf->sdc_parm[0] > 2000 || sdcbuf->sdc_parm[1] > 2000 ||
142972b676d7Smrg	 sdcbuf->sdc_parm[2] > 2000 || sdcbuf->sdc_parm[3] > 2000 ||
143072b676d7Smrg	 sdcbuf->sdc_parm[4] > 2000 || sdcbuf->sdc_parm[5] > 2000) {
143172b676d7Smrg	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
143272b676d7Smrg      } else if(pSiS->xv_sisdirectunlocked) {
143372b676d7Smrg         pSiS->SiS_SD3_Flags &= ~SiS_SD3_OLDGAMMAINUSE;
143472b676d7Smrg#ifdef SISDUALHEAD
143572b676d7Smrg	 if(pSiS->DualHeadMode) {
143672b676d7Smrg	    pSiSEnt->NewGammaBriR = ((float)((int)sdcbuf->sdc_parm[0] - 1000)) / 1000.0;
143772b676d7Smrg	    pSiSEnt->NewGammaBriG = ((float)((int)sdcbuf->sdc_parm[1] - 1000)) / 1000.0;
143872b676d7Smrg	    pSiSEnt->NewGammaBriB = ((float)((int)sdcbuf->sdc_parm[2] - 1000)) / 1000.0;
143972b676d7Smrg	    pSiSEnt->NewGammaConR = ((float)((int)sdcbuf->sdc_parm[3] - 1000)) / 1000.0;
144072b676d7Smrg	    pSiSEnt->NewGammaConG = ((float)((int)sdcbuf->sdc_parm[4] - 1000)) / 1000.0;
144172b676d7Smrg	    pSiSEnt->NewGammaConB = ((float)((int)sdcbuf->sdc_parm[5] - 1000)) / 1000.0;
144272b676d7Smrg	    pSiSEnt->GammaBriR = pSiSEnt->GammaBriG = pSiSEnt->GammaBriB = 1000;
144372b676d7Smrg	 }
144472b676d7Smrg#endif
144572b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
144672b676d7Smrg      break;
144772b676d7Smrg
144872b676d7Smrg   case SDC_CMD_GETGETGAMMACRT2:
144972b676d7Smrg      sdcbuf->sdc_result[0] = (ULong)(pSiS->GammaR2 * 1000);
145072b676d7Smrg      sdcbuf->sdc_result[1] = (ULong)(pSiS->GammaG2 * 1000);
145172b676d7Smrg      sdcbuf->sdc_result[2] = (ULong)(pSiS->GammaB2 * 1000);
145272b676d7Smrg      sdcbuf->sdc_result[3] = pSiS->GammaBriR2;
145372b676d7Smrg      sdcbuf->sdc_result[4] = pSiS->GammaBriG2;
145472b676d7Smrg      sdcbuf->sdc_result[5] = pSiS->GammaBriB2;
145572b676d7Smrg      break;
145672b676d7Smrg
145772b676d7Smrg   case SDC_CMD_GETGETNEWGAMMACRT2:
145872b676d7Smrg      sdcbuf->sdc_result[0] = (ULong)(pSiS->GammaR2 * 1000);
145972b676d7Smrg      sdcbuf->sdc_result[1] = (ULong)(pSiS->GammaG2 * 1000);
146072b676d7Smrg      sdcbuf->sdc_result[2] = (ULong)(pSiS->GammaB2 * 1000);
146172b676d7Smrg      sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiS->NewGammaBriR2 * 1000.0)) + 1000);
146272b676d7Smrg      sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiS->NewGammaBriG2 * 1000.0)) + 1000);
146372b676d7Smrg      sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiS->NewGammaBriB2 * 1000.0)) + 1000);
146472b676d7Smrg      sdcbuf->sdc_result[6] = (CARD32)(((int)(pSiS->NewGammaConR2 * 1000.0)) + 1000);
146572b676d7Smrg      sdcbuf->sdc_result[7] = (CARD32)(((int)(pSiS->NewGammaConG2 * 1000.0)) + 1000);
146672b676d7Smrg      sdcbuf->sdc_result[8] = (CARD32)(((int)(pSiS->NewGammaConB2 * 1000.0)) + 1000);
146772b676d7Smrg      break;
146872b676d7Smrg
146972b676d7Smrg   case SDC_CMD_SETGETGAMMACRT2:
147072b676d7Smrg      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
147172b676d7Smrg	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
147272b676d7Smrg	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000 ||
147372b676d7Smrg	 sdcbuf->sdc_parm[3] < 100 || sdcbuf->sdc_parm[3] > 10000 ||
147472b676d7Smrg	 sdcbuf->sdc_parm[4] < 100 || sdcbuf->sdc_parm[4] > 10000 ||
147572b676d7Smrg	 sdcbuf->sdc_parm[5] < 100 || sdcbuf->sdc_parm[5] > 10000) {
147672b676d7Smrg	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
147772b676d7Smrg      } else if(pSiS->xv_sisdirectunlocked) {
147872b676d7Smrg         pSiS->GammaR2 = (float)sdcbuf->sdc_parm[0] / (float)1000;
147972b676d7Smrg	 pSiS->GammaG2 = (float)sdcbuf->sdc_parm[1] / (float)1000;
148072b676d7Smrg	 pSiS->GammaB2 = (float)sdcbuf->sdc_parm[2] / (float)1000;
148172b676d7Smrg	 pSiS->GammaBriR2 = sdcbuf->sdc_parm[3];
148272b676d7Smrg	 pSiS->GammaBriG2 = sdcbuf->sdc_parm[4];
148372b676d7Smrg	 pSiS->GammaBriB2 = sdcbuf->sdc_parm[5];
148472b676d7Smrg	 pSiS->NewGammaBriR2 = pSiS->NewGammaBriG2 = pSiS->NewGammaBriB2 = 0.0;
148572b676d7Smrg	 pSiS->NewGammaConR2 = pSiS->NewGammaConG2 = pSiS->NewGammaConB2 = 0.0;
148672b676d7Smrg	 pSiS->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
148772b676d7Smrg	 SiS_UpdateGammaCRT2(pScrn);
148872b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
148972b676d7Smrg      break;
149072b676d7Smrg
149172b676d7Smrg   case SDC_CMD_SETGETNEWGAMMACRT2:
149272b676d7Smrg      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
149372b676d7Smrg	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
149472b676d7Smrg	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000 ||
149572b676d7Smrg	 sdcbuf->sdc_parm[3] > 2000 || sdcbuf->sdc_parm[4] > 2000 ||
149672b676d7Smrg	 sdcbuf->sdc_parm[5] > 2000 || sdcbuf->sdc_parm[6] > 2000 ||
149772b676d7Smrg	 sdcbuf->sdc_parm[7] > 2000 || sdcbuf->sdc_parm[8] > 2000) {
149872b676d7Smrg	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
149972b676d7Smrg      } else if(pSiS->xv_sisdirectunlocked) {
150072b676d7Smrg         pSiS->GammaR2 = (float)sdcbuf->sdc_parm[0] / (float)1000;
150172b676d7Smrg	 pSiS->GammaG2 = (float)sdcbuf->sdc_parm[1] / (float)1000;
150272b676d7Smrg	 pSiS->GammaB2 = (float)sdcbuf->sdc_parm[2] / (float)1000;
150372b676d7Smrg	 pSiS->NewGammaBriR2 = ((float)((int)sdcbuf->sdc_parm[3] - 1000)) / 1000.0;
150472b676d7Smrg	 pSiS->NewGammaBriG2 = ((float)((int)sdcbuf->sdc_parm[4] - 1000)) / 1000.0;
150572b676d7Smrg	 pSiS->NewGammaBriB2 = ((float)((int)sdcbuf->sdc_parm[5] - 1000)) / 1000.0;
150672b676d7Smrg	 pSiS->NewGammaConR2 = ((float)((int)sdcbuf->sdc_parm[6] - 1000)) / 1000.0;
150772b676d7Smrg	 pSiS->NewGammaConG2 = ((float)((int)sdcbuf->sdc_parm[7] - 1000)) / 1000.0;
150872b676d7Smrg	 pSiS->NewGammaConB2 = ((float)((int)sdcbuf->sdc_parm[8] - 1000)) / 1000.0;
150972b676d7Smrg	 pSiS->GammaBriR2 = pSiS->GammaBriG2 = pSiS->GammaBriB2 = 1000;
151072b676d7Smrg	 pSiS->SiS_SD3_Flags &= ~SiS_SD3_OLDGAMMAINUSE;
151172b676d7Smrg	 SiS_UpdateGammaCRT2(pScrn);
151272b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
151372b676d7Smrg      break;
151472b676d7Smrg
151572b676d7Smrg   case SDC_CMD_GETHWCURSORSTATUS:
151672b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->HideHWCursor ? 1 : 0;
151772b676d7Smrg      break;
151872b676d7Smrg
151972b676d7Smrg   case SDC_CMD_SETHWCURSORSTATUS:
152072b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
152172b676d7Smrg	 Bool VisibleBackup = pSiS->HWCursorIsVisible;
152272b676d7Smrg	 pSiS->HideHWCursor = sdcbuf->sdc_parm[0] ? TRUE : FALSE;
152372b676d7Smrg	 if(pSiS->CursorInfoPtr) {
152472b676d7Smrg	    if(VisibleBackup) {
152572b676d7Smrg	       if(sdcbuf->sdc_parm[0]) {
152672b676d7Smrg	 	  (pSiS->CursorInfoPtr->HideCursor)(pScrn);
152772b676d7Smrg	       } else {
152872b676d7Smrg		  (pSiS->CursorInfoPtr->ShowCursor)(pScrn);
152972b676d7Smrg	       }
153072b676d7Smrg	    }
153172b676d7Smrg	    pSiS->HWCursorIsVisible = VisibleBackup;
153272b676d7Smrg	 }
153372b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
153472b676d7Smrg      break;
153572b676d7Smrg
153672b676d7Smrg   case SDC_CMD_GETPANELMODE:
153772b676d7Smrg      {
153872b676d7Smrg	 int i = 0;
153972b676d7Smrg	 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
154072b676d7Smrg	    switch(pSiS->SiS_Pr->UsePanelScaler) {
154172b676d7Smrg	    case -1: i |= 0x01; break;
154272b676d7Smrg	    case 1:  i |= 0x02; break;
154372b676d7Smrg	    }
154472b676d7Smrg	    if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
154572b676d7Smrg	       switch(pSiS->SiS_Pr->CenterScreen) {
154672b676d7Smrg	       case -1: i |= 0x04; break;
154772b676d7Smrg	       case 1:  i |= 0x08; break;
154872b676d7Smrg	       }
154972b676d7Smrg	    }
155072b676d7Smrg	 }
155172b676d7Smrg	 sdcbuf->sdc_result[0] = i;
155272b676d7Smrg      }
155372b676d7Smrg      break;
155472b676d7Smrg
155572b676d7Smrg   case SDC_CMD_SETPANELMODE:
155672b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
155772b676d7Smrg         int value = sdcbuf->sdc_parm[0];
155872b676d7Smrg         if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
155972b676d7Smrg	    if(value & 0x01)      pSiS->SiS_Pr->UsePanelScaler = -1;
156072b676d7Smrg	    else if(value & 0x02) pSiS->SiS_Pr->UsePanelScaler = 1;
156172b676d7Smrg	    else		  pSiS->SiS_Pr->UsePanelScaler = 0;
156272b676d7Smrg	    if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
156372b676d7Smrg	       if(value & 0x04)      pSiS->SiS_Pr->CenterScreen = -1;
156472b676d7Smrg	       else if(value & 0x08) pSiS->SiS_Pr->CenterScreen = 1;
156572b676d7Smrg	       else		     pSiS->SiS_Pr->CenterScreen = 0;
156672b676d7Smrg	    }
156772b676d7Smrg         }
156872b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
156972b676d7Smrg      break;
157072b676d7Smrg
157172b676d7Smrg   case SDC_CMD_GETMERGEDMODEDETAILS:
157272b676d7Smrg#ifdef SISMERGED
157372b676d7Smrg      if(pSiS->MergedFB) {
157472b676d7Smrg         int clk, hd, hss, hse, ht, vd, vss, vse, vt;
157572b676d7Smrg	 unsigned int pos, crt1x, crt1y, crt1clk, crt2x, crt2y, crt2clk;
157672b676d7Smrg
157772b676d7Smrg	 clk   = sdcbuf->sdc_parm[0];
157872b676d7Smrg	 hd    = sdcbuf->sdc_parm[1];
157972b676d7Smrg	 hss   = sdcbuf->sdc_parm[2];
158072b676d7Smrg	 hse   = sdcbuf->sdc_parm[3];
158172b676d7Smrg	 ht    = sdcbuf->sdc_parm[4];
158272b676d7Smrg	 vd    = sdcbuf->sdc_parm[5];
158372b676d7Smrg	 vss   = sdcbuf->sdc_parm[6];
158472b676d7Smrg	 vse   = sdcbuf->sdc_parm[7];
158572b676d7Smrg	 vt    = sdcbuf->sdc_parm[8];
158672b676d7Smrg
158772b676d7Smrg	 SISGetMergedModeDetails(pScrn,
158872b676d7Smrg		hd, vd, ht, vt, hss, hse, vss, vse, clk,
158972b676d7Smrg		&pos, &crt1x, &crt1y, &crt1clk, &crt2x, &crt2y, &crt2clk);
159072b676d7Smrg
159172b676d7Smrg	 sdcbuf->sdc_result[0] = pos;
159272b676d7Smrg	 sdcbuf->sdc_result[1] = crt1x;
159372b676d7Smrg	 sdcbuf->sdc_result[2] = crt1y;
159472b676d7Smrg	 sdcbuf->sdc_result[3] = crt1clk;
159572b676d7Smrg	 sdcbuf->sdc_result[4] = crt2x;
159672b676d7Smrg	 sdcbuf->sdc_result[5] = crt2y;
159772b676d7Smrg	 sdcbuf->sdc_result[6] = crt2clk;
159872b676d7Smrg
159972b676d7Smrg	 switch(pSiS->CRT2Position) {
160072b676d7Smrg	 case sisLeftOf:  sdcbuf->sdc_result[7] = SDC_MMODE_POS_LEFTOF; break;
160172b676d7Smrg	 case sisRightOf: sdcbuf->sdc_result[7] = SDC_MMODE_POS_RIGHTOF; break;
160272b676d7Smrg	 case sisAbove:   sdcbuf->sdc_result[7] = SDC_MMODE_POS_ABOVE; break;
160372b676d7Smrg	 case sisBelow:   sdcbuf->sdc_result[7] = SDC_MMODE_POS_BELOW; break;
160472b676d7Smrg	 default:         sdcbuf->sdc_result[7] = SDC_MMODE_POS_CLONE;
160572b676d7Smrg	 }
160672b676d7Smrg
160772b676d7Smrg      } else
160872b676d7Smrg#endif
160972b676d7Smrg         sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
161072b676d7Smrg      break;
161172b676d7Smrg
161272b676d7Smrg   case SDC_CMD_GETDEVICENAME:		/* In DualHead mode, this returns CRT1 data */
161372b676d7Smrg      {
161472b676d7Smrg         SISPtr	mypSiS = pSiS;
161572b676d7Smrg	 sdcbuf->sdc_result[0] = 0;
161672b676d7Smrg#ifdef SISDUALHEAD
161772b676d7Smrg	 if(pSiS->DualHeadMode) {
161872b676d7Smrg	    if(pSiSEnt->pScrn_2) mypSiS = SISPTR(pSiSEnt->pScrn_2);
161972b676d7Smrg	 }
162072b676d7Smrg#endif
162172b676d7Smrg	 sisutil_prepare_string(sdcbuf, mypSiS->devsectname);
162272b676d7Smrg      }
162372b676d7Smrg      break;
162472b676d7Smrg
162572b676d7Smrg   case SDC_CMD_GETMONITORNAME:		/* In DualHead mode, this returns CRT1 data */
162672b676d7Smrg      {
162772b676d7Smrg         ScrnInfoPtr mypScrn = pScrn;
162872b676d7Smrg         sdcbuf->sdc_result[0] = 0;
162972b676d7Smrg#ifdef SISDUALHEAD
163072b676d7Smrg	 if(pSiS->DualHeadMode) {
163172b676d7Smrg	    if(pSiSEnt->pScrn_2) mypScrn = pSiSEnt->pScrn_2;
163272b676d7Smrg	 }
163372b676d7Smrg#endif
163472b676d7Smrg         if(mypScrn->monitor) {
163572b676d7Smrg            sisutil_prepare_string(sdcbuf, mypScrn->monitor->id);
163672b676d7Smrg         }
163772b676d7Smrg      }
163872b676d7Smrg      break;
163972b676d7Smrg
164072b676d7Smrg   case SDC_CMD_GETDEVICENAME2:		/* In DualHead mode, this returns CRT2 data */
164172b676d7Smrg      sdcbuf->sdc_result[0] = 0;
164272b676d7Smrg#ifdef SISDUALHEAD
164372b676d7Smrg      if(pSiS->DualHeadMode) {
164472b676d7Smrg         if(pSiSEnt->pScrn_1) {
164572b676d7Smrg	    sisutil_prepare_string(sdcbuf, SISPTR(pSiSEnt->pScrn_1)->devsectname);
164672b676d7Smrg	 }
164772b676d7Smrg      } else
164872b676d7Smrg#endif
164972b676d7Smrg	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
165072b676d7Smrg      break;
165172b676d7Smrg
165272b676d7Smrg   case SDC_CMD_GETMONITORNAME2:	/* In DualHead mode, this returns CRT2 data */
165372b676d7Smrg      sdcbuf->sdc_result[0] = 0;
165472b676d7Smrg#ifdef SISDUALHEAD
165572b676d7Smrg      if(pSiS->DualHeadMode) {
165672b676d7Smrg         if(pSiSEnt->pScrn_1) {
165772b676d7Smrg	    if(pSiSEnt->pScrn_1->monitor) {
165872b676d7Smrg               sisutil_prepare_string(sdcbuf, pSiSEnt->pScrn_1->monitor->id);
165972b676d7Smrg            }
166072b676d7Smrg	 }
166172b676d7Smrg      } else
166272b676d7Smrg#endif
166372b676d7Smrg	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
166472b676d7Smrg      break;
166572b676d7Smrg
166672b676d7Smrg   case SDC_CMD_SETXVBRIGHTNESS:
166772b676d7Smrg      if(pPriv) {
166872b676d7Smrg         int val = sdcbuf->sdc_parm[0] - 32768;
166972b676d7Smrg         if(val >= -128 && val <= 127) pPriv->brightness = val;
167072b676d7Smrg	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
167172b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
167272b676d7Smrg      break;
167372b676d7Smrg
167472b676d7Smrg   case SDC_CMD_GETXVBRIGHTNESS:
167572b676d7Smrg      if(pPriv) {
167672b676d7Smrg         sdcbuf->sdc_result[0] = pPriv->brightness + 32768;
167772b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
167872b676d7Smrg      break;
167972b676d7Smrg
168072b676d7Smrg   case SDC_CMD_SETXVCONTRAST:
168172b676d7Smrg      if(pPriv) {
168272b676d7Smrg         int val = sdcbuf->sdc_parm[0] - 32768;
168372b676d7Smrg         if(val >= 0 && val <= 7) pPriv->contrast = val;
168472b676d7Smrg	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
168572b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
168672b676d7Smrg      break;
168772b676d7Smrg
168872b676d7Smrg   case SDC_CMD_GETXVCONTRAST:
168972b676d7Smrg      if(pPriv) {
169072b676d7Smrg         sdcbuf->sdc_result[0] = pPriv->contrast + 32768;
169172b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
169272b676d7Smrg      break;
169372b676d7Smrg
169472b676d7Smrg   case SDC_CMD_SETXVHUE:
169572b676d7Smrg      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
169672b676d7Smrg         int val = sdcbuf->sdc_parm[0] - 32768;
169772b676d7Smrg         if(val >= -8 && val <= 7) pPriv->hue = val;
169872b676d7Smrg	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
169972b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
170072b676d7Smrg      break;
170172b676d7Smrg
170272b676d7Smrg   case SDC_CMD_GETXVHUE:
170372b676d7Smrg      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
170472b676d7Smrg         sdcbuf->sdc_result[0] = pPriv->hue + 32768;
170572b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
170672b676d7Smrg      break;
170772b676d7Smrg
170872b676d7Smrg   case SDC_CMD_SETXVSATURATION:
170972b676d7Smrg      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
171072b676d7Smrg         int val = sdcbuf->sdc_parm[0] - 32768;
171172b676d7Smrg         if(val >= -7 && val <= 7) pPriv->saturation = val;
171272b676d7Smrg	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
171372b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
171472b676d7Smrg      break;
171572b676d7Smrg
171672b676d7Smrg   case SDC_CMD_GETXVSATURATION:
171772b676d7Smrg      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
171872b676d7Smrg         sdcbuf->sdc_result[0] = pPriv->saturation + 32768;
171972b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
172072b676d7Smrg      break;
172172b676d7Smrg
172272b676d7Smrg   case SDC_CMD_SETXVGAMMA:
172372b676d7Smrg      if((pPriv) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTXVGAMMA1)) {
172472b676d7Smrg         if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
172572b676d7Smrg	    sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
172672b676d7Smrg	    sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000) {
172772b676d7Smrg	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
172872b676d7Smrg	 } else {
172972b676d7Smrg	    pSiS->XvGammaRed = sdcbuf->sdc_parm[0];
173072b676d7Smrg	    pSiS->XvGammaGreen = sdcbuf->sdc_parm[1];
173172b676d7Smrg	    pSiS->XvGammaBlue = sdcbuf->sdc_parm[2];
173272b676d7Smrg	    SiSUpdateXvGamma(pSiS, pPriv);
173372b676d7Smrg	 }
173472b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
173572b676d7Smrg      break;
173672b676d7Smrg
173772b676d7Smrg   case SDC_CMD_GETXVGAMMA:
173872b676d7Smrg      if((pPriv) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTXVGAMMA1)) {
173972b676d7Smrg         sdcbuf->sdc_result[0] = pSiS->XvGammaRed;
174072b676d7Smrg	 sdcbuf->sdc_result[1] = pSiS->XvGammaGreen;
174172b676d7Smrg	 sdcbuf->sdc_result[2] = pSiS->XvGammaBlue;
174272b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
174372b676d7Smrg      break;
174472b676d7Smrg
174572b676d7Smrg   case SDC_CMD_SETXVCOLORKEY:
174672b676d7Smrg      if(pPriv) {
174772b676d7Smrg         pPriv->colorKey = pSiS->colorKey = sdcbuf->sdc_parm[0];
174872b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
174972b676d7Smrg      break;
175072b676d7Smrg
175172b676d7Smrg   case SDC_CMD_GETXVCOLORKEY:
175272b676d7Smrg      if(pPriv) {
175372b676d7Smrg         sdcbuf->sdc_result[0] = pPriv->colorKey;
175472b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
175572b676d7Smrg      break;
175672b676d7Smrg
175772b676d7Smrg   case SDC_CMD_SETXVAUTOPAINTCOLORKEY:
175872b676d7Smrg      if(pPriv) {
175972b676d7Smrg         pPriv->autopaintColorKey = sdcbuf->sdc_parm[0] ? 1 : 0;
176072b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
176172b676d7Smrg      break;
176272b676d7Smrg
176372b676d7Smrg   case SDC_CMD_GETXVAUTOPAINTCOLORKEY:
176472b676d7Smrg      if(pPriv) {
176572b676d7Smrg         sdcbuf->sdc_result[0] = pPriv->autopaintColorKey ? 1 : 0;
176672b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
176772b676d7Smrg      break;
176872b676d7Smrg
176972b676d7Smrg   case SDC_CMD_SETXVDEFAULTS:
177072b676d7Smrg      if(pPriv) {
177172b676d7Smrg         SISSetPortDefaults(pScrn, pPriv);
177272b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
177372b676d7Smrg      break;
177472b676d7Smrg
177572b676d7Smrg   case SDC_CMD_SETXVDISABLEGFX:
177672b676d7Smrg      if(pPriv) {
177772b676d7Smrg         pPriv->disablegfx = sdcbuf->sdc_parm[0] ? 1 : 0;
177872b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
177972b676d7Smrg      break;
178072b676d7Smrg
178172b676d7Smrg   case SDC_CMD_GETXVDISABLEGFX:
178272b676d7Smrg      if(pPriv) {
178372b676d7Smrg         sdcbuf->sdc_result[0] = pPriv->disablegfx ? 1 : 0;
178472b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
178572b676d7Smrg      break;
178672b676d7Smrg
178772b676d7Smrg   case SDC_CMD_SETXVDISABLEGFXLR:
178872b676d7Smrg      if(pPriv) {
178972b676d7Smrg         pPriv->disablegfxlr = sdcbuf->sdc_parm[0] ? 1 : 0;
179072b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
179172b676d7Smrg      break;
179272b676d7Smrg
179372b676d7Smrg   case SDC_CMD_GETXVDISABLEGFXLR:
179472b676d7Smrg      if(pPriv) {
179572b676d7Smrg         sdcbuf->sdc_result[0] = pPriv->disablegfxlr ? 1 : 0;
179672b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
179772b676d7Smrg      break;
179872b676d7Smrg
179972b676d7Smrg   case SDC_CMD_SETXVSWITCHCRT:
180072b676d7Smrg      if((pPriv) && (pSiS->VGAEngine == SIS_315_VGA)) {
180172b676d7Smrg         if(pPriv->AllowSwitchCRT) {
180272b676d7Smrg	    pPriv->crtnum = sdcbuf->sdc_parm[0] ? 1 : 0;
180372b676d7Smrg#ifdef SISDUALHEAD
180472b676d7Smrg            if(pPriv->dualHeadMode) pSiSEnt->curxvcrtnum = pPriv->crtnum;
180572b676d7Smrg#endif
180672b676d7Smrg	 }
180772b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
180872b676d7Smrg      break;
180972b676d7Smrg
181072b676d7Smrg   case SDC_CMD_GETXVSWITCHCRT:
181172b676d7Smrg      if((pPriv) && (pSiS->VGAEngine == SIS_315_VGA)) {
181272b676d7Smrg#ifdef SISDUALHEAD
181372b676d7Smrg         if(pPriv->dualHeadMode)
181472b676d7Smrg            sdcbuf->sdc_result[0] = pSiSEnt->curxvcrtnum;
181572b676d7Smrg         else
181672b676d7Smrg#endif
181772b676d7Smrg            sdcbuf->sdc_result[0] = pPriv->crtnum;
181872b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
181972b676d7Smrg      break;
182072b676d7Smrg
182172b676d7Smrg
182272b676d7Smrg   case SDC_CMD_SETTVXPOS:
182372b676d7Smrg      {
182472b676d7Smrg	 int value = sdcbuf->sdc_parm[0] - 32768;
182572b676d7Smrg	 if((value < -32) || (value > 32)) {
182672b676d7Smrg	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
182772b676d7Smrg	 } else if(pSiS->xv_sisdirectunlocked) {
182872b676d7Smrg	    pPriv->tvxpos = value;
182972b676d7Smrg	    SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
183072b676d7Smrg	    pPriv->updatetvxpos = FALSE;
183172b676d7Smrg         } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
183272b676d7Smrg      }
183372b676d7Smrg      break;
183472b676d7Smrg
183572b676d7Smrg   case SDC_CMD_GETTVXPOS:
183672b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetTVxposoffset(pScrn) + 32768;
183772b676d7Smrg      break;
183872b676d7Smrg
183972b676d7Smrg   case SDC_CMD_SETTVYPOS:
184072b676d7Smrg      {
184172b676d7Smrg	 int value = sdcbuf->sdc_parm[0] - 32768;
184272b676d7Smrg	 if((value < -32) || (value > 32)) {
184372b676d7Smrg	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
184472b676d7Smrg	 } else if(pSiS->xv_sisdirectunlocked) {
184572b676d7Smrg	    pPriv->tvypos = value;
184672b676d7Smrg	    SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
184772b676d7Smrg	    pPriv->updatetvypos = FALSE;
184872b676d7Smrg	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
184972b676d7Smrg      }
185072b676d7Smrg      break;
185172b676d7Smrg
185272b676d7Smrg   case SDC_CMD_GETTVYPOS:
185372b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetTVyposoffset(pScrn) + 32768;
185472b676d7Smrg      break;
185572b676d7Smrg
185672b676d7Smrg   case SDC_CMD_SETXVDEINT:
185772b676d7Smrg   case SDC_CMD_GETXVDEINT:
185872b676d7Smrg      sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
185972b676d7Smrg      break;
186072b676d7Smrg
186172b676d7Smrg   case SDC_CMD_GETMONGAMMACRT1:
186272b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->CRT1MonGamma;
186372b676d7Smrg      break;
186472b676d7Smrg
186572b676d7Smrg   case SDC_CMD_GETMONGAMMACRT2:
186672b676d7Smrg      sdcbuf->sdc_result[0] = pSiS->CRT2MonGamma;
186772b676d7Smrg      break;
186872b676d7Smrg
186972b676d7Smrg   case SDC_CMD_LOGQUIET:
187072b676d7Smrg      pSiS->SCLogQuiet = sdcbuf->sdc_parm[0] ? TRUE : FALSE;
187172b676d7Smrg      break;
187272b676d7Smrg
187372b676d7Smrg   case SDC_CMD_GETCRT1SATGAIN:
187472b676d7Smrg      sdcbuf->sdc_result[0] = SiS_GetSISCRT1SaturationGain(pScrn);
187572b676d7Smrg      break;
187672b676d7Smrg
187772b676d7Smrg   case SDC_CMD_SETCRT1SATGAIN:
187872b676d7Smrg      if(pSiS->xv_sisdirectunlocked) {
187972b676d7Smrg	 SiS_SetSISCRT1SaturationGain(pScrn, (int)sdcbuf->sdc_parm[0]);
188072b676d7Smrg      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
188172b676d7Smrg      break;
188272b676d7Smrg
188372b676d7Smrg   default:
188472b676d7Smrg      sdcbuf->sdc_result_header = SDC_RESULT_UNDEFCMD;
188572b676d7Smrg   }
188672b676d7Smrg
188772b676d7Smrg   return Success;
188872b676d7Smrg}
188972b676d7Smrg
189072b676d7Smrg/* Proc */
189172b676d7Smrg
189272b676d7Smrgstatic int
189372b676d7SmrgSiSProcSiSCtrlQueryVersion(ClientPtr client)
189472b676d7Smrg{
189572b676d7Smrg    xSiSCtrlQueryVersionReply	  rep;
189672b676d7Smrg    register int		  n;
189772b676d7Smrg
189872b676d7Smrg    REQUEST_SIZE_MATCH(xSiSCtrlQueryVersionReq);
189972b676d7Smrg    rep.type = X_Reply;
190072b676d7Smrg    rep.length = 0;
190172b676d7Smrg    rep.sequenceNumber = client->sequence;
190272b676d7Smrg    rep.majorVersion = SISCTRL_MAJOR_VERSION;
190372b676d7Smrg    rep.minorVersion = SISCTRL_MINOR_VERSION;
190472b676d7Smrg    if(client->swapped) {
190572b676d7Smrg        swaps(&rep.sequenceNumber, n);
190672b676d7Smrg        swapl(&rep.length, n);
190772b676d7Smrg        swaps(&rep.majorVersion, n);
190872b676d7Smrg        swaps(&rep.minorVersion, n);
190972b676d7Smrg    }
191072b676d7Smrg    WriteToClient(client, sizeof(xSiSCtrlQueryVersionReply), (char *)&rep);
191172b676d7Smrg    return (client->noClientException);
191272b676d7Smrg}
191372b676d7Smrg
191472b676d7Smrgstatic int
191572b676d7SmrgSiSProcSiSCtrlCommand(ClientPtr client)
191672b676d7Smrg{
191772b676d7Smrg    REQUEST(xSiSCtrlCommandReq);
191872b676d7Smrg    xSiSCtrlCommandReply rep;
191972b676d7Smrg    ExtensionEntry 	 *myext;
192072b676d7Smrg    xSiSCtrlScreenTable  *myctrl;
192172b676d7Smrg    register int	 n;
192272b676d7Smrg    int 		 i, ret;
192372b676d7Smrg
192472b676d7Smrg    REQUEST_SIZE_MATCH(xSiSCtrlCommandReq);
192572b676d7Smrg
192672b676d7Smrg    memcpy(&rep, stuff, sizeof(xSiSCtrlCommandReply));
192772b676d7Smrg
192872b676d7Smrg    /* Get pointer to ExtensionEntry */
192972b676d7Smrg    if(!(myext = CheckExtension(SISCTRL_PROTOCOL_NAME))) return BadMatch;
193072b676d7Smrg
193172b676d7Smrg    /* Get pointer to our private */
193272b676d7Smrg    if(!(myctrl = (xSiSCtrlScreenTable *)myext->extPrivate)) return BadMatch;
193372b676d7Smrg
193472b676d7Smrg    /* Check if screen index is within out limits */
193572b676d7Smrg    if(rep.screen > myctrl->maxscreens) return BadMatch;
193672b676d7Smrg
193772b676d7Smrg    /* Check if this screen has added itself */
193872b676d7Smrg    if(!(myctrl->HandleSiSDirectCommand[rep.screen])) return BadMatch;
193972b676d7Smrg
194072b676d7Smrg    /* Finally, execute the command */
194172b676d7Smrg    if((ret = (myctrl->HandleSiSDirectCommand[rep.screen])(&rep)) != Success)
194272b676d7Smrg       return ret;
194372b676d7Smrg
194472b676d7Smrg    rep.type = X_Reply;
194572b676d7Smrg    rep.length = (sizeof(xSiSCtrlCommandReply) - sizeof(xGenericReply)) >> 2;
194672b676d7Smrg    rep.sequenceNumber = client->sequence;
194772b676d7Smrg
194872b676d7Smrg    if(client->swapped) {
194972b676d7Smrg       swaps(&rep.sequenceNumber, n);
195072b676d7Smrg       swapl(&rep.length, n);
195172b676d7Smrg       swapl(&rep.screen, n);
195272b676d7Smrg       swapl(&rep.sdc_id, n);
195372b676d7Smrg       swapl(&rep.sdc_command, n);
195472b676d7Smrg       swapl(&rep.sdc_result_header, n);
195572b676d7Smrg       for(i = 0; i < SDC_NUM_PARM_RESULT; i++) {
195672b676d7Smrg	  swapl(&rep.sdc_parm[i], n);
195772b676d7Smrg	  swapl(&rep.sdc_result[i], n);
195872b676d7Smrg       }
195972b676d7Smrg    }
196072b676d7Smrg    WriteToClient(client, sizeof(xSiSCtrlCommandReply), (char *)&rep);
196172b676d7Smrg    return client->noClientException;
196272b676d7Smrg}
196372b676d7Smrg
196472b676d7Smrgstatic int
196572b676d7SmrgSiSProcSiSCtrlDispatch(ClientPtr client)
196672b676d7Smrg{
196772b676d7Smrg    REQUEST(xReq);
196872b676d7Smrg    switch(stuff->data) {
196972b676d7Smrg	case X_SiSCtrlQueryVersion:
197072b676d7Smrg	     return SiSProcSiSCtrlQueryVersion(client);
197172b676d7Smrg	case X_SiSCtrlCommand:
197272b676d7Smrg	     return SiSProcSiSCtrlCommand(client);
197372b676d7Smrg    }
197472b676d7Smrg    return BadRequest;
197572b676d7Smrg}
197672b676d7Smrg
197772b676d7Smrg/* SProc */
197872b676d7Smrg
197972b676d7Smrgstatic int
198072b676d7SmrgSiSSProcSiSCtrlQueryVersion(ClientPtr client)
198172b676d7Smrg{
198272b676d7Smrg    REQUEST(xSiSCtrlQueryVersionReq);
198372b676d7Smrg    register int n;
198472b676d7Smrg    swaps(&stuff->length, n);
198572b676d7Smrg    REQUEST_SIZE_MATCH(xSiSCtrlQueryVersionReq);
198672b676d7Smrg    return SiSProcSiSCtrlQueryVersion(client);
198772b676d7Smrg}
198872b676d7Smrg
198972b676d7Smrgstatic int
199072b676d7SmrgSiSSProcSiSCtrlCommand(ClientPtr client)
199172b676d7Smrg{
199272b676d7Smrg    REQUEST(xSiSCtrlCommandReq);
199372b676d7Smrg    register int n;
199472b676d7Smrg    int i;
199572b676d7Smrg    swaps(&stuff->length, n);
199672b676d7Smrg    swapl(&stuff->screen, n);
199772b676d7Smrg    swapl(&stuff->sdc_id, n);
199872b676d7Smrg    swapl(&stuff->sdc_command, n);
199972b676d7Smrg    swapl(&stuff->sdc_result_header, n);
200072b676d7Smrg    for(i = 0; i < SDC_NUM_PARM_RESULT; i++) {
200172b676d7Smrg       swapl(&stuff->sdc_parm[i], n);
200272b676d7Smrg       swapl(&stuff->sdc_result[i], n);
200372b676d7Smrg    }
200472b676d7Smrg    REQUEST_SIZE_MATCH(xSiSCtrlCommandReq);
200572b676d7Smrg    return SiSProcSiSCtrlCommand(client);
200672b676d7Smrg}
200772b676d7Smrg
200872b676d7Smrgstatic int
200972b676d7SmrgSiSSProcSiSCtrlDispatch(ClientPtr client)
201072b676d7Smrg{
201172b676d7Smrg    REQUEST(xReq);
201272b676d7Smrg    switch(stuff->data) {
201372b676d7Smrg       case X_SiSCtrlQueryVersion:
201472b676d7Smrg	  return SiSSProcSiSCtrlQueryVersion(client);
201572b676d7Smrg       case X_SiSCtrlCommand:
201672b676d7Smrg	  return SiSSProcSiSCtrlCommand(client);
201772b676d7Smrg    }
201872b676d7Smrg    return BadRequest;
201972b676d7Smrg}
202072b676d7Smrg
202172b676d7Smrgstatic void
202272b676d7SmrgSiSCtrlResetProc(ExtensionEntry* extEntry)
202372b676d7Smrg{
202472b676d7Smrg    /* Called by CloseDownExtensions() */
202572b676d7Smrg    /* (CloseDownExtensions() is called BEFORE CloseScreen,
202672b676d7Smrg     * which is why we must not use pSiS->SiSCtrlExtEntry
202772b676d7Smrg     * in SiSCtrlExtUnregister())
202872b676d7Smrg     */
202972b676d7Smrg    if(extEntry->extPrivate) {
203072b676d7Smrg       xfree(extEntry->extPrivate);
203172b676d7Smrg       extEntry->extPrivate = NULL;
203272b676d7Smrg    }
203372b676d7Smrg}
203472b676d7Smrg
203572b676d7Smrgvoid
203672b676d7SmrgSiSCtrlExtInit(ScrnInfoPtr pScrn)
203772b676d7Smrg{
203872b676d7Smrg   SISPtr pSiS = SISPTR(pScrn);
203972b676d7Smrg   ExtensionEntry  *myext;
204072b676d7Smrg   xSiSCtrlScreenTable *myctrl;
204172b676d7Smrg   unsigned int version, revision;
204272b676d7Smrg
204372b676d7Smrg   if((pSiS->VGAEngine != SIS_300_VGA) &&
204472b676d7Smrg      (pSiS->VGAEngine != SIS_315_VGA))
204572b676d7Smrg      return;
204672b676d7Smrg
204772b676d7Smrg   pSiS->SCLogQuiet = FALSE;
204872b676d7Smrg
204972b676d7Smrg   if(!(myext = CheckExtension(SISCTRL_PROTOCOL_NAME))) {
205072b676d7Smrg
205172b676d7Smrg      if(!(myctrl = xcalloc(sizeof(xSiSCtrlScreenTable), 1)))
205272b676d7Smrg         return;
205372b676d7Smrg
205472b676d7Smrg      if(!(myext = AddExtension(SISCTRL_PROTOCOL_NAME, 0, 0,
205572b676d7Smrg				SiSProcSiSCtrlDispatch,
205672b676d7Smrg				SiSSProcSiSCtrlDispatch,
205772b676d7Smrg				SiSCtrlResetProc,
205872b676d7Smrg				StandardMinorOpcode))) {
205972b676d7Smrg         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
206072b676d7Smrg	 		"Failed to add SISCTRL extension\n");
206172b676d7Smrg	 xfree(myctrl);
206272b676d7Smrg	 return;
206372b676d7Smrg      }
206472b676d7Smrg
206572b676d7Smrg      myext->extPrivate = (pointer)myctrl;
206672b676d7Smrg
206772b676d7Smrg      myctrl->maxscreens = SISCTRL_MAX_SCREENS;
206872b676d7Smrg      myctrl->version_major = version = SISCTRL_MAJOR_VERSION;
206972b676d7Smrg      myctrl->version_minor = revision = SISCTRL_MINOR_VERSION;
207072b676d7Smrg
207172b676d7Smrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
207272b676d7Smrg		"Initialized SISCTRL extension version %d.%d\n",
207372b676d7Smrg		version, revision);
207472b676d7Smrg
207572b676d7Smrg   } else {
207672b676d7Smrg
207772b676d7Smrg      if(!(myctrl = (xSiSCtrlScreenTable *)myext->extPrivate)) {
207872b676d7Smrg         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
207972b676d7Smrg		"Internal error: Found SISCTRL extension with NULL-private!\n");
208072b676d7Smrg	 return;
208172b676d7Smrg      }
208272b676d7Smrg
208372b676d7Smrg      version = myctrl->version_major;
208472b676d7Smrg      revision = myctrl->version_minor;
208572b676d7Smrg   }
208672b676d7Smrg
208772b676d7Smrg   if(pScrn->scrnIndex < myctrl->maxscreens) {
208872b676d7Smrg
208972b676d7Smrg      myctrl->HandleSiSDirectCommand[pScrn->scrnIndex] = SiSHandleSiSDirectCommand;
209072b676d7Smrg
209172b676d7Smrg      pSiS->SiSCtrlExtEntry = myext;
209272b676d7Smrg
209372b676d7Smrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
209472b676d7Smrg		"Registered screen %d with SISCTRL extension version %d.%d\n",
209572b676d7Smrg		pScrn->scrnIndex, version, revision);
209672b676d7Smrg   } else {
209772b676d7Smrg
209872b676d7Smrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
209972b676d7Smrg		"Screen number (%d) too high for SISCTRL extension %d.%d\n",
210072b676d7Smrg		pScrn->scrnIndex, version, revision);
210172b676d7Smrg
210272b676d7Smrg   }
210372b676d7Smrg
210472b676d7Smrg}
210572b676d7Smrg
210672b676d7Smrgvoid
210772b676d7SmrgSiSCtrlExtUnregister(SISPtr pSiS, int index)
210872b676d7Smrg{
210972b676d7Smrg   ExtensionEntry  *myext;
211072b676d7Smrg   xSiSCtrlScreenTable *myctrl;
211172b676d7Smrg
211272b676d7Smrg   if(!pSiS->SiSCtrlExtEntry) return;
211372b676d7Smrg
211472b676d7Smrg   /* Since CloseDownExtensions() is called before
211572b676d7Smrg    * our CloseScreen(), we must not use the saved
211672b676d7Smrg    * ptr here, but instead check for the extension.
211772b676d7Smrg    */
211872b676d7Smrg
211972b676d7Smrg   if((myext = CheckExtension(SISCTRL_PROTOCOL_NAME))) {
212072b676d7Smrg      if((myctrl = (xSiSCtrlScreenTable *)myext->extPrivate)) {
212172b676d7Smrg         myctrl->HandleSiSDirectCommand[index] = NULL;
212272b676d7Smrg      }
212372b676d7Smrg   }
212472b676d7Smrg}
212572b676d7Smrg
212672b676d7Smrg/***********************************
212772b676d7Smrg *     Xv attribute interface      *
212872b676d7Smrg ***********************************/
212972b676d7Smrg
213072b676d7Smrg#ifdef XV_SD_DEPRECATED
213172b676d7Smrg
213272b676d7Smrgint
213372b676d7SmrgSISSetPortUtilAttribute(ScrnInfoPtr pScrn, Atom attribute,
213472b676d7Smrg			INT32 value, SISPortPrivPtr pPriv)
213572b676d7Smrg{
213672b676d7Smrg  SISPtr pSiS = SISPTR(pScrn);
213772b676d7Smrg#ifdef SISDUALHEAD
213872b676d7Smrg  SISEntPtr pSiSEnt = pSiS->entityPrivate;;
213972b676d7Smrg#endif
214072b676d7Smrg
214172b676d7Smrg  if(attribute == pSiS->xv_USD) {
214272b676d7Smrg     if(pSiS->enablesisctrl) {
214372b676d7Smrg	 if(value == SIS_DIRECTKEY) {
214472b676d7Smrg	   pSiS->xv_sisdirectunlocked++;
214572b676d7Smrg	} else if(pSiS->xv_sisdirectunlocked) {
214672b676d7Smrg	   pSiS->xv_sisdirectunlocked--;
214772b676d7Smrg	}
214872b676d7Smrg     } else {
214972b676d7Smrg	pSiS->xv_sisdirectunlocked = 0;
215072b676d7Smrg     }
215172b676d7Smrg  } else if(attribute == pSiS->xv_SVF) {
215272b676d7Smrg#ifdef SISDUALHEAD
215372b676d7Smrg     if(!pPriv->dualHeadMode)
215472b676d7Smrg#endif
215572b676d7Smrg	if(pSiS->xv_sisdirectunlocked) {
215672b676d7Smrg	   SISSwitchCRT2Type(pScrn, (ULong)value, FALSE);
215772b676d7Smrg	   SISUpdateVideoParms(pSiS, pPriv);
215872b676d7Smrg	}
215972b676d7Smrg  } else if(attribute == pSiS->xv_CT1) {
216072b676d7Smrg#ifdef SISDUALHEAD
216172b676d7Smrg     if(!pPriv->dualHeadMode)
216272b676d7Smrg#endif
216372b676d7Smrg	if(pSiS->xv_sisdirectunlocked) {
216472b676d7Smrg	   SISSwitchCRT1Status(pScrn, (ULong)value, FALSE);
216572b676d7Smrg	   SISUpdateVideoParms(pSiS, pPriv);
216672b676d7Smrg        }
216772b676d7Smrg  } else if(attribute == pSiS->xv_RDT) {
216872b676d7Smrg#ifdef SISDUALHEAD
216972b676d7Smrg     if(!pPriv->dualHeadMode)
217072b676d7Smrg#endif
217172b676d7Smrg	if(pSiS->xv_sisdirectunlocked) {
217272b676d7Smrg	   SISRedetectCRT2Devices(pScrn);
217372b676d7Smrg	}
217472b676d7Smrg  } else if(attribute == pSiS->xv_TAF) {
217572b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
217672b676d7Smrg	SiS_SetSISTVantiflicker(pScrn, (int)value);
217772b676d7Smrg     }
217872b676d7Smrg  } else if(attribute == pSiS->xv_TSA) {
217972b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
218072b676d7Smrg	SiS_SetSISTVsaturation(pScrn, (int)value);
218172b676d7Smrg     }
218272b676d7Smrg  } else if(attribute == pSiS->xv_TEE) {
218372b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
218472b676d7Smrg	SiS_SetSISTVedgeenhance(pScrn, (int)value);
218572b676d7Smrg     }
218672b676d7Smrg  } else if(attribute == pSiS->xv_CFI) {
218772b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
218872b676d7Smrg	SiS_SetSISTVcfilter(pScrn, value ? 1 : 0);
218972b676d7Smrg     }
219072b676d7Smrg  } else if(attribute == pSiS->xv_YFI) {
219172b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
219272b676d7Smrg	SiS_SetSISTVyfilter(pScrn, value);
219372b676d7Smrg     }
219472b676d7Smrg  } else if(attribute == pSiS->xv_COC) {
219572b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
219672b676d7Smrg	SiS_SetSISTVcolcalib(pScrn, (int)value, TRUE);
219772b676d7Smrg     }
219872b676d7Smrg  } else if(attribute == pSiS->xv_COF) {
219972b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
220072b676d7Smrg	SiS_SetSISTVcolcalib(pScrn, (int)value, FALSE);
220172b676d7Smrg     }
220272b676d7Smrg  } else if(attribute == pSiS->xv_TCO) {
220372b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
220472b676d7Smrg	SiS_SetCHTVcontrast(pScrn, (int)value);
220572b676d7Smrg     }
220672b676d7Smrg  } else if(attribute == pSiS->xv_TTE) {
220772b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
220872b676d7Smrg	SiS_SetCHTVtextenhance(pScrn, (int)value);
220972b676d7Smrg     }
221072b676d7Smrg  } else if(attribute == pSiS->xv_TCF) {
221172b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
221272b676d7Smrg	SiS_SetCHTVchromaflickerfilter(pScrn, (int)value);
221372b676d7Smrg     }
221472b676d7Smrg  } else if(attribute == pSiS->xv_TLF) {
221572b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
221672b676d7Smrg	SiS_SetCHTVlumaflickerfilter(pScrn, (int)value);
221772b676d7Smrg     }
221872b676d7Smrg  } else if(attribute == pSiS->xv_TCC) {
221972b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
222072b676d7Smrg	SiS_SetCHTVcvbscolor(pScrn, value ? 1 : 0);
222172b676d7Smrg     }
222272b676d7Smrg  } else if(attribute == pSiS->xv_OVR) {
222372b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
222472b676d7Smrg	pSiS->UseCHOverScan = -1;
222572b676d7Smrg	pSiS->OptTVSOver = FALSE;
222672b676d7Smrg	if(value == 3) {
222772b676d7Smrg	   if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSOVER) {
222872b676d7Smrg	      pSiS->OptTVSOver = TRUE;
222972b676d7Smrg	   }
223072b676d7Smrg	   pSiS->UseCHOverScan = 1;
223172b676d7Smrg	} else if(value == 2) pSiS->UseCHOverScan = 1;
223272b676d7Smrg	else if(value == 1)   pSiS->UseCHOverScan = 0;
223372b676d7Smrg     }
223472b676d7Smrg  } else if(attribute == pSiS->xv_CMD) {
223572b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
223672b676d7Smrg	int result = 0;
223772b676d7Smrg	pSiS->xv_sd_result = (value & 0xffffff00);
223872b676d7Smrg	result = SISCheckModeIndexForCRT2Type(pScrn, (UShort)(value & 0xff),
223972b676d7Smrg					      (UShort)((value >> 8) & 0xff),
224072b676d7Smrg					      FALSE);
224172b676d7Smrg	pSiS->xv_sd_result |= (result & 0xff);
224272b676d7Smrg     }
224372b676d7Smrg  } else if(attribute == pSiS->xv_SGA) {
224472b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
224572b676d7Smrg	Bool backup = pSiS->XvGamma;
224672b676d7Smrg	Bool backup2 = pSiS->CRT2SepGamma;
224772b676d7Smrg	pSiS->CRT1gamma = (value & 0x01) ? TRUE : FALSE;
224872b676d7Smrg	pSiS->CRT2gamma = (value & 0x02) ? TRUE : FALSE;
224972b676d7Smrg#ifdef SISDUALHEAD
225072b676d7Smrg	if(pPriv->dualHeadMode) {
225172b676d7Smrg	   pSiSEnt->CRT1gamma = pSiS->CRT1gamma;
225272b676d7Smrg	   pSiSEnt->CRT2gamma = pSiS->CRT2gamma;
225372b676d7Smrg	}
225472b676d7Smrg#endif
225572b676d7Smrg	if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSGRCRT2) {
225672b676d7Smrg	   pSiS->CRT2SepGamma = (value & 0x08) ? TRUE : FALSE;
225772b676d7Smrg	   if(pSiS->CRT2SepGamma != backup2) {
225872b676d7Smrg	      if(pSiS->CRT2SepGamma) {
225972b676d7Smrg		 SiS_UpdateGammaCRT2(pScrn);
226072b676d7Smrg	      }
226172b676d7Smrg#ifdef SISGAMMARAMP
226272b676d7Smrg	      else {
226372b676d7Smrg		 SISCalculateGammaRamp(pScrn->pScreen, pScrn);
226472b676d7Smrg	      }
226572b676d7Smrg#endif
226672b676d7Smrg	      /* ATTN: When disabling CRT2 sep gamma,
226772b676d7Smrg	       * as long as SISGAMMARAMP is not defined,
226872b676d7Smrg	       * application needs to reset palette using
226972b676d7Smrg	       * vidmodextension! (See SiS_SD_CANSETGAMMA)
227072b676d7Smrg	       *
227172b676d7Smrg	       * Note: Difference between setting gamma values
227272b676d7Smrg	       * for CRT1 and CRT2: For CRT1, driver only
227372b676d7Smrg	       * stores the values, but does nothing with them.
227472b676d7Smrg	       * For CRT2, the driver will IMMEDIATELY recalc
227572b676d7Smrg	       * the palette. App needs to calc gamma ramp
227672b676d7Smrg	       * itself for CRT1, and set it using the
227772b676d7Smrg	       * VidModExtention.
227872b676d7Smrg	       */
227972b676d7Smrg	   }
228072b676d7Smrg	} else pSiS->CRT2SepGamma = FALSE;
228172b676d7Smrg	pSiS->XvGamma = (value & 0x04) ? TRUE : FALSE;
228272b676d7Smrg	if(pSiS->VGAEngine == SIS_315_VGA) {
228372b676d7Smrg	   if(backup != pSiS->XvGamma) {
228472b676d7Smrg	      SiSUpdateXvGamma(pSiS, pPriv);
228572b676d7Smrg	   }
228672b676d7Smrg	}
228772b676d7Smrg     }
228872b676d7Smrg  } else if(attribute == pSiS->xv_TXS) {
228972b676d7Smrg     if((value < -16) || (value > 16)) return BadValue;
229072b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
229172b676d7Smrg	SiS_SetTVxscale(pScrn, value);
229272b676d7Smrg     }
229372b676d7Smrg  } else if(attribute == pSiS->xv_TYS) {
229472b676d7Smrg     if((value < -4) || (value > 3)) return BadValue;
229572b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
229672b676d7Smrg	SiS_SetTVyscale(pScrn, value);
229772b676d7Smrg     }
229872b676d7Smrg  } else if(attribute == pSiS->xv_BRR) {
229972b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
230072b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
230172b676d7Smrg	pSiS->GammaBriR = value;
230272b676d7Smrg     }
230372b676d7Smrg  } else if(attribute == pSiS->xv_BRG) {
230472b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
230572b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
230672b676d7Smrg	pSiS->GammaBriG = value;
230772b676d7Smrg     }
230872b676d7Smrg  } else if(attribute == pSiS->xv_BRB) {
230972b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
231072b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
231172b676d7Smrg	pSiS->GammaBriB = value;
231272b676d7Smrg     }
231372b676d7Smrg  } else if(attribute == pSiS->xv_PBR) {
231472b676d7Smrg     /* Nop */
231572b676d7Smrg  } else if(attribute == pSiS->xv_PBG) {
231672b676d7Smrg     /* Nop */
231772b676d7Smrg  } else if(attribute == pSiS->xv_PBB) {
231872b676d7Smrg     /* Nop */
231972b676d7Smrg  } else if(attribute == pSiS->xv_BRR2) {
232072b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
232172b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
232272b676d7Smrg#ifdef SISDUALHEAD
232372b676d7Smrg	if(pPriv->dualHeadMode) pSiSEnt->GammaBriR = value;
232472b676d7Smrg#endif
232572b676d7Smrg     }
232672b676d7Smrg  } else if(attribute == pSiS->xv_BRG2) {
232772b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
232872b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
232972b676d7Smrg#ifdef SISDUALHEAD
233072b676d7Smrg	if(pPriv->dualHeadMode) pSiSEnt->GammaBriG = value;
233172b676d7Smrg#endif
233272b676d7Smrg     }
233372b676d7Smrg  } else if(attribute == pSiS->xv_BRB2) {
233472b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
233572b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
233672b676d7Smrg#ifdef SISDUALHEAD
233772b676d7Smrg	if(pPriv->dualHeadMode) pSiSEnt->GammaBriB = value;
233872b676d7Smrg#endif
233972b676d7Smrg     }
234072b676d7Smrg  } else if(attribute == pSiS->xv_PBR2) {
234172b676d7Smrg     /* Nop */
234272b676d7Smrg  } else if(attribute == pSiS->xv_PBG2) {
234372b676d7Smrg     /* Nop */
234472b676d7Smrg  } else if(attribute == pSiS->xv_PBB2) {
234572b676d7Smrg     /* Nop */
234672b676d7Smrg  } else if(attribute == pSiS->xv_GARC2) {
234772b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
234872b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
234972b676d7Smrg	pSiS->GammaR2 = (float)value / (float)1000;
235072b676d7Smrg	SiS_UpdateGammaCRT2(pScrn);
235172b676d7Smrg     }
235272b676d7Smrg  } else if(attribute == pSiS->xv_GAGC2) {
235372b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
235472b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
235572b676d7Smrg	pSiS->GammaG2 = (float)value / (float)1000;
235672b676d7Smrg	SiS_UpdateGammaCRT2(pScrn);
235772b676d7Smrg     }
235872b676d7Smrg  } else if(attribute == pSiS->xv_GABC2) {
235972b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
236072b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
236172b676d7Smrg	pSiS->GammaB2 = (float)value / (float)1000;
236272b676d7Smrg	SiS_UpdateGammaCRT2(pScrn);
236372b676d7Smrg     }
236472b676d7Smrg  } else if(attribute == pSiS->xv_BRRC2) {
236572b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
236672b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
236772b676d7Smrg	pSiS->GammaBriR2 = value;
236872b676d7Smrg	SiS_UpdateGammaCRT2(pScrn);
236972b676d7Smrg     }
237072b676d7Smrg  } else if(attribute == pSiS->xv_BRGC2) {
237172b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
237272b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
237372b676d7Smrg	pSiS->GammaBriG2 = value;
237472b676d7Smrg	SiS_UpdateGammaCRT2(pScrn);
237572b676d7Smrg     }
237672b676d7Smrg  } else if(attribute == pSiS->xv_BRBC2) {
237772b676d7Smrg     if((value < 100) || (value > 10000)) return BadValue;
237872b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
237972b676d7Smrg	pSiS->GammaBriB2 = value;
238072b676d7Smrg	SiS_UpdateGammaCRT2(pScrn);
238172b676d7Smrg     }
238272b676d7Smrg  } else if(attribute == pSiS->xv_PBRC2) {
238372b676d7Smrg     /* Nop */
238472b676d7Smrg  } else if(attribute == pSiS->xv_PBGC2) {
238572b676d7Smrg     /* Nop */
238672b676d7Smrg  } else if(attribute == pSiS->xv_PBBC2) {
238772b676d7Smrg     /* Nop */
238872b676d7Smrg  } else if(attribute == pSiS->xv_SHC) {
238972b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
239072b676d7Smrg	Bool VisibleBackup = pSiS->HWCursorIsVisible;
239172b676d7Smrg	pSiS->HideHWCursor = value ? TRUE : FALSE;
239272b676d7Smrg	if(pSiS->CursorInfoPtr) {
239372b676d7Smrg	   if(VisibleBackup) {
239472b676d7Smrg	      if(value) {
239572b676d7Smrg		 (pSiS->CursorInfoPtr->HideCursor)(pScrn);
239672b676d7Smrg	      } else {
239772b676d7Smrg		 (pSiS->CursorInfoPtr->ShowCursor)(pScrn);
239872b676d7Smrg	      }
239972b676d7Smrg	   }
240072b676d7Smrg	   pSiS->HWCursorIsVisible = VisibleBackup;
240172b676d7Smrg	}
240272b676d7Smrg     }
240372b676d7Smrg  } else if(attribute == pSiS->xv_PMD) {
240472b676d7Smrg     if(pSiS->xv_sisdirectunlocked) {
240572b676d7Smrg        if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
240672b676d7Smrg	   if(value & 0x01)      pSiS->SiS_Pr->UsePanelScaler = -1;
240772b676d7Smrg	   else if(value & 0x02) pSiS->SiS_Pr->UsePanelScaler = 1;
240872b676d7Smrg	   else			 pSiS->SiS_Pr->UsePanelScaler = 0;
240972b676d7Smrg	   if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
241072b676d7Smrg	      if(value & 0x04)      pSiS->SiS_Pr->CenterScreen = -1;
241172b676d7Smrg	      else if(value & 0x08) pSiS->SiS_Pr->CenterScreen = 1;
241272b676d7Smrg	      else		    pSiS->SiS_Pr->CenterScreen = 0;
241372b676d7Smrg	   }
241472b676d7Smrg        }
241572b676d7Smrg     }
241672b676d7Smrg#ifdef TWDEBUG
241772b676d7Smrg  } else if(attribute == pSiS->xv_STR) {
241872b676d7Smrg     ULong port;
241972b676d7Smrg     CARD8 reg;
242072b676d7Smrg     switch((value & 0xff000000) >> 24) {
242172b676d7Smrg     case 0x00: port = SISSR;    break;
242272b676d7Smrg     case 0x01: port = SISPART1; break;
242372b676d7Smrg     case 0x02: port = SISPART2; break;
242472b676d7Smrg     case 0x03: port = SISPART3; break;
242572b676d7Smrg     case 0x04: port = SISPART4; break;
242672b676d7Smrg     case 0x05: port = SISCR;    break;
242772b676d7Smrg     case 0x06: port = SISVID;   break;
242872b676d7Smrg     default:   return BadValue;
242972b676d7Smrg     }
243072b676d7Smrg     outSISIDXREG(port,((value & 0x00ff0000) >> 16), ((value & 0x0000ff00) >> 8));
243172b676d7Smrg     inSISIDXREG(port, ((value & 0x00ff0000) >> 16), reg);
243272b676d7Smrg     xf86DrvMsg(0, 0, "SetREG %x -> %x -> %x\n", ((value & 0x00ff0000) >> 16), ((value & 0x0000ff00) >> 8), reg);
243372b676d7Smrg#endif
243472b676d7Smrg  } else {
243572b676d7Smrg     return BadMatch;
243672b676d7Smrg  }
243772b676d7Smrg
243872b676d7Smrg  return Success;
243972b676d7Smrg}
244072b676d7Smrg
244172b676d7Smrgint
244272b676d7SmrgSISGetPortUtilAttribute(ScrnInfoPtr pScrn,  Atom attribute,
244372b676d7Smrg			INT32 *value, SISPortPrivPtr pPriv)
244472b676d7Smrg{
244572b676d7Smrg  SISPtr pSiS = SISPTR(pScrn);
244672b676d7Smrg#ifdef SISDUALHEAD
244772b676d7Smrg  SISEntPtr pSiSEnt = pSiS->entityPrivate;;
244872b676d7Smrg#endif
244972b676d7Smrg
245072b676d7Smrg  if(attribute == pSiS->xv_QVF) {
245172b676d7Smrg     *value = pSiS->VBFlags;
245272b676d7Smrg  } else if(attribute == pSiS->xv_GDV) {
245372b676d7Smrg     *value = SISDRIVERIVERSION;
245472b676d7Smrg  } else if(attribute == pSiS->xv_GHI) {
245572b676d7Smrg     *value = (pSiS->ChipFlags & 0xffff) | (pSiS->ChipType << 16) | (pSiS->ChipRev << 24);
245672b676d7Smrg  } else if(attribute == pSiS->xv_GBI) {
245772b676d7Smrg     *value = (pSiS->PciBus << 16) | (pSiS->PciDevice << 8) | pSiS->PciFunc;
245872b676d7Smrg  } else if(attribute == pSiS->xv_QVV) {
245972b676d7Smrg     *value = SIS_VBFlagsVersion;
246072b676d7Smrg  } else if(attribute == pSiS->xv_QDD) {
246172b676d7Smrg     *value = pSiS->detectedCRT2Devices;
246272b676d7Smrg  } else if(attribute == pSiS->xv_CT1) {
246372b676d7Smrg     *value = pSiS->CRT1isoff ? 0 : 1;
246472b676d7Smrg  } else if(attribute == pSiS->xv_GSF) {
246572b676d7Smrg     *value = pSiS->SiS_SD_Flags;
246672b676d7Smrg  } else if(attribute == pSiS->xv_GSF2) {
246772b676d7Smrg     *value = pSiS->SiS_SD2_Flags;
246872b676d7Smrg  } else if(attribute == pSiS->xv_USD) {
246972b676d7Smrg     *value = pSiS->xv_sisdirectunlocked;
247072b676d7Smrg  } else if(attribute == pSiS->xv_TAF) {
247172b676d7Smrg     *value = SiS_GetSISTVantiflicker(pScrn);
247272b676d7Smrg  } else if(attribute == pSiS->xv_TSA) {
247372b676d7Smrg     *value = SiS_GetSISTVsaturation(pScrn);
247472b676d7Smrg  } else if(attribute == pSiS->xv_TEE) {
247572b676d7Smrg     *value = SiS_GetSISTVedgeenhance(pScrn);
247672b676d7Smrg  } else if(attribute == pSiS->xv_CFI) {
247772b676d7Smrg     *value = SiS_GetSISTVcfilter(pScrn);
247872b676d7Smrg  } else if(attribute == pSiS->xv_YFI) {
247972b676d7Smrg     *value = SiS_GetSISTVyfilter(pScrn);
248072b676d7Smrg  } else if(attribute == pSiS->xv_COC) {
248172b676d7Smrg     *value = SiS_GetSISTVcolcalib(pScrn, TRUE);
248272b676d7Smrg  } else if(attribute == pSiS->xv_COF) {
248372b676d7Smrg     *value = SiS_GetSISTVcolcalib(pScrn, FALSE);
248472b676d7Smrg  } else if(attribute == pSiS->xv_TCO) {
248572b676d7Smrg     *value = SiS_GetCHTVcontrast(pScrn);
248672b676d7Smrg  } else if(attribute == pSiS->xv_TTE) {
248772b676d7Smrg     *value = SiS_GetCHTVtextenhance(pScrn);
248872b676d7Smrg  } else if(attribute == pSiS->xv_TCF) {
248972b676d7Smrg     *value = SiS_GetCHTVchromaflickerfilter(pScrn);
249072b676d7Smrg  } else if(attribute == pSiS->xv_TLF) {
249172b676d7Smrg     *value = SiS_GetCHTVlumaflickerfilter(pScrn);
249272b676d7Smrg  } else if(attribute == pSiS->xv_TCC) {
249372b676d7Smrg     *value = SiS_GetCHTVcvbscolor(pScrn);
249472b676d7Smrg  } else if(attribute == pSiS->xv_CMDR) {
249572b676d7Smrg     *value = pSiS->xv_sd_result;
249672b676d7Smrg  } else if(attribute == pSiS->xv_OVR) {
249772b676d7Smrg     /* Changing of CRT2 settings not supported in DHM! */
249872b676d7Smrg     *value = 0;
249972b676d7Smrg     if(pSiS->OptTVSOver == 1)         *value = 3;
250072b676d7Smrg     else if(pSiS->UseCHOverScan == 1) *value = 2;
250172b676d7Smrg     else if(pSiS->UseCHOverScan == 0) *value = 1;
250272b676d7Smrg  } else if(attribute == pSiS->xv_SGA) {
250372b676d7Smrg     *value = 0;
250472b676d7Smrg#ifdef SISDUALHEAD
250572b676d7Smrg     if(pPriv->dualHeadMode) {
250672b676d7Smrg        if(pSiSEnt->CRT1gamma) *value |= 0x01;
250772b676d7Smrg	if(pSiSEnt->CRT2gamma) *value |= 0x02;
250872b676d7Smrg     } else {
250972b676d7Smrg#endif
251072b676d7Smrg	if(pSiS->CRT1gamma)    *value |= 0x01;
251172b676d7Smrg	if(pSiS->CRT2gamma)    *value |= 0x02;
251272b676d7Smrg	if(pSiS->CRT2SepGamma) *value |= 0x08;
251372b676d7Smrg#ifdef SISDUALHEAD
251472b676d7Smrg     }
251572b676d7Smrg#endif
251672b676d7Smrg     if(pSiS->XvGamma) *value |= 0x04;
251772b676d7Smrg  } else if(attribute == pSiS->xv_TXS) {
251872b676d7Smrg     *value = SiS_GetTVxscale(pScrn);
251972b676d7Smrg  } else if(attribute == pSiS->xv_TYS) {
252072b676d7Smrg     *value = SiS_GetTVyscale(pScrn);
252172b676d7Smrg  } else if(attribute == pSiS->xv_GSS) {
252272b676d7Smrg     *value = (pScrn->virtualX << 16) | pScrn->virtualY;
252372b676d7Smrg  } else if(attribute == pSiS->xv_BRR) {
252472b676d7Smrg     *value = pSiS->GammaBriR;
252572b676d7Smrg  } else if(attribute == pSiS->xv_BRG) {
252672b676d7Smrg     *value = pSiS->GammaBriG;
252772b676d7Smrg  } else if(attribute == pSiS->xv_BRB) {
252872b676d7Smrg     *value = pSiS->GammaBriB;
252972b676d7Smrg  } else if(attribute == pSiS->xv_PBR) {
253072b676d7Smrg     *value = 1000;
253172b676d7Smrg  } else if(attribute == pSiS->xv_PBG) {
253272b676d7Smrg     *value = 1000;
253372b676d7Smrg  } else if(attribute == pSiS->xv_PBB) {
253472b676d7Smrg     *value = 1000;
253572b676d7Smrg  } else if(attribute == pSiS->xv_BRR2) {
253672b676d7Smrg#ifdef SISDUALHEAD
253772b676d7Smrg     if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriR;
253872b676d7Smrg     else
253972b676d7Smrg#endif
254072b676d7Smrg          *value = pSiS->GammaBriR;
254172b676d7Smrg  } else if(attribute == pSiS->xv_BRG2) {
254272b676d7Smrg#ifdef SISDUALHEAD
254372b676d7Smrg     if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriG;
254472b676d7Smrg     else
254572b676d7Smrg#endif
254672b676d7Smrg          *value = pSiS->GammaBriG;
254772b676d7Smrg  } else if(attribute == pSiS->xv_BRB2) {
254872b676d7Smrg#ifdef SISDUALHEAD
254972b676d7Smrg     if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriB;
255072b676d7Smrg     else
255172b676d7Smrg#endif
255272b676d7Smrg          *value = pSiS->GammaBriB;
255372b676d7Smrg  } else if(attribute == pSiS->xv_PBR2) {
255472b676d7Smrg     *value = 1000;
255572b676d7Smrg  } else if(attribute == pSiS->xv_PBG2) {
255672b676d7Smrg     *value = 1000;
255772b676d7Smrg  } else if(attribute == pSiS->xv_PBB2) {
255872b676d7Smrg     *value = 1000;
255972b676d7Smrg  } else if(attribute == pSiS->xv_GARC2) {
256072b676d7Smrg     *value = (int)(pSiS->GammaR2 * 1000);
256172b676d7Smrg  } else if(attribute == pSiS->xv_GAGC2) {
256272b676d7Smrg     *value = (int)(pSiS->GammaG2 * 1000);
256372b676d7Smrg  } else if(attribute == pSiS->xv_GABC2) {
256472b676d7Smrg     *value = (int)(pSiS->GammaB2 * 1000);
256572b676d7Smrg  } else if(attribute == pSiS->xv_BRRC2) {
256672b676d7Smrg     *value = pSiS->GammaBriR2;
256772b676d7Smrg  } else if(attribute == pSiS->xv_BRGC2) {
256872b676d7Smrg     *value = pSiS->GammaBriG2;
256972b676d7Smrg  } else if(attribute == pSiS->xv_BRBC2) {
257072b676d7Smrg     *value = pSiS->GammaBriB2;
257172b676d7Smrg  } else if(attribute == pSiS->xv_PBRC2) {
257272b676d7Smrg     *value = 1000;
257372b676d7Smrg  } else if(attribute == pSiS->xv_PBGC2) {
257472b676d7Smrg     *value = 1000;
257572b676d7Smrg  } else if(attribute == pSiS->xv_PBBC2) {
257672b676d7Smrg     *value = 1000;
257772b676d7Smrg  } else if(attribute == pSiS->xv_SHC) {
257872b676d7Smrg     *value = pSiS->HideHWCursor ? 1 : 0;
257972b676d7Smrg  } else if(attribute == pSiS->xv_PMD) {
258072b676d7Smrg     *value = 0;
258172b676d7Smrg     if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
258272b676d7Smrg        switch(pSiS->SiS_Pr->UsePanelScaler) {
258372b676d7Smrg           case -1: *value |= 0x01; break;
258472b676d7Smrg           case 1:  *value |= 0x02; break;
258572b676d7Smrg        }
258672b676d7Smrg	if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
258772b676d7Smrg           switch(pSiS->SiS_Pr->CenterScreen) {
258872b676d7Smrg              case -1: *value |= 0x04; break;
258972b676d7Smrg              case 1:  *value |= 0x08; break;
259072b676d7Smrg           }
259172b676d7Smrg	}
259272b676d7Smrg     }
259372b676d7Smrg  } else {
259472b676d7Smrg     return BadMatch;
259572b676d7Smrg  }
259672b676d7Smrg
259772b676d7Smrg  return Success;
259872b676d7Smrg}
259972b676d7Smrg
260072b676d7Smrg#endif /* XV_SD_DEPRECATED */
260172b676d7Smrg
2602