/* $XFree86$ */
/* $XdotOrg$ */
/*
 * SiSUSB driver option evaluation
 *
 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1) Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2) Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3) The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Author:  	Thomas Winischhofer <thomas@winischhofer.net>
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "sisusb.h"

#include "xf86str.h"
#include "xf86Cursor.h"

typedef enum {
    OPTION_NOACCEL,
    OPTION_SW_CURSOR,
    OPTION_HW_CURSOR,
    OPTION_NOXVIDEO,
    OPTION_NOINTERNALMODES,
    OPTION_USERGBCURSOR,
    OPTION_RESTOREBYSET,
    OPTION_CRT1GAMMA,
    OPTION_XVGAMMA,
    OPTION_XVDEFCONTRAST,
    OPTION_XVDEFBRIGHTNESS,
    OPTION_XVDEFHUE,
    OPTION_XVDEFSATURATION,
    OPTION_XVDEFDISABLEGFX,
    OPTION_XVDEFDISABLEGFXLR,
    OPTION_XVUSECHROMAKEY,
    OPTION_XVCHROMAMIN,
    OPTION_XVCHROMAMAX,
    OPTION_XVDISABLECOLORKEY,
    OPTION_XVINSIDECHROMAKEY,
    OPTION_XVYUVCHROMAKEY,
    OPTION_ENABLESISCTRL,
    OPTION_STOREDBRI,
    OPTION_NEWSTOREDBRI,
    OPTION_NEWSTOREDCON,
    OPTION_DISCONNTIMEOUT,
    OPTION_PSEUDO
} SISUSBOpts;

static const OptionInfoRec SISUSBOptions[] = {
    { OPTION_DISCONNTIMEOUT,           	"DisconnectTimeout",      OPTV_INTEGER,   {0}, FALSE },
    { OPTION_ENABLESISCTRL,		"EnableSiSCtrl",   	  OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_SW_CURSOR,         	"SWCursor",               OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_HW_CURSOR,         	"HWCursor",               OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_USERGBCURSOR, 		"UseColorHWCursor",	  OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_NOINTERNALMODES,   	"NoInternalModes",        OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_RESTOREBYSET,		"RestoreBySetMode", 	  OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_CRT1GAMMA,			"CRT1Gamma", 	  	  OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_STOREDBRI,			"GammaBrightness",  	  OPTV_STRING,    {0}, FALSE },
    { OPTION_STOREDBRI,			"StoredGammaBrightness",  OPTV_STRING,    {0}, FALSE },
    { OPTION_NEWSTOREDBRI,		"Brightness",		  OPTV_STRING,	  {0}, FALSE },
    { OPTION_NEWSTOREDBRI,		"NewGammaBrightness",	  OPTV_STRING,	  {0}, FALSE },
    { OPTION_NEWSTOREDCON,		"Contrast",		  OPTV_STRING,	  {0}, FALSE },
    { OPTION_NEWSTOREDCON,		"NewGammaContrast",	  OPTV_STRING,	  {0}, FALSE },
#ifdef SIS_GLOBAL_ENABLEXV
    { OPTION_NOXVIDEO,          	"NoXvideo",               OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_XVGAMMA,			"XvGamma", 	  	  OPTV_STRING,    {0}, FALSE },
    { OPTION_XVDEFCONTRAST,		"XvDefaultContrast", 	  OPTV_INTEGER,   {0}, FALSE },
    { OPTION_XVDEFBRIGHTNESS,		"XvDefaultBrightness", 	  OPTV_INTEGER,   {0}, FALSE },
    { OPTION_XVDEFHUE,			"XvDefaultHue", 	  OPTV_INTEGER,   {0}, FALSE },
    { OPTION_XVDEFSATURATION,		"XvDefaultSaturation", 	  OPTV_INTEGER,   {0}, FALSE },
    { OPTION_XVDEFDISABLEGFX,		"XvDefaultDisableGfx", 	  OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_XVDEFDISABLEGFXLR,		"XvDefaultDisableGfxLR",  OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_XVCHROMAMIN,		"XvChromaMin", 	  	  OPTV_INTEGER,   {0}, FALSE },
    { OPTION_XVCHROMAMAX,		"XvChromaMax", 	  	  OPTV_INTEGER,   {0}, FALSE },
    { OPTION_XVUSECHROMAKEY,		"XvUseChromaKey",         OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_XVINSIDECHROMAKEY,		"XvInsideChromaKey",      OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_XVYUVCHROMAKEY,		"XvYUVChromaKey",         OPTV_BOOLEAN,   {0}, FALSE },
    { OPTION_XVDISABLECOLORKEY,		"XvDisableColorKey",      OPTV_BOOLEAN,   {0}, FALSE },
#endif
    { -1,                       	NULL,                     OPTV_NONE,      {0}, FALSE }
};

static int
SiSUSB_FIFT(const OptionInfoRec *options, int token)
{
    /* Find index from token */
    int i = 0;
    while(options[i].token >= 0) {
       if(options[i].token == token) return i;
       i++;
    }
    return 0; /* Should not happen */
}

