/*
 * 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.
 */


#ifndef SAVAGE_3D_REG_H
#define SAVAGE_3D_REG_H

#define VIDEO_MEM_ADR                   0x02
#define SYSTEM_MEM_ADR                  0x01
#define AGP_MEM_ADR                     0x03

/***********************************************************

  ----------- 3D ENGINE UNIT Registers -------------

  *********************************************************/

typedef union
{
    struct
    {
        unsigned reserved : 4;
        unsigned ofs      : 28;
    }ni;
    u_int32_t ui;
} savageRegZPixelOffset;

/* This reg exists only on Savage4. */
typedef union
{
    struct
    {
        unsigned cmpFunc     :  3;
        unsigned stencilEn   :  1;
        unsigned readMask    :  8;
        unsigned writeMask   :  8;
        unsigned failOp      :  3;
        unsigned passZfailOp :  3;
        unsigned passZpassOp :  3;
        unsigned reserved    :  3;
    }ni;
    u_int32_t ui;
} savageRegStencilCtrl;

/**************************
 Texture Registers
**************************/
/* The layout of this reg differs between Savage4 and Savage3D. */
typedef union
{
    struct
    {
        unsigned tex0Width  : 4;
        unsigned tex0Height : 4;
        unsigned tex0Fmt    : 4;
        unsigned tex1Width  : 4;
        unsigned tex1Height : 4;
        unsigned tex1Fmt    : 4;
        unsigned texBLoopEn : 1;
        unsigned tex0En     : 1;
        unsigned tex1En     : 1;
        unsigned orthProjEn : 1;
        unsigned reserved   : 1;
        unsigned palSize    : 2;
        unsigned newPal     : 1;
    }ni;
    u_int32_t ui;
} savageRegTexDescr_s4;
typedef union
{
    struct
    {
        unsigned texWidth  : 4;
        unsigned reserved1 : 4;
        unsigned texHeight : 4;
        unsigned reserved2 : 4;
	/* Savage3D supports only the first 8 texture formats defined in
	   enum TexFmt in savge_bci.h. */
        unsigned texFmt    : 3;
        unsigned palSize   : 2;
        unsigned reserved3 : 10;
        unsigned newPal    : 1;
    }ni;
    u_int32_t ui;
} savageRegTexDescr_s3d;

/* The layout of this reg is the same on Savage4 and Savage3D,
   but the Savage4 has two of them, Savage3D has only one. */
typedef union
{
    struct
    {
        unsigned inSysTex : 1;
        unsigned inAGPTex : 1;
        unsigned reserved : 1;
        unsigned addr     : 29;
    }ni;
    u_int32_t ui;
} savageRegTexAddr;

/* The layout of this reg is the same on Savage4 and Savage3D. */
typedef union
{
    struct
    {
        unsigned reserved : 3;
        unsigned addr     : 29;
    }ni;
    u_int32_t ui;
} savageRegTexPalAddr;

/* The layout of this reg on Savage4 and Savage3D are very similar. */
typedef union
{
    struct
    {
        unsigned xprClr0 : 16;
        unsigned xprClr1 : 16; /* this is reserved on Savage3D */
    }ni;
    u_int32_t ui;
} savageRegTexXprClr;   /* transparency color in RGB565 format*/

/* The layout of this reg differs between Savage4 and Savage3D.
 * Savage4 has two of them, Savage3D has only one. */
