sis_vga.c 64 KB
Newer Older
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1
/*
2
 * Mode setup and basic video bridge detection
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
3
 *
Thomas Winischhofer's avatar
Thomas Winischhofer committed
4
 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
5
 *
6 7
 * The SISInit() function for old series (except TV and FIFO calculation)
 * was previously based on code which was Copyright (C) 1998,1999 by Alan
8
 * Hourihane, Wigan, England. However, the code has been rewritten entirely
9
 * and is - it its current representation - not covered by this old copyright.
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
10
 *
11 12 13 14 15 16 17 18 19 20
 * 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.
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 24 25 26 27 28 29 30 31
 * 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.
32
 *
33
 * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
34
 *
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
35 36
 */

37 38 39 40
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
41
#include "sis.h"
Thomas Winischhofer's avatar
Thomas Winischhofer committed
42 43 44 45 46 47
#define SIS_NEED_inSISREG
#define SIS_NEED_outSISREG
#define SIS_NEED_inSISIDXREG
#define SIS_NEED_outSISIDXREG
#define SIS_NEED_orSISIDXREG
#define SIS_NEED_andSISIDXREG
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
48 49 50 51 52
#include "sis_regs.h"
#include "sis_dac.h"

static Bool  SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
static Bool  SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode);
53 54 55 56 57
static int   SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl);
static void  SISSense6326(ScrnInfoPtr pScrn);
static void  SiS6326TVDelay(ScrnInfoPtr pScrn, int delay);
extern void  SISSense30x(ScrnInfoPtr pScrn, Bool quiet);
extern void  SISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet);
58

59 60 61 62 63 64 65 66
/* Our very own vgaHW functions */
void SiSVGASave(ScrnInfoPtr pScrn, SISRegPtr save, int flags);
void SiSVGARestore(ScrnInfoPtr pScrn, SISRegPtr restore, int flags);
void SiSVGASaveFonts(ScrnInfoPtr pScrn);
void SiSVGARestoreFonts(ScrnInfoPtr pScrn);
void SISVGALock(SISPtr pSiS);
void SiSVGAUnlock(SISPtr pSiS);
void SiSVGAProtect(ScrnInfoPtr pScrn, Bool on);
Thomas Winischhofer's avatar
Thomas Winischhofer committed
67
#ifdef SIS_PC_PLATFORM
68 69
Bool SiSVGAMapMem(ScrnInfoPtr pScrn);
void SiSVGAUnmapMem(ScrnInfoPtr pScrn);
Thomas Winischhofer's avatar
Thomas Winischhofer committed
70
#endif
71
Bool SiSVGASaveScreen(ScreenPtr pScreen, int mode);
Thomas Winischhofer's avatar
Thomas Winischhofer committed
72
static Bool SiSVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode, int fixsync);
73

74 75 76
const CARD8 SiS6326TVRegs1[14] = {
     0x00,0x01,0x02,0x03,0x04,0x11,0x12,0x13,0x21,0x26,0x27,0x3a,0x3c,0x43
};
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
77 78 79 80 81 82

const CARD8 SiS6326TVRegs1_NTSC[6][14] = {
    {0x81,0x3f,0x49,0x1b,0xa9,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60},
    {0x81,0x3f,0x49,0x1d,0xa0,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60},
    {0x81,0x45,0x24,0x8e,0x26,0x0b,0x00,0x09,0x02,0xfe,0x00,0x09,0x51,0x60},
    {0x81,0x45,0x24,0x8e,0x26,0x07,0x00,0x29,0x04,0x30,0x10,0x3b,0x61,0x60},
83
    {0x81,0x3f,0x24,0x8e,0x26,0x09,0x00,0x09,0x02,0x30,0x10,0x3b,0x51,0x60},  /* 640x400, 640x480 */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
    {0x83,0x5d,0x21,0xbe,0x75,0x03,0x00,0x09,0x08,0x42,0x10,0x4d,0x61,0x79}   /* 640x480u */
};

const CARD8 SiS6326TVRegs2_NTSC[6][54] = {
    {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
     0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
     0xFC, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40,
     0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10,
     0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0},
    {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
     0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
     0xFF, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40,
     0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10,
     0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0},
    {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
     0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
     0xFF, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73,
     0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30,
     0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0},
    {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
     0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
     0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73,
     0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30,
     0xBA, 0xDA, 0x52, 0x00, 0x02, 0xF5, 0x53, 0xF7, 0x02, 0xA0},
    {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,
     0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
     0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73,
     0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30,
     0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0},
    {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C,  /* 640x480u */
     0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94,
     0xDC, 0xDF, 0x94, 0xAF, 0x95, 0x06, 0xDD, 0x07, 0x5F, 0x30, 0x7E,
     0x86, 0x00, 0x4C, 0xA4, 0x30, 0xE3, 0x3B, 0x62, 0x54, 0xAC, 0x30,
     0xEB, 0x43, 0x62, 0x48, 0x34, 0x3D, 0x63, 0x29, 0x03, 0xA0}
};

const CARD8 SiS6326TVRegs1_PAL[6][14] = {
    {0x81,0x2d,0xc8,0x07,0xb2,0x0b,0x00,0x09,0x02,0xed,0x00,0xf8,0x30,0x40},
    {0x80,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40},
123 124
    {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40},  /* 640x480 */
    {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0x8f,0x10,0x9a,0x71,0x40},  /* 800x600 */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    {0x83,0x63,0xa1,0x7a,0xa3,0x0a,0x00,0x09,0x02,0xb5,0x11,0xc0,0x81,0x59},  /* 800x600u */
    {0x81,0x63,0xa4,0x03,0xd9,0x01,0x00,0x09,0x10,0x9f,0x10,0xaa,0x71,0x59}   /* 720x540  */
};

const CARD8 SiS6326TVRegs2_PAL[6][54] = {
    {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,
     0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
     0xE5, 0xDF, 0x94, 0xEF, 0x5A, 0x03, 0x7F, 0x07, 0xFF, 0x10, 0x4E,
     0x56, 0x00, 0x2B, 0x23, 0x20, 0xB4, 0xAC, 0x31, 0x33, 0x2B, 0x20,
     0xBC, 0xB4, 0x31, 0x83, 0xE1, 0x78, 0x31, 0xD6, 0x01, 0xA0},
    {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,
     0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
     0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90,
     0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
     0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0},
140
    {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,  /* 640x480 */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
141 142 143 144
     0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
     0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90,
     0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
     0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0},
145
    {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,  /* 800x600 */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
     0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
     0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90,
     0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
     0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0},
    {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,  /* 800x600u */
     0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
     0xE5, 0xDF, 0x94, 0x7F, 0xBD, 0x08, 0x0E, 0x07, 0x47, 0x40, 0x9D,
     0xA5, 0x00, 0x54, 0x94, 0x40, 0xA4, 0xE4, 0x73, 0x5C, 0x9C, 0x40,
     0xAC, 0xEC, 0x73, 0x0B, 0x0E, 0x00, 0x84, 0x03, 0x04, 0xA0},
    {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D,  /* 720x540  */
     0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94,
     0xE5, 0xDF, 0x94, 0xDF, 0xB0, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x9D,
     0xA5, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40,
     0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0}
};