#ifdef SIS_GLOBAL_ENABLEXV
static void
SiSUSB_PrintIlRange(ScrnInfoPtr pScrn, int token, int min, int max, UChar showhex)
{
    SISUSBPtr pSiSUSB = SISUSBPTR(pScrn);
    static const char *ilparmd = "Invalid parameter for \"%s\". Valid range is %d - %d\n";
    static const char *ilparmh = "Invalid parameter for \"%s\". Valid range is 0x%x - 0x%x\n";

    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
        showhex ? ilparmh : ilparmd,
	pSiSUSB->Options[SiSUSB_FIFT(pSiSUSB->Options, token)].name, min, max);
}

static Bool
SiSUSB_StrIsBoolOff(char *strptr)
{
    if( (!xf86NameCmp(strptr,"off"))   ||
        (!xf86NameCmp(strptr,"false")) ||
        (!xf86NameCmp(strptr,"no"))    ||
        (!xf86NameCmp(strptr,"0")) ) return TRUE;
    return FALSE;
}

static Bool
SiSUSB_StrIsBoolOn(char *strptr)
{
    if( (!xf86NameCmp(strptr,"on"))   ||
        (!xf86NameCmp(strptr,"true")) ||
        (!xf86NameCmp(strptr,"yes"))  ||
        (!xf86NameCmp(strptr,"1")) ) return TRUE;
    return FALSE;
}
#endif

static Bool
SiSUSB_EvalOneOrThreeFloats(ScrnInfoPtr pScrn, int token, const char *myerror,
                         char *strptr, int *v1, int *v2, int *v3)
{
    SISUSBPtr pSiSUSB = SISUSBPTR(pScrn);
    float val1 = 0.0, val2 = 0.0, val3 = 0.0;
    Bool valid = FALSE;
    int result = sscanf(strptr, "%f %f %f", &val1, &val2, &val3);
    if(result == 1) {
       if((val1 >= 0.1) && (val1 <= 10.0)) {
          valid = TRUE;
  	  *v1 = *v2 = *v3 = (int)(val1 * 1000);
       }
    } else if(result == 3) {
       if((val1 >= 0.1) && (val1 <= 10.0) &&
	  (val2 >= 0.1) && (val2 <= 10.0) &&
	  (val3 >= 0.1) && (val3 <= 10.0)) {
	  valid = TRUE;
	  *v1 = (int)(val1 * 1000);
	  *v2 = (int)(val2 * 1000);
	  *v3 = (int)(val3 * 1000);
       }
    }
    if(!valid) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING, myerror,
                  pSiSUSB->Options[SiSUSB_FIFT(pSiSUSB->Options, token)].name);
    }
    return (valid);
}