typedef union
{
    struct
    {
        unsigned filterMode         : 2;
        unsigned mipmapEnable       : 1;
        unsigned dBias              : 9;
        unsigned dMax               : 4;
        unsigned uMode              : 2;
        unsigned vMode              : 2;
        unsigned useDFraction       : 1;
        unsigned texXprEn           : 1;
        unsigned clrBlendAlphaSel   : 2;
        unsigned clrArg1CopyAlpha   : 1;
        unsigned clrArg2CopyAlpha   : 1;
        unsigned clrArg1Invert      : 1;
        unsigned clrArg2Invert      : 1;
        unsigned alphaBlendAlphaSel : 2;
        unsigned alphaArg1Invert    : 1;
        unsigned alphaArg2Invert    : 1;
    }ni;
    u_int32_t ui;
} savageRegTexCtrl_s4;
typedef union
{
    struct
    {
        unsigned filterMode    : 2;
        unsigned mipmapDisable : 1;
        unsigned dBias         : 9;
        unsigned uWrapEn       : 1;
        unsigned vWrapEn       : 1;
        unsigned wrapMode      : 2;
        unsigned texEn         : 1;
        unsigned useDFraction  : 1;
        unsigned reserved1     : 1;
	/* Color Compare Alpha Blend Control
           0 -  reduce dest alpha to 0 or 1
           1 - blend with destination
	   The Utah-Driver doesn't know how to use it and sets it to 0. */
        unsigned CCA           : 1;
        unsigned texXprEn      : 1;
        unsigned reserved2     : 11;
    }ni;
    u_int32_t ui;
} savageRegTexCtrl_s3d;

/* This reg exists only on Savage4. */
typedef union
{
    struct
    {
        unsigned colorArg1Sel    : 2;
        unsigned colorArg2Sel    : 3;
        unsigned colorInvAlphaEn : 1;
        unsigned colorInvArg2En  : 1;
        unsigned colorPremodSel  : 1;
        unsigned colorMod1Sel    : 1;
        unsigned colorMod2Sel    : 2;
        unsigned colorAddSel     : 2;
        unsigned colorDoBlend    : 1;
        unsigned colorDo2sCompl  : 1;
        unsigned colorAddBiasEn  : 1;
        unsigned alphaArg1Sel    : 2;
        unsigned alphaArg2Sel    : 3;
        unsigned alphaMod1Sel    : 1;
        unsigned alphaMod2Sel    : 2;
        unsigned alphaAdd0Sel    : 1;
        unsigned alphaDoBlend    : 1;
        unsigned alphaDo2sCompl  : 1;
        unsigned colorStageClamp : 1;
        unsigned alphaStageClamp : 1;
        unsigned colorDoDiffMul  : 1;
        unsigned LeftShiftVal    : 2;
    }ni;
    u_int32_t ui;
} savageRegTexBlendCtrl;

/* This reg exists only on Savage4. */
typedef union
{
    struct
    {
        unsigned blue  : 8;
        unsigned green : 8;
        unsigned red   : 8;
        unsigned alpha : 8;
    }ni;
    u_int32_t ui;
} savageRegTexBlendColor;

/********************************
 Tiled Surface Registers
**********************************/

typedef union
{
    struct
    {
        unsigned frmBufOffset : 13;
        unsigned reserved     : 12;
        unsigned widthInTile  : 6;
        unsigned bitPerPixel  : 1;
    }ni;
    u_int32_t ui;
} savageRegTiledSurface;

/********************************
 Draw/Shading Control Registers
**********************************/

/* This reg exists only on Savage4. */
typedef union
{
    struct
    {
        unsigned scissorXStart : 11;
        unsigned dPerfAccelEn  : 1;
        unsigned scissorYStart : 12;
        unsigned alphaRefVal   : 8;
    }ni;
    u_int32_t ui;
} savageRegDrawCtrl0;

/* This reg exists only on Savage4. */
typedef union
{
    struct
    {
        unsigned scissorXEnd      : 11;
        unsigned xyOffsetEn       :  1;
        unsigned scissorYEnd      : 12;
        unsigned ditherEn         :  1;
        unsigned nonNormTexCoord  :  1;
        unsigned cullMode         :  2;
        unsigned alphaTestCmpFunc :  3;
        unsigned alphaTestEn      :  1;
    }ni;
    u_int32_t ui;
} savageRegDrawCtrl1;