const CARD8 SiS6326CR[9][15] = {
     {0x79,0x63,0x64,0x1d,0x6a,0x93,0x00,0x6f,0xf0,0x58,0x8a,0x57,0x57,0x70,0x20},  /* PAL 800x600   */
     {0x79,0x4f,0x50,0x95,0x60,0x93,0x00,0x6f,0xba,0x14,0x86,0xdf,0xe0,0x30,0x00},  /* PAL 640x480   */
     {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xe9,0x8b,0xdf,0xe7,0x04,0x00},  /* NTSC 640x480  */
     {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xcb,0x8d,0x8f,0x96,0xe9,0x00},  /* NTSC 640x400  */
     {0x83,0x63,0x64,0x1f,0x6d,0x9b,0x00,0x6f,0xf0,0x48,0x0a,0x23,0x57,0x70,0x20},  /* PAL 800x600u  */
     {0x79,0x59,0x5b,0x1d,0x66,0x93,0x00,0x6f,0xf0,0x42,0x04,0x1b,0x40,0x70,0x20},  /* PAL 720x540   */
     {0x66,0x4f,0x51,0x0a,0x57,0x89,0x00,0x0b,0x3e,0xd9,0x0b,0xb6,0xe7,0x04,0x00},  /* NTSC 640x480u */
     {0xce,0x9f,0x9f,0x92,0xa4,0x16,0x00,0x28,0x5a,0x00,0x04,0xff,0xff,0x29,0x39},  /* 1280x1024-75  */
     {0x09,0xc7,0xc7,0x0d,0xd2,0x0a,0x01,0xe0,0x10,0xb0,0x04,0xaf,0xaf,0xe1,0x1f}   /* 1600x1200-60  */
};

/* Initialize a display mode on 5597/5598, 6326 and 530/620 */
static Bool
SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
178 179 180 181 182 183 184
    SISPtr       pSiS = SISPTR(pScrn);
    SISRegPtr    pReg = &pSiS->ModeReg;
    UChar        temp;
    int          mclk = pSiS->MemClock;
    int          clock = mode->Clock;
    int          width = mode->HDisplay;
    int          height = mode->VDisplay;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
185
    int          rate = (int)SiSCalcVRate(mode);
186 187 188 189
    int          buswidth = pSiS->BusWidth;
    unsigned int vclk[5];
    UShort       CRT_CPUthresholdLow, CRT_CPUthresholdHigh, CRT_ENGthreshold;
    double       a, b, c;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
190
    int          d, factor, offset, fixsync = 1;
191 192
    int          num, denum, div, sbit, scale;
    Bool	 sis6326tvmode, sis6326himode;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
193 194 195

    /* Save the registers for further processing */
    (*pSiS->SiSSave)(pScrn, pReg);
196

197
    /* Initialise the standard VGA registers */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
198 199 200 201 202
    if(!pSiS->UseVESA) {
       if(!SiSVGAInit(pScrn, mode, fixsync)) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "SISInit: SiSVGAInit() failed\n");
          return FALSE;
       }
203
    }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
204

205 206
    /* Determine if chosen mode is suitable for TV on the 6326
     * and if the mode is one of our special hi-res modes.
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
207 208 209 210
     */
    sis6326tvmode = FALSE;
    sis6326himode = FALSE;
    if(pSiS->Chipset == PCI_CHIP_SIS6326) {
211
       if(pSiS->SiS6326Flags & SIS6326_HASTV) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
212 213 214
	  if((pSiS->SiS6326Flags & SIS6326_TVDETECTED) &&
	     ((strcmp(mode->name, "PAL800x600") == 0)   ||	/* Special TV modes */
	      (strcmp(mode->name, "PAL800x600U") == 0)  ||
215
	      (strcmp(mode->name, "PAL720x540") == 0)   ||
Thomas Winischhofer's avatar
Thomas Winischhofer committed
216
	      (strcmp(mode->name, "PAL640x480") == 0)   ||
217 218 219 220
	      (strcmp(mode->name, "NTSC640x480") == 0)  ||
	      (strcmp(mode->name, "NTSC640x480U") == 0) ||
	      (strcmp(mode->name, "NTSC640x400") == 0))) {
	     sis6326tvmode = TRUE;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
221 222 223
	  } else {
	     pReg->sis6326tv[0x00] &= 0xfb;
	  }
224 225
       }
       if((strcmp(mode->name, "SIS1280x1024-75") == 0) ||	/* Special high-res modes */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
226
	  (strcmp(mode->name, "SIS1600x1200-60") == 0)) {
227 228
	  sis6326himode = TRUE;
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
229 230 231 232 233 234
    }

#ifdef UNLOCK_ALWAYS
    outSISIDXREG(SISSR, 0x05, 0x86);
#endif

235 236 237
    if(!pSiS->UseVESA) {
       pReg->sisRegs3C4[0x06] &= 0x01;
    }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
238

239
    /* set interlace */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
240
    if(!(mode->Flags & V_INTERLACE)) {
241
       offset = pSiS->CurrentLayout.displayWidth >> 3;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
242
    } else {
243 244
       offset = pSiS->CurrentLayout.displayWidth >> 2;
       if(!pSiS->UseVESA) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
245
	  pReg->sisRegs3C4[0x06] |= 0x20;
246
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
247 248 249
    }

    /* Enable Linear and Enhanced Gfx Mode */
250 251 252
    if(!pSiS->UseVESA) {
       pReg->sisRegs3C4[0x06] |= 0x82;
    }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
253 254

    /* Enable MMIO at PCI Register 14H (D[6:5]: 11) */
255 256 257 258 259 260
    if(pSiS->oldChipset >= OC_SIS5597) {
       pReg->sisRegs3C4[0x0B] |= 0x60;
    } else {
       pReg->sisRegs3C4[0x0B] |= 0x20;
       pReg->sisRegs3C4[0x0B] &= ~0x40;
    }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
261

262
    if(!pSiS->UseVESA) {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
263

264 265 266
       /* Enable 32bit mem access (D7), read-ahead cache (D5) */
       pReg->sisRegs3C4[0x0C] |= 0x80;
       if(pSiS->oldChipset > OC_SIS6225) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
267
	  pReg->sisRegs3C4[0x0C] |= 0x20;
268
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
269

270 271 272
       /* Some speed-up stuff */
       switch(pSiS->Chipset) {
       case PCI_CHIP_SIS5597:
Thomas Winischhofer's avatar
Thomas Winischhofer committed
273 274
	  /* enable host bus */
	  if(!pSiS->HostBus) {
275 276
	     pReg->sisRegs3C4[0x34] &= ~0x08;
	  } else {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
277
	    pReg->sisRegs3C4[0x34] |= 0x08;
278
	  }
Thomas Winischhofer's avatar
Thomas Winischhofer committed
279
	  /* fall through */
280 281
       case PCI_CHIP_SIS6326:
       case PCI_CHIP_SIS530:
Thomas Winischhofer's avatar
Thomas Winischhofer committed
282 283 284 285
	  /* Enable "dual segment register mode" (D2) and "i/o gating while
	   * write buffer is not empty" (D3)
	   */
	  pReg->sisRegs3C4[0x0B] |= 0x0C;
286 287 288 289
       }

       /* set colordepth */
       if(pSiS->Chipset == PCI_CHIP_SIS530) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
290
	  pReg->sisRegs3C4[0x09] &= 0x7F;
291 292
       }
       switch(pSiS->CurrentLayout.bitsPerPixel) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