static Bool
SiSUSB_EvalOneOrThreeFloats2(ScrnInfoPtr pScrn, int token, const char *myerror,
                         char *strptr, float *v1, float *v2, float *v3)
{
    SISUSBPtr pSiSUSB = SISUSBPTR(pScrn);
    float val1 = 0.0, val2 = 0.0, val3 = 0.0;
    Bool valid = FALSE;
    int result = sscanf(strptr, "%f %f %f", &val1, &val2, &val3);
    if(result == 1) {
       if((val1 >= -1.0) && (val1 <= 1.0)) {
	  valid = TRUE;
	  *v1 = *v2 = *v3 = val1;
       }
    } else if(result == 3) {
       if((val1 >= -1.0) && (val1 <= 1.0) &&
	  (val2 >= -1.0) && (val2 <= 1.0) &&
	  (val3 >= -1.0) && (val3 <= 1.0)) {
	  valid = TRUE;
	  *v1 = val1;
	  *v2 = val2;
	  *v3 = val3;
       }
    }
    if(!valid) {
       xf86DrvMsg(pScrn->scrnIndex, X_WARNING, myerror,
                  pSiSUSB->Options[SiSUSB_FIFT(pSiSUSB->Options, token)].name);
    }
    return (valid);
}

void
SiSUSBOptions(ScrnInfoPtr pScrn)
{
    SISUSBPtr      pSiSUSB = SISUSBPTR(pScrn);
    MessageType from;
    char        *strptr;
    int         ival;
    static const char *disabledstr= "disabled";
    static const char *enabledstr = "enabled";
#ifdef SIS_GLOBAL_ENABLEXV
    static const char *gammaopt   = "%s expects either a boolean, or 1 or 3 real numbers (0.1 - 10.0)\n";
#endif
    static const char *briopt     = "%s expects one or three real numbers (0.1 - 10.0)\n";
    static const char *newbriopt  = "%s expects one or three real numbers (-1.0 - 1.0)\n";
    Bool        val;

    /* Collect all of the relevant option flags (fill in pScrn->options) */
    xf86CollectOptions(pScrn, NULL);

    /* Process the options */
    if(!(pSiSUSB->Options = xalloc(sizeof(SISUSBOptions)))) return;

    memcpy(pSiSUSB->Options, SISUSBOptions, sizeof(SISUSBOptions));

    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSiSUSB->Options);

    /* Set defaults */

#ifdef SISVRAMQ
    /* TODO: Option (315 series VRAM command queue) */
    /* But beware: sisusbfb does not know about this!!! */
    pSiSUSB->cmdQueueSize = 512*1024;
#endif
    pSiSUSB->HWCursor = TRUE;

    pSiSUSB->NoAccel = TRUE;	/* ! */
    pSiSUSB->ShadowFB = TRUE;	/* ! */

    pSiSUSB->timeout = 0;

    pSiSUSB->VESA = -1;
#ifdef SIS_GLOBAL_ENABLEXV
    pSiSUSB->NoXvideo = FALSE;
#else
    pSiSUSB->NoXvideo = TRUE;
#endif
    pSiSUSB->maxxfbmem = 0;
    pSiSUSB->DSTN = FALSE;
    pSiSUSB->FSTN = FALSE;
    pSiSUSB->XvOnCRT2 = FALSE;
    pSiSUSB->noInternalModes = FALSE;
    pSiSUSB->restorebyset = TRUE;
    pSiSUSB->CRT1gamma = TRUE;
    pSiSUSB->CRT1gammaGiven = FALSE;

    pSiSUSB->XvGamma = FALSE;
    pSiSUSB->XvGammaGiven = FALSE;
    pSiSUSB->enablesisctrl = FALSE;
    pSiSUSB->XvDefBri = 10;
    pSiSUSB->XvDefCon = 2;
    pSiSUSB->XvDefHue = 0;
    pSiSUSB->XvDefSat = 0;
    pSiSUSB->XvDefDisableGfx = FALSE;
    pSiSUSB->XvDefDisableGfxLR = FALSE;
    pSiSUSB->XvUseChromaKey = FALSE;
    pSiSUSB->XvDisableColorKey = FALSE;
    pSiSUSB->XvInsideChromaKey = FALSE;
    pSiSUSB->XvYUVChromaKey = FALSE;
    pSiSUSB->XvChromaMin = 0x000101fe;
    pSiSUSB->XvChromaMax = 0x000101ff;
    pSiSUSB->XvGammaRed = pSiSUSB->XvGammaGreen = pSiSUSB->XvGammaBlue =
          pSiSUSB->XvGammaRedDef = pSiSUSB->XvGammaGreenDef = pSiSUSB->XvGammaBlueDef = 1000;
    pSiSUSB->GammaBriR = pSiSUSB->GammaBriG = pSiSUSB->GammaBriB = 1000;
    pSiSUSB->NewGammaBriR = pSiSUSB->NewGammaBriG = pSiSUSB->NewGammaBriB = 0.0;
    pSiSUSB->NewGammaConR = pSiSUSB->NewGammaConG = pSiSUSB->NewGammaConB = 0.0;

    pSiSUSB->HideHWCursor = FALSE;
    pSiSUSB->HWCursorIsVisible = FALSE;

