/*
 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sub license,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <xf86str.h>
#include "savage_driver.h"
#include "savage_util.h"

static int SavageBiosUtil(ScrnInfoPtr pScrn,char *buf);
static int SavageDriverUtil(ScrnInfoPtr pScrn,char *buf);
static int SavageDeviceUtil(ScrnInfoPtr pScrn,char *buf);
static int SavagePanelUtil(ScrnInfoPtr pScrn,char *buf);
static int SavageTvUtil(ScrnInfoPtr pScrn,char *buf);
static int SavageGammaUtil(ScrnInfoPtr pScrn,char *buf);

int  SavageDoUtilCall(ScrnInfoPtr pScrn,char *buf)
{
    ulong pID;
    
    pID = *(ulong *)buf;
    *(ulong *)(buf+8) = 1;
    switch (pID) {
        case UT_XV_FUNC_BIOS:
            SavageBiosUtil(pScrn,buf);
            break;
        case UT_XV_FUNC_DRIVER:
            SavageDriverUtil(pScrn,buf);            
            break;
        case UT_XV_FUNC_DEVICE:
            SavageDeviceUtil(pScrn,buf);            
            break;
        case UT_XV_FUNC_PANEL:
            SavagePanelUtil(pScrn,buf);            
            break;
        case UT_XV_FUNC_TV:
            SavageTvUtil(pScrn,buf);            
            break;
        case UT_XV_FUNC_GAMMA:
            SavageGammaUtil(pScrn,buf);            
            break;
        default:
            /* do not support */
            *(ulong *)(buf+8) = 0x7fffffff;
            break;
    }
    
    return Success;
}

static int SavageBiosUtil(ScrnInfoPtr pScrn,char *buf)
{
    ulong sID,*inbuf,*outbuf;
    SavagePtr psav = SAVPTR(pScrn);
    int tmp;
    
    sID = *(ulong *)(buf + 4);
    inbuf = outbuf = (ulong *)(buf + 12);

    switch (sID) {
        case UT_XV_FUNC_BIOS_GetChipID:
            memcpy(outbuf,psav->ChipName,32);
            break;            
        case UT_XV_FUNC_BIOS_GetVersion:
            /*
             * bios version is gotten by extended bios call and
             * saved in psav->BiosVersion,the format is:
             *   bit_31: 1:Desktop BIOS,0:Laptor BIOS
             *   bit_30~24: core bios version
             *   bit_23~16: controller family number
             *   bit_15~8: major number
             *   bit_7~0: minor number
             * and the utility bios version  format is:AA.BB.CC.DD,means
             *   AA:controller family number,BB:Major number,CC:Minor Number,DD:Desktop/Laptor
             */ 
            tmp = psav->BiosVersion;
            snprintf((char *)outbuf,12,"%02d.%02d.%02d.%02d",
                     (tmp>>16)&0xff,(tmp>>8)&0xff,tmp&0xff,tmp>>31);
            outbuf[11] = '\0';
            break;
        case UT_XV_FUNC_BIOS_GetVideoMemSizeMB:
            outbuf[0] = psav->videoRambytes >> 20;
            break;
        case UT_XV_FUNC_BIOS_GetDate:
        default:
            /* do not support */
            *(ulong *)(buf+8) = 0x7fffffff;
            break;
    }

    return Success;
}

static int SavageDriverUtil(ScrnInfoPtr pScrn,char *buf)
{
    ulong sID,*relPtr,*inbuf,*outbuf;
    SavagePtr psav = SAVPTR(pScrn);
    
    sID = *(ulong *)(buf + 4);
    relPtr = (ulong *)(buf + 8);
    inbuf = outbuf = (ulong *)(buf + 12);

    switch (sID) {
        case UT_XV_FUNC_DRIVER_GetFileName:
            switch (inbuf[0]) {
                case DISPLAY_DRIVER:
                    snprintf((char *)outbuf,32,"savage_drv.o");
                    break;
                case VIDEO_CAPTURE_DRIVER:
                    snprintf((char *)outbuf,32,"savage_drv.o");
                    break;
                case HWOVERLAY_DRIVER:
                    snprintf((char *)outbuf,32,"savage_drv.o");
                    break;
                case HWMPEG2_DECODER:
                    snprintf((char *)outbuf,32,"XvMCSavage.so");
                    break;
                default:
                    /* do not support */
                    *(ulong *)(buf+8) = 0x7fffffff;
                    break;
            }
            break;
        case UT_XV_FUNC_DRIVER_GetFileVersion:
            switch (inbuf[0]) {
                case DISPLAY_DRIVER:
                case VIDEO_CAPTURE_DRIVER:
                case HWOVERLAY_DRIVER:
                case HWMPEG2_DECODER:
                    ((UTDRIVERFILEVERSION *)outbuf)->dwMajorNum = (psav->DrvVersion >> 24) & 0xff ;
                    ((UTDRIVERFILEVERSION *)outbuf)->dwMinorNum = (psav->DrvVersion >> 16) & 0xff;
                    ((UTDRIVERFILEVERSION *)outbuf)->dwReversionNum = psav->DrvVersion & 0xffff;
                    break;
                default:
                    /* do not support */
                    *(ulong *)(buf+8) = 0x7fffffff;
                    break;
            }
            break;
        default:
            /* do not support */
            *(ulong *)(buf+8) = 0x7fffffff;
            break;
    }

    return Success;
}