293 294 295
	  case 8:
	     break;
	  case 16:
296 297
	     offset <<= 1;
	     if(pSiS->CurrentLayout.depth == 15)
Thomas Winischhofer's avatar
Thomas Winischhofer committed
298
		pReg->sisRegs3C4[0x06] |= 0x04;
299
	     else
Thomas Winischhofer's avatar
Thomas Winischhofer committed
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
		pReg->sisRegs3C4[0x06] |= 0x08;
	     break;
	  case 24:
	     offset += (offset << 1);
	     pReg->sisRegs3C4[0x06] |= 0x10;
	     pReg->sisRegs3C4[0x0B] |= 0x90;
	     break;
	  case 32:
	     if(pSiS->Chipset == PCI_CHIP_SIS530) {
		offset <<= 2;
		if(pSiS->oldChipset != OC_SIS620) {
		   pReg->sisRegs3C4[0x06] |= 0x10;
		}
		pReg->sisRegs3C4[0x0B] |= 0x90;
		pReg->sisRegs3C4[0x09] |= 0x80;
	     } else return FALSE;
	     break;
317
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
318 319 320 321
    }

    /* save screen pitch for acceleration functions */
    pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth *
Thomas Winischhofer's avatar
Thomas Winischhofer committed
322
			((pSiS->CurrentLayout.bitsPerPixel + 7) / 8);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
323

Thomas Winischhofer's avatar
Thomas Winischhofer committed
324 325 326
    /* Set accelerator dest color depth to 0 - not supported on 530/620 */
    pSiS->DstColor = 0;