/* This reg exists only on Savage4. */
typedef union
{
    struct
    {
        unsigned dstAlphaMode        :  3;
        unsigned dstMinusSrc         :  1;
        unsigned srcAlphaMode        :  3;
        unsigned binaryFinalAlpha    :  1;
        unsigned dstAlphaModeHighBit :  1;
        unsigned srcAlphaModeHighBit :  1;
        unsigned reserved1           : 15;
        unsigned wrZafterAlphaTst    :  1;
        unsigned drawUpdateEn        :  1;
        unsigned zUpdateEn           :  1;
        unsigned flatShadeEn         :  1;
        unsigned specShadeEn         :  1;
        unsigned flushPdDestWrites   :  1;
        unsigned flushPdZbufWrites   :  1;
    }ni;
    u_int32_t ui;
} savageRegDrawLocalCtrl;

/* This reg exists only on Savage3D. */
typedef union
{
    struct
    {
        unsigned ditherEn          : 1;
        unsigned xyOffsetEn        : 1;
        unsigned cullMode          : 2;
        unsigned vertexCountReset  : 1;
        unsigned flatShadeEn       : 1;
        unsigned specShadeEn       : 1;
        unsigned dstAlphaMode      : 3;
        unsigned srcAlphaMode      : 3;
        unsigned reserved1         : 1;
        unsigned alphaTestCmpFunc  : 3;
        unsigned alphaTestEn       : 1;
        unsigned alphaRefVal       : 8;
        unsigned texBlendCtrl      : 3;
        unsigned flushPdDestWrites : 1;
        unsigned flushPdZbufWrites : 1;
	/* havn't found an equivalent for Savage4. Utah-driver sets it to 0. */
        unsigned interpMode        : 1;
    }ni;
    u_int32_t ui;
} savageRegDrawCtrl;

#define SAVAGETBC_DECAL_S3D                     0
#define SAVAGETBC_MODULATE_S3D                  1
#define SAVAGETBC_DECALALPHA_S3D                2
#define SAVAGETBC_MODULATEALPHA_S3D             3
#define SAVAGETBC_4_S3D                         4
#define SAVAGETBC_5_S3D                         5
#define SAVAGETBC_COPY_S3D                      6
#define SAVAGETBC_7_S3D                         7

/* This reg exists only on Savage3D. */
typedef union
{
    struct
    {
        unsigned scissorXStart : 11;
	unsigned reserved1     : 5;
        unsigned scissorYStart : 11;
	unsigned reserved2     : 5;
    } ni;
    u_int32_t ui;
} savageRegScissorsStart;

/* This reg exists only on Savage3D. */
typedef union
{
    struct
    {
        unsigned scissorXEnd : 11;
	unsigned reserved1   : 5;
        unsigned scissorYEnd : 11;
	unsigned reserved2   : 5;
    } ni;
    u_int32_t ui;
} savageRegScissorsEnd;

/********************************
 Address Registers
**********************************/

/* I havn't found a Savage3D equivalent of this reg in the Utah-driver. 
 * But Tim Roberts claims that the Savage3D supports DMA vertex and
 * command buffers. */
typedef union
{
    struct
    {
        unsigned isSys    : 1;
        unsigned isAGP    : 1;
        unsigned reserved : 1;
        unsigned addr     : 29; /*quad word aligned*/
    }ni;
    u_int32_t ui;
} savageRegVertBufAddr;

/* I havn't found a Savage3D equivalent of this reg in the Utah-driver. 
 * But Tim Roberts claims that the Savage3D supports DMA vertex and
 * command buffers. */
typedef union
{
    struct
    {
        unsigned isSys    : 1;
        unsigned isAGP    : 1;
        unsigned reserved : 1;
        unsigned addr     : 29; /*4-quad word aligned*/
    }ni;
    u_int32_t ui;
} savageRegDMABufAddr;