#if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,99,0,0)
    pSiSUSB->OptUseColorCursor = 0;
#else
    pSiSUSB->OptUseColorCursor = 1;
#endif

    /* Collect the options */

    /* DisconnectTimeout
     *
     * 0 = forever, -1 = abort server immediately
     * otherwise: re-probe for n seconds
     *
     */
    from = X_DEFAULT;
    if(xf86GetOptValInteger(pSiSUSB->Options, OPTION_DISCONNTIMEOUT, &ival)) {
       if(ival < 0) pSiSUSB->timeout = -1;
       else pSiSUSB->timeout = (ival > 32768) ? 32768 : ival;
       from = X_CONFIG;
    }
    switch(pSiSUSB->timeout) {
    case -1:
       xf86DrvMsg(pScrn->scrnIndex, from,
		"Device disconnection will abort X server\n");
       break;
    case 0:
       xf86DrvMsg(pScrn->scrnIndex, from,
		"Device will be re-probed forever after disconnection\n");
       break;
    default:
       xf86DrvMsg(pScrn->scrnIndex, from,
		"Device will be re-probed for %d seconds after disconnection\n",
		pSiSUSB->timeout);
       break;
    }

    /* SWCursor, HWCursor
     * Chooses whether to use the hardware or software cursor
     */
    from = X_DEFAULT;
    if(xf86GetOptValBool(pSiSUSB->Options, OPTION_HW_CURSOR, &pSiSUSB->HWCursor)) {
       from = X_CONFIG;
    }
    if(xf86ReturnOptValBool(pSiSUSB->Options, OPTION_SW_CURSOR, FALSE)) {
       from = X_CONFIG;
       pSiSUSB->HWCursor = FALSE;
       pSiSUSB->OptUseColorCursor = 0;
    }
    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
                                pSiSUSB->HWCursor ? "HW" : "SW");

    /*
     * UseColorHWCursor
     * Enable/disable color hardware cursor
     *
     */
#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,99,0,0)
#ifdef ARGB_CURSOR
#ifdef SIS_ARGB_CURSOR
    if(pSiSUSB->HWCursor) {
       from = X_DEFAULT;
       if(xf86GetOptValBool(pSiSUSB->Options, OPTION_USERGBCURSOR, &pSiSUSB->OptUseColorCursor)) {
    	  from = X_CONFIG;
       }
       xf86DrvMsg(pScrn->scrnIndex, from, "Color HW cursor is %s\n",
                    pSiSUSB->OptUseColorCursor ? enabledstr : disabledstr);
    }