static int SavageDeviceUtil(ScrnInfoPtr pScrn,char *buf)
{
    ulong sID,*relPtr,*inbuf,*outbuf;
    SavagePtr psav = SAVPTR(pScrn);
    
    sID = *(ulong *)(buf + 4);
    relPtr = (ulong *)(buf + 8);
    inbuf = outbuf = (ulong *)(buf + 12);

    switch (sID) {
        case UT_XV_FUNC_DEVICE_GetSupportState:
            outbuf[0] = psav->DisplayOutSupport;
            break;
        case UT_XV_FUNC_DEVICE_GetConnectState:
            outbuf[0] = psav->DisplayOutsConnected;            
            break;
        case UT_XV_FUNC_DEVICE_GetActiveState:
            outbuf[0] = psav->DisplayOutsActive;                        
            break;
        case UT_XV_FUNC_DEVICE_GetSAMMState:
            outbuf[0] = psav->DualHead;
            break;
        case UT_XV_FUNC_DEVICE_SetActiveState:
            psav->DisplayOutsActive = outbuf[0];
            break;
        case UT_XV_FUNC_DEVICE_GetRotateState:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;            
        case UT_XV_FUNC_DEVICE_SetRotateState:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        default:
            /* do not support */
            *(ulong *)(buf+8) = 0x7fffffff;
            break;
    }

    return Success;
    
}

static int SavagePanelUtil(ScrnInfoPtr pScrn,char *buf)
{
    ulong sID,*relPtr,*inbuf,*outbuf;
    SavagePtr psav = SAVPTR(pScrn);
    
    sID = *(ulong *)(buf + 4);
    relPtr = (ulong *)(buf + 8);
    inbuf = outbuf = (ulong *)(buf + 12);

    switch (sID) {
        case UT_XV_FUNC_DEVICE_SetTargetPanel:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;            
        case UT_XV_FUNC_DEVICE_GetPanelInfo:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;            
        case UT_XV_FUNC_DEVICE_GetExpandState:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;            
        case UT_XV_FUNC_DEVICE_SetExpandState:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        default:
            /* do not support */
            *(ulong *)(buf+8) = 0x7fffffff;
            break;
    }

    return Success;

}

static int SavageTvUtil(ScrnInfoPtr pScrn,char *buf)
{
    ulong sID,*relPtr,*inbuf,*outbuf;
    SavagePtr psav = SAVPTR(pScrn);
    
    sID = *(ulong *)(buf + 4);
    relPtr = (ulong *)(buf + 8);
    inbuf = outbuf = (ulong *)(buf + 12);

    switch (sID) {
        case UT_XV_FUNC_TV_GetSupportStandardState:
            outbuf[0] = psav->TvInfo.TvStandardSupport;
            break;
        case UT_XV_FUNC_TV_GetStandard:
            outbuf[0] = psav->TvInfo.TvStandardInUse;
            break;
        case UT_XV_FUNC_TV_SetStandard:
            break;
        case UT_XV_FUNC_TV_GetSupportSignalTypeState:
            outbuf[0] = psav->TvInfo.TvSignalType;            
            break;
        case UT_XV_FUNC_TV_GetSignalType:
            outbuf[0] = psav->TvInfo.TvSignalType;
            break;
        case UT_XV_FUNC_TV_SetSignalType:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_XV_FUNC_TV_GetMaxViewSizeValue:
            ((UTXYVALUE *)outbuf)->dwX = psav->TvInfo.TvSizeX;
            ((UTXYVALUE *)outbuf)->dwY = psav->TvInfo.TvSizeY;            
            break;
        case UT_XV_FUNC_TV_GetViewSizeValue:
            ((UTXYVALUE *)outbuf)->dwX = psav->TvInfo.TvSizeX;
            ((UTXYVALUE *)outbuf)->dwY = psav->TvInfo.TvSizeY;            
            break;
        case UT_XV_FUNC_TV_SetViewSizeValue:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_XV_FUNC_TV_GetMaxViewPositionValue:
            ((UTXYVALUE *)outbuf)->dwX = psav->TvInfo.TvSizeX;
            ((UTXYVALUE *)outbuf)->dwY = psav->TvInfo.TvSizeY;            
            break;
        case UT_XV_FUNC_TV_GetViewPositionValue:
            ((UTXYVALUE *)outbuf)->dwX = psav->TvInfo.TvSizeX;
            ((UTXYVALUE *)outbuf)->dwY = psav->TvInfo.TvSizeY;            
            break;
        case UT_XV_FUNC_TV_SetViewPositionValue:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_XV_FUNC_TV_GetSupportTuningState:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_XV_FUNC_TV_GetTuningItemMaxValue:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_XV_FUNC_TV_GetTuningItemValue:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_XV_FUNC_TV_SetTuningItemValue:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_XV_FUNC_TV_GetSupportSettingState:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_XV_FUNC_TV_GetSettingItemState:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_XV_FUNC_TV_SetSettingItemState:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        default:
            /* do not support */
            *(ulong *)(buf+8) = 0x7fffffff;
            break;
    }
    
    return Success;
    
}

static int SavageGammaUtil(ScrnInfoPtr pScrn,char *buf)
{
    ulong sID,*relPtr,*inbuf,*outbuf;
    SavagePtr psav = SAVPTR(pScrn);
    
    sID = *(ulong *)(buf + 4);
    relPtr = (ulong *)(buf + 8);
    inbuf = outbuf = (ulong *)(buf + 12);

    switch (sID) {
        case UT_ESC_FUNC_GAMMA_GetDeviceSupportState:
            *(ulong *)(buf+8) = 0x7fffffff;            
            break;
        case UT_ESC_FUNC_GAMMA_GetLookUpTable:
            *(ulong *)(buf+8) = 0x7fffffff;            
		    break;
        case UT_ESC_FUNC_GAMMA_SetLookUpTable:
            *(ulong *)(buf+8) = 0x7fffffff;            
		    break;
        default:
            /* do not support */
            *(ulong *)(buf+8) = 0x7fffffff;
            break;
    }

    return Success;
    
}