/********************************
 H/W Debug Registers
**********************************/
/* The layout of this reg is the same on Savage4 and Savage3D. */
typedef union
{
    struct
    {
        unsigned y01        : 1;
        unsigned y12        : 1;
        unsigned y20        : 1;
        unsigned u01        : 1;
        unsigned u12        : 1;
        unsigned u20        : 1;
        unsigned v01        : 1;
        unsigned v12        : 1;
        unsigned v20        : 1;
        unsigned cullEn     : 1;
        unsigned cullOrient : 1;
        unsigned loadNewTex : 1;
        unsigned loadNewPal : 1;
        unsigned doDSetup   : 1;
        unsigned reserved   : 17;
        unsigned kickOff    : 1;
    }ni;
    u_int32_t ui;
} savageRegFlag;

/********************************
 Z Buffer Registers -- Global
**********************************/

/* The layout of this reg differs between Savage4 and Savage3D. */
typedef union
{
    struct
    {
        unsigned zCmpFunc      : 3;
        unsigned reserved1     : 2;
        unsigned zBufEn        : 1;
        unsigned reserved2     : 1;
        unsigned zExpOffset    : 8;
        unsigned reserved3     : 1;
        unsigned stencilRefVal : 8;
        unsigned autoZEnable   : 1;
        unsigned frameID       : 1;
        unsigned reserved4     : 4;
        unsigned floatZEn      : 1;
        unsigned wToZEn        : 1;
    }ni;
    u_int32_t ui;
} savageRegZBufCtrl_s4;
typedef union
{
    struct {
        unsigned zCmpFunc         : 3;
        unsigned drawUpdateEn     : 1;
        unsigned zUpdateEn        : 1;
        unsigned zBufEn           : 1;

        /**
	 * We suspect that, in conjunction with
	 * \c savageRegZBufOffset::zDepthSelect, these 2 bits are actually
	 * \c stencilUpdateEn and \c stencilBufEn.  If not, then some of
	 * the bits in \c reserved2 may fulfill that purpose.
	 */
        unsigned reserved1        : 2;

        unsigned zExpOffset       : 8;
        unsigned wrZafterAlphaTst : 1;
        unsigned reserved2        : 15;
    }ni;
    u_int32_t ui;
} savageRegZBufCtrl_s3d;

/* The layout of this reg on Savage4 and Savage3D is very similar. */
typedef union
{
    struct
    {
	/* In the Utah-Driver the offset is defined as 13-bit, 2k-aligned. */
        unsigned offset           : 14;
        unsigned reserved         : 11; /* 12-bits in Utah-driver */
        unsigned zBufWidthInTiles : 6;
       
        /**
	 * 0 selects 16-bit depth buffer.  On Savage4 hardware, 1 selects
	 * 24-bit depth buffer (with 8-bits for stencil).  Though it has never
	 * been tried, we suspect that on Savage3D hardware, 1 selects 15-bit
	 * depth buffer (with 1-bit for stencil).
	 */
        unsigned zDepthSelect     : 1;
    }ni;
    u_int32_t ui;
} savageRegZBufOffset;

/* The layout of this reg is the same on Savage4 and Savage3D. */
typedef union
{
    struct
    {
        unsigned rLow      : 6;
        unsigned reserved1 : 2;
        unsigned rHigh     : 6;
        unsigned reserved2 : 2;
        unsigned wLow      : 6;
        unsigned reserved3 : 2;
        unsigned wHigh     : 6;
        unsigned reserved4 : 2;
    }ni;
    u_int32_t ui;
} savageRegZWatermarks;

/********************************
 Fog Registers -- Global
**********************************/
/* The layout of this reg is the same on Savage4 and Savage3D. */
typedef union
{
    struct
    {
        unsigned fogClr      : 24;
        unsigned expShift    : 3;
        unsigned reserved    : 1;
        unsigned fogEn       : 1;
        unsigned fogMode     : 1;
        unsigned fogEndShift : 2;
    }ni;
    u_int32_t ui;
} savageRegFogCtrl;

/*not in spec, but tempo for pp and driver*/
typedef union
{
    struct
    {
        unsigned fogDensity : 16;
        unsigned fogStart   : 16;
    }ni;
    u_int32_t ui;
} savageRegFogParam;

