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