327
    if(!pSiS->UseVESA) {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
328

329
       /* set linear framebuffer addresses */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
330 331 332 333 334 335 336
       switch(pScrn->videoRam) {
	  case 512:  temp = 0x00;  break;
	  case 1024: temp = 0x20;  break;
	  case 2048: temp = 0x40;  break;
	  case 4096: temp = 0x60;  break;
	  case 8192: temp = 0x80;  break;
	  default:   temp = 0x20;
337 338 339
       }
       pReg->sisRegs3C4[0x20] = (pSiS->FbAddress & 0x07F80000) >> 19;
       pReg->sisRegs3C4[0x21] = ((pSiS->FbAddress & 0xF8000000) >> 27) | temp;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
340

341
       /* Set screen offset */
342
       pReg->sisRegs3D4[0x13] = offset & 0xFF;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
343

344 345
       /* Set CR registers for our built-in TV and hi-res modes */
       if((sis6326tvmode) || (sis6326himode)) {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
346

347 348 349 350 351 352
	  int index,i;

	  /* We need our very private data for hi-res and TV modes */
	  if(sis6326himode) {
	     if(strcmp(mode->name, "SIS1280x1024-75") == 0)  index = 7;
	     else index = 8;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
353
	  } else {
354
	     if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
355 356 357 358 359 360 361 362 363 364 365 366 367 368
		switch(width) {
		case 800:
		   if((strcmp(mode->name, "PAL800x600U") == 0))
		      index = 4;
		   else
		      index = 0;
		   break;
		case 720:
		   index = 5;
		   break;
		case 640:
		default:
		   index = 1;
		}
369
	     } else {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
370 371 372 373 374 375 376 377 378 379 380
		switch(height) {
		case 400:
		   index = 3;
		   break;
		case 480:
		default:
		   if((strcmp(mode->name, "NTSC640x480U") == 0))
		      index = 6;
		   else
		      index = 2;
		}
381
	     }
Thomas Winischhofer's avatar
Thomas Winischhofer committed
382
	  }
383
	  for(i=0; i<=5; i++) {
384
	     pReg->sisRegs3D4[i] = SiS6326CR[index][i];
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
385
	  }
Thomas Winischhofer's avatar
Thomas Winischhofer committed
386
	  pReg->sisRegs3C4[0x12] = SiS6326CR[index][6];
387 388 389 390 391 392 393 394 395
	  pReg->sisRegs3D4[6] = SiS6326CR[index][7];
	  pReg->sisRegs3D4[7] = SiS6326CR[index][8];
	  pReg->sisRegs3D4[0x10] = SiS6326CR[index][9];
	  pReg->sisRegs3D4[0x11] = SiS6326CR[index][10];
	  pReg->sisRegs3D4[0x12] = SiS6326CR[index][11];
	  pReg->sisRegs3D4[0x15] = SiS6326CR[index][12];
	  pReg->sisRegs3D4[0x16] = SiS6326CR[index][13];
	  pReg->sisRegs3D4[9] &= ~0x20;
	  pReg->sisRegs3D4[9] |= (SiS6326CR[index][14] & 0x20);
396 397 398 399
	  pReg->sisRegs3C4[0x0A] = ((offset & 0xF00) >> 4) | (SiS6326CR[index][14] & 0x0f);

       } else {

Thomas Winischhofer's avatar
Thomas Winischhofer committed
400 401
	  /* Set extended vertical overflow register */
	  pReg->sisRegs3C4[0x0A] = (
Thomas Winischhofer's avatar
Thomas Winischhofer committed
402
	      ((offset                                & 0xF00) >>  4) |
Thomas Winischhofer's avatar
Thomas Winischhofer committed
403 404
	      (((mode->CrtcVTotal - 2)                & 0x400) >> 10) |
	      (((mode->CrtcVDisplay - 1)              & 0x400) >>  9) |
Thomas Winischhofer's avatar
Thomas Winischhofer committed
405
	      (((mode->CrtcVBlankStart - 1)           & 0x400) >>  8) |
Thomas Winischhofer's avatar
Thomas Winischhofer committed
406 407 408 409 410 411 412 413 414 415
	      (((mode->CrtcVSyncStart - fixsync)      & 0x400) >>  7));

	  /* Set extended horizontal overflow register */
	  pReg->sisRegs3C4[0x12] &= 0xE0;
	  pReg->sisRegs3C4[0x12] |= (
	      ((((mode->CrtcHTotal >> 3) - 5)          & 0x100) >> 8) |
	      ((((mode->CrtcHDisplay >> 3) - 1)        & 0x100) >> 7) |
	      ((((mode->CrtcHBlankStart >> 3) - 1)     & 0x100) >> 6) |
	      ((((mode->CrtcHSyncStart >> 3) - fixsync)& 0x100) >> 5) |
	      ((((mode->CrtcHBlankEnd >> 3) - 1)       & 0x40)  >> 2));
416
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
417

418 419
       /* enable (or disable) line compare */
       if(mode->CrtcVDisplay >= 1024)
Thomas Winischhofer's avatar
Thomas Winischhofer committed
420
	  pReg->sisRegs3C4[0x38] |= 0x04;
421
       else
Thomas Winischhofer's avatar
Thomas Winischhofer committed
422
	  pReg->sisRegs3C4[0x38] &= 0xFB;
423 424 425

       /* Enable (or disable) high speed DCLK (some 6326 and 530/620 only) */
       if( ( (pSiS->Chipset == PCI_CHIP_SIS6326) &&
Thomas Winischhofer's avatar
Thomas Winischhofer committed
426 427
	     ( (pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) ||
	       (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) ||
428
	       (pSiS->Flags & A6326REVAB) ) ) ||
Thomas Winischhofer's avatar
Thomas Winischhofer committed
429 430 431 432 433 434 435
	   (pSiS->oldChipset > OC_SIS6326) ) {
	 if( (pSiS->CurrentLayout.bitsPerPixel == 24) ||
	     (pSiS->CurrentLayout.bitsPerPixel == 32) ||
	     (mode->CrtcHDisplay >= 1280) )
	    pReg->sisRegs3C4[0x3E] |= 0x01;
	 else
	    pReg->sisRegs3C4[0x3E] &= 0xFE;
436
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
437

438 439
       /* We use the internal VCLK */
       pReg->sisRegs3C4[0x38] &= 0xFC;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
440

441
       /* Programmable Clock */
442
       pReg->sisRegs3C2 = inSISREG(SISMISCR) | 0x0C;
443

444
#if 0
445
       if(pSiS->oldChipset <= OC_SIS86202) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
446
	  /* TODO: Handle SR07 for clock selection */
447 448 449
	  /* 86C201 does not even have a programmable clock... */
	  /* pReg->sisRegs3C4[0x07] &= 0x??; */
       }
450
#endif
451 452 453 454

       /* Set VCLK */
       if((sis6326tvmode) || (sis6326himode)) {

Thomas Winischhofer's avatar
Thomas Winischhofer committed
455 456 457 458 459
	  /* For our built-in modes, the calculation is not suitable */
	  if(sis6326himode) {
	     if((strcmp(mode->name, "SIS1280x1024-75") == 0)) {
		pReg->sisRegs3C4[0x2A] = 0x5d;	/* 1280x1024-75 */
		pReg->sisRegs3C4[0x2B] = 0xa4;
460
             } else {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
461 462 463
		pReg->sisRegs3C4[0x2A] = 0x59;	/* 1600x1200-60 */
		pReg->sisRegs3C4[0x2B] = 0xa3;
	     }
464
	     pReg->sisRegs3C4[0x13] &= ~0x40;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
465
	  } else {
466
             if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
467 468 469 470 471 472 473 474 475
		/* PAL: 31.500 Mhz */
		if((strcmp(mode->name, "PAL800x600U") == 0)) {
		   pReg->sisRegs3C4[0x2A] = 0x46;
		   pReg->sisRegs3C4[0x2B] = 0x49;
		} else {
		   pReg->sisRegs3C4[0x2A] = 0xab;
		   pReg->sisRegs3C4[0x2B] = 0xe9;
		}
		pReg->sisRegs3C4[0x13] &= ~0x40;
476
	     } else {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
477 478 479 480 481 482 483 484 485
		/* NTSC: 27.000 Mhz */
		if((strcmp(mode->name, "NTSC640x480U") == 0)) {
		   pReg->sisRegs3C4[0x2A] = 0x5a;
		   pReg->sisRegs3C4[0x2B] = 0x65;
		} else {
		   pReg->sisRegs3C4[0x2A] = 0x29;
		   pReg->sisRegs3C4[0x2B] = 0xe2;
		}
		pReg->sisRegs3C4[0x13] |= 0x40;
486
	     }
Thomas Winischhofer's avatar
Thomas Winischhofer committed
487
	  }
488 489 490

       } else if(SiS_compute_vclk(clock, &num, &denum, &div, &sbit, &scale)) {

Thomas Winischhofer's avatar
Thomas Winischhofer committed
491 492 493 494
	  pReg->sisRegs3C4[0x2A] = (num - 1) & 0x7f ;
	  pReg->sisRegs3C4[0x2A] |= (div == 2) ? 0x80 : 0;
	  pReg->sisRegs3C4[0x2B] = ((denum - 1) & 0x1f);
	  pReg->sisRegs3C4[0x2B] |= (((scale -1) & 3) << 5);
495 496

	  /* When setting VCLK, we should set SR13 first */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
497 498 499 500
	  if(sbit)
	     pReg->sisRegs3C4[0x13] |= 0x40;
	  else
	     pReg->sisRegs3C4[0x13] &= 0xBF;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
501 502

#ifdef TWDEBUG
503
	  xf86DrvMsg(0, X_INFO, "2a: %x 2b: %x 13: %x clock %d\n",
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
504 505 506
		pReg->sisRegs3C4[0x2A], pReg->sisRegs3C4[0x2B], pReg->sisRegs3C4[0x13], clock);
#endif

507
       } else {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
508

Thomas Winischhofer's avatar
Thomas Winischhofer committed
509 510
	  /* if SiS_compute_vclk cannot handle the requested clock, try sisCalcClock */
	  SiSCalcClock(pScrn, clock, 2, vclk);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
511

512 513 514 515
#define Midx    0
#define Nidx    1
#define VLDidx  2
#define Pidx    3
516
#define PSNidx  4
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
517

Thomas Winischhofer's avatar
Thomas Winischhofer committed
518 519
	  pReg->sisRegs3C4[0x2A] = (vclk[Midx] - 1) & 0x7f;
	  pReg->sisRegs3C4[0x2A] |= ((vclk[VLDidx] == 2) ? 1 : 0) << 7;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
520

521
	  /* D[4:0]: denumerator */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
522 523 524 525 526 527 528 529 530 531 532 533
	  pReg->sisRegs3C4[0x2B] = (vclk[Nidx] - 1) & 0x1f;

	  if(vclk[Pidx] <= 4){
	     /* postscale 1,2,3,4 */
	     pReg->sisRegs3C4[0x2B] |= (vclk[Pidx] - 1) << 5;
	     pReg->sisRegs3C4[0x13] &= 0xBF;
	  } else {
	     /* postscale 6,8 */
	     pReg->sisRegs3C4[0x2B] |= ((vclk[Pidx] / 2) - 1) << 5;
	     pReg->sisRegs3C4[0x13] |= 0x40;
	  }
	  pReg->sisRegs3C4[0x2B] |= 0x80 ;   /* gain for high frequency */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
534

535 536 537 538
       }

       /* High speed DAC */
       if(clock > 135000)
Thomas Winischhofer's avatar
Thomas Winischhofer committed
539
	  pReg->sisRegs3C4[0x07] |= 0x02;