/**************************************
 Destination Buffer Registers -- Global
***************************************/

/* The layout of this reg on Savage4 and Savage3D are very similar. */
typedef union
{
    struct
    {
        unsigned dstWidthInTile :  7;
        unsigned reserved       :  1;
	/* In the Utah-Driver the offset is defined as 13-bit, 2k-aligned. */
        unsigned offset         : 14;
        unsigned reserved1      :  7;
	/* antiAliasMode does not exist in the Utah-driver. But it includes the
	 * high bit of this in the destPixFmt. However, only values 0 and 2
	 * are used as dstPixFmt, so antiAliasMode is effectively always 0
	 * in the Utah-driver. In other words, treat as reserved on Savage3D.*/
        unsigned antiAliasMode  :  2;
        unsigned dstPixFmt      :  1;
    }ni;
    u_int32_t ui;
} savageRegDestCtrl;

/* The layout of this reg on Savage4 and Savage3D are very similar. */
typedef union
{
    struct
    {
        unsigned destReadLow   : 6;
        unsigned destReadHigh  : 6;
        unsigned destWriteLow  : 6;
        unsigned destWriteHigh : 6;
        unsigned texRead       : 4;
        unsigned reserved4     : 2;
	/* The Utah-driver calls this pixel FIFO length:
	 * 00 - 240, 01 - 180, 10 - 120, 11 - 60
	 * However, it is not used in either driver. */
        unsigned destFlush     : 2;
    }ni;
    u_int32_t ui;
} savageRegDestTexWatermarks;

/* Savage4/Twister/ProSavage register BCI addresses */
#define SAVAGE_DRAWLOCALCTRL_S4       0x1e
#define SAVAGE_TEXPALADDR_S4          0x1f
#define SAVAGE_TEXCTRL0_S4            0x20
#define SAVAGE_TEXCTRL1_S4            0x21
#define SAVAGE_TEXADDR0_S4            0x22
#define SAVAGE_TEXADDR1_S4            0x23
#define SAVAGE_TEXBLEND0_S4           0x24
#define SAVAGE_TEXBLEND1_S4           0x25
#define SAVAGE_TEXXPRCLR_S4           0x26 /* never used */
#define SAVAGE_TEXDESCR_S4            0x27
#define SAVAGE_FOGTABLE_S4            0x28
#define SAVAGE_FOGCTRL_S4             0x30
#define SAVAGE_STENCILCTRL_S4         0x31
#define SAVAGE_ZBUFCTRL_S4            0x32
#define SAVAGE_ZBUFOFF_S4             0x33
#define SAVAGE_DESTCTRL_S4            0x34
#define SAVAGE_DRAWCTRLGLOBAL0_S4     0x35
#define SAVAGE_DRAWCTRLGLOBAL1_S4     0x36
#define SAVAGE_ZWATERMARK_S4          0x37
#define SAVAGE_DESTTEXRWWATERMARK_S4  0x38
#define SAVAGE_TEXBLENDCOLOR_S4       0x39
/* Savage3D/MX/IC register BCI addresses */
#define SAVAGE_TEXPALADDR_S3D         0x18
#define SAVAGE_TEXXPRCLR_S3D          0x19 /* never used */
#define SAVAGE_TEXADDR_S3D            0x1A
#define SAVAGE_TEXDESCR_S3D           0x1B
#define SAVAGE_TEXCTRL_S3D            0x1C
#define SAVAGE_FOGTABLE_S3D           0x20
#define SAVAGE_FOGCTRL_S3D            0x30
#define SAVAGE_DRAWCTRL_S3D           0x31
#define SAVAGE_ZBUFCTRL_S3D           0x32
#define SAVAGE_ZBUFOFF_S3D            0x33
#define SAVAGE_DESTCTRL_S3D           0x34
#define SAVAGE_SCSTART_S3D            0x35
#define SAVAGE_SCEND_S3D              0x36
#define SAVAGE_ZWATERMARK_S3D         0x37 
#define SAVAGE_DESTTEXRWWATERMARK_S3D 0x38

