172b676d7Smrg/* 272b676d7Smrg * Video bridge detection and configuration for 300, 315 and 330 series 372b676d7Smrg * 472b676d7Smrg * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria 572b676d7Smrg * 672b676d7Smrg * Redistribution and use in source and binary forms, with or without 772b676d7Smrg * modification, are permitted provided that the following conditions 872b676d7Smrg * are met: 972b676d7Smrg * 1) Redistributions of source code must retain the above copyright 1072b676d7Smrg * notice, this list of conditions and the following disclaimer. 1172b676d7Smrg * 2) Redistributions in binary form must reproduce the above copyright 1272b676d7Smrg * notice, this list of conditions and the following disclaimer in the 1372b676d7Smrg * documentation and/or other materials provided with the distribution. 1472b676d7Smrg * 3) The name of the author may not be used to endorse or promote products 1572b676d7Smrg * derived from this software without specific prior written permission. 1672b676d7Smrg * 1772b676d7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1872b676d7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1972b676d7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2072b676d7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2172b676d7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2272b676d7Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2372b676d7Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2472b676d7Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2572b676d7Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2672b676d7Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2772b676d7Smrg * 2872b676d7Smrg * Author: Thomas Winischhofer <thomas@winischhofer.net> 2972b676d7Smrg * 3072b676d7Smrg */ 3172b676d7Smrg 3272b676d7Smrg#ifdef HAVE_CONFIG_H 3372b676d7Smrg#include "config.h" 3472b676d7Smrg#endif 3572b676d7Smrg 3672b676d7Smrg#include "sis.h" 3772b676d7Smrg#define SIS_NEED_inSISREG 3872b676d7Smrg#define SIS_NEED_inSISIDXREG 3972b676d7Smrg#define SIS_NEED_outSISIDXREG 4072b676d7Smrg#define SIS_NEED_orSISIDXREG 4172b676d7Smrg#define SIS_NEED_andSISIDXREG 4272b676d7Smrg#define SIS_NEED_setSISIDXREG 4372b676d7Smrg#include "sis_regs.h" 4472b676d7Smrg#include "sis_dac.h" 4572b676d7Smrg 4672b676d7Smrgvoid SISCRT1PreInit(ScrnInfoPtr pScrn); 4772b676d7Smrgvoid SISLCDPreInit(ScrnInfoPtr pScrn, Bool quiet); 4872b676d7Smrgvoid SISTVPreInit(ScrnInfoPtr pScrn, Bool quiet); 4972b676d7Smrgvoid SISCRT2PreInit(ScrnInfoPtr pScrn, Bool quiet); 5072b676d7SmrgBool SISRedetectCRT2Type(ScrnInfoPtr pScrn); 5172b676d7Smrgvoid SISSense30x(ScrnInfoPtr pScrn, Bool quiet); 5272b676d7Smrgvoid SISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet); 5372b676d7Smrgvoid SiSSetupPseudoPanel(ScrnInfoPtr pScrn); 5472b676d7Smrg 5572b676d7Smrgextern Bool SISDetermineLCDACap(ScrnInfoPtr pScrn); 5672b676d7Smrgextern void SISSaveDetectedDevices(ScrnInfoPtr pScrn); 5772b676d7Smrgextern void SISWaitRetraceCRT1(ScrnInfoPtr pScrn); 5872b676d7Smrgextern UChar SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value); 5972b676d7Smrg 6072b676d7Smrg/* From init.c, init301.c ---- (use their data types) */ 6172b676d7Smrgextern BOOLEAN SiS_GetPanelID(struct SiS_Private *SiS_Pr); 6272b676d7Smrgextern unsigned short SiS_SenseLCDDDC(struct SiS_Private *SiS_Pr, SISPtr pSiS); 6372b676d7Smrgextern unsigned short SiS_SenseVGA2DDC(struct SiS_Private *SiS_Pr, SISPtr pSiS); 6472b676d7Smrg 6572b676d7Smrgtypedef struct _SiS_LCD_StStruct 6672b676d7Smrg{ 6772b676d7Smrg ULong VBLCD_lcdflag; 6872b676d7Smrg UShort LCDwidth; 6972b676d7Smrg UShort LCDheight; 7072b676d7Smrg} SiS_LCD_StStruct; 7172b676d7Smrg 7272b676d7Smrgstatic const SiS_LCD_StStruct SiS300_LCD_Type[]= 7372b676d7Smrg{ 7472b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* 0 - invalid */ 7572b676d7Smrg { VB_LCD_800x600, 800, 600 }, /* 1 */ 7672b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* 2 */ 7772b676d7Smrg { VB_LCD_1280x1024,1280, 1024 }, /* 3 */ 7872b676d7Smrg { VB_LCD_1280x960, 1280, 960 }, /* 4 */ 7972b676d7Smrg { VB_LCD_640x480, 640, 480 }, /* 5 */ 8072b676d7Smrg { VB_LCD_1024x600, 1024, 600 }, /* 6 */ 8172b676d7Smrg { VB_LCD_1152x768, 1152, 768 }, /* 7 */ 8272b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* 8 */ 8372b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* 9 */ 8472b676d7Smrg { VB_LCD_1280x768, 1280, 768 }, /* a */ 8572b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* b */ 8672b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* c */ 8772b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* d */ 8872b676d7Smrg { VB_LCD_320x480, 320, 480 }, /* e */ 8972b676d7Smrg { VB_LCD_CUSTOM, 0, 0 } /* f */ 9072b676d7Smrg}; 9172b676d7Smrg 9272b676d7Smrgstatic const SiS_LCD_StStruct SiS315_LCD_Type[]= 9372b676d7Smrg{ 9472b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* 0 - invalid */ 9572b676d7Smrg { VB_LCD_800x600, 800, 600 }, /* 1 */ 9672b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* 2 */ 9772b676d7Smrg { VB_LCD_1280x1024,1280, 1024 }, /* 3 */ 9872b676d7Smrg { VB_LCD_640x480, 640, 480 }, /* 4 */ 9972b676d7Smrg { VB_LCD_1024x600, 1024, 600 }, /* 5 */ 10072b676d7Smrg { VB_LCD_1152x864, 1152, 864 }, /* 6 */ 10172b676d7Smrg { VB_LCD_1280x960, 1280, 960 }, /* 7 */ 10272b676d7Smrg { VB_LCD_1152x768, 1152, 768 }, /* 8 */ 10372b676d7Smrg { VB_LCD_1400x1050,1400, 1050 }, /* 9 */ 10472b676d7Smrg { VB_LCD_1280x768, 1280, 768 }, /* a */ 10572b676d7Smrg { VB_LCD_1600x1200,1600, 1200 }, /* b */ 10672b676d7Smrg { VB_LCD_640x480_2, 640, 480 }, /* c FSTN */ 10772b676d7Smrg { VB_LCD_640x480_3, 640, 480 }, /* d FSTN */ 10872b676d7Smrg { VB_LCD_320x480, 320, 480 }, /* e */ 10972b676d7Smrg { VB_LCD_CUSTOM, 0, 0 } /* f */ 11072b676d7Smrg}; 11172b676d7Smrg 11272b676d7Smrgstatic const SiS_LCD_StStruct SiS661_LCD_Type[]= 11372b676d7Smrg{ 11472b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* 0 - invalid */ 11572b676d7Smrg { VB_LCD_800x600, 800, 600 }, /* 1 */ 11672b676d7Smrg { VB_LCD_1024x768, 1024, 768 }, /* 2 */ 11772b676d7Smrg { VB_LCD_1280x1024,1280, 1024 }, /* 3 */ 11872b676d7Smrg { VB_LCD_640x480, 640, 480 }, /* 4 */ 11972b676d7Smrg { VB_LCD_1024x600, 1024, 600 }, /* 5 - temp */ 12072b676d7Smrg { VB_LCD_1152x864, 1152, 864 }, /* 6 - temp */ 12172b676d7Smrg { VB_LCD_1280x960, 1280, 960 }, /* 7 */ 12272b676d7Smrg { VB_LCD_1280x854, 1280, 854 }, /* 8 */ 12372b676d7Smrg { VB_LCD_1400x1050,1400, 1050 }, /* 9 */ 12472b676d7Smrg { VB_LCD_1280x768, 1280, 768 }, /* a */ 12572b676d7Smrg { VB_LCD_1600x1200,1600, 1200 }, /* b */ 12672b676d7Smrg { VB_LCD_1280x800, 1280, 800 }, /* c */ 12772b676d7Smrg { VB_LCD_1680x1050,1680, 1050 }, /* d */ 12872b676d7Smrg { VB_LCD_1280x720, 1280, 720 }, /* e */ 12972b676d7Smrg { VB_LCD_CUSTOM, 0, 0 } /* f */ 13072b676d7Smrg}; 13172b676d7Smrg 13272b676d7Smrgstatic Bool 13372b676d7SmrgTestDDC1(ScrnInfoPtr pScrn) 13472b676d7Smrg{ 13572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 13672b676d7Smrg UShort old; 13772b676d7Smrg int count = 48; 13872b676d7Smrg 13972b676d7Smrg old = SiS_ReadDDC1Bit(pSiS->SiS_Pr); 14072b676d7Smrg do { 14172b676d7Smrg if(old != SiS_ReadDDC1Bit(pSiS->SiS_Pr)) break; 14272b676d7Smrg } while(count--); 14372b676d7Smrg return (count == -1) ? FALSE : TRUE; 14472b676d7Smrg} 14572b676d7Smrg 14672b676d7Smrgstatic int 14772b676d7SmrgSiS_SISDetectCRT1(ScrnInfoPtr pScrn) 14872b676d7Smrg{ 14972b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 15072b676d7Smrg UShort temp = 0xffff; 15172b676d7Smrg UChar SR1F, CR63=0, CR17; 15272b676d7Smrg int i, ret = 0; 15372b676d7Smrg Bool mustwait = FALSE; 15472b676d7Smrg 15572b676d7Smrg inSISIDXREG(SISSR,0x1F,SR1F); 15672b676d7Smrg setSISIDXREG(SISSR,0x1F,0x3f,0x04); 15772b676d7Smrg if(SR1F & 0xc0) mustwait = TRUE; 15872b676d7Smrg 15972b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 16072b676d7Smrg inSISIDXREG(SISCR,pSiS->myCR63,CR63); 16172b676d7Smrg CR63 &= 0x40; 16272b676d7Smrg andSISIDXREG(SISCR,pSiS->myCR63,0xbf); 16372b676d7Smrg } 16472b676d7Smrg 16572b676d7Smrg inSISIDXREG(SISCR,0x17,CR17); 16672b676d7Smrg CR17 &= 0x80; 16772b676d7Smrg if(!CR17) { 16872b676d7Smrg orSISIDXREG(SISCR,0x17,0x80); 16972b676d7Smrg mustwait = TRUE; 17072b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x01); 17172b676d7Smrg outSISIDXREG(SISSR, 0x00, 0x03); 17272b676d7Smrg } 17372b676d7Smrg 17472b676d7Smrg if(mustwait) { 17572b676d7Smrg for(i=0; i < 10; i++) SISWaitRetraceCRT1(pScrn); 17672b676d7Smrg } 17772b676d7Smrg 17872b676d7Smrg if(pSiS->ChipType >= SIS_330) { 17972b676d7Smrg int watchdog; 18072b676d7Smrg if(pSiS->ChipType >= SIS_340) { 18172b676d7Smrg outSISIDXREG(SISCR, 0x57, 0x4a); 18272b676d7Smrg } else { 18372b676d7Smrg outSISIDXREG(SISCR, 0x57, 0x5f); 18472b676d7Smrg } 18572b676d7Smrg orSISIDXREG(SISCR, 0x53, 0x02); 18672b676d7Smrg watchdog = 655360; 18772b676d7Smrg while((!((inSISREG(SISINPSTAT)) & 0x01)) && --watchdog); 18872b676d7Smrg watchdog = 655360; 18972b676d7Smrg while(((inSISREG(SISINPSTAT)) & 0x01) && --watchdog); 19072b676d7Smrg if((inSISREG(SISMISCW)) & 0x10) temp = 1; 19172b676d7Smrg andSISIDXREG(SISCR, 0x53, 0xfd); 19272b676d7Smrg outSISIDXREG(SISCR, 0x57, 0x00); 19372b676d7Smrg#ifdef TWDEBUG 19472b676d7Smrg xf86DrvMsg(0, X_INFO, "330: Found CRT1: %s\n", (temp == 1) ? "yes" : "no"); 19572b676d7Smrg#endif 19672b676d7Smrg } 19772b676d7Smrg 19872b676d7Smrg if((temp == 0xffff) && (!pSiS->SiS_Pr->DDCPortMixup)) { 19972b676d7Smrg i = 3; 20072b676d7Smrg do { 20172b676d7Smrg temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 0, 0, NULL, pSiS->VBFlags2); 20272b676d7Smrg } while(((temp == 0) || (temp == 0xffff)) && i--); 20372b676d7Smrg 20472b676d7Smrg if((temp == 0) || (temp == 0xffff)) { 20572b676d7Smrg if(TestDDC1(pScrn)) temp = 1; 20672b676d7Smrg } 20772b676d7Smrg } 20872b676d7Smrg 20972b676d7Smrg if((temp) && (temp != 0xffff)) { 21072b676d7Smrg orSISIDXREG(SISCR,0x32,0x20); 21172b676d7Smrg ret = 1; 21272b676d7Smrg } else if(pSiS->ChipType >= SIS_330) { 21372b676d7Smrg andSISIDXREG(SISCR,0x32,~0x20); 21472b676d7Smrg ret = 0; 21572b676d7Smrg } 21672b676d7Smrg 21772b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 21872b676d7Smrg setSISIDXREG(SISCR,pSiS->myCR63,0xBF,CR63); 21972b676d7Smrg } 22072b676d7Smrg 22172b676d7Smrg setSISIDXREG(SISCR,0x17,0x7F,CR17); 22272b676d7Smrg 22372b676d7Smrg outSISIDXREG(SISSR,0x1F,SR1F); 22472b676d7Smrg 22572b676d7Smrg return ret; 22672b676d7Smrg} 22772b676d7Smrg 22872b676d7Smrg/* Detect CRT1 */ 22972b676d7Smrgvoid SISCRT1PreInit(ScrnInfoPtr pScrn) 23072b676d7Smrg{ 23172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 23272b676d7Smrg UChar CR32; 23372b676d7Smrg UChar OtherDevices = 0; 23472b676d7Smrg 23572b676d7Smrg pSiS->CRT1Detected = FALSE; 23672b676d7Smrg 23772b676d7Smrg if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) { 23872b676d7Smrg pSiS->CRT1Detected = TRUE; 23972b676d7Smrg pSiS->CRT1off = 0; 24072b676d7Smrg return; 24172b676d7Smrg } 24272b676d7Smrg 24372b676d7Smrg#ifdef SISDUALHEAD 24472b676d7Smrg if(pSiS->DualHeadMode) { 24572b676d7Smrg pSiS->CRT1Detected = TRUE; 24672b676d7Smrg pSiS->CRT1off = 0; 24772b676d7Smrg return; 24872b676d7Smrg } 24972b676d7Smrg#endif 25072b676d7Smrg 25172b676d7Smrg#ifdef SISMERGED 25272b676d7Smrg if((pSiS->MergedFB) && (!(pSiS->MergedFBAuto))) { 25372b676d7Smrg pSiS->CRT1Detected = TRUE; 25472b676d7Smrg pSiS->CRT1off = 0; 25572b676d7Smrg return; 25672b676d7Smrg } 25772b676d7Smrg#endif 25872b676d7Smrg 25972b676d7Smrg inSISIDXREG(SISCR, 0x32, CR32); 26072b676d7Smrg 26172b676d7Smrg if(pSiS->ChipType >= SIS_330) { 26272b676d7Smrg /* Works reliably on 330 and later */ 26372b676d7Smrg pSiS->CRT1Detected = SiS_SISDetectCRT1(pScrn); 26472b676d7Smrg } else { 26572b676d7Smrg if(CR32 & 0x20) pSiS->CRT1Detected = TRUE; 26672b676d7Smrg else pSiS->CRT1Detected = SiS_SISDetectCRT1(pScrn); 26772b676d7Smrg } 26872b676d7Smrg 26972b676d7Smrg if(CR32 & 0x5F) OtherDevices = 1; 27072b676d7Smrg 27172b676d7Smrg if(pSiS->CRT1off == -1) { 27272b676d7Smrg if(!pSiS->CRT1Detected) { 27372b676d7Smrg 27472b676d7Smrg /* No CRT1 detected. */ 27572b676d7Smrg /* If other devices exist, switch it off */ 27672b676d7Smrg if(OtherDevices) pSiS->CRT1off = 1; 27772b676d7Smrg else pSiS->CRT1off = 0; 27872b676d7Smrg 27972b676d7Smrg } else { 28072b676d7Smrg 28172b676d7Smrg /* CRT1 detected, leave/switch it on */ 28272b676d7Smrg pSiS->CRT1off = 0; 28372b676d7Smrg 28472b676d7Smrg } 28572b676d7Smrg } 28672b676d7Smrg 28772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 28872b676d7Smrg "%sCRT1/VGA detected\n", 28972b676d7Smrg pSiS->CRT1Detected ? "" : "No "); 29072b676d7Smrg} 29172b676d7Smrg 29272b676d7Smrg/* Detect CRT2-LCD and LCD size */ 29372b676d7Smrgvoid SISLCDPreInit(ScrnInfoPtr pScrn, Bool quiet) 29472b676d7Smrg{ 29572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 29672b676d7Smrg UChar CR32, CR36, CR37, CR7D=0, tmp; 29772b676d7Smrg 29872b676d7Smrg pSiS->VBFlags &= ~(CRT2_LCD); 29972b676d7Smrg pSiS->VBLCDFlags = 0; 30072b676d7Smrg pSiS->LCDwidth = 0; 30172b676d7Smrg pSiS->LCDheight = 0; 30272b676d7Smrg 30372b676d7Smrg if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return; 30472b676d7Smrg 30572b676d7Smrg inSISIDXREG(SISCR, 0x32, CR32); 30672b676d7Smrg 30772b676d7Smrg if(CR32 & 0x08) pSiS->VBFlags |= CRT2_LCD; 30872b676d7Smrg 30972b676d7Smrg /* If no panel has been detected by the BIOS during booting, 31072b676d7Smrg * we try to detect it ourselves at this point. We do that 31172b676d7Smrg * if forcecrt2redetection was given, too. 31272b676d7Smrg * This is useful on machines with DVI connectors where the 31372b676d7Smrg * panel was connected after booting. This is only supported 31472b676d7Smrg * on the 315/330 series and the 301/30xB/C bridge (because the 31572b676d7Smrg * 30xLV don't seem to have a DDC port and operate only LVDS 31672b676d7Smrg * panels which mostly don't support DDC). We only do this if 31772b676d7Smrg * there was no secondary VGA detected by the BIOS, because LCD 31872b676d7Smrg * and VGA2 share the same DDC channel and might be misdetected 31972b676d7Smrg * as the wrong type (especially if the LCD panel only supports 32072b676d7Smrg * EDID Version 1). 32172b676d7Smrg * Addendum: For DVI-I connected panels, this is not ideal. 32272b676d7Smrg * Therefore, we disregard an eventually detected secondary 32372b676d7Smrg * VGA if the user forced CRT2 type to LCD. 32472b676d7Smrg * 32572b676d7Smrg * By default, CRT2 redetection is forced since 12/09/2003, as 32672b676d7Smrg * I encountered numerous panels which deliver more or less 32772b676d7Smrg * bogus DDC data confusing the BIOS. Since our DDC detection 32872b676d7Smrg * is waaaay better, we prefer it instead of the primitive 32972b676d7Smrg * and buggy BIOS method. 33072b676d7Smrg * 33172b676d7Smrg */ 33272b676d7Smrg#ifdef SISDUALHEAD 33372b676d7Smrg if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 33472b676d7Smrg#endif 33572b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && 33672b676d7Smrg (pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 33772b676d7Smrg (!(pSiS->VBFlags2 & VB2_30xBDH)) && 33872b676d7Smrg (pSiS->VESA != 1)) { 33972b676d7Smrg 34072b676d7Smrg if(pSiS->forcecrt2redetection) { 34172b676d7Smrg pSiS->VBFlags &= ~CRT2_LCD; 34272b676d7Smrg /* Do NOT clear CR32[D3] here! */ 34372b676d7Smrg } 34472b676d7Smrg 34572b676d7Smrg if(!(pSiS->nocrt2ddcdetection)) { 34672b676d7Smrg if((!(pSiS->VBFlags & CRT2_LCD)) && 34772b676d7Smrg ( (!(CR32 & 0x10)) || 34872b676d7Smrg (pSiS->ForceCRT2Type == CRT2_LCD) ) ) { 34972b676d7Smrg if(!quiet) { 35072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 35172b676d7Smrg "%s LCD/plasma panel, sensing via DDC\n", 35272b676d7Smrg pSiS->forcecrt2redetection ? 35372b676d7Smrg "(Re)-detecting" : "BIOS detected no"); 35472b676d7Smrg } 35572b676d7Smrg if(SiS_SenseLCDDDC(pSiS->SiS_Pr, pSiS)) { 35672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 35772b676d7Smrg "DDC error during LCD panel detection\n"); 35872b676d7Smrg } else { 35972b676d7Smrg inSISIDXREG(SISCR, 0x32, CR32); 36072b676d7Smrg if(CR32 & 0x08) { 36172b676d7Smrg pSiS->VBFlags |= CRT2_LCD; 36272b676d7Smrg pSiS->postVBCR32 |= 0x08; 36372b676d7Smrg } else { 36472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 36572b676d7Smrg "No LCD/plasma panel detected\n"); 36672b676d7Smrg } 36772b676d7Smrg } 36872b676d7Smrg } 36972b676d7Smrg } 37072b676d7Smrg 37172b676d7Smrg } 37272b676d7Smrg#ifdef SISDUALHEAD 37372b676d7Smrg } 37472b676d7Smrg#endif 37572b676d7Smrg 37672b676d7Smrg if(pSiS->VBFlags & CRT2_LCD) { 37772b676d7Smrg inSISIDXREG(SISCR, 0x36, CR36); 37872b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 37972b676d7Smrg if(pSiS->VBFlags2 & VB2_301) { 38072b676d7Smrg if((CR36 & 0x0f) < 0x0f) CR36 &= 0xf7; 38172b676d7Smrg } 38272b676d7Smrg } 38372b676d7Smrg if(pSiS->PRGB != -1) { 38472b676d7Smrg tmp = 0x37; 38572b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && 38672b676d7Smrg (pSiS->ChipType < SIS_661) && 38772b676d7Smrg (pSiS->ROM661New) && 38872b676d7Smrg (!(pSiS->SiS_Pr->PanelSelfDetected))) { 38972b676d7Smrg tmp = 0x35; 39072b676d7Smrg } 39172b676d7Smrg if(pSiS->PRGB == 18) orSISIDXREG(SISCR, tmp, 0x01); 39272b676d7Smrg else if(pSiS->PRGB == 24) andSISIDXREG(SISCR, tmp, 0xfe); 39372b676d7Smrg } 39472b676d7Smrg inSISIDXREG(SISCR, 0x37, CR37); 39572b676d7Smrg if(pSiS->ChipType < SIS_661) { 39672b676d7Smrg inSISIDXREG(SISCR, 0x3C, CR7D); 39772b676d7Smrg } else { 39872b676d7Smrg inSISIDXREG(SISCR, 0x7D, CR7D); 39972b676d7Smrg } 40072b676d7Smrg if(pSiS->SiS_Pr->SiS_CustomT == CUT_BARCO1366) { 40172b676d7Smrg pSiS->VBLCDFlags |= VB_LCD_BARCO1366; 40272b676d7Smrg pSiS->LCDwidth = 1360; 40372b676d7Smrg pSiS->LCDheight = 1024; 40472b676d7Smrg if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 40572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 40672b676d7Smrg "Detected LCD panel (%dx%d, type %d, %sexpanding, RGB%d)\n", 40772b676d7Smrg pSiS->LCDwidth, pSiS->LCDheight, 40872b676d7Smrg ((CR36 & 0xf0) >> 4), 40972b676d7Smrg (CR37 & 0x10) ? "" : "non-", 41072b676d7Smrg (CR37 & 0x01) ? 18 : 24); 41172b676d7Smrg } else if(pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) { 41272b676d7Smrg pSiS->VBLCDFlags |= VB_LCD_848x480; 41372b676d7Smrg pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 848; 41472b676d7Smrg pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 480; 41572b676d7Smrg pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 41672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 41772b676d7Smrg "Assuming LCD/plasma panel (848x480, expanding, RGB24)\n"); 41872b676d7Smrg } else if(pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) { 41972b676d7Smrg pSiS->VBLCDFlags |= VB_LCD_856x480; 42072b676d7Smrg pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 856; 42172b676d7Smrg pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 480; 42272b676d7Smrg pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 42372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 42472b676d7Smrg "Assuming LCD/plasma panel (856x480, expanding, RGB24)\n"); 42572b676d7Smrg } else if(pSiS->FSTN) { 42672b676d7Smrg pSiS->VBLCDFlags |= VB_LCD_320x240; 42772b676d7Smrg pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 320; 42872b676d7Smrg pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 240; 42972b676d7Smrg pSiS->VBLCDFlags &= ~VB_LCD_EXPANDING; 43072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 43172b676d7Smrg "Assuming FSTN LCD panel (320x240, non-expanding)\n"); 43272b676d7Smrg } else { 43372b676d7Smrg if(CR36 == 0) { 43472b676d7Smrg /* Old 650/301LV and ECS A907 BIOS versions "forget" to set CR36, CR37 */ 43572b676d7Smrg if(pSiS->VGAEngine == SIS_315_VGA) { 43672b676d7Smrg if(pSiS->ChipType < SIS_661) { 43772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 43872b676d7Smrg "BIOS provided invalid panel size, probing...\n"); 43972b676d7Smrg if(pSiS->VBFlags2 & VB2_LVDS) pSiS->SiS_Pr->SiS_IF_DEF_LVDS = 1; 44072b676d7Smrg else pSiS->SiS_Pr->SiS_IF_DEF_LVDS = 0; 44172b676d7Smrg SiS_GetPanelID(pSiS->SiS_Pr); 44272b676d7Smrg inSISIDXREG(SISCR, 0x36, CR36); 44372b676d7Smrg inSISIDXREG(SISCR, 0x37, CR37); 44472b676d7Smrg } else { 44572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 44672b676d7Smrg "Broken BIOS, unable to determine panel size, disabling LCD\n"); 44772b676d7Smrg pSiS->VBFlags &= ~CRT2_LCD; 44872b676d7Smrg return; 44972b676d7Smrg } 45072b676d7Smrg } else if(pSiS->VGAEngine == SIS_300_VGA) { 45172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 45272b676d7Smrg "BIOS provided invalid panel size, assuming 1024x768, RGB18\n"); 45372b676d7Smrg setSISIDXREG(SISCR,0x36,0xf0,0x02); 45472b676d7Smrg setSISIDXREG(SISCR,0x37,0xee,0x01); 45572b676d7Smrg CR36 = 0x02; 45672b676d7Smrg inSISIDXREG(SISCR,0x37,CR37); 45772b676d7Smrg } 45872b676d7Smrg } 45972b676d7Smrg if((CR36 & 0x0f) == 0x0f) { 46072b676d7Smrg pSiS->VBLCDFlags |= VB_LCD_CUSTOM; 46172b676d7Smrg pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY; 46272b676d7Smrg pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX; 46372b676d7Smrg if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 46472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 46572b676d7Smrg "Detected LCD/Plasma panel (max. X %d Y %d, pref. %dx%d, RGB%d)\n", 46672b676d7Smrg pSiS->SiS_Pr->CP_MaxX, pSiS->SiS_Pr->CP_MaxY, 46772b676d7Smrg pSiS->SiS_Pr->CP_PreferredX, pSiS->SiS_Pr->CP_PreferredY, 46872b676d7Smrg (CR37 & 0x01) ? 18 : 24); 46972b676d7Smrg } else { 47072b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 47172b676d7Smrg pSiS->VBLCDFlags |= SiS300_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag; 47272b676d7Smrg pSiS->LCDheight = SiS300_LCD_Type[(CR36 & 0x0f)].LCDheight; 47372b676d7Smrg pSiS->LCDwidth = SiS300_LCD_Type[(CR36 & 0x0f)].LCDwidth; 47472b676d7Smrg if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 47572b676d7Smrg } else if((pSiS->ChipType >= SIS_661) || (pSiS->ROM661New)) { 47672b676d7Smrg pSiS->VBLCDFlags |= SiS661_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag; 47772b676d7Smrg pSiS->LCDheight = SiS661_LCD_Type[(CR36 & 0x0f)].LCDheight; 47872b676d7Smrg pSiS->LCDwidth = SiS661_LCD_Type[(CR36 & 0x0f)].LCDwidth; 47972b676d7Smrg if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 48072b676d7Smrg if(pSiS->ChipType < SIS_661) { 48172b676d7Smrg if(!(pSiS->SiS_Pr->PanelSelfDetected)) { 48272b676d7Smrg inSISIDXREG(SISCR,0x35,tmp); 48372b676d7Smrg CR37 &= 0xfc; 48472b676d7Smrg CR37 |= (tmp & 0x01); 48572b676d7Smrg } 48672b676d7Smrg } 48772b676d7Smrg } else { 48872b676d7Smrg pSiS->VBLCDFlags |= SiS315_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag; 48972b676d7Smrg pSiS->LCDheight = SiS315_LCD_Type[(CR36 & 0x0f)].LCDheight; 49072b676d7Smrg pSiS->LCDwidth = SiS315_LCD_Type[(CR36 & 0x0f)].LCDwidth; 49172b676d7Smrg if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 49272b676d7Smrg } 49372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 49472b676d7Smrg "Detected LCD/plasma panel (%dx%d, %d, %sexp., RGB%d [%02x%02x%02x])\n", 49572b676d7Smrg pSiS->LCDwidth, pSiS->LCDheight, 49672b676d7Smrg ((pSiS->VGAEngine == SIS_315_VGA) && (!pSiS->ROM661New)) ? 49772b676d7Smrg ((CR36 & 0x0f) - 1) : ((CR36 & 0xf0) >> 4), 49872b676d7Smrg (CR37 & 0x10) ? "" : "non-", 49972b676d7Smrg (CR37 & 0x01) ? 18 : 24, 50072b676d7Smrg CR36, CR37, CR7D); 50172b676d7Smrg } 50272b676d7Smrg } 50372b676d7Smrg } 50472b676d7Smrg} 50572b676d7Smrg 50672b676d7Smrgvoid SiSSetupPseudoPanel(ScrnInfoPtr pScrn) 50772b676d7Smrg{ 50872b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 50972b676d7Smrg int i; 51072b676d7Smrg 51172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 51272b676d7Smrg "No LCD detected, but forced to enable digital output\n"); 51372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 51472b676d7Smrg "Will not be able to properly filter display modes!\n"); 51572b676d7Smrg 51672b676d7Smrg pSiS->VBFlags |= CRT2_LCD; 51772b676d7Smrg pSiS->SiS_Pr->SiS_CustomT = CUT_UNKNOWNLCD; 51872b676d7Smrg pSiS->SiS_Pr->CP_PrefClock = 0; 51972b676d7Smrg pSiS->SiS_Pr->CP_PreferredIndex = -1; 52072b676d7Smrg pSiS->VBLCDFlags |= (VB_LCD_UNKNOWN | VB_LCD_EXPANDING); 52172b676d7Smrg pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 2048; 52272b676d7Smrg pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 2048; 52372b676d7Smrg for(i=0; i<7; i++) pSiS->SiS_Pr->CP_DataValid[i] = FALSE; 52472b676d7Smrg pSiS->SiS_Pr->CP_HaveCustomData = FALSE; 52572b676d7Smrg pSiS->SiS_Pr->PanelSelfDetected = TRUE; 52672b676d7Smrg outSISIDXREG(SISCR,0x36,0x0f); 52772b676d7Smrg setSISIDXREG(SISCR,0x37,0x0e,0x10); 52872b676d7Smrg orSISIDXREG(SISCR,0x32,0x08); 52972b676d7Smrg} 53072b676d7Smrg 53172b676d7Smrg/* Detect CRT2-TV connector type and PAL/NTSC flag */ 53272b676d7Smrgvoid SISTVPreInit(ScrnInfoPtr pScrn, Bool quiet) 53372b676d7Smrg{ 53472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 53572b676d7Smrg UChar SR16, SR38, CR32, CR35=0, CR38=0, CR79, CR39; 53672b676d7Smrg int temp = 0; 53772b676d7Smrg 53872b676d7Smrg if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return; 53972b676d7Smrg 54072b676d7Smrg inSISIDXREG(SISCR, 0x32, CR32); 54172b676d7Smrg inSISIDXREG(SISCR, 0x35, CR35); 54272b676d7Smrg inSISIDXREG(SISSR, 0x16, SR16); 54372b676d7Smrg inSISIDXREG(SISSR, 0x38, SR38); 54472b676d7Smrg switch(pSiS->VGAEngine) { 54572b676d7Smrg case SIS_300_VGA: 54672b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS630) temp = 0x35; 54772b676d7Smrg break; 54872b676d7Smrg case SIS_315_VGA: 54972b676d7Smrg temp = 0x38; 55072b676d7Smrg break; 55172b676d7Smrg } 55272b676d7Smrg if(temp) { 55372b676d7Smrg inSISIDXREG(SISCR, temp, CR38); 55472b676d7Smrg } 55572b676d7Smrg 55672b676d7Smrg#ifdef TWDEBUG 55772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 55872b676d7Smrg "(vb.c: SISTVPreInit 1: CR32=%02x SR16=%02x SR38=%02x VBFlags 0x%x)\n", 55972b676d7Smrg CR32, SR16, SR38, pSiS->VBFlags); 56072b676d7Smrg#endif 56172b676d7Smrg 56272b676d7Smrg if(CR32 & 0x47) pSiS->VBFlags |= CRT2_TV; 56372b676d7Smrg 56472b676d7Smrg if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 56572b676d7Smrg if(CR32 & 0x80) pSiS->VBFlags |= CRT2_TV; 56672b676d7Smrg } else { 56772b676d7Smrg CR32 &= 0x7f; 56872b676d7Smrg } 56972b676d7Smrg 57072b676d7Smrg if(CR32 & 0x01) 57172b676d7Smrg pSiS->VBFlags |= TV_AVIDEO; 57272b676d7Smrg else if(CR32 & 0x02) 57372b676d7Smrg pSiS->VBFlags |= TV_SVIDEO; 57472b676d7Smrg else if(CR32 & 0x04) 57572b676d7Smrg pSiS->VBFlags |= TV_SCART; 57672b676d7Smrg else if((CR32 & 0x40) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) 57772b676d7Smrg pSiS->VBFlags |= (TV_HIVISION | TV_PAL); 57872b676d7Smrg else if((CR32 & 0x80) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) { 57972b676d7Smrg pSiS->VBFlags |= TV_YPBPR; 58072b676d7Smrg if(pSiS->NewCRLayout) { 58172b676d7Smrg if(CR38 & 0x04) { 58272b676d7Smrg switch(CR35 & 0xE0) { 58372b676d7Smrg case 0x20: pSiS->VBFlags |= TV_YPBPR525P; break; 58472b676d7Smrg case 0x40: pSiS->VBFlags |= TV_YPBPR750P; break; 58572b676d7Smrg case 0x60: pSiS->VBFlags |= TV_YPBPR1080I; break; 58672b676d7Smrg default: pSiS->VBFlags |= TV_YPBPR525I; 58772b676d7Smrg } 58872b676d7Smrg } else pSiS->VBFlags |= TV_YPBPR525I; 58972b676d7Smrg inSISIDXREG(SISCR,0x39,CR39); 59072b676d7Smrg CR39 &= 0x03; 59172b676d7Smrg if(CR39 == 0x00) pSiS->VBFlags |= TV_YPBPR43LB; 59272b676d7Smrg else if(CR39 == 0x01) pSiS->VBFlags |= TV_YPBPR43; 59372b676d7Smrg else if(CR39 == 0x02) pSiS->VBFlags |= TV_YPBPR169; 59472b676d7Smrg else pSiS->VBFlags |= TV_YPBPR43; 59572b676d7Smrg } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 59672b676d7Smrg if(CR38 & 0x08) { 59772b676d7Smrg switch(CR38 & 0x30) { 59872b676d7Smrg case 0x10: pSiS->VBFlags |= TV_YPBPR525P; break; 59972b676d7Smrg case 0x20: pSiS->VBFlags |= TV_YPBPR750P; break; 60072b676d7Smrg case 0x30: pSiS->VBFlags |= TV_YPBPR1080I; break; 60172b676d7Smrg default: pSiS->VBFlags |= TV_YPBPR525I; 60272b676d7Smrg } 60372b676d7Smrg } else pSiS->VBFlags |= TV_YPBPR525I; 60472b676d7Smrg if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) { 60572b676d7Smrg inSISIDXREG(SISCR,0x3B,CR39); 60672b676d7Smrg CR39 &= 0x03; 60772b676d7Smrg if(CR39 == 0x00) pSiS->VBFlags |= TV_YPBPR43LB; 60872b676d7Smrg else if(CR39 == 0x01) pSiS->VBFlags |= TV_YPBPR169; 60972b676d7Smrg else if(CR39 == 0x03) pSiS->VBFlags |= TV_YPBPR43; 61072b676d7Smrg } 61172b676d7Smrg } 61272b676d7Smrg } else if((CR38 & 0x04) && (pSiS->VBFlags2 & VB2_CHRONTEL)) 61372b676d7Smrg pSiS->VBFlags |= (TV_CHSCART | TV_PAL); 61472b676d7Smrg else if((CR38 & 0x08) && (pSiS->VBFlags2 & VB2_CHRONTEL)) 61572b676d7Smrg pSiS->VBFlags |= (TV_CHYPBPR525I | TV_NTSC); 61672b676d7Smrg 61772b676d7Smrg if(pSiS->VBFlags & (TV_SCART | TV_SVIDEO | TV_AVIDEO)) { 61872b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 61972b676d7Smrg /* Should be SR38, but this does not work. */ 62072b676d7Smrg if(SR16 & 0x20) 62172b676d7Smrg pSiS->VBFlags |= TV_PAL; 62272b676d7Smrg else 62372b676d7Smrg pSiS->VBFlags |= TV_NTSC; 62472b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS550) { 62572b676d7Smrg inSISIDXREG(SISCR, 0x7a, CR79); 62672b676d7Smrg if(CR79 & 0x08) { 62772b676d7Smrg inSISIDXREG(SISCR, 0x79, CR79); 62872b676d7Smrg CR79 >>= 5; 62972b676d7Smrg } 63072b676d7Smrg if(CR79 & 0x01) { 63172b676d7Smrg pSiS->VBFlags |= TV_PAL; 63272b676d7Smrg if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM; 63372b676d7Smrg else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN; 63472b676d7Smrg } else 63572b676d7Smrg pSiS->VBFlags |= TV_NTSC; 63672b676d7Smrg } else if(pSiS->Chipset == PCI_CHIP_SIS650) { 63772b676d7Smrg inSISIDXREG(SISCR, 0x79, CR79); 63872b676d7Smrg if(CR79 & 0x20) { 63972b676d7Smrg pSiS->VBFlags |= TV_PAL; 64072b676d7Smrg if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM; 64172b676d7Smrg else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN; 64272b676d7Smrg } else 64372b676d7Smrg pSiS->VBFlags |= TV_NTSC; 64472b676d7Smrg } else if(pSiS->NewCRLayout) { 64572b676d7Smrg if(SR38 & 0x01) { 64672b676d7Smrg pSiS->VBFlags |= TV_PAL; 64772b676d7Smrg if(CR35 & 0x04) pSiS->VBFlags |= TV_PALM; 64872b676d7Smrg else if(CR35 & 0x08) pSiS->VBFlags |= TV_PALN; 64972b676d7Smrg } else { 65072b676d7Smrg pSiS->VBFlags |= TV_NTSC; 65172b676d7Smrg if(CR35 & 0x02) pSiS->VBFlags |= TV_NTSCJ; 65272b676d7Smrg } 65372b676d7Smrg } else { /* 315, 330 */ 65472b676d7Smrg if(SR38 & 0x01) { 65572b676d7Smrg pSiS->VBFlags |= TV_PAL; 65672b676d7Smrg if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM; 65772b676d7Smrg else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN; 65872b676d7Smrg } else 65972b676d7Smrg pSiS->VBFlags |= TV_NTSC; 66072b676d7Smrg } 66172b676d7Smrg } 66272b676d7Smrg 66372b676d7Smrg#ifdef TWDEBUG 66472b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 66572b676d7Smrg "(vb.c: SISTVPreInit 2: VBFlags 0x%x)\n", pSiS->VBFlags); 66672b676d7Smrg#endif 66772b676d7Smrg 66872b676d7Smrg if((pSiS->VBFlags & (TV_SCART|TV_SVIDEO|TV_AVIDEO)) && !quiet) { 66972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected default TV standard %s\n", 67072b676d7Smrg (pSiS->VBFlags & TV_NTSC) ? 67172b676d7Smrg ((pSiS->VBFlags & TV_NTSCJ) ? "NTSCJ" : "NTSC") : 67272b676d7Smrg ((pSiS->VBFlags & TV_PALM) ? "PALM" : 67372b676d7Smrg ((pSiS->VBFlags & TV_PALN) ? "PALN" : "PAL"))); 67472b676d7Smrg } 67572b676d7Smrg 67672b676d7Smrg if((pSiS->VBFlags & TV_HIVISION) && !quiet) { 67772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "BIOS reports HiVision TV\n"); 67872b676d7Smrg } 67972b676d7Smrg 68072b676d7Smrg if((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART|TV_CHYPBPR525I)) && !quiet) { 68172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chrontel: %s forced\n", 68272b676d7Smrg (pSiS->VBFlags & TV_CHSCART) ? "SCART (PAL)" : "YPbPr (480i)"); 68372b676d7Smrg } 68472b676d7Smrg 68572b676d7Smrg if((pSiS->VBFlags & TV_YPBPR) && !quiet) { 68672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected YPbPr TV (by default %s)\n", 68772b676d7Smrg (pSiS->VBFlags & TV_YPBPR525I) ? "480i" : 68872b676d7Smrg ((pSiS->VBFlags & TV_YPBPR525P) ? "480p" : 68972b676d7Smrg ((pSiS->VBFlags & TV_YPBPR750P) ? "720p" : "1080i"))); 69072b676d7Smrg } 69172b676d7Smrg} 69272b676d7Smrg 69372b676d7Smrg/* Detect CRT2-VGA */ 69472b676d7Smrgvoid SISCRT2PreInit(ScrnInfoPtr pScrn, Bool quiet) 69572b676d7Smrg{ 69672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 69772b676d7Smrg UChar CR32; 69872b676d7Smrg 69972b676d7Smrg /* CRT2-VGA only supported on these bridges */ 70072b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) 70172b676d7Smrg return; 70272b676d7Smrg 70372b676d7Smrg inSISIDXREG(SISCR, 0x32, CR32); 70472b676d7Smrg 70572b676d7Smrg if(CR32 & 0x10) pSiS->VBFlags |= CRT2_VGA; 70672b676d7Smrg 70772b676d7Smrg /* See the comment in initextx.c/SiS_SenseVGA2DDC() */ 70872b676d7Smrg if(pSiS->SiS_Pr->DDCPortMixup) return; 70972b676d7Smrg 71072b676d7Smrg#ifdef SISDUALHEAD 71172b676d7Smrg if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 71272b676d7Smrg#endif 71372b676d7Smrg 71472b676d7Smrg if(pSiS->forcecrt2redetection) { 71572b676d7Smrg pSiS->VBFlags &= ~CRT2_VGA; 71672b676d7Smrg } 71772b676d7Smrg 71872b676d7Smrg /* We don't trust the normal sensing method for VGA2 since 71972b676d7Smrg * it is performed by the BIOS during POST, and it is 72072b676d7Smrg * impossible to sense VGA2 if the bridge is disabled. 72172b676d7Smrg * Therefore, we try sensing VGA2 by DDC as well (if not 72272b676d7Smrg * detected otherwise and only if there is no LCD panel 72372b676d7Smrg * which is prone to be misdetected as a secondary VGA) 72472b676d7Smrg */ 72572b676d7Smrg if(!(pSiS->nocrt2ddcdetection)) { 72672b676d7Smrg if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD))) { 72772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 72872b676d7Smrg "%s secondary VGA, sensing via DDC\n", 72972b676d7Smrg pSiS->forcecrt2redetection ? 73072b676d7Smrg "Forced re-detection of" : "BIOS detected no"); 73172b676d7Smrg if(SiS_SenseVGA2DDC(pSiS->SiS_Pr, pSiS)) { 73272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 73372b676d7Smrg "DDC error during secondary VGA detection\n"); 73472b676d7Smrg } else { 73572b676d7Smrg inSISIDXREG(SISCR, 0x32, CR32); 73672b676d7Smrg if(CR32 & 0x10) { 73772b676d7Smrg pSiS->VBFlags |= CRT2_VGA; 73872b676d7Smrg pSiS->postVBCR32 |= 0x10; 73972b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 74072b676d7Smrg "Detected secondary VGA connection\n"); 74172b676d7Smrg } else { 74272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 74372b676d7Smrg "No secondary VGA connection detected\n"); 74472b676d7Smrg } 74572b676d7Smrg } 74672b676d7Smrg } 74772b676d7Smrg } 74872b676d7Smrg#ifdef SISDUALHEAD 74972b676d7Smrg } 75072b676d7Smrg#endif 75172b676d7Smrg} 75272b676d7Smrg 75372b676d7Smrgstatic int 75472b676d7SmrgSISDoSense(ScrnInfoPtr pScrn, UShort type, UShort test) 75572b676d7Smrg{ 75672b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 75772b676d7Smrg int temp, mytest, result, i, j; 75872b676d7Smrg 75972b676d7Smrg#ifdef TWDEBUG 76072b676d7Smrg xf86DrvMsg(0, X_INFO, "Sense: %x %x\n", type, test); 76172b676d7Smrg#endif 76272b676d7Smrg 76372b676d7Smrg for(j = 0; j < 10; j++) { 76472b676d7Smrg result = 0; 76572b676d7Smrg for(i = 0; i < 3; i++) { 76672b676d7Smrg mytest = test; 76772b676d7Smrg outSISIDXREG(SISPART4,0x11,(type & 0x00ff)); 76872b676d7Smrg temp = (type >> 8) | (mytest & 0x00ff); 76972b676d7Smrg setSISIDXREG(SISPART4,0x10,0xe0,temp); 77072b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x1500); 77172b676d7Smrg mytest >>= 8; 77272b676d7Smrg mytest &= 0x7f; 77372b676d7Smrg inSISIDXREG(SISPART4,0x03,temp); 77472b676d7Smrg temp ^= 0x0e; 77572b676d7Smrg temp &= mytest; 77672b676d7Smrg if(temp == mytest) result++; 77772b676d7Smrg#if 1 77872b676d7Smrg outSISIDXREG(SISPART4,0x11,0x00); 77972b676d7Smrg andSISIDXREG(SISPART4,0x10,0xe0); 78072b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x1000); 78172b676d7Smrg#endif 78272b676d7Smrg } 78372b676d7Smrg if((result == 0) || (result >= 2)) break; 78472b676d7Smrg } 78572b676d7Smrg return(result); 78672b676d7Smrg} 78772b676d7Smrg 78872b676d7Smrg#define GETROMWORD(w) (pSiS->BIOS[w] | (pSiS->BIOS[w+1] << 8)) 78972b676d7Smrg 79072b676d7Smrg/* Sense connected devices on 30x */ 79172b676d7Smrgvoid 79272b676d7SmrgSISSense30x(ScrnInfoPtr pScrn, Bool quiet) 79372b676d7Smrg{ 79472b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 79572b676d7Smrg UChar backupP4_0d, backupP2_00, backupP2_4d, backupSR_1e, biosflag=0; 79672b676d7Smrg UShort svhs=0, svhs_c=0; 79772b676d7Smrg UShort cvbs=0, cvbs_c=0; 79872b676d7Smrg UShort vga2=0, vga2_c=0; 79972b676d7Smrg int myflag, result; /* , i; */ 80072b676d7Smrg 80172b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 80272b676d7Smrg 80372b676d7Smrg#ifdef TWDEBUG 80472b676d7Smrg inSISIDXREG(SISCR,0x32,backupP2_4d); 80572b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 80672b676d7Smrg "(vb.c: SISSense30c 1: CR32=%02x, VBFlags 0x%x)\n", backupP2_4d, pSiS->VBFlags); 80772b676d7Smrg#endif 80872b676d7Smrg 80972b676d7Smrg if(pSiS->VBFlags2 & VB2_301) { 81072b676d7Smrg svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1; 81172b676d7Smrg inSISIDXREG(SISPART4,0x01,myflag); 81272b676d7Smrg if(myflag & 0x04) { 81372b676d7Smrg svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd; 81472b676d7Smrg } 81572b676d7Smrg } else if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) { 81672b676d7Smrg svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190; 81772b676d7Smrg } else if(pSiS->VBFlags2 & (VB2_301LV | VB2_302LV)) { 81872b676d7Smrg svhs = 0x0200; cvbs = 0x0100; 81972b676d7Smrg } else if(pSiS->VBFlags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) { 82072b676d7Smrg svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190; 82172b676d7Smrg } else return; 82272b676d7Smrg 82372b676d7Smrg vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804; 82472b676d7Smrg if(pSiS->VBFlags2 & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) { 82572b676d7Smrg svhs_c = 0x0408; cvbs_c = 0x0808; 82672b676d7Smrg } 82772b676d7Smrg biosflag = 2; 82872b676d7Smrg 82972b676d7Smrg if(pSiS->Chipset == PCI_CHIP_SIS300) { 83072b676d7Smrg inSISIDXREG(SISSR,0x3b,myflag); 83172b676d7Smrg if(!(myflag & 0x01)) vga2 = vga2_c = 0; 83272b676d7Smrg } 83372b676d7Smrg 83472b676d7Smrg if(pSiS->SiS_Pr->UseROM) { 83572b676d7Smrg if(pSiS->VGAEngine == SIS_300_VGA) { 83672b676d7Smrg if(pSiS->VBFlags2 & VB2_301) { 83772b676d7Smrg inSISIDXREG(SISPART4,0x01,myflag); 83872b676d7Smrg if(!(myflag & 0x04)) { 83972b676d7Smrg vga2 = GETROMWORD(0xf8); svhs = GETROMWORD(0xfa); cvbs = GETROMWORD(0xfc); 84072b676d7Smrg } 84172b676d7Smrg } 84272b676d7Smrg biosflag = pSiS->BIOS[0xfe]; 84372b676d7Smrg } else if((pSiS->Chipset == PCI_CHIP_SIS660) || 84472b676d7Smrg (pSiS->Chipset == PCI_CHIP_SIS340)) { 84572b676d7Smrg if(pSiS->ROM661New) { 84672b676d7Smrg biosflag = 2; 84772b676d7Smrg vga2 = GETROMWORD(0x63); 84872b676d7Smrg if(pSiS->BIOS[0x6f] & 0x01) { 84972b676d7Smrg if(pSiS->VBFlags2 & VB2_SISUMC) vga2 = GETROMWORD(0x4d); 85072b676d7Smrg } 85172b676d7Smrg svhs = cvbs = GETROMWORD(0x65); 85272b676d7Smrg if(pSiS->BIOS[0x5d] & 0x04) biosflag |= 0x01; 85372b676d7Smrg } 85472b676d7Smrg } 85572b676d7Smrg /* No "else", some BIOSes carry wrong data */ 85672b676d7Smrg } 85772b676d7Smrg 85872b676d7Smrg if(pSiS->ChipType >= XGI_20) { 85972b676d7Smrg if(pSiS->HaveXGIBIOS) { 86072b676d7Smrg biosflag = pSiS->BIOS[0x58] & 0x03; 86172b676d7Smrg } else { 86272b676d7Smrg /* These boards have a s-video connector, but its 86372b676d7Smrg * pins are routed both the bridge's composite and 86472b676d7Smrg * svideo pins. This is for using the S-video plug 86572b676d7Smrg * for YPbPr output. Anyway, since a svideo connected 86672b676d7Smrg * TV would also been detected as a composite connected 86772b676d7Smrg * one, we don't check for composite if svideo is 86872b676d7Smrg * detected. 86972b676d7Smrg */ 87072b676d7Smrg biosflag &= ~0x02; 87172b676d7Smrg } 87272b676d7Smrg } 87372b676d7Smrg 87472b676d7Smrg if(!(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 87572b676d7Smrg vga2 = vga2_c = 0; 87672b676d7Smrg } 87772b676d7Smrg 87872b676d7Smrg inSISIDXREG(SISSR,0x1e,backupSR_1e); 87972b676d7Smrg orSISIDXREG(SISSR,0x1e,0x20); 88072b676d7Smrg 88172b676d7Smrg inSISIDXREG(SISPART4,0x0d,backupP4_0d); 88272b676d7Smrg if(pSiS->VBFlags2 & VB2_30xCLV) { 88372b676d7Smrg setSISIDXREG(SISPART4,0x0d,~0x07,0x01); 88472b676d7Smrg } else { 88572b676d7Smrg orSISIDXREG(SISPART4,0x0d,0x04); 88672b676d7Smrg } 88772b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x2000); 88872b676d7Smrg 88972b676d7Smrg inSISIDXREG(SISPART2,0x00,backupP2_00); 89072b676d7Smrg outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc)); 89172b676d7Smrg 89272b676d7Smrg inSISIDXREG(SISPART2,0x4d,backupP2_4d); 89372b676d7Smrg if(pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE) { 89472b676d7Smrg outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10)); 89572b676d7Smrg } 89672b676d7Smrg 89772b676d7Smrg if(!(pSiS->VBFlags2 & VB2_30xCLV)) { 89872b676d7Smrg SISDoSense(pScrn, 0, 0); 89972b676d7Smrg } 90072b676d7Smrg 90172b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x14); 90272b676d7Smrg pSiS->postVBCR32 &= ~0x14; 90372b676d7Smrg 90472b676d7Smrg if(vga2_c || vga2) { 90572b676d7Smrg if(SISDoSense(pScrn, vga2, vga2_c)) { 90672b676d7Smrg if(biosflag & 0x01) { 90772b676d7Smrg if(!quiet) { 90872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 90972b676d7Smrg "SiS30x: Detected TV connected to SCART output\n"); 91072b676d7Smrg } 91172b676d7Smrg pSiS->VBFlags |= TV_SCART; 91272b676d7Smrg orSISIDXREG(SISCR, 0x32, 0x04); 91372b676d7Smrg pSiS->postVBCR32 |= 0x04; 91472b676d7Smrg } else { 91572b676d7Smrg if(!quiet) { 91672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 91772b676d7Smrg "SiS30x: Detected secondary VGA connection\n"); 91872b676d7Smrg } 91972b676d7Smrg pSiS->VBFlags |= VGA2_CONNECTED; 92072b676d7Smrg orSISIDXREG(SISCR, 0x32, 0x10); 92172b676d7Smrg pSiS->postVBCR32 |= 0x10; 92272b676d7Smrg } 92372b676d7Smrg } 92472b676d7Smrg if(biosflag & 0x01) pSiS->SiS_SD_Flags |= SiS_SD_VBHASSCART; 92572b676d7Smrg } 92672b676d7Smrg 92772b676d7Smrg andSISIDXREG(SISCR, 0x32, 0x3f); 92872b676d7Smrg pSiS->postVBCR32 &= 0x3f; 92972b676d7Smrg 93072b676d7Smrg if(pSiS->VBFlags2 & VB2_30xCLV) { 93172b676d7Smrg orSISIDXREG(SISPART4,0x0d,0x04); 93272b676d7Smrg } 93372b676d7Smrg 93472b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) { 93572b676d7Smrg if(pSiS->SenseYPbPr) { 93672b676d7Smrg outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10)); 93772b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x2000); 93872b676d7Smrg /* New BIOS (2.x) uses vga2 sensing here for all bridges >301LV */ 93972b676d7Smrg if((result = SISDoSense(pScrn, svhs, 0x0604))) { 94072b676d7Smrg if((result = SISDoSense(pScrn, cvbs, 0x0804))) { 94172b676d7Smrg if(!quiet) { 94272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 94372b676d7Smrg "SiS30x: Detected TV connected to YPbPr component output\n"); 94472b676d7Smrg } 94572b676d7Smrg orSISIDXREG(SISCR,0x32,0x80); 94672b676d7Smrg pSiS->VBFlags |= TV_YPBPR; 94772b676d7Smrg pSiS->postVBCR32 |= 0x80; 94872b676d7Smrg } 94972b676d7Smrg } 95072b676d7Smrg outSISIDXREG(SISPART2,0x4d,backupP2_4d); 95172b676d7Smrg } 95272b676d7Smrg } 95372b676d7Smrg 95472b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x03); 95572b676d7Smrg pSiS->postVBCR32 &= ~0x03; 95672b676d7Smrg 95772b676d7Smrg if(!(pSiS->VBFlags & TV_YPBPR)) { 95872b676d7Smrg 95972b676d7Smrg if((result = SISDoSense(pScrn, svhs, svhs_c))) { 96072b676d7Smrg if(!quiet) { 96172b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 96272b676d7Smrg "SiS30x: Detected TV connected to SVIDEO output\n"); 96372b676d7Smrg } 96472b676d7Smrg pSiS->VBFlags |= TV_SVIDEO; 96572b676d7Smrg orSISIDXREG(SISCR, 0x32, 0x02); 96672b676d7Smrg pSiS->postVBCR32 |= 0x02; 96772b676d7Smrg } 96872b676d7Smrg 96972b676d7Smrg if((biosflag & 0x02) || (!result)) { 97072b676d7Smrg if(SISDoSense(pScrn, cvbs, cvbs_c)) { 97172b676d7Smrg if(!quiet) { 97272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 97372b676d7Smrg "SiS30x: Detected TV connected to COMPOSITE output\n"); 97472b676d7Smrg } 97572b676d7Smrg pSiS->VBFlags |= TV_AVIDEO; 97672b676d7Smrg orSISIDXREG(SISCR, 0x32, 0x01); 97772b676d7Smrg pSiS->postVBCR32 |= 0x01; 97872b676d7Smrg } 97972b676d7Smrg } 98072b676d7Smrg 98172b676d7Smrg } 98272b676d7Smrg 98372b676d7Smrg SISDoSense(pScrn, 0, 0); 98472b676d7Smrg 98572b676d7Smrg outSISIDXREG(SISPART2,0x00,backupP2_00); 98672b676d7Smrg outSISIDXREG(SISPART4,0x0d,backupP4_0d); 98772b676d7Smrg outSISIDXREG(SISSR,0x1e,backupSR_1e); 98872b676d7Smrg 98972b676d7Smrg if(pSiS->VBFlags2 & VB2_30xCLV) { 99072b676d7Smrg inSISIDXREG(SISPART2,0x00,biosflag); 99172b676d7Smrg if(biosflag & 0x20) { 99272b676d7Smrg for(myflag = 2; myflag > 0; myflag--) { 99372b676d7Smrg biosflag ^= 0x20; 99472b676d7Smrg outSISIDXREG(SISPART2,0x00,biosflag); 99572b676d7Smrg } 99672b676d7Smrg } 99772b676d7Smrg } 99872b676d7Smrg 99972b676d7Smrg outSISIDXREG(SISPART2,0x00,backupP2_00); 100072b676d7Smrg 100172b676d7Smrg#ifdef TWDEBUG 100272b676d7Smrg inSISIDXREG(SISCR,0x32,backupP2_4d); 100372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 100472b676d7Smrg "(vb.c: SISSense30c 2: CR32=0x%02x, VBFlags 0x%x)\n", backupP2_4d, pSiS->VBFlags); 100572b676d7Smrg#endif 100672b676d7Smrg} 100772b676d7Smrg 100872b676d7Smrgvoid 100972b676d7SmrgSISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet) 101072b676d7Smrg{ 101172b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 101272b676d7Smrg int temp1=0, temp2, i; 101372b676d7Smrg UChar test[3]; 101472b676d7Smrg 101572b676d7Smrg if(pSiS->SiS_Pr->SiS_IF_DEF_CH70xx == 1) { 101672b676d7Smrg 101772b676d7Smrg /* Chrontel 700x */ 101872b676d7Smrg 101972b676d7Smrg /* Read power status */ 102072b676d7Smrg temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x0e); /* Power status */ 102172b676d7Smrg if((temp1 & 0x03) != 0x03) { 102272b676d7Smrg /* Power all outputs */ 102372b676d7Smrg SiS_SetCH700x(pSiS->SiS_Pr, 0x0e,0x0b); 102472b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 102572b676d7Smrg } 102672b676d7Smrg /* Sense connected TV devices */ 102772b676d7Smrg for(i = 0; i < 3; i++) { 102872b676d7Smrg SiS_SetCH700x(pSiS->SiS_Pr, 0x10, 0x01); 102972b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 103072b676d7Smrg SiS_SetCH700x(pSiS->SiS_Pr, 0x10, 0x00); 103172b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 103272b676d7Smrg temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x10); 103372b676d7Smrg if(!(temp1 & 0x08)) test[i] = 0x02; 103472b676d7Smrg else if(!(temp1 & 0x02)) test[i] = 0x01; 103572b676d7Smrg else test[i] = 0; 103672b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 103772b676d7Smrg } 103872b676d7Smrg 103972b676d7Smrg if(test[0] == test[1]) temp1 = test[0]; 104072b676d7Smrg else if(test[0] == test[2]) temp1 = test[0]; 104172b676d7Smrg else if(test[1] == test[2]) temp1 = test[1]; 104272b676d7Smrg else { 104372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 104472b676d7Smrg "Chrontel: TV detection unreliable - test results varied\n"); 104572b676d7Smrg temp1 = test[2]; 104672b676d7Smrg } 104772b676d7Smrg 104872b676d7Smrg } else if(pSiS->SiS_Pr->SiS_IF_DEF_CH70xx == 2) { 104972b676d7Smrg 105072b676d7Smrg /* Chrontel 701x */ 105172b676d7Smrg 105272b676d7Smrg /* Backup Power register */ 105372b676d7Smrg temp1 = SiS_GetCH701x(pSiS->SiS_Pr, 0x49); 105472b676d7Smrg 105572b676d7Smrg /* Enable TV path */ 105672b676d7Smrg SiS_SetCH701x(pSiS->SiS_Pr, 0x49, 0x20); 105772b676d7Smrg 105872b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 105972b676d7Smrg 106072b676d7Smrg /* Sense connected TV devices */ 106172b676d7Smrg temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20); 106272b676d7Smrg temp2 |= 0x01; 106372b676d7Smrg SiS_SetCH701x(pSiS->SiS_Pr, 0x20, temp2); 106472b676d7Smrg 106572b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 106672b676d7Smrg 106772b676d7Smrg temp2 ^= 0x01; 106872b676d7Smrg SiS_SetCH701x(pSiS->SiS_Pr, 0x20, temp2); 106972b676d7Smrg 107072b676d7Smrg SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 107172b676d7Smrg 107272b676d7Smrg temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20); 107372b676d7Smrg 107472b676d7Smrg /* Restore Power register */ 107572b676d7Smrg SiS_SetCH701x(pSiS->SiS_Pr, 0x49, temp1); 107672b676d7Smrg 107772b676d7Smrg temp1 = 0; 107872b676d7Smrg if(temp2 & 0x02) temp1 |= 0x01; 107972b676d7Smrg if(temp2 & 0x10) temp1 |= 0x01; 108072b676d7Smrg if(temp2 & 0x04) temp1 |= 0x02; 108172b676d7Smrg 108272b676d7Smrg if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04; 108372b676d7Smrg 108472b676d7Smrg } 108572b676d7Smrg 108672b676d7Smrg switch(temp1) { 108772b676d7Smrg case 0x01: 108872b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 108972b676d7Smrg "Chrontel: Detected TV connected to COMPOSITE output\n"); 109072b676d7Smrg pSiS->VBFlags |= TV_AVIDEO; 109172b676d7Smrg orSISIDXREG(SISCR, 0x32, 0x01); 109272b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x06); 109372b676d7Smrg pSiS->postVBCR32 |= 0x01; 109472b676d7Smrg pSiS->postVBCR32 &= ~0x06; 109572b676d7Smrg break; 109672b676d7Smrg case 0x02: 109772b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 109872b676d7Smrg "Chrontel: Detected TV connected to SVIDEO output\n"); 109972b676d7Smrg pSiS->VBFlags |= TV_SVIDEO; 110072b676d7Smrg orSISIDXREG(SISCR, 0x32, 0x02); 110172b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x05); 110272b676d7Smrg pSiS->postVBCR32 |= 0x02; 110372b676d7Smrg pSiS->postVBCR32 &= ~0x05; 110472b676d7Smrg break; 110572b676d7Smrg case 0x04: 110672b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 110772b676d7Smrg "Chrontel: Detected TV connected to SCART or YPBPR output\n"); 110872b676d7Smrg if(pSiS->chtvtype == -1) { 110972b676d7Smrg if(!quiet) { 111072b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 111172b676d7Smrg "Chrontel: Use CHTVType option to select either SCART or YPBPR525I\n"); 111272b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 111372b676d7Smrg "Chrontel: Using SCART by default\n"); 111472b676d7Smrg } 111572b676d7Smrg pSiS->chtvtype = 1; 111672b676d7Smrg } 111772b676d7Smrg if(pSiS->chtvtype) 111872b676d7Smrg pSiS->VBFlags |= TV_CHSCART; 111972b676d7Smrg else 112072b676d7Smrg pSiS->VBFlags |= TV_CHYPBPR525I; 112172b676d7Smrg break; 112272b676d7Smrg default: 112372b676d7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 112472b676d7Smrg "Chrontel: No TV detected.\n"); 112572b676d7Smrg andSISIDXREG(SISCR, 0x32, ~0x07); 112672b676d7Smrg pSiS->postVBCR32 &= ~0x07; 112772b676d7Smrg } 112872b676d7Smrg} 112972b676d7Smrg 113072b676d7Smrg/* Redetect CRT2 devices. Calling this requires a reset 113172b676d7Smrg * of the current display mode if TRUE is returned. 113272b676d7Smrg */ 113372b676d7SmrgBool SISRedetectCRT2Type(ScrnInfoPtr pScrn) 113472b676d7Smrg{ 113572b676d7Smrg SISPtr pSiS = SISPTR(pScrn); 113672b676d7Smrg ULong VBFlagsBackup = pSiS->VBFlags; 113772b676d7Smrg Bool backup1 = pSiS->forcecrt2redetection; 113872b676d7Smrg Bool backup2 = pSiS->nocrt2ddcdetection; 113972b676d7Smrg 114072b676d7Smrg#ifdef SISDUALHEAD 114172b676d7Smrg if(pSiS->DualHeadMode) return FALSE; 114272b676d7Smrg#endif 114372b676d7Smrg 114472b676d7Smrg pSiS->VBFlags &= ~(CRT2_DEFAULT | 114572b676d7Smrg CRT2_ENABLE | 114672b676d7Smrg TV_STANDARD | 114772b676d7Smrg TV_INTERFACE | 114872b676d7Smrg TV_YPBPRALL | 114972b676d7Smrg TV_YPBPRAR | 115072b676d7Smrg TV_CHSCART | 115172b676d7Smrg TV_CHYPBPR525I | 115272b676d7Smrg CRT1_LCDA | 115372b676d7Smrg DISPTYPE_CRT1); 115472b676d7Smrg 115572b676d7Smrg /* At first, re-do the sensing for TV and VGA2 */ 115672b676d7Smrg if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 115772b676d7Smrg SISSense30x(pScrn, TRUE); 115872b676d7Smrg } else if(pSiS->VBFlags2 & VB2_CHRONTEL) { 115972b676d7Smrg SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x9c); 116072b676d7Smrg SISSenseChrontel(pScrn, TRUE); 116172b676d7Smrg SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x00); 116272b676d7Smrg } 116372b676d7Smrg 116472b676d7Smrg SISTVPreInit(pScrn, TRUE); 116572b676d7Smrg 116672b676d7Smrg pSiS->forcecrt2redetection = TRUE; 116772b676d7Smrg pSiS->nocrt2ddcdetection = FALSE; 116872b676d7Smrg 116972b676d7Smrg /* We only re-detect LCD for the TMDS-SiS-bridges. LVDS 117072b676d7Smrg * is practically never being hot-plugged (and even if, 117172b676d7Smrg * there is no way of detecting this). 117272b676d7Smrg */ 117372b676d7Smrg if((pSiS->VGAEngine == SIS_315_VGA) && 117472b676d7Smrg (pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 117572b676d7Smrg (!(pSiS->VBFlags2 & VB2_30xBDH)) && 117672b676d7Smrg (pSiS->VESA != 1) && 117772b676d7Smrg (pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) { 117872b676d7Smrg SISLCDPreInit(pScrn, TRUE); 117972b676d7Smrg } else { 118072b676d7Smrg pSiS->VBFlags |= (pSiS->detectedCRT2Devices & CRT2_LCD); 118172b676d7Smrg } 118272b676d7Smrg 118372b676d7Smrg /* Secondary VGA is only supported on these bridges: */ 118472b676d7Smrg if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 118572b676d7Smrg SISCRT2PreInit(pScrn, TRUE); 118672b676d7Smrg } 118772b676d7Smrg 118872b676d7Smrg pSiS->forcecrt2redetection = backup1; 118972b676d7Smrg pSiS->nocrt2ddcdetection = backup2; 119072b676d7Smrg 119172b676d7Smrg pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA; 119272b676d7Smrg if(SISDetermineLCDACap(pScrn)) { 119372b676d7Smrg pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA; 119472b676d7Smrg } 119572b676d7Smrg SISSaveDetectedDevices(pScrn); 119672b676d7Smrg 119772b676d7Smrg pSiS->VBFlags = VBFlagsBackup; 119872b676d7Smrg 119972b676d7Smrg /* If LCD disappeared, don't use it and don't advertise LCDA support. Duh! */ 120072b676d7Smrg if(!(pSiS->detectedCRT2Devices & CRT2_LCD)) { 120172b676d7Smrg pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTLCDA); 120272b676d7Smrg if(pSiS->VBFlags & CRT2_LCD) { 120372b676d7Smrg /* If CRT2 was LCD, disable CRT2 and adapt display mode flags */ 120472b676d7Smrg pSiS->VBFlags &= ~(CRT2_LCD | DISPLAY_MODE); 120572b676d7Smrg /* Switch on CRT1 as an emergency measure */ 120672b676d7Smrg pSiS->VBFlags |= (SINGLE_MODE | DISPTYPE_CRT1); 120772b676d7Smrg pSiS->CRT1off = 0; 120872b676d7Smrg } 120972b676d7Smrg /* If CRT1 was LCD, switch to CRT1-VGA. No need to adapt display mode flags. */ 121072b676d7Smrg pSiS->VBFlags &= ~(CRT1_LCDA); 121172b676d7Smrg pSiS->VBFlags_backup = pSiS->VBFlags; 121272b676d7Smrg } 121372b676d7Smrg 121472b676d7Smrg pSiS->VBFlagsInit = pSiS->VBFlags; 121572b676d7Smrg 121672b676d7Smrg /* Save new detection result registers to write them back in EnterVT() */ 121772b676d7Smrg inSISIDXREG(SISCR,0x32,pSiS->myCR32); 121872b676d7Smrg inSISIDXREG(SISCR,0x36,pSiS->myCR36); 121972b676d7Smrg inSISIDXREG(SISCR,0x37,pSiS->myCR37); 122072b676d7Smrg 122172b676d7Smrg return TRUE; 122272b676d7Smrg} 122372b676d7Smrg 122472b676d7Smrg 1225