#endif
#endif
#endif

    /* RestoreBySetMode
     * Set this to force the driver to set the old mode instead of restoring
     * the register contents. This can be used to overcome problems with
     * LCD panels and video bridges.
     */
    if(xf86GetOptValBool(pSiSUSB->Options, OPTION_RESTOREBYSET, &val)) {
       pSiSUSB->restorebyset = val ? TRUE : FALSE;
    }

    /* EnableSiSCtrl */
    /* Allow sisctrl tool to change driver settings */
    from = X_DEFAULT;
    if(xf86GetOptValBool(pSiSUSB->Options, OPTION_ENABLESISCTRL, &val)) {
       if(val) pSiSUSB->enablesisctrl = TRUE;
       from = X_CONFIG;
    }
    xf86DrvMsg(pScrn->scrnIndex, from, "SiSCtrl utility interface is %s\n",
  	pSiSUSB->enablesisctrl ? enabledstr : disabledstr);


    /* CRT1Gamma - enable/disable gamma correction for CRT1
     */
    if(xf86GetOptValBool(pSiSUSB->Options, OPTION_CRT1GAMMA, &val)) {
       pSiSUSB->CRT1gamma = val;
       pSiSUSB->CRT1gammaGiven = TRUE;
    }

    /* NoInternalModes (300/315/330 series only)
     * Don't use that.
     */
    if(xf86GetOptValBool(pSiSUSB->Options, OPTION_NOINTERNALMODES, &pSiSUSB->noInternalModes)) {
       if(pSiSUSB->noInternalModes) {
	  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Usage of built-in modes is %s\n", disabledstr);
       }
    }

    /* NoXVideo
     * Set this to TRUE to disable Xv hardware video acceleration
     */
#ifdef SIS_GLOBAL_ENABLEXV
    if(!pSiSUSB->NoXvideo) {
       if(xf86ReturnOptValBool(pSiSUSB->Options, OPTION_NOXVIDEO, FALSE)) {
          pSiSUSB->NoXvideo = TRUE;
          xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "XVideo extension (Xv) disabled\n");
       }

       if(!pSiSUSB->NoXvideo) {

	  /* Some Xv properties' defaults can be set by options */
          if(xf86GetOptValInteger(pSiSUSB->Options, OPTION_XVDEFCONTRAST, &ival)) {
             if((ival >= 0) && (ival <= 7)) pSiSUSB->XvDefCon = ival;
             else SiSUSB_PrintIlRange(pScrn, OPTION_XVDEFCONTRAST, 0, 7, 0);
          }
          if(xf86GetOptValInteger(pSiSUSB->Options, OPTION_XVDEFBRIGHTNESS, &ival)) {
             if((ival >= -128) && (ival <= 127)) pSiSUSB->XvDefBri = ival;
             else SiSUSB_PrintIlRange(pScrn, OPTION_XVDEFBRIGHTNESS, -128, 127, 0);
          }

          if(xf86GetOptValInteger(pSiSUSB->Options, OPTION_XVDEFHUE, &ival)) {
             if((ival >= -8) && (ival <= 7)) pSiSUSB->XvDefHue = ival;
             else SiSUSB_PrintIlRange(pScrn, OPTION_XVDEFHUE, -8, 7, 0);
          }
          if(xf86GetOptValInteger(pSiSUSB->Options, OPTION_XVDEFSATURATION, &ival)) {
             if((ival >= -7) && (ival <= 7)) pSiSUSB->XvDefSat = ival;
             else SiSUSB_PrintIlRange(pScrn, OPTION_XVDEFSATURATION, -7, 7, 0);
          }

	  if(xf86GetOptValBool(pSiSUSB->Options, OPTION_XVDEFDISABLEGFX, &val)) {
	     if(val) pSiSUSB->XvDefDisableGfx = TRUE;
	     xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
	        "Graphics display will be %s during Xv usage\n",
		val ? disabledstr : enabledstr);
          }

	  if(xf86GetOptValBool(pSiSUSB->Options, OPTION_XVDEFDISABLEGFXLR, &val)) {
	     if(val) pSiSUSB->XvDefDisableGfxLR = TRUE;
	     xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
		   "Graphics display left/right of overlay will be %s during Xv usage\n",
		   val ? disabledstr : enabledstr);
          }
	  if(xf86GetOptValBool(pSiSUSB->Options, OPTION_XVDISABLECOLORKEY, &val)) {
	     if(val) pSiSUSB->XvDisableColorKey = TRUE;
	     xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
		   "Xv Color key is %s\n",
		   val ? disabledstr : enabledstr);
          }
	  if(xf86GetOptValBool(pSiSUSB->Options, OPTION_XVUSECHROMAKEY, &val)) {
	     xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
		   "Xv Chroma-keying is %s\n",
		   val ? enabledstr : disabledstr);
	     if(val) pSiSUSB->XvUseChromaKey = TRUE;
          }
	  if(xf86GetOptValBool(pSiSUSB->Options, OPTION_XVINSIDECHROMAKEY, &val)) {
	     xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
		   "Xv: Video is transparent if %s chroma key range\n",
		   val ? "inside" : "outside");
	     if(val) pSiSUSB->XvInsideChromaKey = TRUE;
          }
	  if(xf86GetOptValInteger(pSiSUSB->Options, OPTION_XVCHROMAMIN, &ival)) {
             if((ival >= 0) && (ival <= 0xffffff)) pSiSUSB->XvChromaMin = ival;
             else SiSUSB_PrintIlRange(pScrn, OPTION_XVCHROMAMIN, 0, 0xffffff, 1);
          }
	  if(xf86GetOptValInteger(pSiSUSB->Options, OPTION_XVCHROMAMAX, &ival)) {
             if((ival >= 0) && (ival <= 0xffffff)) pSiSUSB->XvChromaMax = ival;
             else SiSUSB_PrintIlRange(pScrn, OPTION_XVCHROMAMAX, 0, 0xffffff, 1);
          }

	  /* XvGamma - enable/disable gamma correction for Xv
	   * Supported for CRT1 only
           */
	  if((strptr = (char *)xf86GetOptValString(pSiSUSB->Options, OPTION_XVGAMMA))) {
             if(SiSUSB_StrIsBoolOff(strptr)) {
		pSiSUSB->XvGamma = FALSE;
		pSiSUSB->XvGammaGiven = TRUE;
	     } else if(SiSUSB_StrIsBoolOn(strptr)) {
	        pSiSUSB->XvGamma = pSiSUSB->XvGammaGiven = TRUE;
             } else {
		if(SiSUSB_EvalOneOrThreeFloats(pScrn, OPTION_XVGAMMA, gammaopt, strptr,
		   		&pSiSUSB->XvGammaRed, &pSiSUSB->XvGammaGreen, &pSiSUSB->XvGammaBlue)) {
		   pSiSUSB->XvGamma = pSiSUSB->XvGammaGiven = TRUE;
		   pSiSUSB->XvGammaRedDef = pSiSUSB->XvGammaRed;
		   pSiSUSB->XvGammaGreenDef = pSiSUSB->XvGammaGreen;
		   pSiSUSB->XvGammaBlue = pSiSUSB->XvGammaBlue;
		}
	     }
          }

       }
    }