540 541

       if(pSiS->oldChipset > OC_SIS6225) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
	  /* 1 or 2 cycle DRAM (set by option FastVram) */
	  if(pSiS->newFastVram == -1) {
	     if(pSiS->oldChipset == OC_SIS620) {
		/* Use different default on the 620 */
		pReg->sisRegs3C4[0x34] |= 0x40;
		pReg->sisRegs3C4[0x34] &= ~0x80;
	     } else {
		pReg->sisRegs3C4[0x34] |= 0x80;
		pReg->sisRegs3C4[0x34] &= ~0x40;
	     }
	  } else if(pSiS->newFastVram == 1)
	     pReg->sisRegs3C4[0x34] |= 0xC0;
	  else
	     pReg->sisRegs3C4[0x34] &= ~0xC0;

	  if(pSiS->oldChipset == OC_SIS620) {
	     /* Enable SGRAM burst timing (= bit clear) on the 620 */
	     if(pSiS->Flags & SYNCDRAM) {
		pReg->sisRegs3C4[0x35] &= ~0x20;
	     } else {
		pReg->sisRegs3C4[0x35] |= 0x20;
	     }
	  }
565 566 567
       }

    } /* VESA */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
568 569 570 571 572

    /* Logical line length */
    pSiS->ValidWidth = TRUE;
    pReg->sisRegs3C4[0x27] &= 0xCF;
    if(pSiS->CurrentLayout.bitsPerPixel == 24) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
573 574 575
       /* "Invalid logical width" */
       pReg->sisRegs3C4[0x27] |= 0x30;
       pSiS->ValidWidth = FALSE;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
