summaryrefslogtreecommitdiff
path: root/src/sis_vb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sis_vb.c')
-rw-r--r--src/sis_vb.c948
1 files changed, 760 insertions, 188 deletions
diff --git a/src/sis_vb.c b/src/sis_vb.c
index 319df6a..4134f71 100644
--- a/src/sis_vb.c
+++ b/src/sis_vb.c
@@ -1,26 +1,31 @@
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sis/sis_vb.c,v 1.19 2003/09/05 09:38:37 twini Exp $ */
+/* $XFree86$ */
+/* $XdotOrg$ */
/*
* Video bridge detection and configuration for 300, 315 and 330 series
*
- * Copyright 2002, 2003 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
*
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the copyright holder not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. The copyright holder makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1) Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2) Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3) The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Thomas Winischhofer <thomas@winischhofer.net>
*
@@ -36,85 +41,107 @@
#include "sis_vb.h"
#include "sis_dac.h"
-extern void SISWaitRetraceCRT1(ScrnInfoPtr pScrn);
+extern BOOLEAN SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension);
+extern USHORT SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
+extern USHORT SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
+
+extern void SISDetermineLCDACap(ScrnInfoPtr pScrn);
+extern void SISSaveDetectedDevices(ScrnInfoPtr pScrn);
+
+extern void SISWaitRetraceCRT1(ScrnInfoPtr pScrn);
+extern unsigned char SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, unsigned char value);
static const SiS_LCD_StStruct SiS300_LCD_Type[]=
{
- { VB_LCD_1024x768, 1024, 768, LCD_1024x768 }, /* 0 - invalid */
- { VB_LCD_800x600, 800, 600, LCD_800x600 }, /* 1 */
- { VB_LCD_1024x768, 1024, 768, LCD_1024x768 }, /* 2 */
- { VB_LCD_1280x1024,1280, 1024, LCD_1280x1024}, /* 3 */
- { VB_LCD_1280x960, 1280, 960, LCD_1280x960 }, /* 4 */
- { VB_LCD_640x480, 640, 480, LCD_640x480 }, /* 5 */
- { VB_LCD_1024x600, 1024, 600, LCD_1024x600 }, /* 6 */
- { VB_LCD_1152x768, 1152, 768, LCD_1152x768 }, /* 7 */
- { VB_LCD_1024x768, 1024, 768, LCD_1024x768 }, /* 8 */
- { VB_LCD_1024x768, 1024, 768, LCD_1024x768 }, /* 9 */
- { VB_LCD_1280x768, 1280, 768, LCD_1280x768 }, /* a */
- { VB_LCD_1024x768, 1024, 768, LCD_1024x768 }, /* b */
- { VB_LCD_1024x768, 1024, 768, LCD_1024x768 }, /* c */
- { VB_LCD_1024x768, 1024, 768, LCD_1024x768 }, /* d */
- { VB_LCD_320x480, 320, 480, LCD_320x480 }, /* e */
- { VB_LCD_CUSTOM, 0, 0, LCD_CUSTOM } /* f */
+ { VB_LCD_1024x768, 1024, 768 }, /* 0 - invalid */
+ { VB_LCD_800x600, 800, 600 }, /* 1 */
+ { VB_LCD_1024x768, 1024, 768 }, /* 2 */
+ { VB_LCD_1280x1024,1280, 1024 }, /* 3 */
+ { VB_LCD_1280x960, 1280, 960 }, /* 4 */
+ { VB_LCD_640x480, 640, 480 }, /* 5 */
+ { VB_LCD_1024x600, 1024, 600 }, /* 6 */
+ { VB_LCD_1152x768, 1152, 768 }, /* 7 */
+ { VB_LCD_1024x768, 1024, 768 }, /* 8 */
+ { VB_LCD_1024x768, 1024, 768 }, /* 9 */
+ { VB_LCD_1280x768, 1280, 768 }, /* a */
+ { VB_LCD_1024x768, 1024, 768 }, /* b */
+ { VB_LCD_1024x768, 1024, 768 }, /* c */
+ { VB_LCD_1024x768, 1024, 768 }, /* d */
+ { VB_LCD_320x480, 320, 480 }, /* e */
+ { VB_LCD_CUSTOM, 0, 0 } /* f */
};
static const SiS_LCD_StStruct SiS315_LCD_Type[]=
{
- { VB_LCD_1024x768, 1024, 768, LCD_1024x768 }, /* 0 - invalid */
- { VB_LCD_800x600, 800, 600, LCD_800x600 }, /* 1 */
- { VB_LCD_1024x768, 1024, 768, LCD_1024x768 }, /* 2 */
- { VB_LCD_1280x1024,1280, 1024, LCD_1280x1024 }, /* 3 */
- { VB_LCD_640x480, 640, 480, LCD_640x480 }, /* 4 */
- { VB_LCD_1024x600, 1024, 600, LCD_1024x600 }, /* 5 */
- { VB_LCD_1152x864, 1152, 864, LCD_1152x864 }, /* 6 */
- { VB_LCD_1280x960, 1280, 960, LCD_1280x960 }, /* 7 */
- { VB_LCD_1152x768, 1152, 768, LCD_1152x768 }, /* 8 */
- { VB_LCD_1400x1050,1400, 1050, LCD_1400x1050 }, /* 9 */
- { VB_LCD_1280x768, 1280, 768, LCD_1280x768 }, /* a */
- { VB_LCD_1600x1200,1600, 1200, LCD_1600x1200 }, /* b */
- { VB_LCD_640x480_2, 640, 480, LCD_640x480_2 }, /* c DSTN/FSTN */
- { VB_LCD_640x480_3, 640, 480, LCD_640x480_3 }, /* d DSTN/FSTN */
- { VB_LCD_320x480, 320, 480, LCD_320x480 }, /* e */
- { VB_LCD_CUSTOM, 0, 0, LCD_CUSTOM, } /* f */
+ { VB_LCD_1024x768, 1024, 768 }, /* 0 - invalid */
+ { VB_LCD_800x600, 800, 600 }, /* 1 */
+ { VB_LCD_1024x768, 1024, 768 }, /* 2 */
+ { VB_LCD_1280x1024,1280, 1024 }, /* 3 */
+ { VB_LCD_640x480, 640, 480 }, /* 4 */
+ { VB_LCD_1024x600, 1024, 600 }, /* 5 */
+ { VB_LCD_1152x864, 1152, 864 }, /* 6 */
+ { VB_LCD_1280x960, 1280, 960 }, /* 7 */
+ { VB_LCD_1152x768, 1152, 768 }, /* 8 */
+ { VB_LCD_1400x1050,1400, 1050 }, /* 9 */
+ { VB_LCD_1280x768, 1280, 768 }, /* a */
+ { VB_LCD_1600x1200,1600, 1200 }, /* b */
+ { VB_LCD_640x480_2, 640, 480 }, /* c DSTN/FSTN */
+ { VB_LCD_640x480_3, 640, 480 }, /* d DSTN/FSTN */
+ { VB_LCD_320x480, 320, 480 }, /* e */
+ { VB_LCD_CUSTOM, 0, 0 } /* f */
+};
+
+static const SiS_LCD_StStruct SiS661_LCD_Type[]=
+{
+ { VB_LCD_1024x768, 1024, 768 }, /* 0 - invalid */
+ { VB_LCD_800x600, 800, 600 }, /* 1 */
+ { VB_LCD_1024x768, 1024, 768 }, /* 2 */
+ { VB_LCD_1280x1024,1280, 1024 }, /* 3 */
+ { VB_LCD_640x480, 640, 480 }, /* 4 */
+ { VB_LCD_1024x600, 1024, 600 }, /* 5 */
+ { VB_LCD_1152x864, 1152, 864 }, /* 6 */
+ { VB_LCD_1280x960, 1280, 960 }, /* 7 */
+ { VB_LCD_1152x768, 1152, 768 }, /* 8 */
+ { VB_LCD_1400x1050,1400, 1050 }, /* 9 */
+ { VB_LCD_1280x768, 1280, 768 }, /* a */
+ { VB_LCD_1600x1200,1600, 1200 }, /* b */
+ { VB_LCD_1280x800, 1280, 800 }, /* c */
+ { VB_LCD_1680x1050,1680, 1050 }, /* d */
+ { VB_LCD_1280x720, 1280, 720 }, /* e */
+ { VB_LCD_CUSTOM, 0, 0 } /* f */
};
static Bool
-SISTestMonitorType(ScrnInfoPtr pScrn, int r, int g, int b)
+TestDDC1(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
- unsigned short testval = (r * 77) + (g * 151) + (b * 28);
-
- if((testval & 0xff) > 0x80) testval += 0x100;
- testval >>= 8;
-
- outSISREG(SISCOLIDX,0x00);
- outSISREG(SISCOLDATA,testval);
- outSISREG(SISCOLDATA,testval);
- outSISREG(SISCOLDATA,testval);
+ unsigned short old;
+ int count = 48;
- while(!(inSISREG(SISINPSTAT) & 0x01)) {}
- while(inSISREG(SISINPSTAT) & 0x01) {}
-
- return((inSISREG(SISMISCW) & 0x10) ? TRUE : FALSE);
+ old = SiS_ReadDDC1Bit(pSiS->SiS_Pr);
+ do {
+ if(old != SiS_ReadDDC1Bit(pSiS->SiS_Pr)) break;
+ } while(count--);
+ return (count == -1) ? FALSE : TRUE;
}
static int
-SISDetectCRT1(ScrnInfoPtr pScrn)
+SiS_SISDetectCRT1(ScrnInfoPtr pScrn)
{
SISPtr pSiS = SISPTR(pScrn);
- unsigned char SR1F,CR63=0,CR17,pel;
- int i, ret=0;
+ unsigned short temp = 0xffff;
+ unsigned char SR1F, CR63=0, CR17;
+ int i, ret = 0;
Bool mustwait = FALSE;
inSISIDXREG(SISSR,0x1F,SR1F);
- orSISIDXREG(SISSR,0x1F,0x04);
- andSISIDXREG(SISSR,0x1F,0x3F);
+ setSISIDXREG(SISSR,0x1F,0x3f,0x04);
if(SR1F & 0xc0) mustwait = TRUE;
if(pSiS->VGAEngine == SIS_315_VGA) {
- inSISIDXREG(SISCR,0x63,CR63);
+ inSISIDXREG(SISCR,pSiS->myCR63,CR63);
CR63 &= 0x40;
- andSISIDXREG(SISCR,0x63,0xBF);
+ andSISIDXREG(SISCR,pSiS->myCR63,0xbf);
}
inSISIDXREG(SISCR,0x17,CR17);
@@ -129,35 +156,51 @@ SISDetectCRT1(ScrnInfoPtr pScrn)
if(mustwait) {
for(i=0; i < 10; i++) SISWaitRetraceCRT1(pScrn);
}
-
- pel = inSISREG(SISPEL);
- outSISREG(SISPEL,0xff);
-
- outSISREG(SISCOLIDX,0x00);
- for(i = 0; i < (256 * 3); i++) {
- outSISREG(SISCOLDATA,0x00);
+
+ if(pSiS->sishw_ext.jChipType >= SIS_330) {
+ if(pSiS->sishw_ext.jChipType >= SIS_340) {
+ outSISIDXREG(SISCR, 0x57, 0x4a);
+ } else {
+ outSISIDXREG(SISCR, 0x57, 0x5f);
+ }
+ orSISIDXREG(SISCR, 0x53, 0x02);
+ while((inSISREG(SISINPSTAT)) & 0x01) break;
+ while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
+ if((inSISREG(SISMISCW)) & 0x10) temp = 1;
+ andSISIDXREG(SISCR, 0x53, 0xfd);
+ andSISIDXREG(SISCR, 0x57, 0x00);
+#ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "330: Found CRT1: %s\n", (temp == 1) ? "yes" : "no");
+#endif
}
- SISWaitRetraceCRT1(pScrn);
- SISWaitRetraceCRT1(pScrn);
-
- if(SISTestMonitorType(pScrn, 0x0f, 0x0f, 0x0f)) ret |= 1;
- if(SISTestMonitorType(pScrn, 0x0f, 0x0f, 0x0f)) ret |= 1;
+ if(temp == 0xffff) {
+ i = 3;
+ do {
+ temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 0, 0, NULL);
+ } while(((temp == 0) || (temp == 0xffff)) && i--);
- SISTestMonitorType(pScrn, 0x00, 0x00, 0x00);
-
- outSISREG(SISPEL,pel);
+ if((temp == 0) || (temp == 0xffff)) {
+ if(TestDDC1(pScrn)) temp = 1;
+ }
+ }
+
+ if((temp) && (temp != 0xffff)) {
+ orSISIDXREG(SISCR,0x32,0x20);
+ ret = 1;
+ } else if(pSiS->sishw_ext.jChipType >= SIS_330) {
+ andSISIDXREG(SISCR,0x32,~0x20);
+ ret = 0;
+ }
if(pSiS->VGAEngine == SIS_315_VGA) {
- setSISIDXREG(SISCR,0x63,0xBF,CR63);
+ setSISIDXREG(SISCR,pSiS->myCR63,0xBF,CR63);
}
setSISIDXREG(SISCR,0x17,0x7F,CR17);
outSISIDXREG(SISSR,0x1F,SR1F);
- if(ret) orSISIDXREG(SISCR,0x32,0x20);
-
return ret;
}
@@ -170,84 +213,100 @@ void SISCRT1PreInit(ScrnInfoPtr pScrn)
unsigned char OtherDevices = 0;
if(!(pSiS->VBFlags & VB_VIDEOBRIDGE)) {
- pSiS->CRT1off = 0;
- return;
+ pSiS->CRT1off = 0;
+ return;
}
#ifdef SISDUALHEAD
if(pSiS->DualHeadMode) {
- pSiS->CRT1off = 0;
- return;
+ pSiS->CRT1off = 0;
+ return;
}
#endif
#ifdef SISMERGED
- if(pSiS->MergedFB) {
- pSiS->CRT1off = 0;
- return;
+ if((pSiS->MergedFB) && (!(pSiS->MergedFBAuto))) {
+ pSiS->CRT1off = 0;
+ return;
}
#endif
inSISIDXREG(SISCR, 0x32, CR32);
- if(CR32 & 0x20) CRT1Detected = 1;
- else CRT1Detected = SISDetectCRT1(pScrn);
+ if(pSiS->sishw_ext.jChipType >= SIS_330) {
+ /* Works reliably on 330 and later */
+ CRT1Detected = SiS_SISDetectCRT1(pScrn);
+ } else {
+ if(CR32 & 0x20) CRT1Detected = 1;
+ else CRT1Detected = SiS_SISDetectCRT1(pScrn);
+ }
if(CR32 & 0x5F) OtherDevices = 1;
if(pSiS->CRT1off == -1) {
if(!CRT1Detected) {
- /* BIOS detected no CRT1. */
+ /* No CRT1 detected. */
/* If other devices exist, switch it off */
if(OtherDevices) pSiS->CRT1off = 1;
else pSiS->CRT1off = 0;
} else {
- /* BIOS detected CRT1, leave/switch it on */
+ /* CRT1 detected, leave/switch it on */
pSiS->CRT1off = 0;
}
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "%sCRT1 connection detected\n",
+ "%sCRT1 (VGA) connection detected\n",
CRT1Detected ? "" : "No ");
}
/* Detect CRT2-LCD and LCD size */
-void SISLCDPreInit(ScrnInfoPtr pScrn)
+void SISLCDPreInit(ScrnInfoPtr pScrn, Bool quiet)
{
SISPtr pSiS = SISPTR(pScrn);
- unsigned char CR32, CR36, CR37;
+ unsigned char CR32, CR36, CR37, CR7D=0, tmp;
+
+ pSiS->VBFlags &= ~(CRT2_LCD);
+ pSiS->VBLCDFlags = 0;
+ pSiS->LCDwidth = 0;
+ pSiS->LCDheight = 0;
- if(!(pSiS->VBFlags & VB_VIDEOBRIDGE)) {
- return;
- }
+ if(!(pSiS->VBFlags & VB_VIDEOBRIDGE)) return;
inSISIDXREG(SISCR, 0x32, CR32);
if(CR32 & 0x08) pSiS->VBFlags |= CRT2_LCD;
- /* TW: If no panel has been detected by the BIOS during booting,
- * we try to detect it ourselves at this point. This is useful
- * on machines with DVI connectors where the panel was
- * connected after booting. This is only supported on the
- * 315/330 series and the 301/30xB bridge (because the 30xLV/LVX
- * don't seem to have a DDC port and operates only LVDS panels
- * which mostly don't support DDC). We only do this if there was no
- * secondary VGA detected by the BIOS, because LCD and VGA2
- * share the same DDC channel and might be misdetected as the
- * wrong type (especially if the LCD panel only supports
+ /* If no panel has been detected by the BIOS during booting,
+ * we try to detect it ourselves at this point. We do that
+ * if forcecrt2redetection was given, too.
+ * This is useful on machines with DVI connectors where the
+ * panel was connected after booting. This is only supported
+ * on the 315/330 series and the 301/30xB/C bridge (because the
+ * 30xLV don't seem to have a DDC port and operate only LVDS
+ * panels which mostly don't support DDC). We only do this if
+ * there was no secondary VGA detected by the BIOS, because LCD
+ * and VGA2 share the same DDC channel and might be misdetected
+ * as the wrong type (especially if the LCD panel only supports
* EDID Version 1).
+ *
+ * By default, CRT2 redetection is forced since 12/09/2003, as
+ * I encountered numerous panels which deliver more or less
+ * bogus DDC data confusing the BIOS. Since our DDC detection
+ * is waaaay better, we prefer it instead of the primitive
+ * and buggy BIOS method.
*/
#ifdef SISDUALHEAD
if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) {
#endif
if((pSiS->VGAEngine == SIS_315_VGA) &&
(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
- (!(pSiS->VBFlags & VB_30xBDH))) {
+ (!(pSiS->VBFlags & VB_30xBDH)) &&
+ (!pSiS->VESA)) {
if(pSiS->forcecrt2redetection) {
pSiS->VBFlags &= ~CRT2_LCD;
@@ -255,10 +314,12 @@ void SISLCDPreInit(ScrnInfoPtr pScrn)
if(!(pSiS->nocrt2ddcdetection)) {
if((!(pSiS->VBFlags & CRT2_LCD)) && (!(CR32 & 0x10))) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "%s LCD/Plasma panel, sensing via DDC\n",
- pSiS->forcecrt2redetection ?
- "Forced re-detection of" : "BIOS detected no");
+ if(!quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "%s LCD/plasma panel, sensing via DDC\n",
+ pSiS->forcecrt2redetection ?
+ "Forced re-detection of" : "BIOS detected no");
+ }
if(SiS_SenseLCDDDC(pSiS->SiS_Pr, pSiS)) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"DDC error during LCD panel detection\n");
@@ -269,7 +330,7 @@ void SISLCDPreInit(ScrnInfoPtr pScrn)
pSiS->postVBCR32 |= 0x08;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "No LCD/Plasma panel detected\n");
+ "No LCD/plasma panel detected\n");
}
}
}
@@ -283,6 +344,7 @@ void SISLCDPreInit(ScrnInfoPtr pScrn)
if(pSiS->VBFlags & CRT2_LCD) {
inSISIDXREG(SISCR, 0x36, CR36);
inSISIDXREG(SISCR, 0x37, CR37);
+ inSISIDXREG(SISCR, 0x7D, CR7D);
if(pSiS->SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
pSiS->VBLCDFlags |= VB_LCD_BARCO1366;
pSiS->LCDwidth = 1360;
@@ -299,12 +361,11 @@ void SISLCDPreInit(ScrnInfoPtr pScrn)
pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 848;
pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 480;
pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
- pSiS->sishw_ext.ulCRT2LCDType = LCD_848x480;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Assuming LCD/plasma panel (848x480, expanding, RGB24)\n");
} else {
if((pSiS->VGAEngine == SIS_315_VGA) && (!CR36)) {
- /* TW: Old 650/301LV BIOS version "forgot" to set CR36, CR37 */
+ /* Old 650/301LV BIOS version "forgot" to set CR36, CR37 */
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"BIOS-provided LCD information invalid, probing myself...\n");
if(pSiS->VBFlags & VB_LVDS) pSiS->SiS_Pr->SiS_IF_DEF_LVDS = 1;
@@ -317,10 +378,9 @@ void SISLCDPreInit(ScrnInfoPtr pScrn)
pSiS->VBLCDFlags |= VB_LCD_CUSTOM;
pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY;
pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX;
- pSiS->sishw_ext.ulCRT2LCDType = LCD_CUSTOM;
if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected non-standard LCD/Plasma panel (max. X %d Y %d, preferred %dx%d, RGB%d)\n",
+ "Detected LCD/Plasma panel (max. X %d Y %d, preferred %dx%d, RGB%d)\n",
pSiS->SiS_Pr->CP_MaxX, pSiS->SiS_Pr->CP_MaxY,
pSiS->SiS_Pr->CP_PreferredX, pSiS->SiS_Pr->CP_PreferredY,
(CR37 & 0x01) ? 18 : 24);
@@ -329,37 +389,51 @@ void SISLCDPreInit(ScrnInfoPtr pScrn)
pSiS->VBLCDFlags |= SiS300_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag;
pSiS->LCDheight = SiS300_LCD_Type[(CR36 & 0x0f)].LCDheight;
pSiS->LCDwidth = SiS300_LCD_Type[(CR36 & 0x0f)].LCDwidth;
- pSiS->sishw_ext.ulCRT2LCDType = SiS300_LCD_Type[(CR36 & 0x0f)].LCDtype;
if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
- } else {
+ } else if((pSiS->sishw_ext.jChipType >= SIS_661) || (pSiS->ROM661New)) {
+ pSiS->VBLCDFlags |= SiS661_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag;
+ pSiS->LCDheight = SiS661_LCD_Type[(CR36 & 0x0f)].LCDheight;
+ pSiS->LCDwidth = SiS661_LCD_Type[(CR36 & 0x0f)].LCDwidth;
+ if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
+ if(pSiS->sishw_ext.jChipType < SIS_661) {
+ if(!(pSiS->SiS_Pr->PanelSelfDetected)) {
+ inSISIDXREG(SISCR,0x35,tmp);
+ CR37 &= 0xfc;
+ CR37 |= (tmp & 0x01);
+ }
+ }
+ } else {
pSiS->VBLCDFlags |= SiS315_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag;
pSiS->LCDheight = SiS315_LCD_Type[(CR36 & 0x0f)].LCDheight;
pSiS->LCDwidth = SiS315_LCD_Type[(CR36 & 0x0f)].LCDwidth;
- pSiS->sishw_ext.ulCRT2LCDType = SiS315_LCD_Type[(CR36 & 0x0f)].LCDtype;
if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "Detected LCD/Plasma panel (%dx%d, type %d, %sexpanding, RGB%d)\n",
+ "Detected LCD/plasma panel (%dx%d, %d, %sexp., RGB%d [%02x%02x%02x])\n",
pSiS->LCDwidth, pSiS->LCDheight,
- (pSiS->VGAEngine == SIS_315_VGA) ? ((CR36 & 0x0f) - 1) : ((CR36 & 0xf0) >> 4),
+ ((pSiS->VGAEngine == SIS_315_VGA) &&
+ (!pSiS->NewCRLayout)) ?
+ ((CR36 & 0x0f) - 1) : ((CR36 & 0xf0) >> 4),
(CR37 & 0x10) ? "" : "non-",
- (CR37 & 0x01) ? 18 : 24);
+ (CR37 & 0x01) ? 18 : 24,
+ CR36, CR37, CR7D);
}
}
}
+
}
/* Detect CRT2-TV connector type and PAL/NTSC flag */
-void SISTVPreInit(ScrnInfoPtr pScrn)
+void SISTVPreInit(ScrnInfoPtr pScrn, Bool quiet)
{
SISPtr pSiS = SISPTR(pScrn);
- unsigned char SR16, SR38, CR32, CR38=0, CR79;
+ unsigned char SR16, SR38, CR32, CR35=0, CR38=0, CR79, CR39;
int temp = 0;
-
- if(!(pSiS->VBFlags & VB_VIDEOBRIDGE))
- return;
+
+ if(!(pSiS->VBFlags & VB_VIDEOBRIDGE)) return;
inSISIDXREG(SISCR, 0x32, CR32);
+ inSISIDXREG(SISCR, 0x35, CR35);
inSISIDXREG(SISSR, 0x16, SR16);
inSISIDXREG(SISSR, 0x38, SR38);
switch(pSiS->VGAEngine) {
@@ -380,27 +454,64 @@ void SISTVPreInit(ScrnInfoPtr pScrn)
CR32, SR16, SR38);
#endif
- if(CR32 & 0x47)
- pSiS->VBFlags |= CRT2_TV;
+ if(CR32 & 0x47) pSiS->VBFlags |= CRT2_TV;
- if(CR32 & 0x04)
- pSiS->VBFlags |= TV_SCART;
+ if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) {
+ if(CR32 & 0x80) pSiS->VBFlags |= CRT2_TV;
+ } else {
+ CR32 &= 0x7f;
+ }
+
+ if(CR32 & 0x01)
+ pSiS->VBFlags |= TV_AVIDEO;
else if(CR32 & 0x02)
pSiS->VBFlags |= TV_SVIDEO;
- else if(CR32 & 0x01)
- pSiS->VBFlags |= TV_AVIDEO;
- else if(CR32 & 0x40)
- pSiS->VBFlags |= (TV_SVIDEO | TV_HIVISION);
- else if((CR38 & 0x04) && (pSiS->VBFlags & (VB_301LV | VB_302LV)))
- pSiS->VBFlags |= TV_HIVISION_LV;
- else if((CR38 & 0x04) && (pSiS->VBFlags & VB_CHRONTEL))
+ else if(CR32 & 0x04)
+ pSiS->VBFlags |= TV_SCART;
+ else if((CR32 & 0x40) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION))
+ pSiS->VBFlags |= (TV_HIVISION | TV_PAL);
+ else if((CR32 & 0x80) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) {
+ pSiS->VBFlags |= TV_YPBPR;
+ if(pSiS->NewCRLayout) {
+ if(CR38 & 0x04) {
+ switch(CR35 & 0xE0) {
+ case 0x20: pSiS->VBFlags |= TV_YPBPR525P; break;
+ case 0x40: pSiS->VBFlags |= TV_YPBPR750P; break;
+ case 0x60: pSiS->VBFlags |= TV_YPBPR1080I; break;
+ default: pSiS->VBFlags |= TV_YPBPR525I;
+ }
+ } else pSiS->VBFlags |= TV_YPBPR525I;
+ inSISIDXREG(SISCR,0x39,CR39);
+ CR39 &= 0x03;
+ if(CR39 == 0x00) pSiS->VBFlags |= TV_YPBPR43LB;
+ else if(CR39 == 0x01) pSiS->VBFlags |= TV_YPBPR43;
+ else if(CR39 == 0x02) pSiS->VBFlags |= TV_YPBPR169;
+ else pSiS->VBFlags |= TV_YPBPR43;
+ } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) {
+ if(CR38 & 0x08) {
+ switch(CR38 & 0x30) {
+ case 0x10: pSiS->VBFlags |= TV_YPBPR525P; break;
+ case 0x20: pSiS->VBFlags |= TV_YPBPR750P; break;
+ case 0x30: pSiS->VBFlags |= TV_YPBPR1080I; break;
+ default: pSiS->VBFlags |= TV_YPBPR525I;
+ }
+ } else pSiS->VBFlags |= TV_YPBPR525I;
+ if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) {
+ inSISIDXREG(SISCR,0x3B,CR39);
+ CR39 &= 0x03;
+ if(CR39 == 0x00) pSiS->VBFlags |= TV_YPBPR43LB;
+ else if(CR39 == 0x01) pSiS->VBFlags |= TV_YPBPR169;
+ else if(CR39 == 0x03) pSiS->VBFlags |= TV_YPBPR43;
+ }
+ }
+ } else if((CR38 & 0x04) && (pSiS->VBFlags & VB_CHRONTEL))
pSiS->VBFlags |= (TV_CHSCART | TV_PAL);
else if((CR38 & 0x08) && (pSiS->VBFlags & VB_CHRONTEL))
- pSiS->VBFlags |= (TV_CHHDTV | TV_NTSC);
-
- if(pSiS->VBFlags & (TV_SCART | TV_SVIDEO | TV_AVIDEO | TV_HIVISION | TV_HIVISION_LV)) {
+ pSiS->VBFlags |= (TV_CHYPBPR525I | TV_NTSC);
+
+ if(pSiS->VBFlags & (TV_SCART | TV_SVIDEO | TV_AVIDEO)) {
if(pSiS->VGAEngine == SIS_300_VGA) {
- /* TW: Should be SR38, but this does not work. */
+ /* Should be SR38, but this does not work. */
if(SR16 & 0x20)
pSiS->VBFlags |= TV_PAL;
else
@@ -417,7 +528,7 @@ void SISTVPreInit(ScrnInfoPtr pScrn)
else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN;
} else
pSiS->VBFlags |= TV_NTSC;
- } else if((pSiS->Chipset == PCI_CHIP_SIS650) || (pSiS->Chipset == PCI_CHIP_SIS660)) {
+ } else if(pSiS->Chipset == PCI_CHIP_SIS650) {
inSISIDXREG(SISCR, 0x79, CR79);
if(CR79 & 0x20) {
pSiS->VBFlags |= TV_PAL;
@@ -425,6 +536,15 @@ void SISTVPreInit(ScrnInfoPtr pScrn)
else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN;
} else
pSiS->VBFlags |= TV_NTSC;
+ } else if(pSiS->NewCRLayout) {
+ if(SR38 & 0x01) {
+ pSiS->VBFlags |= TV_PAL;
+ if(CR35 & 0x04) pSiS->VBFlags |= TV_PALM;
+ else if(CR35 & 0x08) pSiS->VBFlags |= TV_PALN;
+ } else {
+ pSiS->VBFlags |= TV_NTSC;
+ if(CR35 & 0x02) pSiS->VBFlags |= TV_NTSCJ;
+ }
} else { /* 315, 330 */
if(SR38 & 0x01) {
pSiS->VBFlags |= TV_PAL;
@@ -434,30 +554,41 @@ void SISTVPreInit(ScrnInfoPtr pScrn)
pSiS->VBFlags |= TV_NTSC;
}
}
-
- if(pSiS->VBFlags & (TV_SCART | TV_SVIDEO | TV_AVIDEO | TV_HIVISION | TV_HIVISION_LV | TV_CHSCART | TV_CHHDTV)) {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
- "%sTV standard %s\n",
- (pSiS->VBFlags & (TV_CHSCART | TV_CHHDTV)) ? "Using " : "Detected default ",
- (pSiS->VBFlags & TV_NTSC) ?
- ((pSiS->VBFlags & TV_CHHDTV) ? "480i HDTV" : "NTSC") :
- ((pSiS->VBFlags & TV_PALM) ? "PALM" :
- ((pSiS->VBFlags & TV_PALN) ? "PALN" : "PAL")));
+
+ if((pSiS->VBFlags & (TV_SCART|TV_SVIDEO|TV_AVIDEO)) && !quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected default TV standard %s\n",
+ (pSiS->VBFlags & TV_NTSC) ?
+ ((pSiS->VBFlags & TV_NTSCJ) ? "NTSCJ" : "NTSC") :
+ ((pSiS->VBFlags & TV_PALM) ? "PALM" :
+ ((pSiS->VBFlags & TV_PALN) ? "PALN" : "PAL")));
+ }
+
+ if((pSiS->VBFlags & TV_HIVISION) && !quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "BIOS reports HiVision TV\n");
+ }
+
+ if((pSiS->VBFlags & VB_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART|TV_CHYPBPR525I)) && !quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chrontel: %s forced\n",
+ (pSiS->VBFlags & TV_CHSCART) ? "SCART (PAL)" : "YPbPr (480i)");
+ }
+
+ if((pSiS->VBFlags & TV_YPBPR) && !quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected YPbPr TV (by default %s)\n",
+ (pSiS->VBFlags & TV_YPBPR525I) ? "480i" :
+ ((pSiS->VBFlags & TV_YPBPR525P) ? "480p" :
+ ((pSiS->VBFlags & TV_YPBPR750P) ? "720p" : "1080i")));
}
}
/* Detect CRT2-VGA */
-void SISCRT2PreInit(ScrnInfoPtr pScrn)
+void SISCRT2PreInit(ScrnInfoPtr pScrn, Bool quiet)
{
SISPtr pSiS = SISPTR(pScrn);
unsigned char CR32;
- if(!(pSiS->VBFlags & VB_VIDEOBRIDGE))
- return;
-
- /* CRT2-VGA not supported on LVDS and 30xLV */
- if(pSiS->VBFlags & (VB_LVDS|VB_301LV|VB_302LV))
- return;
+ /* CRT2-VGA only supported on these bridges */
+ if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))
+ return;
inSISIDXREG(SISCR, 0x32, CR32);
@@ -479,33 +610,474 @@ void SISCRT2PreInit(ScrnInfoPtr pScrn)
* which is prone to be misdetected as a secondary VGA)
*/
if(!(pSiS->nocrt2ddcdetection)) {
- if(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)) {
- if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD))) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "%s secondary VGA, sensing via DDC\n",
- pSiS->forcecrt2redetection ?
- "Forced redetection of" : "BIOS detected no");
- if(SiS_SenseVGA2DDC(pSiS->SiS_Pr, pSiS)) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "%s secondary VGA, sensing via DDC\n",
+ pSiS->forcecrt2redetection ?
+ "Forced re-detection of" : "BIOS detected no");
+ if(SiS_SenseVGA2DDC(pSiS->SiS_Pr, pSiS)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"DDC error during secondary VGA detection\n");
- } else {
- inSISIDXREG(SISCR, 0x32, CR32);
- if(CR32 & 0x10) {
- pSiS->VBFlags |= CRT2_VGA;
- pSiS->postVBCR32 |= 0x10;
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ } else {
+ inSISIDXREG(SISCR, 0x32, CR32);
+ if(CR32 & 0x10) {
+ pSiS->VBFlags |= CRT2_VGA;
+ pSiS->postVBCR32 |= 0x10;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"Detected secondary VGA connection\n");
- } else {
- xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"No secondary VGA connection detected\n");
- }
}
- }
+ }
+ }
+ }
+#ifdef SISDUALHEAD
+ }
+#endif
+}
+
+static int
+SISDoSense(ScrnInfoPtr pScrn, unsigned short type, unsigned short test)
+{
+ SISPtr pSiS = SISPTR(pScrn);
+ int temp, mytest, result, i, j;
+
+#ifdef TWDEBUG
+ xf86DrvMsg(0, X_INFO, "Sense: %x %x\n", type, test);
+#endif
+
+ for(j = 0; j < 10; j++) {
+ result = 0;
+ for(i = 0; i < 3; i++) {
+ mytest = test;
+ outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
+ temp = (type >> 8) | (mytest & 0x00ff);
+ setSISIDXREG(SISPART4,0x10,0xe0,temp);
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x1500);
+ mytest >>= 8;
+ mytest &= 0x7f;
+ inSISIDXREG(SISPART4,0x03,temp);
+ temp ^= 0x0e;
+ temp &= mytest;
+ if(temp == mytest) result++;
+#if 1
+ outSISIDXREG(SISPART4,0x11,0x00);
+ andSISIDXREG(SISPART4,0x10,0xe0);
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x1000);
+#endif
+ }
+ if((result == 0) || (result >= 2)) break;
+ }
+ return(result);
+}
+
+#define GETROMWORD(w) (pSiS->BIOS[w] | (pSiS->BIOS[w+1] << 8))
+
+/* Sense connected devices on 30x */
+void
+SISSense30x(ScrnInfoPtr pScrn, Bool quiet)
+{
+ SISPtr pSiS = SISPTR(pScrn);
+ unsigned char backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
+ unsigned short svhs=0, svhs_c=0;
+ unsigned short cvbs=0, cvbs_c=0;
+ unsigned short vga2=0, vga2_c=0;
+ int myflag, result; /* , i; */
+
+ if(!(pSiS->VBFlags & VB_SISBRIDGE)) return;
+
+ if(pSiS->VBFlags & VB_301) {
+ svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
+ inSISIDXREG(SISPART4,0x01,myflag);
+ if(myflag & 0x04) {
+ svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
+ }
+ } else if(pSiS->VBFlags & (VB_301B | VB_302B)) {
+ svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
+ } else if(pSiS->VBFlags & (VB_301LV | VB_302LV)) {
+ svhs = 0x0200; cvbs = 0x0100;
+ } else if(pSiS->VBFlags & (VB_301C | VB_302ELV)) {
+ svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
+ } else return;
+
+ vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
+ if(pSiS->VBFlags & (VB_301LV|VB_302LV|VB_302ELV)) {
+ svhs_c = 0x0408; cvbs_c = 0x0808;
+ }
+ biosflag = 2;
+
+ if(pSiS->Chipset == PCI_CHIP_SIS300) {
+ inSISIDXREG(SISSR,0x3b,myflag);
+ if(!(myflag & 0x01)) vga2 = vga2_c = 0;
+ }
+
+ if(pSiS->sishw_ext.UseROM) {
+ if(pSiS->VGAEngine == SIS_300_VGA) {
+ if(pSiS->VBFlags & VB_301) {
+ inSISIDXREG(SISPART4,0x01,myflag);
+ if(!(myflag & 0x04)) {
+ vga2 = GETROMWORD(0xf8); svhs = GETROMWORD(0xfa); cvbs = GETROMWORD(0xfc);
+ }
+ }
+ biosflag = pSiS->BIOS[0xfe];
+ } else if((pSiS->Chipset == PCI_CHIP_SIS660) ||
+ (pSiS->Chipset == PCI_CHIP_SIS340)) {
+ if(pSiS->ROM661New) {
+ biosflag = 2;
+ vga2 = GETROMWORD(0x63); svhs = cvbs = GETROMWORD(0x65);
+ if(pSiS->BIOS[0x5d] & 0x04) biosflag |= 0x01;
+ }
+ } else if(!pSiS->ROM661New) {
+#if 0 /* eg. 1.15.23 has wrong values here */
+ myflag = 0;
+ if(pSiS->VBFlags & VB_301) {
+ if(pSiS->Chipset == PCI_CHIP_SIS330) {
+ myflag = 0xe5; i = 0x11b;
+ } else {
+ myflag = 0xbd; i = 0xf3
+ }
+ } else if(pSiS->VBFlags & (VB_301B|VB_302B|VB_301LV|VB_302LV)) {
+ if(pSiS->Chipset == PCI_CHIP_SIS330) {
+ myflag = 0xeb; i = 0x11b;
+ } else {
+ myflag = 0xc3; i = 0xf3
+ }
+ }
+ if(myflag) {
+ biosflag = pSiS->BIOS[i]; vga2 = GETROMWORD(myflag);
+ svhs = GETROMWORD(myflag+2); cvbs = GETROMWORD(myflag+4);
+ }
+#endif
+ }
+ }
+
+ if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) {
+ vga2 = vga2_c = 0;
+ }
+
+ inSISIDXREG(SISSR,0x1e,backupSR_1e);
+ orSISIDXREG(SISSR,0x1e,0x20);
+
+ inSISIDXREG(SISPART4,0x0d,backupP4_0d);
+ if(pSiS->VBFlags & VB_301C) {
+ setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
+ } else {
+ orSISIDXREG(SISPART4,0x0d,0x04);
+ }
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x2000);
+
+ inSISIDXREG(SISPART2,0x00,backupP2_00);
+ outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
+
+ inSISIDXREG(SISPART2,0x4d,backupP2_4d);
+ if(pSiS->VBFlags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) {
+ outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
+ }
+
+ if(!(pSiS->VBFlags & VB_301C)) {
+ SISDoSense(pScrn, 0, 0);
+ }
+
+ andSISIDXREG(SISCR, 0x32, ~0x14);
+ pSiS->postVBCR32 &= ~0x14;
+
+ if(vga2_c || vga2) {
+ if(SISDoSense(pScrn, vga2, vga2_c)) {
+ if(biosflag & 0x01) {
+ if(!quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "SiS30x: Detected TV connected to SCART output\n");
+ }
+ pSiS->VBFlags |= TV_SCART;
+ orSISIDXREG(SISCR, 0x32, 0x04);
+ pSiS->postVBCR32 |= 0x04;
+ } else {
+ if(!quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "SiS30x: Detected secondary VGA connection\n");
+ }
+ pSiS->VBFlags |= VGA2_CONNECTED;
+ orSISIDXREG(SISCR, 0x32, 0x10);
+ pSiS->postVBCR32 |= 0x10;
+ }
+ }
+ if(biosflag & 0x01) pSiS->SiS_SD_Flags |= SiS_SD_VBHASSCART;
+ }
+
+ andSISIDXREG(SISCR, 0x32, 0x3f);
+ pSiS->postVBCR32 &= 0x3f;
+
+ if(pSiS->VBFlags & VB_301C) {
+ orSISIDXREG(SISPART4,0x0d,0x04);
+ }
+
+ if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) {
+ if(pSiS->SenseYPbPr) {
+ outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x2000);
+ if((result = SISDoSense(pScrn, svhs, 0x0604))) {
+ if((result = SISDoSense(pScrn, cvbs, 0x0804))) {
+ if(!quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "SiS30x: Detected TV connected to YPbPr component output\n");
+ }
+ orSISIDXREG(SISCR,0x32,0x80);
+ pSiS->VBFlags |= TV_YPBPR;
+ pSiS->postVBCR32 |= 0x80;
+ }
+ }
+ outSISIDXREG(SISPART2,0x4d,backupP2_4d);
+ }
+ }
+
+ andSISIDXREG(SISCR, 0x32, ~0x03);
+ pSiS->postVBCR32 &= ~0x03;
+
+ if(!(pSiS->VBFlags & TV_YPBPR)) {
+
+ if((result = SISDoSense(pScrn, svhs, svhs_c))) {
+ if(!quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "SiS30x: Detected TV connected to SVIDEO output\n");
+ }
+ pSiS->VBFlags |= TV_SVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x02);
+ pSiS->postVBCR32 |= 0x02;
+ }
+
+ if((biosflag & 0x02) || (!result)) {
+ if(SISDoSense(pScrn, cvbs, cvbs_c)) {
+ if(!quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "SiS30x: Detected TV connected to COMPOSITE output\n");
+ }
+ pSiS->VBFlags |= TV_AVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x01);
+ pSiS->postVBCR32 |= 0x01;
}
}
}
+
+ SISDoSense(pScrn, 0, 0);
+
+ outSISIDXREG(SISPART2,0x00,backupP2_00);
+ outSISIDXREG(SISPART4,0x0d,backupP4_0d);
+ outSISIDXREG(SISSR,0x1e,backupSR_1e);
+
+ if(pSiS->VBFlags & VB_301C) {
+ inSISIDXREG(SISPART2,0x00,biosflag);
+ if(biosflag & 0x20) {
+ for(myflag = 2; myflag > 0; myflag--) {
+ biosflag ^= 0x20;
+ outSISIDXREG(SISPART2,0x00,biosflag);
+ }
+ }
+ }
+
+ outSISIDXREG(SISPART2,0x00,backupP2_00);
}
+void
+SISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet)
+{
+ SISPtr pSiS = SISPTR(pScrn);
+ int temp1=0, temp2, i;
+ unsigned char test[3];
+
+ if(pSiS->SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+
+ /* Chrontel 700x */
+
+ /* Read power status */
+ temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x0e); /* Power status */
+ if((temp1 & 0x03) != 0x03) {
+ /* Power all outputs */
+ SiS_SetCH700x(pSiS->SiS_Pr, 0x0B0E);
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+ }
+ /* Sense connected TV devices */
+ for(i = 0; i < 3; i++) {
+ SiS_SetCH700x(pSiS->SiS_Pr, 0x0110);
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+ SiS_SetCH700x(pSiS->SiS_Pr, 0x0010);
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+ temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x10);
+ if(!(temp1 & 0x08)) test[i] = 0x02;
+ else if(!(temp1 & 0x02)) test[i] = 0x01;
+ else test[i] = 0;
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+ }
+
+ if(test[0] == test[1]) temp1 = test[0];
+ else if(test[0] == test[2]) temp1 = test[0];
+ else if(test[1] == test[2]) temp1 = test[1];
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Chrontel: TV detection unreliable - test results varied\n");
+ temp1 = test[2];
+ }
+
+ } else if(pSiS->SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+
+ /* Chrontel 701x */
+
+ /* Backup Power register */
+ temp1 = SiS_GetCH701x(pSiS->SiS_Pr, 0x49);
+
+ /* Enable TV path */
+ SiS_SetCH701x(pSiS->SiS_Pr, 0x2049);
+
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+
+ /* Sense connected TV devices */
+ temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20);
+ temp2 |= 0x01;
+ SiS_SetCH701x(pSiS->SiS_Pr, (temp2 << 8) | 0x20);
+
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+
+ temp2 ^= 0x01;
+ SiS_SetCH701x(pSiS->SiS_Pr, (temp2 << 8) | 0x20);
+
+ SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
+
+ temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20);
+
+ /* Restore Power register */
+ SiS_SetCH701x(pSiS->SiS_Pr, (temp1 << 8) | 0x49);
+
+ temp1 = 0;
+ if(temp2 & 0x02) temp1 |= 0x01;
+ if(temp2 & 0x10) temp1 |= 0x01;
+ if(temp2 & 0x04) temp1 |= 0x02;
+
+ if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
+
+ }
+
+ switch(temp1) {
+ case 0x01:
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Chrontel: Detected TV connected to COMPOSITE output\n");
+ pSiS->VBFlags |= TV_AVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x01);
+ andSISIDXREG(SISCR, 0x32, ~0x06);
+ pSiS->postVBCR32 |= 0x01;
+ pSiS->postVBCR32 &= ~0x06;
+ break;
+ case 0x02:
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Chrontel: Detected TV connected to SVIDEO output\n");
+ pSiS->VBFlags |= TV_SVIDEO;
+ orSISIDXREG(SISCR, 0x32, 0x02);
+ andSISIDXREG(SISCR, 0x32, ~0x05);
+ pSiS->postVBCR32 |= 0x02;
+ pSiS->postVBCR32 &= ~0x05;
+ break;
+ case 0x04:
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Chrontel: Detected TV connected to SCART or YPBPR output\n");
+ if(pSiS->chtvtype == -1) {
+ if(!quiet) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Chrontel: Use CHTVType option to select either SCART or YPBPR525I\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Chrontel: Using SCART by default\n");
+ }
+ pSiS->chtvtype = 1;
+ }
+ if(pSiS->chtvtype)
+ pSiS->VBFlags |= TV_CHSCART;
+ else
+ pSiS->VBFlags |= TV_CHYPBPR525I;
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Chrontel: No TV detected.\n");
+ andSISIDXREG(SISCR, 0x32, ~0x07);
+ pSiS->postVBCR32 &= ~0x07;
+ }
+}
+
+/* Redetect CRT2 devices. Calling this requires a reset
+ * of the current display mode if TRUE is returned.
+ */
+Bool SISRedetectCRT2Type(ScrnInfoPtr pScrn)
+{
+ SISPtr pSiS = SISPTR(pScrn);
+ unsigned long VBFlagsBackup = pSiS->VBFlags;
+ Bool backup1 = pSiS->forcecrt2redetection;
+ Bool backup2 = pSiS->nocrt2ddcdetection;
+
+#ifdef SISDUALHEAD
+ if(pSiS->DualHeadMode) return FALSE;
+#endif
+
+ pSiS->VBFlags &= (VB_VIDEOBRIDGE | DISPLAY_MODE);
+
+ /* At first, re-do the sensing for TV and VGA2 */
+ if(pSiS->VBFlags & VB_SISBRIDGE) {
+ SISSense30x(pScrn, FALSE);
+ } else if(pSiS->VBFlags & VB_CHRONTEL) {
+ SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x9c);
+ SISSenseChrontel(pScrn, TRUE);
+ SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x00);
+ }
+
+ SISTVPreInit(pScrn, TRUE);
+
+ pSiS->forcecrt2redetection = TRUE;
+ pSiS->nocrt2ddcdetection = FALSE;
+
+ /* We only re-detect LCD for the TMDS-SiS-bridges. LVDS
+ * is practically never being hot-plugged (and even if,
+ * there is no way of detecting this).
+ */
+ if((pSiS->VGAEngine == SIS_315_VGA) &&
+ (pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
+ (!(pSiS->VBFlags & VB_30xBDH)) &&
+ (!pSiS->VESA)) {
+ SISLCDPreInit(pScrn, TRUE);
+ } else {
+ pSiS->VBFlags |= (pSiS->detectedCRT2Devices & CRT2_LCD);
+ }
+
+ /* Secondary VGA is only supported on these bridges: */
+ if(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)) {
+ SISCRT2PreInit(pScrn, TRUE);
+ }
+
+ pSiS->forcecrt2redetection = backup1;
+ pSiS->nocrt2ddcdetection = backup2;
+
+ SISDetermineLCDACap(pScrn);
+ SISSaveDetectedDevices(pScrn);
+
+ pSiS->VBFlags = VBFlagsBackup;
+
+ /* If LCD disappeared, don't use it and don't advertise LCDA support. Duh! */
+ if(!(pSiS->detectedCRT2Devices & CRT2_LCD)) {
+ pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTLCDA);
+ if(pSiS->VBFlags & CRT2_LCD) {
+ /* If CRT2 was LCD, disable CRT2 and adapt display mode flags */
+ pSiS->VBFlags &= ~(CRT2_LCD | DISPLAY_MODE);
+ /* Switch on CRT1 as an emergency measure */
+ pSiS->VBFlags |= (SINGLE_MODE | DISPTYPE_CRT1);
+ pSiS->CRT1off = 0;
+ }
+ /* If CRT1 was LCD, switch to CRT1-VGA. No need to adapt display mode flags. */
+ pSiS->VBFlags &= ~(CRT1_LCDA);
+ pSiS->VBFlags_backup = pSiS->VBFlags;
+ }
+
+ /* Save new detection result registers to write them back in EnterVT() */
+ inSISIDXREG(SISCR,0x32,pSiS->myCR32);
+ inSISIDXREG(SISCR,0x36,pSiS->myCR36);
+ inSISIDXREG(SISCR,0x37,pSiS->myCR37);
+
+ return TRUE;
+}