#endif

    {
       Bool GotNewBri = FALSE;
       if((strptr = (char *)xf86GetOptValString(pSiSUSB->Options, OPTION_NEWSTOREDCON))) {
	  SiSUSB_EvalOneOrThreeFloats2(pScrn, OPTION_NEWSTOREDCON, newbriopt, strptr,
		&pSiSUSB->NewGammaConR, &pSiSUSB->NewGammaConG, &pSiSUSB->NewGammaConB);
	  GotNewBri = TRUE;
       }
       if((strptr = (char *)xf86GetOptValString(pSiSUSB->Options, OPTION_NEWSTOREDBRI))) {
	  SiSUSB_EvalOneOrThreeFloats2(pScrn, OPTION_NEWSTOREDBRI, newbriopt, strptr,
		&pSiSUSB->NewGammaBriR, &pSiSUSB->NewGammaBriG, &pSiSUSB->NewGammaBriB);
	  GotNewBri = TRUE;
       }
       if(!GotNewBri) {
          if((strptr = (char *)xf86GetOptValString(pSiSUSB->Options, OPTION_STOREDBRI))) {
             SiSUSB_EvalOneOrThreeFloats(pScrn, OPTION_STOREDBRI, briopt, strptr,
		  &pSiSUSB->GammaBriR, &pSiSUSB->GammaBriG, &pSiSUSB->GammaBriB);
	     pSiSUSB->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
	  }
       }
    }

}

const OptionInfoRec *
SISUSBAvailableOptions(int chipid, int busid)
{
    return SISUSBOptions;
}