576
    } else {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
       switch(pScrn->virtualX * (pSiS->CurrentLayout.bitsPerPixel >> 3)) {
	 case 1024:
		pReg->sisRegs3C4[0x27] |= 0x00;
		break;
	 case 2048:
		pReg->sisRegs3C4[0x27] |= 0x10;
		break;
	 case 4096:
		pReg->sisRegs3C4[0x27] |= 0x20;
		break;
	 default:
		/* Invalid logical width */
		pReg->sisRegs3C4[0x27] |= 0x30;
		pSiS->ValidWidth = FALSE;
		break;
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
593 594 595 596
    }

    /* Acceleration stuff */
    if(!pSiS->NoAccel) {
597 598
       pReg->sisRegs3C4[0x27] |= 0x40;   /* Enable engine programming registers */
       if( (pSiS->TurboQueue) &&	 /* Handle TurboQueue */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
599 600
	   (pSiS->oldChipset > OC_SIS6225) &&
	   ( (pSiS->Chipset != PCI_CHIP_SIS530) ||
601
	     (pSiS->CurrentLayout.bitsPerPixel != 24) ) ) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
602
	  pReg->sisRegs3C4[0x27] |= 0x80;        /* Enable TQ */
603 604 605 606 607 608 609 610 611
	  if((pSiS->Chipset == PCI_CHIP_SIS530) ||
	     ((pSiS->Chipset == PCI_CHIP_SIS6326 &&
	      (pSiS->ChipRev == 0xd0 || pSiS->ChipRev == 0xd1 ||
	       pSiS->ChipRev == 0xd2 || pSiS->ChipRev == 0x92 ||
	       pSiS->ChipRev == 0x0a || pSiS->ChipRev == 0x1a ||
	       pSiS->ChipRev == 0x2a || pSiS->ChipRev == 0x0b ||
	       pSiS->ChipRev == 0x1b || pSiS->ChipRev == 0x2b) ) ) ) {
	     /* pReg->sisRegs3C4[0x3D] |= 0x80;  */     /* Queue is 62K (530/620 specs) */
	     pReg->sisRegs3C4[0x3D] &= 0x7F;         /* Queue is 30K (530/620 specs) */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
612
	  }
613 614 615 616 617
	  /* Locate the TQ at the beginning of the last 64K block of
	   * video RAM. The address is to be specified in 32K steps.
	   */
	  pReg->sisRegs3C4[0x2C] = (pScrn->videoRam - 64) / 32;
	  if(pSiS->Chipset != PCI_CHIP_SIS530) {	/* 530/620: Reserved (don't touch) */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
618
	     pReg->sisRegs3C4[0x3C] &= 0xFC; 		/* 6326: Queue is all for 2D */
619 620 621 622
	  }						/* 5597: Must be 0           */
       } else {
	  pReg->sisRegs3C4[0x27] &= 0x7F;
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
623 624
    }

625 626 627

    if(!pSiS->UseVESA) {

Thomas Winischhofer's avatar
Thomas Winischhofer committed
628
       /* No idea what this does. The Windows driver does it, so we do it as well */
629
       if(pSiS->Chipset == PCI_CHIP_SIS6326) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
630 631
	  if((pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) ||
	     (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) ||
632 633 634 635 636
	     (pSiS->Flags & A6326REVAB)) {
	     if((pSiS->Flags & (SYNCDRAM | RAMFLAG)) == (SYNCDRAM | RAMFLAG)) {
	        if(!(pReg->sisRegs3C4[0x0E] & 0x03)) {
	           pReg->sisRegs3C4[0x3E] |= 0x02;
	        }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
637
	     }
Thomas Winischhofer's avatar
Thomas Winischhofer committed
638
	  }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
639 640
       }

641
       /* Set memclock */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
642
#if 0
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
       /* We don't need to do this; the SetMClk option was not used since 4.0. */
       if((pSiS->Chipset == PCI_CHIP_SIS5597) || (pSiS->Chipset == PCI_CHIP_SIS6326)) {
          if(pSiS->MemClock > 66000) {
             SiSCalcClock(pScrn, pSiS->MemClock, 1, vclk);

             pReg->sisRegs3C4[0x28] = (vclk[Midx] - 1) & 0x7f ;
             pReg->sisRegs3C4[0x28] |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ;
             pReg->sisRegs3C4[0x29] = (vclk[Nidx] -1) & 0x1f ;   /* bits [4:0] contain denumerator -MC */
             if(vclk[Pidx] <= 4) {
                pReg->sisRegs3C4[0x29] |= (vclk[Pidx] - 1) << 5 ; /* postscale 1,2,3,4 */
                pReg->sisRegs3C4[0x13] &= 0x7F;
             } else {
                pReg->sisRegs3C4[0x29] |= ((vclk[Pidx] / 2) - 1) << 5 ;  /* postscale 6,8 */
                pReg->sisRegs3C4[0x13] |= 0x80;
             }
             /* Check programmed memory clock. Enable only to check the above code */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
659
/*
660 661 662 663 664 665 666 667 668
             mclk = 14318 * ((pReg->sisRegs3C4[0x28] & 0x7f) + 1);
             mclk /= ((pReg->sisRegs3C4[0x29] & 0x0f) + 1);
             if(!(pReg->sisRegs3C4[0x13] & 0x80)) {
                mclk /= (((pReg->sisRegs3C4[0x29] & 0x60) >> 5) + 1);
             } else {
                if((pReg->sisRegs3C4[0x29] & 0x60) == 0x40) mclk /= 6;
                if((pReg->sisRegs3C4[0x29] & 0x60) == 0x60) mclk /= 8;
             }
             xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,2,
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
669 670 671
                 "Setting memory clock to %.3f MHz\n",
                 mclk/1000.0);
*/
672 673
          }
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
674 675
#endif

676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
       /* Set threshold values */
       /*
        * CPU/CRT Threshold:                     FIFO
        *                           MCLK     ___________      VCLK
        * cpu/engine <---o       o--------->|___________| -----------> CRT
        *                ^       ^            ^       ^
        *                 \     /             |       |
        *                  \   /              |< gap >|
        *                   \ /               |       |
        *           selector switch   Thrsh. low     high
        *
        * CRT consumes the data in the FIFO during scanline display. When the
        * amount of data in the FIFO reaches the Threshold low value, the selector
        * switch will switch to the right, and the FIFO will be refilled with data.
        * When the amount of data in the FIFO reaches the Threshold high value, the
        * selector switch will switch to the left and allows the CPU and the chip
        * engines to access the video RAM.
        *
        * The Threshold low values should be increased at higher bpps, simply because
        * there is more data needed for the CRT. When Threshold low and high are very
        * close to each other, the selector switch will be activated more often, which
        * decreases performance.
        *
        */
       switch(pSiS->Chipset) {
       case PCI_CHIP_SIS5597:  factor = 65; break;
       case PCI_CHIP_SIS6326:  factor = 30; break;
       case PCI_CHIP_SIS530:   factor = (pSiS->Flags & UMA) ? 60 : 30; break;
       default:                factor = (pScrn->videoRam > 1024) ? 24 : 12;
       }
       a = width * height * rate * 1.40 * factor * ((pSiS->CurrentLayout.bitsPerPixel + 1) / 8);
       b = (mclk / 1000) * 999488.0 * (buswidth / 8);
       c = ((a / b) + 1.0) / 2;
       d = (int)c + 2;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
710

711 712 713 714 715
       CRT_CPUthresholdLow = d;
       if((pSiS->Flags & (RAMFLAG | SYNCDRAM)) == (RAMFLAG | SYNCDRAM)) {
          CRT_CPUthresholdLow += 2;
       }
       CRT_CPUthresholdHigh = CRT_CPUthresholdLow + 3;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
716

717
       CRT_ENGthreshold = 0x0F;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
718

719 720
#if 0  /* See comment in sis_dac.c on why this is commented */
       if(pSiS->Chipset == PCI_CHIP_SIS530) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
721
	  if((pSiS->oldChipset == OC_SIS530A) &&
722 723 724 725
	     (pSiS->Flags & UMA) &&
	     (mclk == 100000) &&
	     (pSiS->Flags & ESS137xPRESENT)) {
	       if(!(pSiS->Flags & SECRETFLAG)) index = 0;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
726 727 728
	       if((temp = SiS_CalcSpecial530Threshold(pSiS, mode, index)) {
		   CRT_CPUthresholdLow = temp;
		   break;
729
	       }
Thomas Winischhofer's avatar
Thomas Winischhofer committed
730
	  }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
731 732 733
       }
#endif

734 735
       switch(pSiS->Chipset) {
       case PCI_CHIP_SIS530:
Thomas Winischhofer's avatar
Thomas Winischhofer committed
736 737 738
	  if(CRT_CPUthresholdLow > 0x1f)  CRT_CPUthresholdLow = 0x1f;
	  CRT_CPUthresholdHigh = 0x1f;
	  break;
739 740 741
       case PCI_CHIP_SIS5597:
       case PCI_CHIP_SIS6326:
       default:
Thomas Winischhofer's avatar
Thomas Winischhofer committed
742 743
	  if(CRT_CPUthresholdLow > 0x0f)  CRT_CPUthresholdLow  = 0x0f;
	  if(CRT_CPUthresholdHigh > 0x0f) CRT_CPUthresholdHigh = 0x0f;
744
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
745

746
       pReg->sisRegs3C4[0x08] = ((CRT_CPUthresholdLow & 0x0F) << 4) |
Thomas Winischhofer's avatar
Thomas Winischhofer committed
747
				(CRT_ENGthreshold & 0x0F);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
748

749 750
       pReg->sisRegs3C4[0x09] &= 0xF0;
       pReg->sisRegs3C4[0x09] |= (CRT_CPUthresholdHigh & 0x0F);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
751

752
       pReg->sisRegs3C4[0x3F] &= 0xEB;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
753
       pReg->sisRegs3C4[0x3F] |= ((CRT_CPUthresholdHigh & 0x10) |
Thomas Winischhofer's avatar
Thomas Winischhofer committed
754
				  ((CRT_CPUthresholdLow & 0x10) >> 2));
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
755

756
       if(pSiS->oldChipset >= OC_SIS530A) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
757
	  pReg->sisRegs3C4[0x3F] &= 0xDF;
758 759
	  pReg->sisRegs3C4[0x3F] |= 0x58;
       }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
760

761 762
       /* Set SiS6326 TV registers */
       if((pSiS->Chipset == PCI_CHIP_SIS6326) && (sis6326tvmode)) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
763 764 765
	  UChar tmp;
	  int index=0, i, j, k;
	  int fsc;
766

Thomas Winischhofer's avatar
Thomas Winischhofer committed
767 768 769
	  if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
	     pReg->sisRegs3C4[0x0D] |= 0x04;
	     switch(width) {
770 771 772 773 774 775 776 777 778 779 780
	     case 800:
	        if((strcmp(mode->name, "PAL800x600U") == 0))  index = 4;
	        else	        			      index = 3;
	        break;
	     case 720: index = 5;  break;
	     case 640:
	     default:  index = 2;
	     }
	     for(i=0; i<14; i++) {
	        pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_PAL[index][i];
	     }
Thomas Winischhofer's avatar
Thomas Winischhofer committed
781 782 783 784
	     fsc = (SiS6326TVRegs1_PAL[index][2] << 16) |
		   (SiS6326TVRegs1_PAL[index][3] << 8)  |
		   (SiS6326TVRegs1_PAL[index][4]);
	  } else {
785 786 787
	     pReg->sisRegs3C4[0x0D] &= ~0x04;
	     if((strcmp(mode->name, "NTSC640x480U") == 0))  index = 5;
	     else 					    index = 4;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
788
	     for(i=0; i<14; i++) {
789 790
	        pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_NTSC[index][i];
	     }
Thomas Winischhofer's avatar
Thomas Winischhofer committed
791
	     fsc = (SiS6326TVRegs1_NTSC[index][2] << 16) |
792 793
	           (SiS6326TVRegs1_NTSC[index][3] << 8)  |
	           (SiS6326TVRegs1_NTSC[index][4]);
Thomas Winischhofer's avatar
Thomas Winischhofer committed
794 795
	  }
	  if(pSiS->sis6326fscadjust) {
796 797 798 799
	     fsc += pSiS->sis6326fscadjust;
	     pReg->sis6326tv[2] = (fsc >> 16) & 0xff;
	     pReg->sis6326tv[3] = (fsc >> 8) & 0xff;
	     pReg->sis6326tv[4] = fsc & 0xff;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
800 801 802 803 804 805 806
	  }
	  tmp = pReg->sis6326tv[0x43];
	  if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp |= 0x10;
	  tmp |= 0x08;
	  pReg->sis6326tv[0x43] = tmp;
	  j = 0; k = 0;
	  for(i=0; i<=0x44; i++) {
807
	     if(SiS6326TVRegs1[j] == i) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
808
		j++;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
809
		continue;
810 811
	     }
	     if(pSiS->SiS6326Flags & SIS6326_TVPAL) {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
812
		tmp = SiS6326TVRegs2_PAL[index][k];
813
	     } else {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
814
		tmp = SiS6326TVRegs2_NTSC[index][k];
815 816 817
	     }
	     pReg->sis6326tv[i] = tmp;
	     k++;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
818 819 820 821 822
	  }
	  pReg->sis6326tv[0x43] |= 0x08;
	  if((pSiS->ChipRev == 0xc1) || (pSiS->ChipRev == 0xc2)) {
	     pReg->sis6326tv[0x43] &= ~0x08;
	  }