#define SAVAGE_FIRST_REG 0x18
#define SAVAGE_NR_REGS   34
typedef struct savage_registers_s4_t {
    u_int32_t                   unused1[6];        /* 0x18-0x1d */
    savageRegDrawLocalCtrl     drawLocalCtrl;     /* 0x1e */
    savageRegTexPalAddr        texPalAddr;        /* 0x1f */
    savageRegTexCtrl_s4        texCtrl[2];        /* 0x20, 0x21 */
    savageRegTexAddr           texAddr[2];        /* 0x22, 0x23 */
    savageRegTexBlendCtrl      texBlendCtrl[2];   /* 0x24, 0x25 */
    savageRegTexXprClr         texXprClr;         /* 0x26 */
    savageRegTexDescr_s4       texDescr;          /* 0x27 */
    u_int8_t                   fogTable[32];      /* 0x28-0x2f (8dwords) */
    savageRegFogCtrl           fogCtrl;           /* 0x30 */
    savageRegStencilCtrl       stencilCtrl;       /* 0x31 */
    savageRegZBufCtrl_s4       zBufCtrl;          /* 0x32 */
    savageRegZBufOffset        zBufOffset;        /* 0x33 */
    savageRegDestCtrl          destCtrl;          /* 0x34 */
    savageRegDrawCtrl0         drawCtrl0;         /* 0x35 */
    savageRegDrawCtrl1         drawCtrl1;         /* 0x36 */
    savageRegZWatermarks       zWatermarks;       /* 0x37 */
    savageRegDestTexWatermarks destTexWatermarks; /* 0x38 */
    savageRegTexBlendColor     texBlendColor;     /* 0x39 */
} savageRegistersS4;
typedef struct savage_registers_s3d_t {
    savageRegTexPalAddr        texPalAddr;        /* 0x18 */
    savageRegTexXprClr         texXprClr;         /* 0x19 */
    savageRegTexAddr           texAddr;           /* 0x1a */
    savageRegTexDescr_s3d      texDescr;          /* 0x1b */
    savageRegTexCtrl_s3d       texCtrl;           /* 0x1c */
    u_int32_t                  unused1[3];        /* 0x1d-0x1f */
    u_int8_t                   fogTable[64];      /* 0x20-0x2f (16dwords) */
    savageRegFogCtrl           fogCtrl;           /* 0x30 */
    savageRegDrawCtrl          drawCtrl;          /* 0x31 */
    savageRegZBufCtrl_s3d      zBufCtrl;          /* 0x32 */
    savageRegZBufOffset        zBufOffset;        /* 0x33 */
    savageRegDestCtrl          destCtrl;          /* 0x34 */
    savageRegScissorsStart     scissorsStart;     /* 0x35 */
    savageRegScissorsEnd       scissorsEnd;       /* 0x36 */
    savageRegZWatermarks       zWatermarks;       /* 0x37 */
    savageRegDestTexWatermarks destTexWatermarks; /* 0x38 */
    u_int32_t                   unused2;           /* 0x39 */
} savageRegistersS3D;
typedef union savage_registers_t {
    savageRegistersS4  s4;
    savageRegistersS3D s3d;
    u_int32_t           ui[SAVAGE_NR_REGS];
} savageRegisters;


#define DV_PF_555           (0x1<<8)
#define DV_PF_565           (0x2<<8)
#define DV_PF_8888          (0x4<<8)

#define SAVAGEPACKCOLORA4L4(l,a) \
  ((l >> 4) | (a & 0xf0))

#define SAVAGEPACKCOLOR4444(r,g,b,a) \
  ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))

#define SAVAGEPACKCOLOR1555(r,g,b,a) \
  ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
    ((a) ? 0x8000 : 0))

#define SAVAGEPACKCOLOR8888(r,g,b,a) \
  (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))

#define SAVAGEPACKCOLOR565(r,g,b) \
  ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))


#endif