sis_vga.c revision 72b676d7
172b676d7Smrg/* $XFree86$ */ 272b676d7Smrg/* $XdotOrg$ */ 372b676d7Smrg/* 472b676d7Smrg * Mode setup and basic video bridge detection 572b676d7Smrg * 672b676d7Smrg * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria. 772b676d7Smrg * 872b676d7Smrg * The SISInit() function for old series (except TV and FIFO calculation) 972b676d7Smrg * was previously based on code which was Copyright (C) 1998,1999 by Alan 1072b676d7Smrg * Hourihane, Wigan, England. However, the code has been rewritten entirely 1172b676d7Smrg * and is - it its current representation - not covered by this old copyright. 1272b676d7Smrg * 1372b676d7Smrg * Redistribution and use in source and binary forms, with or without 1472b676d7Smrg * modification, are permitted provided that the following conditions 1572b676d7Smrg * are met: 1672b676d7Smrg * 1) Redistributions of source code must retain the above copyright 1772b676d7Smrg * notice, this list of conditions and the following disclaimer. 1872b676d7Smrg * 2) Redistributions in binary form must reproduce the above copyright 1972b676d7Smrg * notice, this list of conditions and the following disclaimer in the 2072b676d7Smrg * documentation and/or other materials provided with the distribution. 2172b676d7Smrg * 3) The name of the author may not be used to endorse or promote products 2272b676d7Smrg * derived from this software without specific prior written permission. 2372b676d7Smrg * 2472b676d7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2572b676d7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2672b676d7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2772b676d7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2872b676d7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2972b676d7Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3072b676d7Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3172b676d7Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3272b676d7Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3372b676d7Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3472b676d7Smrg * 3572b676d7Smrg * Author: Thomas Winischhofer <thomas@winischhofer.net> 3672b676d7Smrg * 3772b676d7Smrg */ 3872b676d7Smrg 3972b676d7Smrg#ifdef HAVE_CONFIG_H 4072b676d7Smrg#include "config.h" 4172b676d7Smrg#endif 4272b676d7Smrg 4372b676d7Smrg#include "sis.h" 4472b676d7Smrg#define SIS_NEED_inSISREG 4572b676d7Smrg#define SIS_NEED_outSISREG 4672b676d7Smrg#define SIS_NEED_inSISIDXREG 4772b676d7Smrg#define SIS_NEED_outSISIDXREG 4872b676d7Smrg#define SIS_NEED_orSISIDXREG 4972b676d7Smrg#define SIS_NEED_andSISIDXREG 5072b676d7Smrg#include "sis_regs.h" 5172b676d7Smrg#include "sis_dac.h" 5272b676d7Smrg 5372b676d7Smrgstatic Bool SISInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 5472b676d7Smrgstatic Bool SIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode); 5572b676d7Smrgstatic int SIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl); 5672b676d7Smrgstatic void SISSense6326(ScrnInfoPtr pScrn); 5772b676d7Smrgstatic void SiS6326TVDelay(ScrnInfoPtr pScrn, int delay); 5872b676d7Smrgextern void SISSense30x(ScrnInfoPtr pScrn, Bool quiet); 5972b676d7Smrgextern void SISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet); 6072b676d7Smrg 6172b676d7Smrg/* Our very own vgaHW functions */ 6272b676d7Smrgvoid SiSVGASave(ScrnInfoPtr pScrn, SISRegPtr save, int flags); 6372b676d7Smrgvoid SiSVGARestore(ScrnInfoPtr pScrn, SISRegPtr restore, int flags); 6472b676d7Smrgvoid SiSVGASaveFonts(ScrnInfoPtr pScrn); 6572b676d7Smrgvoid SiSVGARestoreFonts(ScrnInfoPtr pScrn); 6672b676d7Smrgvoid SISVGALock(SISPtr pSiS); 6772b676d7Smrgvoid SiSVGAUnlock(SISPtr pSiS); 6872b676d7Smrgvoid SiSVGAProtect(ScrnInfoPtr pScrn, Bool on); 6972b676d7Smrg#ifdef SIS_PC_PLATFORM 7072b676d7SmrgBool SiSVGAMapMem(ScrnInfoPtr pScrn); 7172b676d7Smrgvoid SiSVGAUnmapMem(ScrnInfoPtr pScrn); 7272b676d7Smrg#endif 7372b676d7SmrgBool SiSVGASaveScreen(ScreenPtr pScreen, int mode); 7472b676d7Smrgstatic Bool SiSVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode, int fixsync); 7572b676d7Smrg 7672b676d7Smrgconst CARD8 SiS6326TVRegs1[14] = { 7772b676d7Smrg 0x00,0x01,0x02,0x03,0x04,0x11,0x12,0x13,0x21,0x26,0x27,0x3a,0x3c,0x43 7872b676d7Smrg}; 7972b676d7Smrg 8072b676d7Smrgconst CARD8 SiS6326TVRegs1_NTSC[6][14] = { 8172b676d7Smrg {0x81,0x3f,0x49,0x1b,0xa9,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60}, 8272b676d7Smrg {0x81,0x3f,0x49,0x1d,0xa0,0x03,0x00,0x09,0x08,0x7d,0x00,0x88,0x30,0x60}, 8372b676d7Smrg {0x81,0x45,0x24,0x8e,0x26,0x0b,0x00,0x09,0x02,0xfe,0x00,0x09,0x51,0x60}, 8472b676d7Smrg {0x81,0x45,0x24,0x8e,0x26,0x07,0x00,0x29,0x04,0x30,0x10,0x3b,0x61,0x60}, 8572b676d7Smrg {0x81,0x3f,0x24,0x8e,0x26,0x09,0x00,0x09,0x02,0x30,0x10,0x3b,0x51,0x60}, /* 640x400, 640x480 */ 8672b676d7Smrg {0x83,0x5d,0x21,0xbe,0x75,0x03,0x00,0x09,0x08,0x42,0x10,0x4d,0x61,0x79} /* 640x480u */ 8772b676d7Smrg}; 8872b676d7Smrg 8972b676d7Smrgconst CARD8 SiS6326TVRegs2_NTSC[6][54] = { 9072b676d7Smrg {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 9172b676d7Smrg 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 9272b676d7Smrg 0xFC, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40, 9372b676d7Smrg 0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10, 9472b676d7Smrg 0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0}, 9572b676d7Smrg {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 9672b676d7Smrg 0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 9772b676d7Smrg 0xFF, 0xDF, 0x94, 0x1F, 0x4A, 0x03, 0x71, 0x07, 0x97, 0x10, 0x40, 9872b676d7Smrg 0x48, 0x00, 0x26, 0xB6, 0x10, 0x5C, 0xEC, 0x21, 0x2E, 0xBE, 0x10, 9972b676d7Smrg 0x64, 0xF4, 0x21, 0x13, 0x75, 0x08, 0x31, 0x6A, 0x01, 0xA0}, 10072b676d7Smrg {0x11, 0x17, 0x03, 0x0A, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 10172b676d7Smrg 0x0D, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 10272b676d7Smrg 0xFF, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73, 10372b676d7Smrg 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30, 10472b676d7Smrg 0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0}, 10572b676d7Smrg {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 10672b676d7Smrg 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 10772b676d7Smrg 0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73, 10872b676d7Smrg 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30, 10972b676d7Smrg 0xBA, 0xDA, 0x52, 0x00, 0x02, 0xF5, 0x53, 0xF7, 0x02, 0xA0}, 11072b676d7Smrg {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, 11172b676d7Smrg 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 11272b676d7Smrg 0xDC, 0xDF, 0x94, 0x3F, 0x8C, 0x06, 0xCE, 0x07, 0x27, 0x30, 0x73, 11372b676d7Smrg 0x7B, 0x00, 0x48, 0x68, 0x30, 0xB2, 0xD2, 0x52, 0x50, 0x70, 0x30, 11472b676d7Smrg 0xBA, 0xDA, 0x52, 0xDC, 0x02, 0xD1, 0x53, 0xF7, 0x02, 0xA0}, 11572b676d7Smrg {0x11, 0x17, 0x03, 0x09, 0x94, 0x02, 0x05, 0x06, 0x09, 0x50, 0x0C, /* 640x480u */ 11672b676d7Smrg 0x0C, 0x06, 0x0D, 0x04, 0x0A, 0x94, 0x06, 0x0D, 0x04, 0x0A, 0x94, 11772b676d7Smrg 0xDC, 0xDF, 0x94, 0xAF, 0x95, 0x06, 0xDD, 0x07, 0x5F, 0x30, 0x7E, 11872b676d7Smrg 0x86, 0x00, 0x4C, 0xA4, 0x30, 0xE3, 0x3B, 0x62, 0x54, 0xAC, 0x30, 11972b676d7Smrg 0xEB, 0x43, 0x62, 0x48, 0x34, 0x3D, 0x63, 0x29, 0x03, 0xA0} 12072b676d7Smrg}; 12172b676d7Smrg 12272b676d7Smrgconst CARD8 SiS6326TVRegs1_PAL[6][14] = { 12372b676d7Smrg {0x81,0x2d,0xc8,0x07,0xb2,0x0b,0x00,0x09,0x02,0xed,0x00,0xf8,0x30,0x40}, 12472b676d7Smrg {0x80,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40}, 12572b676d7Smrg {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0xed,0x10,0xf8,0x71,0x40}, /* 640x480 */ 12672b676d7Smrg {0x81,0x2d,0xa4,0x03,0xd9,0x0b,0x00,0x09,0x02,0x8f,0x10,0x9a,0x71,0x40}, /* 800x600 */ 12772b676d7Smrg {0x83,0x63,0xa1,0x7a,0xa3,0x0a,0x00,0x09,0x02,0xb5,0x11,0xc0,0x81,0x59}, /* 800x600u */ 12872b676d7Smrg {0x81,0x63,0xa4,0x03,0xd9,0x01,0x00,0x09,0x10,0x9f,0x10,0xaa,0x71,0x59} /* 720x540 */ 12972b676d7Smrg}; 13072b676d7Smrg 13172b676d7Smrgconst CARD8 SiS6326TVRegs2_PAL[6][54] = { 13272b676d7Smrg {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, 13372b676d7Smrg 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 13472b676d7Smrg 0xE5, 0xDF, 0x94, 0xEF, 0x5A, 0x03, 0x7F, 0x07, 0xFF, 0x10, 0x4E, 13572b676d7Smrg 0x56, 0x00, 0x2B, 0x23, 0x20, 0xB4, 0xAC, 0x31, 0x33, 0x2B, 0x20, 13672b676d7Smrg 0xBC, 0xB4, 0x31, 0x83, 0xE1, 0x78, 0x31, 0xD6, 0x01, 0xA0}, 13772b676d7Smrg {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, 13872b676d7Smrg 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 13972b676d7Smrg 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90, 14072b676d7Smrg 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, 14172b676d7Smrg 0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0}, 14272b676d7Smrg {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 640x480 */ 14372b676d7Smrg 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 14472b676d7Smrg 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90, 14572b676d7Smrg 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, 14672b676d7Smrg 0x6A, 0x5A, 0x73, 0x03, 0xC1, 0xF8, 0x63, 0xB6, 0x03, 0xA0}, 14772b676d7Smrg {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 800x600 */ 14872b676d7Smrg 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 14972b676d7Smrg 0xE5, 0xDF, 0x94, 0xDF, 0xB2, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x90, 15072b676d7Smrg 0x98, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, 15172b676d7Smrg 0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0}, 15272b676d7Smrg {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 800x600u */ 15372b676d7Smrg 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 15472b676d7Smrg 0xE5, 0xDF, 0x94, 0x7F, 0xBD, 0x08, 0x0E, 0x07, 0x47, 0x40, 0x9D, 15572b676d7Smrg 0xA5, 0x00, 0x54, 0x94, 0x40, 0xA4, 0xE4, 0x73, 0x5C, 0x9C, 0x40, 15672b676d7Smrg 0xAC, 0xEC, 0x73, 0x0B, 0x0E, 0x00, 0x84, 0x03, 0x04, 0xA0}, 15772b676d7Smrg {0x15, 0x4E, 0x35, 0x6E, 0x94, 0x02, 0x04, 0x38, 0x3A, 0x50, 0x3D, /* 720x540 */ 15872b676d7Smrg 0x70, 0x06, 0x3E, 0x35, 0x6D, 0x94, 0x05, 0x3F, 0x36, 0x6E, 0x94, 15972b676d7Smrg 0xE5, 0xDF, 0x94, 0xDF, 0xB0, 0x07, 0xFB, 0x07, 0xF7, 0x30, 0x9D, 16072b676d7Smrg 0xA5, 0x00, 0x4F, 0x3F, 0x40, 0x62, 0x52, 0x73, 0x57, 0x47, 0x40, 16172b676d7Smrg 0x6A, 0x5A, 0x73, 0xA0, 0xC1, 0x95, 0x73, 0xB6, 0x03, 0xA0} 16272b676d7Smrg}; 16372b676d7Smrg 16472b676d7Smrgconst CARD8 SiS6326CR[9][15] = { 16572b676d7Smrg {0x79,0x63,0x64,0x1d,0x6a,0x93,0x00,0x6f,0xf0,0x58,0x8a,0x57,0x57,0x70,0x20}, /* PAL 800x600 */ 16672b676d7Smrg {0x79,0x4f,0x50,0x95,0x60,0x93,0x00,0x6f,0xba,0x14,0x86,0xdf,0xe0,0x30,0x00}, /* PAL 640x480 */ 16772b676d7Smrg {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xe9,0x8b,0xdf,0xe7,0x04,0x00}, /* NTSC 640x480 */ 16872b676d7Smrg {0x5f,0x4f,0x50,0x82,0x53,0x9f,0x00,0x0b,0x3e,0xcb,0x8d,0x8f,0x96,0xe9,0x00}, /* NTSC 640x400 */ 16972b676d7Smrg {0x83,0x63,0x64,0x1f,0x6d,0x9b,0x00,0x6f,0xf0,0x48,0x0a,0x23,0x57,0x70,0x20}, /* PAL 800x600u */ 17072b676d7Smrg {0x79,0x59,0x5b,0x1d,0x66,0x93,0x00,0x6f,0xf0,0x42,0x04,0x1b,0x40,0x70,0x20}, /* PAL 720x540 */ 17172b676d7Smrg {0x66,0x4f,0x51,0x0a,0x57,0x89,0x00,0x0b,0x3e,0xd9,0x0b,0xb6,0xe7,0x04,0x00}, /* NTSC 640x480u */ 17272b676d7Smrg {0xce,0x9f,0x9f,0x92,0xa4,0x16,0x00,0x28,0x5a,0x00,0x04,0xff,0xff,0x29,0x39}, /* 1280x1024-75 */ 17372b676d7Smrg {0x09,0xc7,0xc7,0x0d,0xd2,0x0a,0x01,0xe0,0x10,0xb0,0x04,0xaf,0xaf,0xe1,0x1f} /* 1600x1200-60 */ 17472b676d7Smrg}; 17572b676d7Smrg 17672b676d7Smrg/* Initialize a display mode on 5597/5598, 6326 and 530/620 */ 17772b676d7Smrgstatic Bool 17872b676d7SmrgSISInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 17972b676d7Smrg{ 18072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 18172b676d7Smrg SISRegPtr pReg = &pSiS->ModeReg; 18272b676d7Smrg UChar temp; 18372b676d7Smrg int mclk = pSiS->MemClock; 18472b676d7Smrg int clock = mode->Clock; 18572b676d7Smrg int width = mode->HDisplay; 18672b676d7Smrg int height = mode->VDisplay; 18772b676d7Smrg int rate = (int)SiSCalcVRate(mode); 18872b676d7Smrg int buswidth = pSiS->BusWidth; 18972b676d7Smrg unsigned int vclk[5]; 19072b676d7Smrg UShort CRT_CPUthresholdLow, CRT_CPUthresholdHigh, CRT_ENGthreshold; 19172b676d7Smrg double a, b, c; 19272b676d7Smrg int d, factor, offset, fixsync = 1; 19372b676d7Smrg int num, denum, div, sbit, scale; 19472b676d7Smrg Bool sis6326tvmode, sis6326himode; 19572b676d7Smrg 19672b676d7Smrg /* Save the registers for further processing */ 19772b676d7Smrg (*pSiS->SiSSave)(pScrn, pReg); 19872b676d7Smrg 19972b676d7Smrg /* Initialise the standard VGA registers */ 20072b676d7Smrg if(!pSiS->UseVESA) { 20172b676d7Smrg if(!SiSVGAInit(pScrn, mode, fixsync)) { 20272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "SISInit: SiSVGAInit() failed\n"); 20372b676d7Smrg return FALSE; 20472b676d7Smrg } 20572b676d7Smrg } 20672b676d7Smrg 20772b676d7Smrg /* Determine if chosen mode is suitable for TV on the 6326 20872b676d7Smrg * and if the mode is one of our special hi-res modes. 20972b676d7Smrg */ 21072b676d7Smrg sis6326tvmode = FALSE; 21172b676d7Smrg sis6326himode = FALSE; 21272b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS6326) { 21372b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_HASTV) { 21472b676d7Smrg if((pSiS->SiS6326Flags & SIS6326_TVDETECTED) && 21572b676d7Smrg ((strcmp(mode->name, "PAL800x600") == 0) || /* Special TV modes */ 21672b676d7Smrg (strcmp(mode->name, "PAL800x600U") == 0) || 21772b676d7Smrg (strcmp(mode->name, "PAL720x540") == 0) || 21872b676d7Smrg (strcmp(mode->name, "PAL640x480") == 0) || 21972b676d7Smrg (strcmp(mode->name, "NTSC640x480") == 0) || 22072b676d7Smrg (strcmp(mode->name, "NTSC640x480U") == 0) || 22172b676d7Smrg (strcmp(mode->name, "NTSC640x400") == 0))) { 22272b676d7Smrg sis6326tvmode = TRUE; 22372b676d7Smrg } else { 22472b676d7Smrg pReg->sis6326tv[0x00] &= 0xfb; 22572b676d7Smrg } 22672b676d7Smrg } 22772b676d7Smrg if((strcmp(mode->name, "SIS1280x1024-75") == 0) || /* Special high-res modes */ 22872b676d7Smrg (strcmp(mode->name, "SIS1600x1200-60") == 0)) { 22972b676d7Smrg sis6326himode = TRUE; 23072b676d7Smrg } 23172b676d7Smrg } 23272b676d7Smrg 23372b676d7Smrg#ifdef UNLOCK_ALWAYS 23472b676d7Smrg outSISIDXREG(SISSR, 0x05, 0x86); 23572b676d7Smrg#endif 23672b676d7Smrg 23772b676d7Smrg if(!pSiS->UseVESA) { 23872b676d7Smrg pReg->sisRegs3C4[0x06] &= 0x01; 23972b676d7Smrg } 24072b676d7Smrg 24172b676d7Smrg /* set interlace */ 24272b676d7Smrg if(!(mode->Flags & V_INTERLACE)) { 24372b676d7Smrg offset = pSiS->CurrentLayout.displayWidth >> 3; 24472b676d7Smrg } else { 24572b676d7Smrg offset = pSiS->CurrentLayout.displayWidth >> 2; 24672b676d7Smrg if(!pSiS->UseVESA) { 24772b676d7Smrg pReg->sisRegs3C4[0x06] |= 0x20; 24872b676d7Smrg } 24972b676d7Smrg } 25072b676d7Smrg 25172b676d7Smrg /* Enable Linear and Enhanced Gfx Mode */ 25272b676d7Smrg if(!pSiS->UseVESA) { 25372b676d7Smrg pReg->sisRegs3C4[0x06] |= 0x82; 25472b676d7Smrg } 25572b676d7Smrg 25672b676d7Smrg /* Enable MMIO at PCI Register 14H (D[6:5]: 11) */ 25772b676d7Smrg if(pSiS->oldChipset >= OC_SIS5597) { 25872b676d7Smrg pReg->sisRegs3C4[0x0B] |= 0x60; 25972b676d7Smrg } else { 26072b676d7Smrg pReg->sisRegs3C4[0x0B] |= 0x20; 26172b676d7Smrg pReg->sisRegs3C4[0x0B] &= ~0x40; 26272b676d7Smrg } 26372b676d7Smrg 26472b676d7Smrg if(!pSiS->UseVESA) { 26572b676d7Smrg 26672b676d7Smrg /* Enable 32bit mem access (D7), read-ahead cache (D5) */ 26772b676d7Smrg pReg->sisRegs3C4[0x0C] |= 0x80; 26872b676d7Smrg if(pSiS->oldChipset > OC_SIS6225) { 26972b676d7Smrg pReg->sisRegs3C4[0x0C] |= 0x20; 27072b676d7Smrg } 27172b676d7Smrg 27272b676d7Smrg /* Some speed-up stuff */ 27372b676d7Smrg switch(pSiS->Chipset) { 27472b676d7Smrg case PCI_CHIP_SIS5597: 27572b676d7Smrg /* enable host bus */ 27672b676d7Smrg if(!pSiS->HostBus) { 27772b676d7Smrg pReg->sisRegs3C4[0x34] &= ~0x08; 27872b676d7Smrg } else { 27972b676d7Smrg pReg->sisRegs3C4[0x34] |= 0x08; 28072b676d7Smrg } 28172b676d7Smrg /* fall through */ 28272b676d7Smrg case PCI_CHIP_SIS6326: 28372b676d7Smrg case PCI_CHIP_SIS530: 28472b676d7Smrg /* Enable "dual segment register mode" (D2) and "i/o gating while 28572b676d7Smrg * write buffer is not empty" (D3) 28672b676d7Smrg */ 28772b676d7Smrg pReg->sisRegs3C4[0x0B] |= 0x0C; 28872b676d7Smrg } 28972b676d7Smrg 29072b676d7Smrg /* set colordepth */ 29172b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS530) { 29272b676d7Smrg pReg->sisRegs3C4[0x09] &= 0x7F; 29372b676d7Smrg } 29472b676d7Smrg switch(pSiS->CurrentLayout.bitsPerPixel) { 29572b676d7Smrg case 8: 29672b676d7Smrg break; 29772b676d7Smrg case 16: 29872b676d7Smrg offset <<= 1; 29972b676d7Smrg if(pSiS->CurrentLayout.depth == 15) 30072b676d7Smrg pReg->sisRegs3C4[0x06] |= 0x04; 30172b676d7Smrg else 30272b676d7Smrg pReg->sisRegs3C4[0x06] |= 0x08; 30372b676d7Smrg break; 30472b676d7Smrg case 24: 30572b676d7Smrg offset += (offset << 1); 30672b676d7Smrg pReg->sisRegs3C4[0x06] |= 0x10; 30772b676d7Smrg pReg->sisRegs3C4[0x0B] |= 0x90; 30872b676d7Smrg break; 30972b676d7Smrg case 32: 31072b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS530) { 31172b676d7Smrg offset <<= 2; 31272b676d7Smrg if(pSiS->oldChipset != OC_SIS620) { 31372b676d7Smrg pReg->sisRegs3C4[0x06] |= 0x10; 31472b676d7Smrg } 31572b676d7Smrg pReg->sisRegs3C4[0x0B] |= 0x90; 31672b676d7Smrg pReg->sisRegs3C4[0x09] |= 0x80; 31772b676d7Smrg } else return FALSE; 31872b676d7Smrg break; 31972b676d7Smrg } 32072b676d7Smrg } 32172b676d7Smrg 32272b676d7Smrg /* save screen pitch for acceleration functions */ 32372b676d7Smrg pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth * 32472b676d7Smrg ((pSiS->CurrentLayout.bitsPerPixel + 7) / 8); 32572b676d7Smrg 32672b676d7Smrg /* Set accelerator dest color depth to 0 - not supported on 530/620 */ 32772b676d7Smrg pSiS->DstColor = 0; 32872b676d7Smrg 32972b676d7Smrg if(!pSiS->UseVESA) { 33072b676d7Smrg 33172b676d7Smrg /* set linear framebuffer addresses */ 33272b676d7Smrg switch(pScrn->videoRam) { 33372b676d7Smrg case 512: temp = 0x00; break; 33472b676d7Smrg case 1024: temp = 0x20; break; 33572b676d7Smrg case 2048: temp = 0x40; break; 33672b676d7Smrg case 4096: temp = 0x60; break; 33772b676d7Smrg case 8192: temp = 0x80; break; 33872b676d7Smrg default: temp = 0x20; 33972b676d7Smrg } 34072b676d7Smrg pReg->sisRegs3C4[0x20] = (pSiS->FbAddress & 0x07F80000) >> 19; 34172b676d7Smrg pReg->sisRegs3C4[0x21] = ((pSiS->FbAddress & 0xF8000000) >> 27) | temp; 34272b676d7Smrg 34372b676d7Smrg /* Set screen offset */ 34472b676d7Smrg pReg->sisRegs3D4[0x13] = offset & 0xFF; 34572b676d7Smrg 34672b676d7Smrg /* Set CR registers for our built-in TV and hi-res modes */ 34772b676d7Smrg if((sis6326tvmode) || (sis6326himode)) { 34872b676d7Smrg 34972b676d7Smrg int index,i; 35072b676d7Smrg 35172b676d7Smrg /* We need our very private data for hi-res and TV modes */ 35272b676d7Smrg if(sis6326himode) { 35372b676d7Smrg if(strcmp(mode->name, "SIS1280x1024-75") == 0) index = 7; 35472b676d7Smrg else index = 8; 35572b676d7Smrg } else { 35672b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 35772b676d7Smrg switch(width) { 35872b676d7Smrg case 800: 35972b676d7Smrg if((strcmp(mode->name, "PAL800x600U") == 0)) 36072b676d7Smrg index = 4; 36172b676d7Smrg else 36272b676d7Smrg index = 0; 36372b676d7Smrg break; 36472b676d7Smrg case 720: 36572b676d7Smrg index = 5; 36672b676d7Smrg break; 36772b676d7Smrg case 640: 36872b676d7Smrg default: 36972b676d7Smrg index = 1; 37072b676d7Smrg } 37172b676d7Smrg } else { 37272b676d7Smrg switch(height) { 37372b676d7Smrg case 400: 37472b676d7Smrg index = 3; 37572b676d7Smrg break; 37672b676d7Smrg case 480: 37772b676d7Smrg default: 37872b676d7Smrg if((strcmp(mode->name, "NTSC640x480U") == 0)) 37972b676d7Smrg index = 6; 38072b676d7Smrg else 38172b676d7Smrg index = 2; 38272b676d7Smrg } 38372b676d7Smrg } 38472b676d7Smrg } 38572b676d7Smrg for(i=0; i<=5; i++) { 38672b676d7Smrg pReg->sisRegs3D4[i] = SiS6326CR[index][i]; 38772b676d7Smrg } 38872b676d7Smrg pReg->sisRegs3C4[0x12] = SiS6326CR[index][6]; 38972b676d7Smrg pReg->sisRegs3D4[6] = SiS6326CR[index][7]; 39072b676d7Smrg pReg->sisRegs3D4[7] = SiS6326CR[index][8]; 39172b676d7Smrg pReg->sisRegs3D4[0x10] = SiS6326CR[index][9]; 39272b676d7Smrg pReg->sisRegs3D4[0x11] = SiS6326CR[index][10]; 39372b676d7Smrg pReg->sisRegs3D4[0x12] = SiS6326CR[index][11]; 39472b676d7Smrg pReg->sisRegs3D4[0x15] = SiS6326CR[index][12]; 39572b676d7Smrg pReg->sisRegs3D4[0x16] = SiS6326CR[index][13]; 39672b676d7Smrg pReg->sisRegs3D4[9] &= ~0x20; 39772b676d7Smrg pReg->sisRegs3D4[9] |= (SiS6326CR[index][14] & 0x20); 39872b676d7Smrg pReg->sisRegs3C4[0x0A] = ((offset & 0xF00) >> 4) | (SiS6326CR[index][14] & 0x0f); 39972b676d7Smrg 40072b676d7Smrg } else { 40172b676d7Smrg 40272b676d7Smrg /* Set extended vertical overflow register */ 40372b676d7Smrg pReg->sisRegs3C4[0x0A] = ( 40472b676d7Smrg ((offset & 0xF00) >> 4) | 40572b676d7Smrg (((mode->CrtcVTotal - 2) & 0x400) >> 10) | 40672b676d7Smrg (((mode->CrtcVDisplay - 1) & 0x400) >> 9) | 40772b676d7Smrg (((mode->CrtcVBlankStart - 1) & 0x400) >> 8) | 40872b676d7Smrg (((mode->CrtcVSyncStart - fixsync) & 0x400) >> 7)); 40972b676d7Smrg 41072b676d7Smrg /* Set extended horizontal overflow register */ 41172b676d7Smrg pReg->sisRegs3C4[0x12] &= 0xE0; 41272b676d7Smrg pReg->sisRegs3C4[0x12] |= ( 41372b676d7Smrg ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | 41472b676d7Smrg ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | 41572b676d7Smrg ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 6) | 41672b676d7Smrg ((((mode->CrtcHSyncStart >> 3) - fixsync)& 0x100) >> 5) | 41772b676d7Smrg ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 2)); 41872b676d7Smrg } 41972b676d7Smrg 42072b676d7Smrg /* enable (or disable) line compare */ 42172b676d7Smrg if(mode->CrtcVDisplay >= 1024) 42272b676d7Smrg pReg->sisRegs3C4[0x38] |= 0x04; 42372b676d7Smrg else 42472b676d7Smrg pReg->sisRegs3C4[0x38] &= 0xFB; 42572b676d7Smrg 42672b676d7Smrg /* Enable (or disable) high speed DCLK (some 6326 and 530/620 only) */ 42772b676d7Smrg if( ( (pSiS->Chipset == PCI_CHIP_SIS6326) && 42872b676d7Smrg ( (pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) || 42972b676d7Smrg (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) || 43072b676d7Smrg (pSiS->Flags & A6326REVAB) ) ) || 43172b676d7Smrg (pSiS->oldChipset > OC_SIS6326) ) { 43272b676d7Smrg if( (pSiS->CurrentLayout.bitsPerPixel == 24) || 43372b676d7Smrg (pSiS->CurrentLayout.bitsPerPixel == 32) || 43472b676d7Smrg (mode->CrtcHDisplay >= 1280) ) 43572b676d7Smrg pReg->sisRegs3C4[0x3E] |= 0x01; 43672b676d7Smrg else 43772b676d7Smrg pReg->sisRegs3C4[0x3E] &= 0xFE; 43872b676d7Smrg } 43972b676d7Smrg 44072b676d7Smrg /* We use the internal VCLK */ 44172b676d7Smrg pReg->sisRegs3C4[0x38] &= 0xFC; 44272b676d7Smrg 44372b676d7Smrg /* Programmable Clock */ 44472b676d7Smrg pReg->sisRegs3C2 = inSISREG(SISMISCR) | 0x0C; 44572b676d7Smrg 44672b676d7Smrg#if 0 44772b676d7Smrg if(pSiS->oldChipset <= OC_SIS86202) { 44872b676d7Smrg /* TODO: Handle SR07 for clock selection */ 44972b676d7Smrg /* 86C201 does not even have a programmable clock... */ 45072b676d7Smrg /* pReg->sisRegs3C4[0x07] &= 0x??; */ 45172b676d7Smrg } 45272b676d7Smrg#endif 45372b676d7Smrg 45472b676d7Smrg /* Set VCLK */ 45572b676d7Smrg if((sis6326tvmode) || (sis6326himode)) { 45672b676d7Smrg 45772b676d7Smrg /* For our built-in modes, the calculation is not suitable */ 45872b676d7Smrg if(sis6326himode) { 45972b676d7Smrg if((strcmp(mode->name, "SIS1280x1024-75") == 0)) { 46072b676d7Smrg pReg->sisRegs3C4[0x2A] = 0x5d; /* 1280x1024-75 */ 46172b676d7Smrg pReg->sisRegs3C4[0x2B] = 0xa4; 46272b676d7Smrg } else { 46372b676d7Smrg pReg->sisRegs3C4[0x2A] = 0x59; /* 1600x1200-60 */ 46472b676d7Smrg pReg->sisRegs3C4[0x2B] = 0xa3; 46572b676d7Smrg } 46672b676d7Smrg pReg->sisRegs3C4[0x13] &= ~0x40; 46772b676d7Smrg } else { 46872b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 46972b676d7Smrg /* PAL: 31.500 Mhz */ 47072b676d7Smrg if((strcmp(mode->name, "PAL800x600U") == 0)) { 47172b676d7Smrg pReg->sisRegs3C4[0x2A] = 0x46; 47272b676d7Smrg pReg->sisRegs3C4[0x2B] = 0x49; 47372b676d7Smrg } else { 47472b676d7Smrg pReg->sisRegs3C4[0x2A] = 0xab; 47572b676d7Smrg pReg->sisRegs3C4[0x2B] = 0xe9; 47672b676d7Smrg } 47772b676d7Smrg pReg->sisRegs3C4[0x13] &= ~0x40; 47872b676d7Smrg } else { 47972b676d7Smrg /* NTSC: 27.000 Mhz */ 48072b676d7Smrg if((strcmp(mode->name, "NTSC640x480U") == 0)) { 48172b676d7Smrg pReg->sisRegs3C4[0x2A] = 0x5a; 48272b676d7Smrg pReg->sisRegs3C4[0x2B] = 0x65; 48372b676d7Smrg } else { 48472b676d7Smrg pReg->sisRegs3C4[0x2A] = 0x29; 48572b676d7Smrg pReg->sisRegs3C4[0x2B] = 0xe2; 48672b676d7Smrg } 48772b676d7Smrg pReg->sisRegs3C4[0x13] |= 0x40; 48872b676d7Smrg } 48972b676d7Smrg } 49072b676d7Smrg 49172b676d7Smrg } else if(SiS_compute_vclk(clock, &num, &denum, &div, &sbit, &scale)) { 49272b676d7Smrg 49372b676d7Smrg pReg->sisRegs3C4[0x2A] = (num - 1) & 0x7f ; 49472b676d7Smrg pReg->sisRegs3C4[0x2A] |= (div == 2) ? 0x80 : 0; 49572b676d7Smrg pReg->sisRegs3C4[0x2B] = ((denum - 1) & 0x1f); 49672b676d7Smrg pReg->sisRegs3C4[0x2B] |= (((scale -1) & 3) << 5); 49772b676d7Smrg 49872b676d7Smrg /* When setting VCLK, we should set SR13 first */ 49972b676d7Smrg if(sbit) 50072b676d7Smrg pReg->sisRegs3C4[0x13] |= 0x40; 50172b676d7Smrg else 50272b676d7Smrg pReg->sisRegs3C4[0x13] &= 0xBF; 50372b676d7Smrg 50472b676d7Smrg#ifdef TWDEBUG 50572b676d7Smrg xf86DrvMsg(0, X_INFO, "2a: %x 2b: %x 13: %x clock %d\n", 50672b676d7Smrg pReg->sisRegs3C4[0x2A], pReg->sisRegs3C4[0x2B], pReg->sisRegs3C4[0x13], clock); 50772b676d7Smrg#endif 50872b676d7Smrg 50972b676d7Smrg } else { 51072b676d7Smrg 51172b676d7Smrg /* if SiS_compute_vclk cannot handle the requested clock, try sisCalcClock */ 51272b676d7Smrg SiSCalcClock(pScrn, clock, 2, vclk); 51372b676d7Smrg 51472b676d7Smrg#define Midx 0 51572b676d7Smrg#define Nidx 1 51672b676d7Smrg#define VLDidx 2 51772b676d7Smrg#define Pidx 3 51872b676d7Smrg#define PSNidx 4 51972b676d7Smrg 52072b676d7Smrg pReg->sisRegs3C4[0x2A] = (vclk[Midx] - 1) & 0x7f; 52172b676d7Smrg pReg->sisRegs3C4[0x2A] |= ((vclk[VLDidx] == 2) ? 1 : 0) << 7; 52272b676d7Smrg 52372b676d7Smrg /* D[4:0]: denumerator */ 52472b676d7Smrg pReg->sisRegs3C4[0x2B] = (vclk[Nidx] - 1) & 0x1f; 52572b676d7Smrg 52672b676d7Smrg if(vclk[Pidx] <= 4){ 52772b676d7Smrg /* postscale 1,2,3,4 */ 52872b676d7Smrg pReg->sisRegs3C4[0x2B] |= (vclk[Pidx] - 1) << 5; 52972b676d7Smrg pReg->sisRegs3C4[0x13] &= 0xBF; 53072b676d7Smrg } else { 53172b676d7Smrg /* postscale 6,8 */ 53272b676d7Smrg pReg->sisRegs3C4[0x2B] |= ((vclk[Pidx] / 2) - 1) << 5; 53372b676d7Smrg pReg->sisRegs3C4[0x13] |= 0x40; 53472b676d7Smrg } 53572b676d7Smrg pReg->sisRegs3C4[0x2B] |= 0x80 ; /* gain for high frequency */ 53672b676d7Smrg 53772b676d7Smrg } 53872b676d7Smrg 53972b676d7Smrg /* High speed DAC */ 54072b676d7Smrg if(clock > 135000) 54172b676d7Smrg pReg->sisRegs3C4[0x07] |= 0x02; 54272b676d7Smrg 54372b676d7Smrg if(pSiS->oldChipset > OC_SIS6225) { 54472b676d7Smrg /* 1 or 2 cycle DRAM (set by option FastVram) */ 54572b676d7Smrg if(pSiS->newFastVram == -1) { 54672b676d7Smrg if(pSiS->oldChipset == OC_SIS620) { 54772b676d7Smrg /* Use different default on the 620 */ 54872b676d7Smrg pReg->sisRegs3C4[0x34] |= 0x40; 54972b676d7Smrg pReg->sisRegs3C4[0x34] &= ~0x80; 55072b676d7Smrg } else { 55172b676d7Smrg pReg->sisRegs3C4[0x34] |= 0x80; 55272b676d7Smrg pReg->sisRegs3C4[0x34] &= ~0x40; 55372b676d7Smrg } 55472b676d7Smrg } else if(pSiS->newFastVram == 1) 55572b676d7Smrg pReg->sisRegs3C4[0x34] |= 0xC0; 55672b676d7Smrg else 55772b676d7Smrg pReg->sisRegs3C4[0x34] &= ~0xC0; 55872b676d7Smrg 55972b676d7Smrg if(pSiS->oldChipset == OC_SIS620) { 56072b676d7Smrg /* Enable SGRAM burst timing (= bit clear) on the 620 */ 56172b676d7Smrg if(pSiS->Flags & SYNCDRAM) { 56272b676d7Smrg pReg->sisRegs3C4[0x35] &= ~0x20; 56372b676d7Smrg } else { 56472b676d7Smrg pReg->sisRegs3C4[0x35] |= 0x20; 56572b676d7Smrg } 56672b676d7Smrg } 56772b676d7Smrg } 56872b676d7Smrg 56972b676d7Smrg } /* VESA */ 57072b676d7Smrg 57172b676d7Smrg /* Logical line length */ 57272b676d7Smrg pSiS->ValidWidth = TRUE; 57372b676d7Smrg pReg->sisRegs3C4[0x27] &= 0xCF; 57472b676d7Smrg if(pSiS->CurrentLayout.bitsPerPixel == 24) { 57572b676d7Smrg /* "Invalid logical width" */ 57672b676d7Smrg pReg->sisRegs3C4[0x27] |= 0x30; 57772b676d7Smrg pSiS->ValidWidth = FALSE; 57872b676d7Smrg } else { 57972b676d7Smrg switch(pScrn->virtualX * (pSiS->CurrentLayout.bitsPerPixel >> 3)) { 58072b676d7Smrg case 1024: 58172b676d7Smrg pReg->sisRegs3C4[0x27] |= 0x00; 58272b676d7Smrg break; 58372b676d7Smrg case 2048: 58472b676d7Smrg pReg->sisRegs3C4[0x27] |= 0x10; 58572b676d7Smrg break; 58672b676d7Smrg case 4096: 58772b676d7Smrg pReg->sisRegs3C4[0x27] |= 0x20; 58872b676d7Smrg break; 58972b676d7Smrg default: 59072b676d7Smrg /* Invalid logical width */ 59172b676d7Smrg pReg->sisRegs3C4[0x27] |= 0x30; 59272b676d7Smrg pSiS->ValidWidth = FALSE; 59372b676d7Smrg break; 59472b676d7Smrg } 59572b676d7Smrg } 59672b676d7Smrg 59772b676d7Smrg /* Acceleration stuff */ 59872b676d7Smrg if(!pSiS->NoAccel) { 59972b676d7Smrg pReg->sisRegs3C4[0x27] |= 0x40; /* Enable engine programming registers */ 60072b676d7Smrg if( (pSiS->TurboQueue) && /* Handle TurboQueue */ 60172b676d7Smrg (pSiS->oldChipset > OC_SIS6225) && 60272b676d7Smrg ( (pSiS->Chipset != PCI_CHIP_SIS530) || 60372b676d7Smrg (pSiS->CurrentLayout.bitsPerPixel != 24) ) ) { 60472b676d7Smrg pReg->sisRegs3C4[0x27] |= 0x80; /* Enable TQ */ 60572b676d7Smrg if((pSiS->Chipset == PCI_CHIP_SIS530) || 60672b676d7Smrg ((pSiS->Chipset == PCI_CHIP_SIS6326 && 60772b676d7Smrg (pSiS->ChipRev == 0xd0 || pSiS->ChipRev == 0xd1 || 60872b676d7Smrg pSiS->ChipRev == 0xd2 || pSiS->ChipRev == 0x92 || 60972b676d7Smrg pSiS->ChipRev == 0x0a || pSiS->ChipRev == 0x1a || 61072b676d7Smrg pSiS->ChipRev == 0x2a || pSiS->ChipRev == 0x0b || 61172b676d7Smrg pSiS->ChipRev == 0x1b || pSiS->ChipRev == 0x2b) ) ) ) { 61272b676d7Smrg /* pReg->sisRegs3C4[0x3D] |= 0x80; */ /* Queue is 62K (530/620 specs) */ 61372b676d7Smrg pReg->sisRegs3C4[0x3D] &= 0x7F; /* Queue is 30K (530/620 specs) */ 61472b676d7Smrg } 61572b676d7Smrg /* Locate the TQ at the beginning of the last 64K block of 61672b676d7Smrg * video RAM. The address is to be specified in 32K steps. 61772b676d7Smrg */ 61872b676d7Smrg pReg->sisRegs3C4[0x2C] = (pScrn->videoRam - 64) / 32; 61972b676d7Smrg if(pSiS->Chipset != PCI_CHIP_SIS530) { /* 530/620: Reserved (don't touch) */ 62072b676d7Smrg pReg->sisRegs3C4[0x3C] &= 0xFC; /* 6326: Queue is all for 2D */ 62172b676d7Smrg } /* 5597: Must be 0 */ 62272b676d7Smrg } else { 62372b676d7Smrg pReg->sisRegs3C4[0x27] &= 0x7F; 62472b676d7Smrg } 62572b676d7Smrg } 62672b676d7Smrg 62772b676d7Smrg 62872b676d7Smrg if(!pSiS->UseVESA) { 62972b676d7Smrg 63072b676d7Smrg /* No idea what this does. The Windows driver does it, so we do it as well */ 63172b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS6326) { 63272b676d7Smrg if((pSiS->ChipRev == 0xd0) || (pSiS->ChipRev == 0xd1) || 63372b676d7Smrg (pSiS->ChipRev == 0xd2) || (pSiS->ChipRev == 0x92) || 63472b676d7Smrg (pSiS->Flags & A6326REVAB)) { 63572b676d7Smrg if((pSiS->Flags & (SYNCDRAM | RAMFLAG)) == (SYNCDRAM | RAMFLAG)) { 63672b676d7Smrg if(!(pReg->sisRegs3C4[0x0E] & 0x03)) { 63772b676d7Smrg pReg->sisRegs3C4[0x3E] |= 0x02; 63872b676d7Smrg } 63972b676d7Smrg } 64072b676d7Smrg } 64172b676d7Smrg } 64272b676d7Smrg 64372b676d7Smrg /* Set memclock */ 64472b676d7Smrg#if 0 64572b676d7Smrg /* We don't need to do this; the SetMClk option was not used since 4.0. */ 64672b676d7Smrg if((pSiS->Chipset == PCI_CHIP_SIS5597) || (pSiS->Chipset == PCI_CHIP_SIS6326)) { 64772b676d7Smrg if(pSiS->MemClock > 66000) { 64872b676d7Smrg SiSCalcClock(pScrn, pSiS->MemClock, 1, vclk); 64972b676d7Smrg 65072b676d7Smrg pReg->sisRegs3C4[0x28] = (vclk[Midx] - 1) & 0x7f ; 65172b676d7Smrg pReg->sisRegs3C4[0x28] |= ((vclk[VLDidx] == 2 ) ? 1 : 0 ) << 7 ; 65272b676d7Smrg pReg->sisRegs3C4[0x29] = (vclk[Nidx] -1) & 0x1f ; /* bits [4:0] contain denumerator -MC */ 65372b676d7Smrg if(vclk[Pidx] <= 4) { 65472b676d7Smrg pReg->sisRegs3C4[0x29] |= (vclk[Pidx] - 1) << 5 ; /* postscale 1,2,3,4 */ 65572b676d7Smrg pReg->sisRegs3C4[0x13] &= 0x7F; 65672b676d7Smrg } else { 65772b676d7Smrg pReg->sisRegs3C4[0x29] |= ((vclk[Pidx] / 2) - 1) << 5 ; /* postscale 6,8 */ 65872b676d7Smrg pReg->sisRegs3C4[0x13] |= 0x80; 65972b676d7Smrg } 66072b676d7Smrg /* Check programmed memory clock. Enable only to check the above code */ 66172b676d7Smrg/* 66272b676d7Smrg mclk = 14318 * ((pReg->sisRegs3C4[0x28] & 0x7f) + 1); 66372b676d7Smrg mclk /= ((pReg->sisRegs3C4[0x29] & 0x0f) + 1); 66472b676d7Smrg if(!(pReg->sisRegs3C4[0x13] & 0x80)) { 66572b676d7Smrg mclk /= (((pReg->sisRegs3C4[0x29] & 0x60) >> 5) + 1); 66672b676d7Smrg } else { 66772b676d7Smrg if((pReg->sisRegs3C4[0x29] & 0x60) == 0x40) mclk /= 6; 66872b676d7Smrg if((pReg->sisRegs3C4[0x29] & 0x60) == 0x60) mclk /= 8; 66972b676d7Smrg } 67072b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO,2, 67172b676d7Smrg "Setting memory clock to %.3f MHz\n", 67272b676d7Smrg mclk/1000.0); 67372b676d7Smrg*/ 67472b676d7Smrg } 67572b676d7Smrg } 67672b676d7Smrg#endif 67772b676d7Smrg 67872b676d7Smrg /* Set threshold values */ 67972b676d7Smrg /* 68072b676d7Smrg * CPU/CRT Threshold: FIFO 68172b676d7Smrg * MCLK ___________ VCLK 68272b676d7Smrg * cpu/engine <---o o--------->|___________| -----------> CRT 68372b676d7Smrg * ^ ^ ^ ^ 68472b676d7Smrg * \ / | | 68572b676d7Smrg * \ / |< gap >| 68672b676d7Smrg * \ / | | 68772b676d7Smrg * selector switch Thrsh. low high 68872b676d7Smrg * 68972b676d7Smrg * CRT consumes the data in the FIFO during scanline display. When the 69072b676d7Smrg * amount of data in the FIFO reaches the Threshold low value, the selector 69172b676d7Smrg * switch will switch to the right, and the FIFO will be refilled with data. 69272b676d7Smrg * When the amount of data in the FIFO reaches the Threshold high value, the 69372b676d7Smrg * selector switch will switch to the left and allows the CPU and the chip 69472b676d7Smrg * engines to access the video RAM. 69572b676d7Smrg * 69672b676d7Smrg * The Threshold low values should be increased at higher bpps, simply because 69772b676d7Smrg * there is more data needed for the CRT. When Threshold low and high are very 69872b676d7Smrg * close to each other, the selector switch will be activated more often, which 69972b676d7Smrg * decreases performance. 70072b676d7Smrg * 70172b676d7Smrg */ 70272b676d7Smrg switch(pSiS->Chipset) { 70372b676d7Smrg case PCI_CHIP_SIS5597: factor = 65; break; 70472b676d7Smrg case PCI_CHIP_SIS6326: factor = 30; break; 70572b676d7Smrg case PCI_CHIP_SIS530: factor = (pSiS->Flags & UMA) ? 60 : 30; break; 70672b676d7Smrg default: factor = (pScrn->videoRam > 1024) ? 24 : 12; 70772b676d7Smrg } 70872b676d7Smrg a = width * height * rate * 1.40 * factor * ((pSiS->CurrentLayout.bitsPerPixel + 1) / 8); 70972b676d7Smrg b = (mclk / 1000) * 999488.0 * (buswidth / 8); 71072b676d7Smrg c = ((a / b) + 1.0) / 2; 71172b676d7Smrg d = (int)c + 2; 71272b676d7Smrg 71372b676d7Smrg CRT_CPUthresholdLow = d; 71472b676d7Smrg if((pSiS->Flags & (RAMFLAG | SYNCDRAM)) == (RAMFLAG | SYNCDRAM)) { 71572b676d7Smrg CRT_CPUthresholdLow += 2; 71672b676d7Smrg } 71772b676d7Smrg CRT_CPUthresholdHigh = CRT_CPUthresholdLow + 3; 71872b676d7Smrg 71972b676d7Smrg CRT_ENGthreshold = 0x0F; 72072b676d7Smrg 72172b676d7Smrg#if 0 /* See comment in sis_dac.c on why this is commented */ 72272b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS530) { 72372b676d7Smrg if((pSiS->oldChipset == OC_SIS530A) && 72472b676d7Smrg (pSiS->Flags & UMA) && 72572b676d7Smrg (mclk == 100000) && 72672b676d7Smrg (pSiS->Flags & ESS137xPRESENT)) { 72772b676d7Smrg if(!(pSiS->Flags & SECRETFLAG)) index = 0; 72872b676d7Smrg if((temp = SiS_CalcSpecial530Threshold(pSiS, mode, index)) { 72972b676d7Smrg CRT_CPUthresholdLow = temp; 73072b676d7Smrg break; 73172b676d7Smrg } 73272b676d7Smrg } 73372b676d7Smrg } 73472b676d7Smrg#endif 73572b676d7Smrg 73672b676d7Smrg switch(pSiS->Chipset) { 73772b676d7Smrg case PCI_CHIP_SIS530: 73872b676d7Smrg if(CRT_CPUthresholdLow > 0x1f) CRT_CPUthresholdLow = 0x1f; 73972b676d7Smrg CRT_CPUthresholdHigh = 0x1f; 74072b676d7Smrg break; 74172b676d7Smrg case PCI_CHIP_SIS5597: 74272b676d7Smrg case PCI_CHIP_SIS6326: 74372b676d7Smrg default: 74472b676d7Smrg if(CRT_CPUthresholdLow > 0x0f) CRT_CPUthresholdLow = 0x0f; 74572b676d7Smrg if(CRT_CPUthresholdHigh > 0x0f) CRT_CPUthresholdHigh = 0x0f; 74672b676d7Smrg } 74772b676d7Smrg 74872b676d7Smrg pReg->sisRegs3C4[0x08] = ((CRT_CPUthresholdLow & 0x0F) << 4) | 74972b676d7Smrg (CRT_ENGthreshold & 0x0F); 75072b676d7Smrg 75172b676d7Smrg pReg->sisRegs3C4[0x09] &= 0xF0; 75272b676d7Smrg pReg->sisRegs3C4[0x09] |= (CRT_CPUthresholdHigh & 0x0F); 75372b676d7Smrg 75472b676d7Smrg pReg->sisRegs3C4[0x3F] &= 0xEB; 75572b676d7Smrg pReg->sisRegs3C4[0x3F] |= ((CRT_CPUthresholdHigh & 0x10) | 75672b676d7Smrg ((CRT_CPUthresholdLow & 0x10) >> 2)); 75772b676d7Smrg 75872b676d7Smrg if(pSiS->oldChipset >= OC_SIS530A) { 75972b676d7Smrg pReg->sisRegs3C4[0x3F] &= 0xDF; 76072b676d7Smrg pReg->sisRegs3C4[0x3F] |= 0x58; 76172b676d7Smrg } 76272b676d7Smrg 76372b676d7Smrg /* Set SiS6326 TV registers */ 76472b676d7Smrg if((pSiS->Chipset == PCI_CHIP_SIS6326) && (sis6326tvmode)) { 76572b676d7Smrg UChar tmp; 76672b676d7Smrg int index=0, i, j, k; 76772b676d7Smrg int fsc; 76872b676d7Smrg 76972b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 77072b676d7Smrg pReg->sisRegs3C4[0x0D] |= 0x04; 77172b676d7Smrg switch(width) { 77272b676d7Smrg case 800: 77372b676d7Smrg if((strcmp(mode->name, "PAL800x600U") == 0)) index = 4; 77472b676d7Smrg else index = 3; 77572b676d7Smrg break; 77672b676d7Smrg case 720: index = 5; break; 77772b676d7Smrg case 640: 77872b676d7Smrg default: index = 2; 77972b676d7Smrg } 78072b676d7Smrg for(i=0; i<14; i++) { 78172b676d7Smrg pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_PAL[index][i]; 78272b676d7Smrg } 78372b676d7Smrg fsc = (SiS6326TVRegs1_PAL[index][2] << 16) | 78472b676d7Smrg (SiS6326TVRegs1_PAL[index][3] << 8) | 78572b676d7Smrg (SiS6326TVRegs1_PAL[index][4]); 78672b676d7Smrg } else { 78772b676d7Smrg pReg->sisRegs3C4[0x0D] &= ~0x04; 78872b676d7Smrg if((strcmp(mode->name, "NTSC640x480U") == 0)) index = 5; 78972b676d7Smrg else index = 4; 79072b676d7Smrg for(i=0; i<14; i++) { 79172b676d7Smrg pReg->sis6326tv[SiS6326TVRegs1[i]] = SiS6326TVRegs1_NTSC[index][i]; 79272b676d7Smrg } 79372b676d7Smrg fsc = (SiS6326TVRegs1_NTSC[index][2] << 16) | 79472b676d7Smrg (SiS6326TVRegs1_NTSC[index][3] << 8) | 79572b676d7Smrg (SiS6326TVRegs1_NTSC[index][4]); 79672b676d7Smrg } 79772b676d7Smrg if(pSiS->sis6326fscadjust) { 79872b676d7Smrg fsc += pSiS->sis6326fscadjust; 79972b676d7Smrg pReg->sis6326tv[2] = (fsc >> 16) & 0xff; 80072b676d7Smrg pReg->sis6326tv[3] = (fsc >> 8) & 0xff; 80172b676d7Smrg pReg->sis6326tv[4] = fsc & 0xff; 80272b676d7Smrg } 80372b676d7Smrg tmp = pReg->sis6326tv[0x43]; 80472b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp |= 0x10; 80572b676d7Smrg tmp |= 0x08; 80672b676d7Smrg pReg->sis6326tv[0x43] = tmp; 80772b676d7Smrg j = 0; k = 0; 80872b676d7Smrg for(i=0; i<=0x44; i++) { 80972b676d7Smrg if(SiS6326TVRegs1[j] == i) { 81072b676d7Smrg j++; 81172b676d7Smrg continue; 81272b676d7Smrg } 81372b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVPAL) { 81472b676d7Smrg tmp = SiS6326TVRegs2_PAL[index][k]; 81572b676d7Smrg } else { 81672b676d7Smrg tmp = SiS6326TVRegs2_NTSC[index][k]; 81772b676d7Smrg } 81872b676d7Smrg pReg->sis6326tv[i] = tmp; 81972b676d7Smrg k++; 82072b676d7Smrg } 82172b676d7Smrg pReg->sis6326tv[0x43] |= 0x08; 82272b676d7Smrg if((pSiS->ChipRev == 0xc1) || (pSiS->ChipRev == 0xc2)) { 82372b676d7Smrg pReg->sis6326tv[0x43] &= ~0x08; 82472b676d7Smrg } 82572b676d7Smrg 82672b676d7Smrg tmp = pReg->sis6326tv[0]; 82772b676d7Smrg tmp |= 0x18; 82872b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVCVBS) tmp &= ~0x10; 82972b676d7Smrg if(pSiS->SiS6326Flags & SIS6326_TVSVIDEO) tmp &= ~0x08; 83072b676d7Smrg tmp |= 0x04; 83172b676d7Smrg pReg->sis6326tv[0] = tmp; 83272b676d7Smrg } 83372b676d7Smrg 83472b676d7Smrg } /* VESA */ 83572b676d7Smrg 83672b676d7Smrg return TRUE; 83772b676d7Smrg} 83872b676d7Smrg 83972b676d7Smrg/* Init a mode for SiS 300, 315, 330, 340 series 84072b676d7Smrg * This function is now only used for setting up some 84172b676d7Smrg * variables (eg. scrnOffset). 84272b676d7Smrg */ 84372b676d7SmrgBool 84472b676d7SmrgSIS300Init(ScrnInfoPtr pScrn, DisplayModePtr mode) 84572b676d7Smrg{ 84672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 84772b676d7Smrg SISRegPtr pReg = &pSiS->ModeReg; 84872b676d7Smrg UShort temp; 84972b676d7Smrg DisplayModePtr realmode = mode; 85072b676d7Smrg 85172b676d7Smrg PDEBUG(xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, "SIS300Init()\n")); 85272b676d7Smrg 85372b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 4, 85472b676d7Smrg "virtualX = %d depth = %d Logical width = %d\n", 85572b676d7Smrg pScrn->virtualX, pSiS->CurrentLayout.bitsPerPixel, 85672b676d7Smrg pScrn->virtualX * pSiS->CurrentLayout.bitsPerPixel/8); 85772b676d7Smrg 85872b676d7Smrg#ifdef SISMERGED 85972b676d7Smrg if(pSiS->MergedFB) { 86072b676d7Smrg realmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1; 86172b676d7Smrg } 86272b676d7Smrg#endif 86372b676d7Smrg 86472b676d7Smrg /* Copy current register settings to structure */ 86572b676d7Smrg (*pSiS->SiSSave)(pScrn, pReg); 86672b676d7Smrg 86772b676d7Smrg /* Calculate Offset/Display Pitch */ 86872b676d7Smrg pSiS->scrnOffset = pSiS->CurrentLayout.displayWidth * 86972b676d7Smrg ((pSiS->CurrentLayout.bitsPerPixel + 7) / 8); 87072b676d7Smrg 87172b676d7Smrg pSiS->scrnPitch = pSiS->scrnPitch2 = pSiS->scrnOffset; 87272b676d7Smrg if(!(pSiS->VBFlags & CRT1_LCDA)) { 87372b676d7Smrg if(realmode->Flags & V_INTERLACE) pSiS->scrnPitch <<= 1; 87472b676d7Smrg } 87572b676d7Smrg /* CRT2 mode can never be interlaced */ 87672b676d7Smrg 87772b676d7Smrg#ifdef UNLOCK_ALWAYS 87872b676d7Smrg outSISIDXREG(SISSR, 0x05, 0x86); 87972b676d7Smrg#endif 88072b676d7Smrg 88172b676d7Smrg switch(pSiS->CurrentLayout.bitsPerPixel) { 88272b676d7Smrg case 8: 88372b676d7Smrg pSiS->DstColor = 0x0000; 88472b676d7Smrg pSiS->SiS310_AccelDepth = 0x00000000; 88572b676d7Smrg break; 88672b676d7Smrg case 16: 88772b676d7Smrg if(pSiS->CurrentLayout.depth == 15) 88872b676d7Smrg pSiS->DstColor = (short) 0x4000; 88972b676d7Smrg else 89072b676d7Smrg pSiS->DstColor = (short) 0x8000; 89172b676d7Smrg pSiS->SiS310_AccelDepth = 0x00010000; 89272b676d7Smrg break; 89372b676d7Smrg case 32: 89472b676d7Smrg pSiS->DstColor = (short) 0xC000; 89572b676d7Smrg pSiS->SiS310_AccelDepth = 0x00020000; 89672b676d7Smrg break; 89772b676d7Smrg } 89872b676d7Smrg 89972b676d7Smrg /* Enable PCI LINEAR ADDRESSING (0x80), MMIO (0x01), PCI_IO (0x20) */ 90072b676d7Smrg pReg->sisRegs3C4[0x20] = 0xA1; 90172b676d7Smrg 90272b676d7Smrg /* Now initialize TurboQueue. TB is always located at the very top of 90372b676d7Smrg * the videoRAM (notably NOT the x framebuffer memory, which can/should 90472b676d7Smrg * be limited by MaxXFbMem when using DRI). Also, enable the accelerators. 90572b676d7Smrg */ 90672b676d7Smrg if(!pSiS->NoAccel) { 90772b676d7Smrg pReg->sisRegs3C4[0x1E] |= 0x42; /* Enable 2D accelerator */ 90872b676d7Smrg pReg->sisRegs3C4[0x1E] |= 0x18; /* Enable 3D accelerator */ 90972b676d7Smrg switch(pSiS->VGAEngine) { 91072b676d7Smrg case SIS_300_VGA: 91172b676d7Smrg if(pSiS->TurboQueue) { /* set Turbo Queue as 512k */ 91272b676d7Smrg temp = ((pScrn->videoRam/64)-8); /* 8=512k, 4=256k, 2=128k, 1=64k */ 91372b676d7Smrg pReg->sisRegs3C4[0x26] = temp & 0xFF; 91472b676d7Smrg pReg->sisRegs3C4[0x27] = 91572b676d7Smrg (pReg->sisRegs3C4[0x27] & 0xfc) | (((temp >> 8) & 3) | 0xF0); 91672b676d7Smrg } /* line above new for saving D2&3 of status register */ 91772b676d7Smrg break; 91872b676d7Smrg case SIS_315_VGA: 91972b676d7Smrg#ifndef SISVRAMQ 92072b676d7Smrg /* See comments in sis_driver.c */ 92172b676d7Smrg pReg->sisRegs3C4[0x27] = 0x1F; 92272b676d7Smrg pReg->sisRegs3C4[0x26] = 0x22; 92372b676d7Smrg pReg->sisMMIO85C0 = (pScrn->videoRam - 512) * 1024; 92472b676d7Smrg#endif 92572b676d7Smrg break; 92672b676d7Smrg } 92772b676d7Smrg } 92872b676d7Smrg 92972b676d7Smrg return TRUE; 93072b676d7Smrg} 93172b676d7Smrg 93272b676d7Smrgstatic void 93372b676d7SmrgSiS6326TVDelay(ScrnInfoPtr pScrn, int delay) 93472b676d7Smrg{ 93572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 93672b676d7Smrg int i; 93772b676d7Smrg UChar temp; 93872b676d7Smrg 93972b676d7Smrg for(i=0; i<delay; i++) { 94072b676d7Smrg inSISIDXREG(SISSR, 0x05, temp); 94172b676d7Smrg } 94272b676d7Smrg (void)temp; 94372b676d7Smrg} 94472b676d7Smrg 94572b676d7Smrgstatic int 94672b676d7SmrgSIS6326DoSense(ScrnInfoPtr pScrn, int tempbh, int tempbl, int tempch, int tempcl) 94772b676d7Smrg{ 94872b676d7Smrg UChar temp; 94972b676d7Smrg 95072b676d7Smrg SiS6326SetTVReg(pScrn, 0x42, tempbl); 95172b676d7Smrg temp = SiS6326GetTVReg(pScrn, 0x43); 95272b676d7Smrg temp &= 0xfc; 95372b676d7Smrg temp |= tempbh; 95472b676d7Smrg SiS6326SetTVReg(pScrn, 0x43, temp); 95572b676d7Smrg SiS6326TVDelay(pScrn, 0x1000); 95672b676d7Smrg temp = SiS6326GetTVReg(pScrn, 0x43); 95772b676d7Smrg temp |= 0x04; 95872b676d7Smrg SiS6326SetTVReg(pScrn, 0x43, temp); 95972b676d7Smrg SiS6326TVDelay(pScrn, 0x8000); 96072b676d7Smrg temp = SiS6326GetTVReg(pScrn, 0x44); 96172b676d7Smrg if(!(tempch & temp)) tempcl = 0; 96272b676d7Smrg return tempcl; 96372b676d7Smrg} 96472b676d7Smrg 96572b676d7Smrgstatic void 96672b676d7SmrgSISSense6326(ScrnInfoPtr pScrn) 96772b676d7Smrg{ 96872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 96972b676d7Smrg UChar temp; 97072b676d7Smrg int result; 97172b676d7Smrg 97272b676d7Smrg pSiS->SiS6326Flags &= (SIS6326_HASTV | SIS6326_TVPAL); 97372b676d7Smrg temp = SiS6326GetTVReg(pScrn, 0x43); 97472b676d7Smrg temp &= 0xfb; 97572b676d7Smrg SiS6326SetTVReg(pScrn, 0x43, temp); 97672b676d7Smrg result = SIS6326DoSense(pScrn, 0x01, 0xb0, 0x06, SIS6326_TVSVIDEO); /* 0x02 */ 97772b676d7Smrg pSiS->SiS6326Flags |= result; 97872b676d7Smrg result = SIS6326DoSense(pScrn, 0x01, 0xa0, 0x01, SIS6326_TVCVBS); /* 0x04 */ 97972b676d7Smrg pSiS->SiS6326Flags |= result; 98072b676d7Smrg temp = SiS6326GetTVReg(pScrn, 0x43); 98172b676d7Smrg temp &= 0xfb; 98272b676d7Smrg SiS6326SetTVReg(pScrn, 0x43, temp); 98372b676d7Smrg if(pSiS->SiS6326Flags & (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) { 98472b676d7Smrg pSiS->SiS6326Flags |= SIS6326_TVDETECTED; 98572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 98672b676d7Smrg "SiS6326: Detected TV connected to %s output\n", 98772b676d7Smrg (((pSiS->SiS6326Flags & (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) == 98872b676d7Smrg (SIS6326_TVSVIDEO | SIS6326_TVCVBS)) ? 98972b676d7Smrg "both SVIDEO and COMPOSITE" : 99072b676d7Smrg ((pSiS->SiS6326Flags & SIS6326_TVSVIDEO) ? 99172b676d7Smrg "SVIDEO" : "COMPOSITE"))); 99272b676d7Smrg } else { 99372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 99472b676d7Smrg "SiS6326: No TV detected\n"); 99572b676d7Smrg } 99672b676d7Smrg} 99772b676d7Smrg 99872b676d7Smrgstatic Bool 99972b676d7SmrgSISIsUMC(SISPtr pSiS) 100072b676d7Smrg{ 100172b676d7Smrg UShort p4_0f, p4_25, p4_27, temp; 100272b676d7Smrg 100372b676d7Smrg inSISIDXREG(SISPART4, 0x0f, p4_0f); 100472b676d7Smrg inSISIDXREG(SISPART4, 0x25, p4_25); 100572b676d7Smrg inSISIDXREG(SISPART4, 0x27, p4_27); 100672b676d7Smrg andSISIDXREG(SISPART4, 0x0f, 0x7f); 100772b676d7Smrg orSISIDXREG(SISPART4, 0x25, 0x08); 100872b676d7Smrg andSISIDXREG(SISPART4, 0x27, 0xfd); 100972b676d7Smrg inSISIDXREG(SISPART4, 0x26, temp); 101072b676d7Smrg outSISIDXREG(SISPART4, 0x27, p4_27); 101172b676d7Smrg outSISIDXREG(SISPART4, 0x25, p4_25); 101272b676d7Smrg outSISIDXREG(SISPART4, 0x0f, p4_0f); 101372b676d7Smrg return((temp & 0x08) ? TRUE : FALSE); 101472b676d7Smrg} 101572b676d7Smrg 101672b676d7Smrg/* Detect video bridge and set VBFlags accordingly */ 101772b676d7Smrgvoid SISVGAPreInit(ScrnInfoPtr pScrn) 101872b676d7Smrg{ 101972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 102072b676d7Smrg int temp,temp1,temp2,sistypeidx; 102172b676d7Smrg int upperlimitlvds, lowerlimitlvds; 102272b676d7Smrg int upperlimitch, lowerlimitch; 102372b676d7Smrg int chronteltype, chrontelidreg, upperlimitvb; 102472b676d7Smrg static const char *detectvb = "Detected SiS%s video bridge (%s, ID %d; Rev 0x%x)\n"; 102572b676d7Smrg#if 0 102672b676d7Smrg UChar sr17=0; 102772b676d7Smrg#endif 102872b676d7Smrg static const char *ChrontelTypeStr[] = { 102972b676d7Smrg "7004", 103072b676d7Smrg "7005", 103172b676d7Smrg "7007", 103272b676d7Smrg "7006", 103372b676d7Smrg "7008", 103472b676d7Smrg "7013", 103572b676d7Smrg "7019", 103672b676d7Smrg "7020", 103772b676d7Smrg "(unknown)" 103872b676d7Smrg }; 103972b676d7Smrg static const char *SiSVBTypeStr[] = { 104072b676d7Smrg "301", /* 0 */ 104172b676d7Smrg "301B", /* 1 */ 104272b676d7Smrg "301B-DH", /* 2 */ 104372b676d7Smrg "301LV", /* 3 */ 104472b676d7Smrg "302LV", /* 4 */ 104572b676d7Smrg "301C", /* 5 */ 104672b676d7Smrg "302ELV", /* 6 */ 104772b676d7Smrg "302B" /* 7 */ 104872b676d7Smrg }; 104972b676d7Smrg 105072b676d7Smrg switch(pSiS->Chipset) { 105172b676d7Smrg case PCI_CHIP_SIS300: 105272b676d7Smrg case PCI_CHIP_SIS540: 105372b676d7Smrg case PCI_CHIP_SIS630: 105472b676d7Smrg case PCI_CHIP_SIS550: 105572b676d7Smrg case PCI_CHIP_SIS315: 105672b676d7Smrg case PCI_CHIP_SIS315H: 105772b676d7Smrg case PCI_CHIP_SIS315PRO: 105872b676d7Smrg case PCI_CHIP_SIS650: 105972b676d7Smrg case PCI_CHIP_SIS330: 106072b676d7Smrg case PCI_CHIP_SIS660: 106172b676d7Smrg case PCI_CHIP_SIS340: 106272b676d7Smrg case PCI_CHIP_XGIXG20: 106372b676d7Smrg case PCI_CHIP_XGIXG40: 106472b676d7Smrg pSiS->ModeInit = SIS300Init; 106572b676d7Smrg break; 106672b676d7Smrg default: 106772b676d7Smrg pSiS->ModeInit = SISInit; 106872b676d7Smrg } 106972b676d7Smrg 107072b676d7Smrg if((pSiS->Chipset == PCI_CHIP_SIS6326) && (pSiS->SiS6326Flags & SIS6326_HASTV)) { 107172b676d7Smrg UChar sr0d; 107272b676d7Smrg inSISIDXREG(SISSR, 0x0d, sr0d); 107372b676d7Smrg if(sr0d & 0x04) { 107472b676d7Smrg pSiS->SiS6326Flags |= SIS6326_TVPAL; 107572b676d7Smrg } 107672b676d7Smrg SISSense6326(pScrn); 107772b676d7Smrg } 107872b676d7Smrg 107972b676d7Smrg pSiS->VBFlags = pSiS->VBFlags2 = 0; /* reset VBFlags */ 108072b676d7Smrg pSiS->SiS_Pr->SiS_UseLCDA = FALSE; 108172b676d7Smrg pSiS->SiS_Pr->Backup = FALSE; 108272b676d7Smrg 108372b676d7Smrg /* Videobridges only available for 300/315/330/340 series */ 108472b676d7Smrg if((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) 108572b676d7Smrg return; 108672b676d7Smrg 108772b676d7Smrg /* No video bridge ever on XGI Z7 (XG20) */ 108872b676d7Smrg if(pSiS->ChipType == XGI_20) 108972b676d7Smrg return; 109072b676d7Smrg 109172b676d7Smrg inSISIDXREG(SISPART4, 0x00, temp); 109272b676d7Smrg temp &= 0x0F; 109372b676d7Smrg if(temp == 1) { 109472b676d7Smrg 109572b676d7Smrg inSISIDXREG(SISPART4, 0x01, temp1); 109672b676d7Smrg temp1 &= 0xff; 109772b676d7Smrg 109872b676d7Smrg if(temp1 >= 0xC0) { 109972b676d7Smrg if(SISIsUMC(pSiS)) pSiS->VBFlags2 |= VB2_SISUMC; 110072b676d7Smrg } 110172b676d7Smrg 110272b676d7Smrg if(temp1 >= 0xE0) { 110372b676d7Smrg inSISIDXREG(SISPART4, 0x39, temp2); 110472b676d7Smrg if(temp2 == 0xff) { 110572b676d7Smrg pSiS->VBFlags2 |= VB2_302LV; 110672b676d7Smrg sistypeidx = 4; 110772b676d7Smrg } else { 110872b676d7Smrg pSiS->VBFlags2 |= VB2_301C; /* VB_302ELV; */ 110972b676d7Smrg sistypeidx = 5; /* 6; */ 111072b676d7Smrg } 111172b676d7Smrg } else if(temp1 >= 0xD0) { 111272b676d7Smrg pSiS->VBFlags2 |= VB2_301LV; 111372b676d7Smrg sistypeidx = 3; 111472b676d7Smrg } else if(temp1 >= 0xC0) { 111572b676d7Smrg pSiS->VBFlags2 |= VB2_301C; 111672b676d7Smrg sistypeidx = 5; 111772b676d7Smrg } else if(temp1 >= 0xB0) { 111872b676d7Smrg pSiS->VBFlags2 |= VB2_301B; 111972b676d7Smrg sistypeidx = 1; 112072b676d7Smrg inSISIDXREG(SISPART4, 0x23, temp2); 112172b676d7Smrg if(!(temp2 & 0x02)) { 112272b676d7Smrg pSiS->VBFlags2 |= VB2_30xBDH; 112372b676d7Smrg sistypeidx = 2; 112472b676d7Smrg } 112572b676d7Smrg } else { 112672b676d7Smrg pSiS->VBFlags2 |= VB2_301; 112772b676d7Smrg sistypeidx = 0; 112872b676d7Smrg } 112972b676d7Smrg 113072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, detectvb, SiSVBTypeStr[sistypeidx], 113172b676d7Smrg (pSiS->VBFlags2 & VB2_SISUMC) ? "UMC-0" : "Charter/UMC-1", 1, temp1); 113272b676d7Smrg 113372b676d7Smrg SISSense30x(pScrn, FALSE); 113472b676d7Smrg 113572b676d7Smrg } else if(temp == 2) { 113672b676d7Smrg 113772b676d7Smrg inSISIDXREG(SISPART4, 0x01, temp1); 113872b676d7Smrg temp1 &= 0xff; 113972b676d7Smrg 114072b676d7Smrg if(temp1 >= 0xC0) { 114172b676d7Smrg if(SISIsUMC(pSiS)) pSiS->VBFlags2 |= VB2_SISUMC; 114272b676d7Smrg } 114372b676d7Smrg 114472b676d7Smrg if(temp1 >= 0xE0) { 114572b676d7Smrg pSiS->VBFlags2 |= VB2_302LV; 114672b676d7Smrg sistypeidx = 4; 114772b676d7Smrg } else if(temp1 >= 0xD0) { 114872b676d7Smrg pSiS->VBFlags2 |= VB2_301LV; 114972b676d7Smrg sistypeidx = 3; 115072b676d7Smrg } else { 115172b676d7Smrg pSiS->VBFlags2 |= VB2_302B; 115272b676d7Smrg sistypeidx = 7; 115372b676d7Smrg } 115472b676d7Smrg 115572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, detectvb, SiSVBTypeStr[sistypeidx], 115672b676d7Smrg (pSiS->VBFlags2 & VB2_SISUMC) ? "UMC-0" : "Charter/UMC-1", 2, temp1); 115772b676d7Smrg 115872b676d7Smrg SISSense30x(pScrn, FALSE); 115972b676d7Smrg 116072b676d7Smrg } else if (temp == 3) { 116172b676d7Smrg 116272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, detectvb, "303", "unsupported, unknown", temp, 0); 116372b676d7Smrg 116472b676d7Smrg } else { 116572b676d7Smrg 116672b676d7Smrg if(pSiS->NewCRLayout) { 116772b676d7Smrg inSISIDXREG(SISCR, 0x38, temp); 116872b676d7Smrg temp = (temp >> 5) & 0x07; 116972b676d7Smrg } else { 117072b676d7Smrg inSISIDXREG(SISCR, 0x37, temp); 117172b676d7Smrg temp = (temp >> 1) & 0x07; 117272b676d7Smrg } 117372b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 117472b676d7Smrg lowerlimitlvds = 2; upperlimitlvds = 4; 117572b676d7Smrg lowerlimitch = 4; upperlimitch = 5; 117672b676d7Smrg chronteltype = 1; chrontelidreg = 0x25; 117772b676d7Smrg upperlimitvb = upperlimitlvds; 117872b676d7Smrg } else { 117972b676d7Smrg lowerlimitlvds = 2; upperlimitlvds = 3; 118072b676d7Smrg lowerlimitch = 3; upperlimitch = 3; 118172b676d7Smrg chronteltype = 2; chrontelidreg = 0x4b; 118272b676d7Smrg upperlimitvb = upperlimitlvds; 118372b676d7Smrg if(pSiS->NewCRLayout) { 118472b676d7Smrg upperlimitvb = 4; 118572b676d7Smrg } 118672b676d7Smrg } 118772b676d7Smrg 118872b676d7Smrg if((temp >= lowerlimitlvds) && (temp <= upperlimitlvds)) { 118972b676d7Smrg pSiS->VBFlags2 |= VB2_LVDS; 119072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 119172b676d7Smrg "Detected LVDS transmitter (External chip ID %d)\n", temp); 119272b676d7Smrg } 119372b676d7Smrg if((temp >= lowerlimitch) && (temp <= upperlimitch)) { 119472b676d7Smrg /* Set global for init301.c */ 119572b676d7Smrg pSiS->SiS_Pr->SiS_IF_DEF_CH70xx = chronteltype; 119672b676d7Smrg 119772b676d7Smrg if(chronteltype == 1) { 119872b676d7Smrg /* Set general purpose IO for Chrontel communication */ 119972b676d7Smrg SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x9c); 120072b676d7Smrg } 120172b676d7Smrg 120272b676d7Smrg /* Read Chrontel version number */ 120372b676d7Smrg temp1 = SiS_GetCH70xx(pSiS->SiS_Pr, chrontelidreg); 120472b676d7Smrg if(chronteltype == 1) { 120572b676d7Smrg /* See Chrontel TB31 for explanation */ 120672b676d7Smrg temp2 = SiS_GetCH700x(pSiS->SiS_Pr, 0x0e); 120772b676d7Smrg if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) { 120872b676d7Smrg SiS_SetCH700x(pSiS->SiS_Pr, 0x0e, 0x0b); 120972b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 300); 121072b676d7Smrg } 121172b676d7Smrg temp2 = SiS_GetCH70xx(pSiS->SiS_Pr, chrontelidreg); 121272b676d7Smrg if(temp2 != temp1) temp1 = temp2; 121372b676d7Smrg } 121472b676d7Smrg if(temp1 == 0xFFFF) { /* 0xFFFF = error reading DDC port */ 121572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 121672b676d7Smrg "Detected Chrontel 70xx, but encountered error reading I2C port\n"); 121772b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x07); 121872b676d7Smrg pSiS->postVBCR32 &= ~0x07; 121972b676d7Smrg } else if((temp1 >= 0x19) && (temp1 <= 200)) { 122072b676d7Smrg /* We only support device ids 0x19-200; other values may indicate DDC problems */ 122172b676d7Smrg pSiS->VBFlags2 |= VB2_CHRONTEL; 122272b676d7Smrg switch (temp1) { 122372b676d7Smrg case 0x32: temp2 = 0; pSiS->ChrontelType = CHRONTEL_700x; break; 122472b676d7Smrg case 0x3A: temp2 = 1; pSiS->ChrontelType = CHRONTEL_700x; break; 122572b676d7Smrg case 0x50: temp2 = 2; pSiS->ChrontelType = CHRONTEL_700x; break; 122672b676d7Smrg case 0x2A: temp2 = 3; pSiS->ChrontelType = CHRONTEL_700x; break; 122772b676d7Smrg case 0x40: temp2 = 4; pSiS->ChrontelType = CHRONTEL_700x; break; 122872b676d7Smrg case 0x22: temp2 = 5; pSiS->ChrontelType = CHRONTEL_700x; break; 122972b676d7Smrg case 0x19: temp2 = 6; pSiS->ChrontelType = CHRONTEL_701x; break; 123072b676d7Smrg case 0x20: temp2 = 7; pSiS->ChrontelType = CHRONTEL_701x; break; /* ID for 7020? */ 123172b676d7Smrg default: temp2 = 8; pSiS->ChrontelType = CHRONTEL_701x; break; 123272b676d7Smrg } 123372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 123472b676d7Smrg "Detected Chrontel %s TV encoder (ID 0x%02x; chip ID %d)\n", 123572b676d7Smrg ChrontelTypeStr[temp2], temp1, temp); 123672b676d7Smrg 123772b676d7Smrg /* Sense connected TV's */ 123872b676d7Smrg SISSenseChrontel(pScrn, FALSE); 123972b676d7Smrg 124072b676d7Smrg } else if(temp1 == 0) { 124172b676d7Smrg /* This indicates a communication problem, but it only occures if there 124272b676d7Smrg * is no TV attached. So we don't use TV in this case. 124372b676d7Smrg */ 124472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 124572b676d7Smrg "Detected Chrontel TV encoder in promiscuous state (DDC/I2C mix-up)\n"); 124672b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x07); 124772b676d7Smrg pSiS->postVBCR32 &= ~0x07; 124872b676d7Smrg } else { 124972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 125072b676d7Smrg "Chrontel: Unsupported device id (%d) detected\n",temp1); 125172b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x07); 125272b676d7Smrg pSiS->postVBCR32 &= ~0x07; 125372b676d7Smrg } 125472b676d7Smrg if(chronteltype == 1) { 125572b676d7Smrg /* Set general purpose IO for Chrontel communication */ 125672b676d7Smrg SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x00); 125772b676d7Smrg } 125872b676d7Smrg } 125972b676d7Smrg if((pSiS->NewCRLayout) && (temp == 4)) { 126072b676d7Smrg pSiS->VBFlags2 |= VB2_CONEXANT; 126172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 126272b676d7Smrg "Detected Conexant video bridge - UNSUPPORTED\n"); 126372b676d7Smrg } 126472b676d7Smrg if((pSiS->VGAEngine == SIS_300_VGA) && (temp == 3)) { 126572b676d7Smrg pSiS->VBFlags2 |= VB2_TRUMPION; 126672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 126772b676d7Smrg "Detected Trumpion Zurac (I/II/III) LVDS scaler\n"); 126872b676d7Smrg } 126972b676d7Smrg if(temp > upperlimitvb) { 127072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 127172b676d7Smrg "Detected unknown bridge type (%d)\n", temp); 127272b676d7Smrg } 127372b676d7Smrg } 127472b676d7Smrg 127572b676d7Smrg /* Old BIOSes store the detected CRT2 type in SR17, 16 and 13 127672b676d7Smrg * instead of CR32. However, since our detection routines 127772b676d7Smrg * store their results to CR32, we now copy the 127872b676d7Smrg * remaining bits (for LCD and VGA) to CR32 for unified usage. 127972b676d7Smrg * SR17[0] CRT1 [1] LCD [2] TV [3] VGA2 128072b676d7Smrg * [4] AVIDEO [5] SVIDEO 128172b676d7Smrg * SR13[0] SCART [1] HiVision 128272b676d7Smrg * SR16[5] PAL/NTSC [6] LCD-SCALE [7] OVERSCAN 128372b676d7Smrg */ 128472b676d7Smrg 128572b676d7Smrg#if 0 128672b676d7Smrg inSISIDXREG(SISSR, 0x17, sr17); 128772b676d7Smrg if( (pSiS->VGAEngine == SIS_300_VGA) && 128872b676d7Smrg (pSiS->Chipset != PCI_CHIP_SIS300) && 128972b676d7Smrg (sr17 & 0x0F) ) { 129072b676d7Smrg 129172b676d7Smrg UChar cr32; 129272b676d7Smrg inSISIDXREG(SISCR, 0x32, cr32); 129372b676d7Smrg 129472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 129572b676d7Smrg "Converting SR17 (%02x) to CR32 (%02x)\n", sr17, cr32); 129672b676d7Smrg 129772b676d7Smrg if(sr17 & 0x01) { /* CRT1 */ 129872b676d7Smrg orSISIDXREG(SISCR, 0x32, 0x20); 129972b676d7Smrg pSiS->postVBCR32 |= 0x20; 130072b676d7Smrg } else { 130172b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x20); 130272b676d7Smrg pSiS->postVBCR32 &= ~0x20; 130372b676d7Smrg } 130472b676d7Smrg 130572b676d7Smrg if(sr17 & 0x02) { /* LCD */ 130672b676d7Smrg orSISIDXREG(SISCR, 0x32, 0x08); 130772b676d7Smrg pSiS->postVBCR32 |= 0x08; 130872b676d7Smrg } else { 130972b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x08); 131072b676d7Smrg pSiS->postVBCR32 &= ~0x08; 131172b676d7Smrg } 131272b676d7Smrg 131372b676d7Smrg /* No Hivision, no DVI here */ 131472b676d7Smrg andSISIDXREG(SISCR,0x32,~0xc0); 131572b676d7Smrg pSiS->postVBCR32 &= ~0xc0; 131672b676d7Smrg } 131772b676d7Smrg#endif 131872b676d7Smrg 131972b676d7Smrg /* Try to find out if the bridge uses LCDA for low resolution and 132072b676d7Smrg * text modes. If sisfb saved this for us, use it. Otherwise, 132172b676d7Smrg * check if we are running on a low mode on LCD and read the 132272b676d7Smrg * relevant registers ourselves. 132372b676d7Smrg */ 132472b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 132572b676d7Smrg 132672b676d7Smrg if(pSiS->VBFlags2 & VB2_SISLCDABRIDGE) { 132772b676d7Smrg if(pSiS->sisfblcda != 0xff) { 132872b676d7Smrg if((pSiS->sisfblcda & 0x03) == 0x03) { 132972b676d7Smrg pSiS->SiS_Pr->SiS_UseLCDA = TRUE; 133072b676d7Smrg pSiS->ChipFlags |= SiSCF_UseLCDA; 133172b676d7Smrg } 133272b676d7Smrg } else { 133372b676d7Smrg inSISIDXREG(SISCR,0x34,temp); 133472b676d7Smrg if(temp <= 0x13) { 133572b676d7Smrg inSISIDXREG(SISCR,0x38,temp); 133672b676d7Smrg if((temp & 0x03) == 0x03) { 133772b676d7Smrg pSiS->SiS_Pr->SiS_UseLCDA = TRUE; 133872b676d7Smrg pSiS->ChipFlags |= SiSCF_UseLCDA; 133972b676d7Smrg pSiS->SiS_Pr->Backup = TRUE; 134072b676d7Smrg } else { 134172b676d7Smrg orSISIDXREG(SISPART1,0x2f,0x01); /* Unlock CRT2 */ 134272b676d7Smrg inSISIDXREG(SISPART1,0x13,temp); 134372b676d7Smrg if(temp & 0x04) { 134472b676d7Smrg pSiS->SiS_Pr->SiS_UseLCDA = TRUE; 134572b676d7Smrg pSiS->ChipFlags |= SiSCF_UseLCDA; 134672b676d7Smrg pSiS->SiS_Pr->Backup = TRUE; 134772b676d7Smrg } 134872b676d7Smrg } 134972b676d7Smrg } 135072b676d7Smrg } 135172b676d7Smrg if(pSiS->ChipFlags & SiSCF_UseLCDA) { 135272b676d7Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 3, 135372b676d7Smrg "BIOS uses LCDA for low resolution and text modes\n"); 135472b676d7Smrg if(pSiS->SiS_Pr->Backup == TRUE) { 135572b676d7Smrg inSISIDXREG(SISCR,0x34,pSiS->SiS_Pr->Backup_Mode); 135672b676d7Smrg inSISIDXREG(SISPART1,0x14,pSiS->SiS_Pr->Backup_14); 135772b676d7Smrg inSISIDXREG(SISPART1,0x15,pSiS->SiS_Pr->Backup_15); 135872b676d7Smrg inSISIDXREG(SISPART1,0x16,pSiS->SiS_Pr->Backup_16); 135972b676d7Smrg inSISIDXREG(SISPART1,0x17,pSiS->SiS_Pr->Backup_17); 136072b676d7Smrg inSISIDXREG(SISPART1,0x18,pSiS->SiS_Pr->Backup_18); 136172b676d7Smrg inSISIDXREG(SISPART1,0x19,pSiS->SiS_Pr->Backup_19); 136272b676d7Smrg inSISIDXREG(SISPART1,0x1a,pSiS->SiS_Pr->Backup_1a); 136372b676d7Smrg inSISIDXREG(SISPART1,0x1b,pSiS->SiS_Pr->Backup_1b); 136472b676d7Smrg inSISIDXREG(SISPART1,0x1c,pSiS->SiS_Pr->Backup_1c); 136572b676d7Smrg inSISIDXREG(SISPART1,0x1d,pSiS->SiS_Pr->Backup_1d); 136672b676d7Smrg } 136772b676d7Smrg } 136872b676d7Smrg } 136972b676d7Smrg } 137072b676d7Smrg} 137172b676d7Smrg 137272b676d7Smrgstatic void 137372b676d7SmrgSiS_WriteAttr(SISPtr pSiS, int index, int value) 137472b676d7Smrg{ 137572b676d7Smrg (void)inSISREG(SISINPSTAT); 137672b676d7Smrg index |= 0x20; 137772b676d7Smrg outSISREG(SISAR, index); 137872b676d7Smrg outSISREG(SISAR, value); 137972b676d7Smrg} 138072b676d7Smrg 138172b676d7Smrgstatic int 138272b676d7SmrgSiS_ReadAttr(SISPtr pSiS, int index) 138372b676d7Smrg{ 138472b676d7Smrg (void)inSISREG(SISINPSTAT); 138572b676d7Smrg index |= 0x20; 138672b676d7Smrg outSISREG(SISAR, index); 138772b676d7Smrg return(inSISREG(SISARR)); 138872b676d7Smrg} 138972b676d7Smrg 139072b676d7Smrgstatic void 139172b676d7SmrgSiS_EnablePalette(SISPtr pSiS) 139272b676d7Smrg{ 139372b676d7Smrg (void)inSISREG(SISINPSTAT); 139472b676d7Smrg outSISREG(SISAR, 0x00); 139572b676d7Smrg pSiS->VGAPaletteEnabled = TRUE; 139672b676d7Smrg} 139772b676d7Smrg 139872b676d7Smrgstatic void 139972b676d7SmrgSiS_DisablePalette(SISPtr pSiS) 140072b676d7Smrg{ 140172b676d7Smrg (void)inSISREG(SISINPSTAT); 140272b676d7Smrg outSISREG(SISAR, 0x20); 140372b676d7Smrg pSiS->VGAPaletteEnabled = FALSE; 140472b676d7Smrg} 140572b676d7Smrg 140672b676d7Smrgvoid 140772b676d7SmrgSISVGALock(SISPtr pSiS) 140872b676d7Smrg{ 140972b676d7Smrg orSISIDXREG(SISCR, 0x11, 0x80); /* Protect CRTC[0-7] */ 141072b676d7Smrg} 141172b676d7Smrg 141272b676d7Smrgvoid 141372b676d7SmrgSiSVGAUnlock(SISPtr pSiS) 141472b676d7Smrg{ 141572b676d7Smrg andSISIDXREG(SISCR, 0x11, 0x7f); /* Unprotect CRTC[0-7] */ 141672b676d7Smrg} 141772b676d7Smrg 141872b676d7Smrg#define SIS_FONTS_SIZE (8 * 8192) 141972b676d7Smrg 142072b676d7Smrgvoid 142172b676d7SmrgSiSVGASaveFonts(ScrnInfoPtr pScrn) 142272b676d7Smrg{ 142372b676d7Smrg#ifdef SIS_PC_PLATFORM 142472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 142572b676d7Smrg pointer vgaMemBase = pSiS->VGAMemBase; 142672b676d7Smrg UChar miscOut, attr10, gr4, gr5, gr6, seq2, seq4, scrn; 142772b676d7Smrg 142872b676d7Smrg if((pSiS->fonts) || (vgaMemBase == NULL)) return; 142972b676d7Smrg 143072b676d7Smrg /* If in graphics mode, don't save anything */ 143172b676d7Smrg attr10 = SiS_ReadAttr(pSiS, 0x10); 143272b676d7Smrg if(attr10 & 0x01) return; 143372b676d7Smrg 143472b676d7Smrg if(!(pSiS->fonts = xalloc(SIS_FONTS_SIZE * 2))) { 143572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 143672b676d7Smrg "Could not save console fonts, mem allocation failed\n"); 143772b676d7Smrg return; 143872b676d7Smrg } 143972b676d7Smrg 144072b676d7Smrg /* save the registers that are needed here */ 144172b676d7Smrg miscOut = inSISREG(SISMISCR); 144272b676d7Smrg inSISIDXREG(SISGR, 0x04, gr4); 144372b676d7Smrg inSISIDXREG(SISGR, 0x05, gr5); 144472b676d7Smrg inSISIDXREG(SISGR, 0x06, gr6); 144572b676d7Smrg inSISIDXREG(SISSR, 0x02, seq2); 144672b676d7Smrg inSISIDXREG(SISSR, 0x04, seq4); 144772b676d7Smrg 144872b676d7Smrg /* Force into color mode */ 144972b676d7Smrg outSISREG(SISMISCW, miscOut | 0x01); 145072b676d7Smrg 145172b676d7Smrg inSISIDXREG(SISSR, 0x01, scrn); 145272b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); 145372b676d7Smrg outSISIDXREG(SISSR, 0x01, scrn | 0x20); 145472b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); 145572b676d7Smrg 145672b676d7Smrg SiS_WriteAttr(pSiS, 0x10, 0x01); /* graphics mode */ 145772b676d7Smrg 145872b676d7Smrg /*font1 */ 145972b676d7Smrg outSISIDXREG(SISSR, 0x02, 0x04); /* write to plane 2 */ 146072b676d7Smrg outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ 146172b676d7Smrg outSISIDXREG(SISGR, 0x04, 0x02); /* read plane 2 */ 146272b676d7Smrg outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ 146372b676d7Smrg outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ 146472b676d7Smrg slowbcopy_frombus(vgaMemBase, pSiS->fonts, SIS_FONTS_SIZE); 146572b676d7Smrg 146672b676d7Smrg /* font2 */ 146772b676d7Smrg outSISIDXREG(SISSR, 0x02, 0x08); /* write to plane 3 */ 146872b676d7Smrg outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ 146972b676d7Smrg outSISIDXREG(SISGR, 0x04, 0x03); /* read plane 3 */ 147072b676d7Smrg outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ 147172b676d7Smrg outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ 147272b676d7Smrg slowbcopy_frombus(vgaMemBase, pSiS->fonts + SIS_FONTS_SIZE, SIS_FONTS_SIZE); 147372b676d7Smrg 147472b676d7Smrg inSISIDXREG(SISSR, 0x01, scrn); 147572b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); 147672b676d7Smrg outSISIDXREG(SISSR, 0x01, scrn & ~0x20); 147772b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); 147872b676d7Smrg 147972b676d7Smrg /* Restore clobbered registers */ 148072b676d7Smrg SiS_WriteAttr(pSiS, 0x10, attr10); 148172b676d7Smrg outSISIDXREG(SISSR, 0x02, seq2); 148272b676d7Smrg outSISIDXREG(SISSR, 0x04, seq4); 148372b676d7Smrg outSISIDXREG(SISGR, 0x04, gr4); 148472b676d7Smrg outSISIDXREG(SISGR, 0x05, gr5); 148572b676d7Smrg outSISIDXREG(SISGR, 0x06, gr6); 148672b676d7Smrg outSISREG(SISMISCW, miscOut); 148772b676d7Smrg#endif 148872b676d7Smrg} 148972b676d7Smrg 149072b676d7Smrgstatic void 149172b676d7SmrgSiSVGASaveMode(ScrnInfoPtr pScrn, SISRegPtr save) 149272b676d7Smrg{ 149372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 149472b676d7Smrg int i; 149572b676d7Smrg 149672b676d7Smrg save->sisRegMiscOut = inSISREG(SISMISCR); 149772b676d7Smrg 149872b676d7Smrg for(i = 0; i < 25; i++) { 149972b676d7Smrg inSISIDXREG(SISCR, i, save->sisRegs3D4[i]); 150072b676d7Smrg } 150172b676d7Smrg 150272b676d7Smrg SiS_EnablePalette(pSiS); 150372b676d7Smrg for(i = 0; i < 21; i++) { 150472b676d7Smrg save->sisRegsATTR[i] = SiS_ReadAttr(pSiS, i); 150572b676d7Smrg } 150672b676d7Smrg SiS_DisablePalette(pSiS); 150772b676d7Smrg 150872b676d7Smrg for(i = 0; i < 9; i++) { 150972b676d7Smrg inSISIDXREG(SISGR, i, save->sisRegsGR[i]); 151072b676d7Smrg } 151172b676d7Smrg 151272b676d7Smrg for(i = 1; i < 5; i++) { 151372b676d7Smrg inSISIDXREG(SISSR, i, save->sisRegs3C4[i]); 151472b676d7Smrg } 151572b676d7Smrg} 151672b676d7Smrg 151772b676d7Smrgstatic void 151872b676d7SmrgSiSVGASaveColormap(ScrnInfoPtr pScrn, SISRegPtr save) 151972b676d7Smrg{ 152072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 152172b676d7Smrg int i; 152272b676d7Smrg 152372b676d7Smrg if(pSiS->VGACMapSaved) return; 152472b676d7Smrg 152572b676d7Smrg outSISREG(SISPEL, 0xff); 152672b676d7Smrg 152772b676d7Smrg outSISREG(SISCOLIDXR, 0x00); 152872b676d7Smrg for(i = 0; i < 768; i++) { 152972b676d7Smrg save->sisDAC[i] = inSISREG(SISCOLDATA); 153072b676d7Smrg (void)inSISREG(SISINPSTAT); 153172b676d7Smrg (void)inSISREG(SISINPSTAT); 153272b676d7Smrg } 153372b676d7Smrg 153472b676d7Smrg SiS_DisablePalette(pSiS); 153572b676d7Smrg pSiS->VGACMapSaved = TRUE; 153672b676d7Smrg} 153772b676d7Smrg 153872b676d7Smrgvoid 153972b676d7SmrgSiSVGASave(ScrnInfoPtr pScrn, SISRegPtr save, int flags) 154072b676d7Smrg{ 154172b676d7Smrg if(save == NULL) return; 154272b676d7Smrg 154372b676d7Smrg if(flags & SISVGA_SR_CMAP) SiSVGASaveColormap(pScrn, save); 154472b676d7Smrg if(flags & SISVGA_SR_MODE) SiSVGASaveMode(pScrn, save); 154572b676d7Smrg if(flags & SISVGA_SR_FONTS) SiSVGASaveFonts(pScrn); 154672b676d7Smrg} 154772b676d7Smrg 154872b676d7Smrgvoid 154972b676d7SmrgSiSVGARestoreFonts(ScrnInfoPtr pScrn) 155072b676d7Smrg{ 155172b676d7Smrg#ifdef SIS_PC_PLATFORM 155272b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 155372b676d7Smrg pointer vgaMemBase = pSiS->VGAMemBase; 155472b676d7Smrg UChar miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4, scrn; 155572b676d7Smrg 155672b676d7Smrg if((!pSiS->fonts) || (vgaMemBase == NULL)) return; 155772b676d7Smrg 155872b676d7Smrg /* save the registers that are needed here */ 155972b676d7Smrg miscOut = inSISREG(SISMISCR); 156072b676d7Smrg attr10 = SiS_ReadAttr(pSiS, 0x10); 156172b676d7Smrg inSISIDXREG(SISGR, 0x01, gr1); 156272b676d7Smrg inSISIDXREG(SISGR, 0x03, gr3); 156372b676d7Smrg inSISIDXREG(SISGR, 0x04, gr4); 156472b676d7Smrg inSISIDXREG(SISGR, 0x05, gr5); 156572b676d7Smrg inSISIDXREG(SISGR, 0x06, gr6); 156672b676d7Smrg inSISIDXREG(SISGR, 0x08, gr8); 156772b676d7Smrg inSISIDXREG(SISSR, 0x02, seq2); 156872b676d7Smrg inSISIDXREG(SISSR, 0x04, seq4); 156972b676d7Smrg 157072b676d7Smrg /* Force into color mode */ 157172b676d7Smrg outSISREG(SISMISCW, miscOut | 0x01); 157272b676d7Smrg inSISIDXREG(SISSR, 0x01, scrn); 157372b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); 157472b676d7Smrg outSISIDXREG(SISSR, 0x01, scrn | 0x20); 157572b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); 157672b676d7Smrg 157772b676d7Smrg SiS_WriteAttr(pSiS, 0x10, 0x01); /* graphics mode */ 157872b676d7Smrg if(pScrn->depth == 4) { 157972b676d7Smrg outSISIDXREG(SISGR, 0x03, 0x00); /* don't rotate, write unmodified */ 158072b676d7Smrg outSISIDXREG(SISGR, 0x08, 0xFF); /* write all bits in a byte */ 158172b676d7Smrg outSISIDXREG(SISGR, 0x01, 0x00); /* all planes come from CPU */ 158272b676d7Smrg } 158372b676d7Smrg 158472b676d7Smrg outSISIDXREG(SISSR, 0x02, 0x04); /* write to plane 2 */ 158572b676d7Smrg outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ 158672b676d7Smrg outSISIDXREG(SISGR, 0x04, 0x02); /* read plane 2 */ 158772b676d7Smrg outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ 158872b676d7Smrg outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ 158972b676d7Smrg slowbcopy_tobus(pSiS->fonts, vgaMemBase, SIS_FONTS_SIZE); 159072b676d7Smrg 159172b676d7Smrg outSISIDXREG(SISSR, 0x02, 0x08); /* write to plane 3 */ 159272b676d7Smrg outSISIDXREG(SISSR, 0x04, 0x06); /* enable plane graphics */ 159372b676d7Smrg outSISIDXREG(SISGR, 0x04, 0x03); /* read plane 3 */ 159472b676d7Smrg outSISIDXREG(SISGR, 0x05, 0x00); /* write mode 0, read mode 0 */ 159572b676d7Smrg outSISIDXREG(SISGR, 0x06, 0x05); /* set graphics */ 159672b676d7Smrg slowbcopy_tobus(pSiS->fonts + SIS_FONTS_SIZE, vgaMemBase, SIS_FONTS_SIZE); 159772b676d7Smrg 159872b676d7Smrg inSISIDXREG(SISSR, 0x01, scrn); 159972b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); 160072b676d7Smrg outSISIDXREG(SISSR, 0x01, scrn & ~0x20); 160172b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); 160272b676d7Smrg 160372b676d7Smrg /* restore the registers that were changed */ 160472b676d7Smrg outSISREG(SISMISCW, miscOut); 160572b676d7Smrg SiS_WriteAttr(pSiS, 0x10, attr10); 160672b676d7Smrg outSISIDXREG(SISGR, 0x01, gr1); 160772b676d7Smrg outSISIDXREG(SISGR, 0x03, gr3); 160872b676d7Smrg outSISIDXREG(SISGR, 0x04, gr4); 160972b676d7Smrg outSISIDXREG(SISGR, 0x05, gr5); 161072b676d7Smrg outSISIDXREG(SISGR, 0x06, gr6); 161172b676d7Smrg outSISIDXREG(SISGR, 0x08, gr8); 161272b676d7Smrg outSISIDXREG(SISSR, 0x02, seq2); 161372b676d7Smrg outSISIDXREG(SISSR, 0x04, seq4); 161472b676d7Smrg#endif 161572b676d7Smrg} 161672b676d7Smrg 161772b676d7Smrgstatic void 161872b676d7SmrgSiSVGARestoreMode(ScrnInfoPtr pScrn, SISRegPtr restore) 161972b676d7Smrg{ 162072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 162172b676d7Smrg int i; 162272b676d7Smrg 162372b676d7Smrg outSISREG(SISMISCW, restore->sisRegMiscOut); 162472b676d7Smrg 162572b676d7Smrg for(i = 1; i < 5; i++) { 162672b676d7Smrg outSISIDXREG(SISSR, i, restore->sisRegs3C4[i]); 162772b676d7Smrg } 162872b676d7Smrg 162972b676d7Smrg outSISIDXREG(SISCR, 17, restore->sisRegs3D4[17] & ~0x80); 163072b676d7Smrg 163172b676d7Smrg for(i = 0; i < 25; i++) { 163272b676d7Smrg outSISIDXREG(SISCR, i, restore->sisRegs3D4[i]); 163372b676d7Smrg } 163472b676d7Smrg 163572b676d7Smrg for(i = 0; i < 9; i++) { 163672b676d7Smrg outSISIDXREG(SISGR, i, restore->sisRegsGR[i]); 163772b676d7Smrg } 163872b676d7Smrg 163972b676d7Smrg SiS_EnablePalette(pSiS); 164072b676d7Smrg for(i = 0; i < 21; i++) { 164172b676d7Smrg SiS_WriteAttr(pSiS, i, restore->sisRegsATTR[i]); 164272b676d7Smrg } 164372b676d7Smrg SiS_DisablePalette(pSiS); 164472b676d7Smrg} 164572b676d7Smrg 164672b676d7Smrg 164772b676d7Smrgstatic void 164872b676d7SmrgSiSVGARestoreColormap(ScrnInfoPtr pScrn, SISRegPtr restore) 164972b676d7Smrg{ 165072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 165172b676d7Smrg int i; 165272b676d7Smrg 165372b676d7Smrg if(!pSiS->VGACMapSaved) return; 165472b676d7Smrg 165572b676d7Smrg outSISREG(SISPEL, 0xff); 165672b676d7Smrg 165772b676d7Smrg outSISREG(SISCOLIDX, 0x00); 165872b676d7Smrg for(i = 0; i < 768; i++) { 165972b676d7Smrg outSISREG(SISCOLDATA, restore->sisDAC[i]); 166072b676d7Smrg (void)inSISREG(SISINPSTAT); 166172b676d7Smrg (void)inSISREG(SISINPSTAT); 166272b676d7Smrg } 166372b676d7Smrg 166472b676d7Smrg SiS_DisablePalette(pSiS); 166572b676d7Smrg} 166672b676d7Smrg 166772b676d7Smrgvoid 166872b676d7SmrgSiSVGARestore(ScrnInfoPtr pScrn, SISRegPtr restore, int flags) 166972b676d7Smrg{ 167072b676d7Smrg if(restore == NULL) return; 167172b676d7Smrg 167272b676d7Smrg if(flags & SISVGA_SR_MODE) SiSVGARestoreMode(pScrn, restore); 167372b676d7Smrg if(flags & SISVGA_SR_FONTS) SiSVGARestoreFonts(pScrn); 167472b676d7Smrg if(flags & SISVGA_SR_CMAP) SiSVGARestoreColormap(pScrn, restore); 167572b676d7Smrg} 167672b676d7Smrg 167772b676d7Smrgstatic void 167872b676d7SmrgSiS_SeqReset(SISPtr pSiS, Bool start) 167972b676d7Smrg{ 168072b676d7Smrg if(start) { 168172b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); /* Synchronous Reset */ 168272b676d7Smrg } else { 168372b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); /* End Reset */ 168472b676d7Smrg } 168572b676d7Smrg} 168672b676d7Smrg 168772b676d7Smrgvoid 168872b676d7SmrgSiSVGAProtect(ScrnInfoPtr pScrn, Bool on) 168972b676d7Smrg{ 169072b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 169172b676d7Smrg UChar tmp; 169272b676d7Smrg 169372b676d7Smrg if(!pScrn->vtSema) return; 169472b676d7Smrg 169572b676d7Smrg if(on) { 169672b676d7Smrg inSISIDXREG(SISSR, 0x01, tmp); 169772b676d7Smrg SiS_SeqReset(pSiS, TRUE); /* start synchronous reset */ 169872b676d7Smrg outSISIDXREG(SISSR, 0x01, tmp | 0x20); /* disable display */ 169972b676d7Smrg SiS_EnablePalette(pSiS); 170072b676d7Smrg } else { 170172b676d7Smrg andSISIDXREG(SISSR, 0x01, ~0x20); /* enable display */ 170272b676d7Smrg SiS_SeqReset(pSiS, FALSE); /* clear synchronous reset */ 170372b676d7Smrg SiS_DisablePalette(pSiS); 170472b676d7Smrg } 170572b676d7Smrg} 170672b676d7Smrg 170772b676d7Smrg#ifdef SIS_PC_PLATFORM 170872b676d7SmrgBool 170972b676d7SmrgSiSVGAMapMem(ScrnInfoPtr pScrn) 171072b676d7Smrg{ 171172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 171272b676d7Smrg 171372b676d7Smrg /* Map only once */ 171472b676d7Smrg if(pSiS->VGAMemBase) return TRUE; 171572b676d7Smrg 171672b676d7Smrg if(pSiS->VGAMapSize == 0) pSiS->VGAMapSize = (64 * 1024); 171772b676d7Smrg if(pSiS->VGAMapPhys == 0) pSiS->VGAMapPhys = 0xA0000; 171872b676d7Smrg 171972b676d7Smrg#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,3,0,0,0) 172072b676d7Smrg pSiS->VGAMemBase = xf86MapDomainMemory(pScrn->scrnIndex, VIDMEM_MMIO_32BIT, 172172b676d7Smrg pSiS->PciTag, pSiS->VGAMapPhys, pSiS->VGAMapSize); 172272b676d7Smrg#else 172372b676d7Smrg pSiS->VGAMemBase = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT, 172472b676d7Smrg pSiS->VGAMapPhys, pSiS->VGAMapSize); 172572b676d7Smrg#endif 172672b676d7Smrg 172772b676d7Smrg return(pSiS->VGAMemBase != NULL); 172872b676d7Smrg} 172972b676d7Smrg 173072b676d7Smrgvoid 173172b676d7SmrgSiSVGAUnmapMem(ScrnInfoPtr pScrn) 173272b676d7Smrg{ 173372b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 173472b676d7Smrg 173572b676d7Smrg if(pSiS->VGAMemBase == NULL) return; 173672b676d7Smrg 173772b676d7Smrg xf86UnMapVidMem(pScrn->scrnIndex, pSiS->VGAMemBase, pSiS->VGAMapSize); 173872b676d7Smrg pSiS->VGAMemBase = NULL; 173972b676d7Smrg} 174072b676d7Smrg#endif 174172b676d7Smrg 174272b676d7Smrg#if 0 174372b676d7Smrgstatic CARD32 174472b676d7SmrgSiS_HBlankKGA(DisplayModePtr mode, SISRegPtr regp, int nBits, unsigned int Flags) 174572b676d7Smrg{ 174672b676d7Smrg int nExtBits = (nBits < 6) ? 0 : nBits - 6; 174772b676d7Smrg CARD32 ExtBits; 174872b676d7Smrg CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6; 174972b676d7Smrg 175072b676d7Smrg regp->sisRegs3D4[3] = (regp->sisRegs3D4[3] & ~0x1F) | 175172b676d7Smrg (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F); 175272b676d7Smrg regp->sisRegs3D4[5] = (regp->sisRegs3D4[5] & ~0x80) | 175372b676d7Smrg ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2); 175472b676d7Smrg ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask; 175572b676d7Smrg 175672b676d7Smrg if( (Flags & SISKGA_FIX_OVERSCAN) && 175772b676d7Smrg ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) { 175872b676d7Smrg int i = (regp->sisRegs3D4[3] & 0x1F) | 175972b676d7Smrg ((regp->sisRegs3D4[5] & 0x80) >> 2) | 176072b676d7Smrg ExtBits; 176172b676d7Smrg if(Flags & SISKGA_ENABLE_ON_ZERO) { 176272b676d7Smrg if( (i-- > (((mode->CrtcHBlankStart >> 3) - 1) & (0x3F | ExtBitMask))) && 176372b676d7Smrg (mode->CrtcHBlankEnd == mode->CrtcHTotal) ) { 176472b676d7Smrg i = 0; 176572b676d7Smrg } 176672b676d7Smrg } else if (Flags & SISKGA_BE_TOT_DEC) i--; 176772b676d7Smrg regp->sisRegs3D4[3] = (regp->sisRegs3D4[3] & ~0x1F) | (i & 0x1F); 176872b676d7Smrg regp->sisRegs3D4[5] = (regp->sisRegs3D4[5] & ~0x80) | ((i << 2) & 0x80); 176972b676d7Smrg ExtBits = i & ExtBitMask; 177072b676d7Smrg } 177172b676d7Smrg return ExtBits >> 6; 177272b676d7Smrg} 177372b676d7Smrg#endif 177472b676d7Smrg 177572b676d7Smrgstatic CARD32 177672b676d7SmrgSiS_VBlankKGA(DisplayModePtr mode, SISRegPtr regp, int nBits, unsigned int Flags) 177772b676d7Smrg{ 177872b676d7Smrg CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8); 177972b676d7Smrg CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8; 178072b676d7Smrg CARD32 ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask; 178172b676d7Smrg CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1); 178272b676d7Smrg int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF; 178372b676d7Smrg regp->sisRegs3D4[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 178472b676d7Smrg 178572b676d7Smrg if((Flags & SISKGA_FIX_OVERSCAN) && (mode->CrtcVBlankEnd == mode->CrtcVTotal)) { 178672b676d7Smrg int i = regp->sisRegs3D4[22] | ExtBits; 178772b676d7Smrg if(Flags & SISKGA_ENABLE_ON_ZERO) { 178872b676d7Smrg if( ((BitMask && ((i & BitMask) > (VBlankStart & BitMask))) || 178972b676d7Smrg ((i > VBlankStart) && /* 8-bit case */ 179072b676d7Smrg ((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */ 179172b676d7Smrg (!(regp->sisRegs3D4[9] & 0x9F)) ) { /* 1 scanline/row */ 179272b676d7Smrg i = 0; 179372b676d7Smrg } else { 179472b676d7Smrg i--; 179572b676d7Smrg } 179672b676d7Smrg } else if(Flags & SISKGA_BE_TOT_DEC) i--; 179772b676d7Smrg 179872b676d7Smrg regp->sisRegs3D4[22] = i & 0xFF; 179972b676d7Smrg ExtBits = i & 0xFF00; 180072b676d7Smrg } 180172b676d7Smrg return (ExtBits >> 8); 180272b676d7Smrg} 180372b676d7Smrg 180472b676d7SmrgBool 180572b676d7SmrgSiSVGAInit(ScrnInfoPtr pScrn, DisplayModePtr mode, int fixsync) 180672b676d7Smrg{ 180772b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 180872b676d7Smrg SISRegPtr regp = &pSiS->ModeReg; 180972b676d7Smrg int depth = pScrn->depth; 181072b676d7Smrg unsigned int i; 181172b676d7Smrg 181272b676d7Smrg /* Sync */ 181372b676d7Smrg if((mode->Flags & (V_PHSYNC | V_NHSYNC)) && (mode->Flags & (V_PVSYNC | V_NVSYNC))) { 181472b676d7Smrg regp->sisRegMiscOut = 0x23; 181572b676d7Smrg if(mode->Flags & V_NHSYNC) regp->sisRegMiscOut |= 0x40; 181672b676d7Smrg if(mode->Flags & V_NVSYNC) regp->sisRegMiscOut |= 0x80; 181772b676d7Smrg } else { 181872b676d7Smrg int VDisplay = mode->VDisplay; 181972b676d7Smrg 182072b676d7Smrg if(mode->Flags & V_DBLSCAN) VDisplay *= 2; 182172b676d7Smrg if(mode->VScan > 1) VDisplay *= mode->VScan; 182272b676d7Smrg 182372b676d7Smrg if(VDisplay < 400) regp->sisRegMiscOut = 0xA3; /* +hsync -vsync */ 182472b676d7Smrg else if (VDisplay < 480) regp->sisRegMiscOut = 0x63; /* -hsync +vsync */ 182572b676d7Smrg else if (VDisplay < 768) regp->sisRegMiscOut = 0xE3; /* -hsync -vsync */ 182672b676d7Smrg else regp->sisRegMiscOut = 0x23; /* +hsync +vsync */ 182772b676d7Smrg } 182872b676d7Smrg 182972b676d7Smrg regp->sisRegMiscOut |= (mode->ClockIndex & 0x03) << 2; 183072b676d7Smrg 183172b676d7Smrg /* Seq */ 183272b676d7Smrg if(depth == 4) regp->sisRegs3C4[0] = 0x02; 183372b676d7Smrg else regp->sisRegs3C4[0] = 0x00; 183472b676d7Smrg 183572b676d7Smrg if(mode->Flags & V_CLKDIV2) regp->sisRegs3C4[1] = 0x09; 183672b676d7Smrg else regp->sisRegs3C4[1] = 0x01; 183772b676d7Smrg 183872b676d7Smrg regp->sisRegs3C4[2] = 0x0F; 183972b676d7Smrg 184072b676d7Smrg regp->sisRegs3C4[3] = 0x00; 184172b676d7Smrg 184272b676d7Smrg if(depth < 8) regp->sisRegs3C4[4] = 0x06; 184372b676d7Smrg else regp->sisRegs3C4[4] = 0x0E; 184472b676d7Smrg 184572b676d7Smrg /* CRTC */ 184672b676d7Smrg regp->sisRegs3D4[0] = (mode->CrtcHTotal >> 3) - 5; 184772b676d7Smrg regp->sisRegs3D4[1] = (mode->CrtcHDisplay >> 3) - 1; 184872b676d7Smrg regp->sisRegs3D4[2] = (mode->CrtcHBlankStart >> 3) - 1; 184972b676d7Smrg regp->sisRegs3D4[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80; 185072b676d7Smrg i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F); 185172b676d7Smrg if(i < 0x80) regp->sisRegs3D4[3] |= i; 185272b676d7Smrg regp->sisRegs3D4[4] = (mode->CrtcHSyncStart >> 3) - fixsync; 185372b676d7Smrg regp->sisRegs3D4[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) | 185472b676d7Smrg (((mode->CrtcHSyncEnd >> 3) - fixsync) & 0x1F); 185572b676d7Smrg regp->sisRegs3D4[6] = (mode->CrtcVTotal - 2) & 0xFF; 185672b676d7Smrg regp->sisRegs3D4[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8) | 185772b676d7Smrg (((mode->CrtcVDisplay - 1) & 0x100) >> 7) | 185872b676d7Smrg (((mode->CrtcVSyncStart - fixsync) & 0x100) >> 6) | 185972b676d7Smrg (((mode->CrtcVBlankStart - 1) & 0x100) >> 5) | 186072b676d7Smrg 0x10 | 186172b676d7Smrg (((mode->CrtcVTotal - 2) & 0x200) >> 4) | 186272b676d7Smrg (((mode->CrtcVDisplay - 1) & 0x200) >> 3) | 186372b676d7Smrg (((mode->CrtcVSyncStart - fixsync) & 0x200) >> 2); 186472b676d7Smrg regp->sisRegs3D4[8] = 0x00; 186572b676d7Smrg regp->sisRegs3D4[9] = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40; 186672b676d7Smrg if(mode->Flags & V_DBLSCAN) regp->sisRegs3D4[9] |= 0x80; 186772b676d7Smrg if(mode->VScan >= 32) regp->sisRegs3D4[9] |= 0x1F; 186872b676d7Smrg else if (mode->VScan > 1) regp->sisRegs3D4[9] |= mode->VScan - 1; 186972b676d7Smrg regp->sisRegs3D4[10] = 0x00; 187072b676d7Smrg regp->sisRegs3D4[11] = 0x00; 187172b676d7Smrg regp->sisRegs3D4[12] = 0x00; 187272b676d7Smrg regp->sisRegs3D4[13] = 0x00; 187372b676d7Smrg regp->sisRegs3D4[14] = 0x00; 187472b676d7Smrg regp->sisRegs3D4[15] = 0x00; 187572b676d7Smrg regp->sisRegs3D4[16] = (mode->CrtcVSyncStart - fixsync) & 0xFF; 187672b676d7Smrg regp->sisRegs3D4[17] = ((mode->CrtcVSyncEnd - fixsync) & 0x0F) | 0x20; 187772b676d7Smrg regp->sisRegs3D4[18] = (mode->CrtcVDisplay - 1) & 0xFF; 187872b676d7Smrg regp->sisRegs3D4[19] = pScrn->displayWidth >> 4; 187972b676d7Smrg regp->sisRegs3D4[20] = 0x00; 188072b676d7Smrg regp->sisRegs3D4[21] = (mode->CrtcVBlankStart - 1) & 0xFF; 188172b676d7Smrg regp->sisRegs3D4[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 188272b676d7Smrg if(depth < 8) regp->sisRegs3D4[23] = 0xE3; 188372b676d7Smrg else regp->sisRegs3D4[23] = 0xC3; 188472b676d7Smrg regp->sisRegs3D4[24] = 0xFF; 188572b676d7Smrg 188672b676d7Smrg#if 0 188772b676d7Smrg SiS_HBlankKGA(mode, regp, 0, SISKGA_FIX_OVERSCAN | SISKGA_ENABLE_ON_ZERO); 188872b676d7Smrg#endif 188972b676d7Smrg SiS_VBlankKGA(mode, regp, 0, SISKGA_FIX_OVERSCAN | SISKGA_ENABLE_ON_ZERO); 189072b676d7Smrg 189172b676d7Smrg /* GR */ 189272b676d7Smrg regp->sisRegsGR[0] = 0x00; 189372b676d7Smrg regp->sisRegsGR[1] = 0x00; 189472b676d7Smrg regp->sisRegsGR[2] = 0x00; 189572b676d7Smrg regp->sisRegsGR[3] = 0x00; 189672b676d7Smrg regp->sisRegsGR[4] = 0x00; 189772b676d7Smrg if(depth == 4) regp->sisRegsGR[5] = 0x02; 189872b676d7Smrg else regp->sisRegsGR[5] = 0x40; 189972b676d7Smrg regp->sisRegsGR[6] = 0x05; /* only map 64k VGA memory !!!! */ 190072b676d7Smrg regp->sisRegsGR[7] = 0x0F; 190172b676d7Smrg regp->sisRegsGR[8] = 0xFF; 190272b676d7Smrg 190372b676d7Smrg /* Attr */ 190472b676d7Smrg for(i = 0; i <= 15; i++) { /* standard colormap translation */ 190572b676d7Smrg regp->sisRegsATTR[i] = i; 190672b676d7Smrg } 190772b676d7Smrg if(depth == 4) regp->sisRegsATTR[16] = 0x81; 190872b676d7Smrg else regp->sisRegsATTR[16] = 0x41; 190972b676d7Smrg if(depth >= 4) regp->sisRegsATTR[17] = 0xFF; 191072b676d7Smrg else regp->sisRegsATTR[17] = 0x01; 191172b676d7Smrg regp->sisRegsATTR[18] = 0x0F; 191272b676d7Smrg regp->sisRegsATTR[19] = 0x00; 191372b676d7Smrg regp->sisRegsATTR[20] = 0x00; 191472b676d7Smrg 191572b676d7Smrg return TRUE; 191672b676d7Smrg} 191772b676d7Smrg 191872b676d7Smrgstatic void 191972b676d7SmrgSISVGABlankScreen(ScrnInfoPtr pScrn, Bool on) 192072b676d7Smrg{ 192172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 192272b676d7Smrg UChar tmp; 192372b676d7Smrg 192472b676d7Smrg inSISIDXREG(SISSR, 0x01, tmp); 192572b676d7Smrg if(on) tmp &= ~0x20; 192672b676d7Smrg else tmp |= 0x20; 192772b676d7Smrg SiS_SeqReset(pSiS, TRUE); 192872b676d7Smrg outSISIDXREG(SISSR, 0x01, tmp); 192972b676d7Smrg SiS_SeqReset(pSiS, FALSE); 193072b676d7Smrg} 193172b676d7Smrg 193272b676d7SmrgBool 193372b676d7SmrgSiSVGASaveScreen(ScreenPtr pScreen, int mode) 193472b676d7Smrg{ 193572b676d7Smrg ScrnInfoPtr pScrn = NULL; 193672b676d7Smrg Bool on = xf86IsUnblank(mode); 193772b676d7Smrg 193872b676d7Smrg if(pScreen == NULL) return FALSE; 193972b676d7Smrg 194072b676d7Smrg pScrn = xf86Screens[pScreen->myNum]; 194172b676d7Smrg 194272b676d7Smrg if(pScrn->vtSema) { 194372b676d7Smrg SISVGABlankScreen(pScrn, on); 194472b676d7Smrg } 194572b676d7Smrg return TRUE; 194672b676d7Smrg} 194772b676d7Smrg 194872b676d7Smrg#undef SIS_FONTS_SIZE 194972b676d7Smrg 195072b676d7Smrg 1951