823

Thomas Winischhofer's avatar
Thomas Winischhofer committed
824 825 826 827 828 829
	  tmp = pReg->sis6326tv[0];
	  tmp |= 0x18;
	  if(pSiS->SiS6326Flags & SIS6326_TVCVBS)   tmp &= ~0x10;
	  if(pSiS->SiS6326Flags & SIS6326_TVSVIDEO) tmp &= ~0x08;
	  tmp |= 0x04;
	  pReg->sis6326tv[0] = tmp;
830 831 832
       }

    } /* VESA */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
833

Thomas Winischhofer's avatar
Thomas Winischhofer committed
834
    return TRUE;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
835 836
}

837
/* Init a mode for SiS 300, 315, 330, 340 series
838 839
 * This function is now only used for setting up some
 * variables (eg. scrnOffset).
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
840 841 842 843
 */
Bool
SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
844 845 846
    SISPtr    pSiS = SISPTR(pScrn);
    SISRegPtr pReg = &pSiS->ModeReg;
    UShort    temp;
847
    DisplayModePtr realmode = mode;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
848

849
    PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "SIS300Init()\n"));
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
850 851

    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4,
Thomas Winischhofer's avatar
Thomas Winischhofer committed
852
	"virtualX = %d depth = %d Logical width = %d\n",
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
853
	pScrn->virtualX, pSiS->CurrentLayout.bitsPerPixel,
Thomas Winischhofer's avatar
Thomas Winischhofer committed
854
	pScrn->virtualX * pSiS->CurrentLayout.bitsPerPixel/8);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
855

856 857 858 859 860 861
#ifdef SISMERGED
    if(pSiS->MergedFB) {
       realmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
    }
#endif

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
862 863 864
    /* Copy current register settings to structure */
    (*pSiS->SiSSave)(pScrn, pReg);

865
    /* Calculate Offset/Display Pitch */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
866
    pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth *
867 868 869
                          ((pSiS->CurrentLayout.bitsPerPixel + 7) / 8);

    pSiS->scrnPitch = pSiS->scrnPitch2 = pSiS->scrnOffset;
870 871 872 873
    if(!(pSiS->VBFlags & CRT1_LCDA)) {
       if(realmode->Flags & V_INTERLACE) pSiS->scrnPitch <<= 1;
    }
    /* CRT2 mode can never be interlaced */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
874 875 876 877 878 879

#ifdef UNLOCK_ALWAYS
    outSISIDXREG(SISSR, 0x05, 0x86);
#endif

    switch(pSiS->CurrentLayout.bitsPerPixel) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
880 881
	case 8:
	    pSiS->DstColor = 0x0000;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
882
	    pSiS->SiS310_AccelDepth = 0x00000000;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
883 884
	    break;
	case 16:
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
885 886 887
	    if(pSiS->CurrentLayout.depth == 15)
	        pSiS->DstColor = (short) 0x4000;
	    else
Thomas Winischhofer's avatar
Thomas Winischhofer committed
888
	        pSiS->DstColor = (short) 0x8000;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
889
	    pSiS->SiS310_AccelDepth = 0x00010000;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
890 891 892
	    break;
	case 32:
	    pSiS->DstColor = (short) 0xC000;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
893
	    pSiS->SiS310_AccelDepth = 0x00020000;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
894
	    break;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
895 896
    }

897
    /* Enable PCI LINEAR ADDRESSING (0x80), MMIO (0x01), PCI_IO (0x20) */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
898 899
    pReg->sisRegs3C4[0x20] = 0xA1;

900 901 902 903 904
    /* Now initialize TurboQueue. TB is always located at the very top of
     * the videoRAM (notably NOT the x framebuffer memory, which can/should
     * be limited by MaxXFbMem when using DRI). Also, enable the accelerators.
     */
    if(!pSiS->NoAccel) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
905
	pReg->sisRegs3C4[0x1E] |= 0x42;  /* Enable 2D accelerator */
906 907
	pReg->sisRegs3C4[0x1E] |= 0x18;  /* Enable 3D accelerator */
	switch(pSiS->VGAEngine) {
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
908
	case SIS_300_VGA:
909 910
	  if(pSiS->TurboQueue) {    		/* set Turbo Queue as 512k */
	    temp = ((pScrn->videoRam/64)-8);    /* 8=512k, 4=256k, 2=128k, 1=64k */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
911
	    pReg->sisRegs3C4[0x26] = temp & 0xFF;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
912 913
	    pReg->sisRegs3C4[0x27] =
		(pReg->sisRegs3C4[0x27] & 0xfc) | (((temp >> 8) & 3) | 0xF0);
Thomas Winischhofer's avatar
Thomas Winischhofer committed
914
	  }	/* line above new for saving D2&3 of status register */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
915 916
	  break;
	case SIS_315_VGA:
917
#ifndef SISVRAMQ
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
918 919 920 921
	  /* See comments in sis_driver.c */
	  pReg->sisRegs3C4[0x27] = 0x1F;
	  pReg->sisRegs3C4[0x26] = 0x22;
	  pReg->sisMMIO85C0 = (pScrn->videoRam - 512) * 1024;
922
#endif
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
923 924 925 926
	  break;
	}
    }

Thomas Winischhofer's avatar
Thomas Winischhofer committed
927
    return TRUE;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
928 929 930 931 932 933 934
}

static void
SiS6326TVDelay(ScrnInfoPtr pScrn, int delay)
{
    SISPtr  pSiS = SISPTR(pScrn);
    int i;
935
    UChar temp;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
936 937

    for(i=0; i<delay; i++) {
938
       inSISIDXREG(SISSR, 0x05, temp);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
939
    }
940
    (void)temp;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
941 942
}

943
static int
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
944 945
SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl)
{
946
    UChar temp;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
947 948 949 950 951 952 953 954 955 956 957 958 959

    SiS6326SetTVReg(pScrn, 0x42, tempbl);
    temp = SiS6326GetTVReg(pScrn, 0x43);
    temp &= 0xfc;
    temp |= tempbh;
    SiS6326SetTVReg(pScrn, 0x43, temp);
    SiS6326TVDelay(pScrn, 0x1000);
    temp = SiS6326GetTVReg(pScrn, 0x43);
    temp |= 0x04;
    SiS6326SetTVReg(pScrn, 0x43, temp);
    SiS6326TVDelay(pScrn, 0x8000);
    temp = SiS6326GetTVReg(pScrn, 0x44);
    if(!(tempch & temp)) tempcl = 0;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
960
    return tempcl;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
961 962
}

963
static void
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
964 965 966
SISSense6326(ScrnInfoPtr pScrn)
{
    SISPtr pSiS = SISPTR(pScrn);
967 968
    UChar  temp;
    int    result;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
969 970 971 972 973 974 975 976 977 978 979 980 981

    pSiS->SiS6326Flags &= (SIS6326_HASTV | SIS6326_TVPAL);
    temp = SiS6326GetTVReg(pScrn, 0x43);
    temp &= 0xfb;
    SiS6326SetTVReg(pScrn, 0x43, temp);
    result = SIS6326DoSense(pScrn, 0x01, 0xb0, 0x06, SIS6326_TVSVIDEO);  /* 0x02 */
    pSiS->SiS6326Flags |= result;
    result = SIS6326DoSense(pScrn, 0x01, 0xa0, 0x01, SIS6326_TVCVBS);    /* 0x04 */
    pSiS->SiS6326Flags |= result;
    temp = SiS6326GetTVReg(pScrn, 0x43);
    temp &= 0xfb;
    SiS6326SetTVReg(pScrn, 0x43, temp);
    if(pSiS->SiS6326Flags & (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) {
982 983 984
       pSiS->SiS6326Flags |= SIS6326_TVDETECTED;
       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
	    "SiS6326: Detected TV connected to %s output\n",
985 986
		(((pSiS->SiS6326Flags & (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) ==
		   (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) ?
Thomas Winischhofer's avatar
Thomas Winischhofer committed
987 988 989
			"both SVIDEO and COMPOSITE" :
			   ((pSiS->SiS6326Flags & SIS6326_TVSVIDEO) ?
				"SVIDEO" : "COMPOSITE")));
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
990
    } else {
991 992
       xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
	    "SiS6326: No TV detected\n");
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
993 994 995
    }
}

996
static Bool
Thomas Winischhofer's avatar
Thomas Winischhofer committed
997 998
SISIsUMC(SISPtr pSiS)
{
999
    UShort p4_0f, p4_25, p4_27, temp;
1000

Thomas Winischhofer's avatar
Thomas Winischhofer committed
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
    inSISIDXREG(SISPART4, 0x0f, p4_0f);
    inSISIDXREG(SISPART4, 0x25, p4_25);
    inSISIDXREG(SISPART4, 0x27, p4_27);
    andSISIDXREG(SISPART4, 0x0f, 0x7f);
    orSISIDXREG(SISPART4, 0x25, 0x08);
    andSISIDXREG(SISPART4, 0x27, 0xfd);
    inSISIDXREG(SISPART4, 0x26, temp);
    outSISIDXREG(SISPART4, 0x27, p4_27);
    outSISIDXREG(SISPART4, 0x25, p4_25);
    outSISIDXREG(SISPART4, 0x0f, p4_0f);
    return((temp & 0x08) ? TRUE : FALSE);
}

1014
/* Detect video bridge and set VBFlags accordingly */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1015 1016
void SISVGAPreInit(ScrnInfoPtr pScrn)
{
1017
    SISPtr pSiS = SISPTR(pScrn);
1018 1019 1020 1021
    int    temp,temp1,temp2,sistypeidx;
    int    upperlimitlvds, lowerlimitlvds;
    int    upperlimitch, lowerlimitch;
    int    chronteltype, chrontelidreg, upperlimitvb;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1022
    static const char *detectvb = "Detected SiS%s video bridge (%s, ID %d; Rev 0x%x)\n";
1023
#if 0
1024
    UChar sr17=0;
1025
#endif
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1026
    static const char *ChrontelTypeStr[] = {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1027
	"7004",
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1028 1029 1030 1031 1032 1033 1034 1035 1036
	"7005",
	"7007",
	"7006",
	"7008",
	"7013",
	"7019",
	"7020",
	"(unknown)"
    };
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1037
    static const char *SiSVBTypeStr[] = {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1038
	"301",		/* 0 */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1039 1040 1041 1042 1043 1044 1045 1046
	"301B",		/* 1 */
	"301B-DH",	/* 2 */
	"301LV",	/* 3 */
	"302LV",	/* 4 */
	"301C",		/* 5 */
	"302ELV",	/* 6 */
	"302B"		/* 7 */
    };
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1047

1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059
    switch(pSiS->Chipset) {
       case PCI_CHIP_SIS300:
       case PCI_CHIP_SIS540:
       case PCI_CHIP_SIS630:
       case PCI_CHIP_SIS550:
       case PCI_CHIP_SIS315:
       case PCI_CHIP_SIS315H:
       case PCI_CHIP_SIS315PRO:
       case PCI_CHIP_SIS650:
       case PCI_CHIP_SIS330:
       case PCI_CHIP_SIS660:
       case PCI_CHIP_SIS340:
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1060 1061
       case PCI_CHIP_XGIXG20:
       case PCI_CHIP_XGIXG40:
1062 1063 1064 1065
          pSiS->ModeInit = SIS300Init;
          break;
       default:
          pSiS->ModeInit = SISInit;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1066
    }
1067

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1068
    if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) {
1069 1070 1071 1072 1073 1074
       UChar sr0d;
       inSISIDXREG(SISSR, 0x0d, sr0d);
       if(sr0d & 0x04) {
	  pSiS->SiS6326Flags |= SIS6326_TVPAL;
       }
       SISSense6326(pScrn);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1075 1076
    }

Thomas Winischhofer's avatar
Thomas Winischhofer committed
1077
    pSiS->VBFlags = pSiS->VBFlags2 = 0; /* reset VBFlags */
1078 1079
    pSiS->SiS_Pr->SiS_UseLCDA = FALSE;
    pSiS->SiS_Pr->Backup = FALSE;
1080

1081
    /* Videobridges only available for 300/315/330/340 series */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1082
    if((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA))
1083
       return;
1084

Thomas Winischhofer's avatar
Thomas Winischhofer committed
1085 1086 1087 1088
    /* No video bridge ever on XGI Z7 (XG20) */
    if(pSiS->ChipType == XGI_20)
       return;

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1089 1090
    inSISIDXREG(SISPART4, 0x00, temp);
    temp &= 0x0F;
1091
    if(temp == 1) {
1092

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
1093 1094
        inSISIDXREG(SISPART4, 0x01, temp1);
	temp1 &= 0xff;
1095

Thomas Winischhofer's avatar
Thomas Winischhofer committed
1096
	if(temp1 >= 0xC0) {
1097
	   if(SISIsUMC(pSiS)) pSiS->VBFlags2 |= VB2_SISUMC;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1098
	}
1099

1100
        if(temp1 >= 0xE0) {
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1101
		inSISIDXREG(SISPART4, 0x39, temp2);
1102
		if(temp2 == 0xff) {
1103
		   pSiS->VBFlags2 |= VB2_302LV;
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1104
		   sistypeidx = 4;
1105
		} else {
1106
		   pSiS->VBFlags2 |= VB2_301C;	/* VB_302ELV; */
Thomas Winischhofer's avatar
Thomas Winischhofer committed
1107
		   sistypeidx = 5; 		/* 6; */