1227 lines
38 KiB
C
1227 lines
38 KiB
C
/* $XFree86$ */
|
|
/* $XdotOrg$ */
|
|
/*
|
|
* Video bridge detection and configuration for 300, 315 and 330 series
|
|
*
|
|
* Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
|
|
*
|
|
* 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.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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>
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "sis.h"
|
|
#define SIS_NEED_inSISREG
|
|
#define SIS_NEED_inSISIDXREG
|
|
#define SIS_NEED_outSISIDXREG
|
|
#define SIS_NEED_orSISIDXREG
|
|
#define SIS_NEED_andSISIDXREG
|
|
#define SIS_NEED_setSISIDXREG
|
|
#include "sis_regs.h"
|
|
#include "sis_dac.h"
|
|
|
|
void SISCRT1PreInit(ScrnInfoPtr pScrn);
|
|
void SISLCDPreInit(ScrnInfoPtr pScrn, Bool quiet);
|
|
void SISTVPreInit(ScrnInfoPtr pScrn, Bool quiet);
|
|
void SISCRT2PreInit(ScrnInfoPtr pScrn, Bool quiet);
|
|
Bool SISRedetectCRT2Type(ScrnInfoPtr pScrn);
|
|
void SISSense30x(ScrnInfoPtr pScrn, Bool quiet);
|
|
void SISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet);
|
|
void SiSSetupPseudoPanel(ScrnInfoPtr pScrn);
|
|
|
|
extern Bool SISDetermineLCDACap(ScrnInfoPtr pScrn);
|
|
extern void SISSaveDetectedDevices(ScrnInfoPtr pScrn);
|
|
extern void SISWaitRetraceCRT1(ScrnInfoPtr pScrn);
|
|
extern UChar SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value);
|
|
|
|
/* From init.c, init301.c ---- (use their data types) */
|
|
extern BOOLEAN SiS_GetPanelID(struct SiS_Private *SiS_Pr);
|
|
extern unsigned short SiS_SenseLCDDDC(struct SiS_Private *SiS_Pr, SISPtr pSiS);
|
|
extern unsigned short SiS_SenseVGA2DDC(struct SiS_Private *SiS_Pr, SISPtr pSiS);
|
|
|
|
typedef struct _SiS_LCD_StStruct
|
|
{
|
|
ULong VBLCD_lcdflag;
|
|
UShort LCDwidth;
|
|
UShort LCDheight;
|
|
} SiS_LCD_StStruct;
|
|
|
|
static const SiS_LCD_StStruct SiS300_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_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 }, /* 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 FSTN */
|
|
{ VB_LCD_640x480_3, 640, 480 }, /* d 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 - temp */
|
|
{ VB_LCD_1152x864, 1152, 864 }, /* 6 - temp */
|
|
{ VB_LCD_1280x960, 1280, 960 }, /* 7 */
|
|
{ VB_LCD_1280x854, 1280, 854 }, /* 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
|
|
TestDDC1(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
UShort old;
|
|
int count = 48;
|
|
|
|
old = SiS_ReadDDC1Bit(pSiS->SiS_Pr);
|
|
do {
|
|
if(old != SiS_ReadDDC1Bit(pSiS->SiS_Pr)) break;
|
|
} while(count--);
|
|
return (count == -1) ? FALSE : TRUE;
|
|
}
|
|
|
|
static int
|
|
SiS_SISDetectCRT1(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
UShort temp = 0xffff;
|
|
UChar SR1F, CR63=0, CR17;
|
|
int i, ret = 0;
|
|
Bool mustwait = FALSE;
|
|
|
|
inSISIDXREG(SISSR,0x1F,SR1F);
|
|
setSISIDXREG(SISSR,0x1F,0x3f,0x04);
|
|
if(SR1F & 0xc0) mustwait = TRUE;
|
|
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
inSISIDXREG(SISCR,pSiS->myCR63,CR63);
|
|
CR63 &= 0x40;
|
|
andSISIDXREG(SISCR,pSiS->myCR63,0xbf);
|
|
}
|
|
|
|
inSISIDXREG(SISCR,0x17,CR17);
|
|
CR17 &= 0x80;
|
|
if(!CR17) {
|
|
orSISIDXREG(SISCR,0x17,0x80);
|
|
mustwait = TRUE;
|
|
outSISIDXREG(SISSR, 0x00, 0x01);
|
|
outSISIDXREG(SISSR, 0x00, 0x03);
|
|
}
|
|
|
|
if(mustwait) {
|
|
for(i=0; i < 10; i++) SISWaitRetraceCRT1(pScrn);
|
|
}
|
|
|
|
if(pSiS->ChipType >= SIS_330) {
|
|
int watchdog;
|
|
if(pSiS->ChipType >= SIS_340) {
|
|
outSISIDXREG(SISCR, 0x57, 0x4a);
|
|
} else {
|
|
outSISIDXREG(SISCR, 0x57, 0x5f);
|
|
}
|
|
orSISIDXREG(SISCR, 0x53, 0x02);
|
|
watchdog = 655360;
|
|
while((!((inSISREG(SISINPSTAT)) & 0x01)) && --watchdog);
|
|
watchdog = 655360;
|
|
while(((inSISREG(SISINPSTAT)) & 0x01) && --watchdog);
|
|
if((inSISREG(SISMISCW)) & 0x10) temp = 1;
|
|
andSISIDXREG(SISCR, 0x53, 0xfd);
|
|
outSISIDXREG(SISCR, 0x57, 0x00);
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(0, X_INFO, "330: Found CRT1: %s\n", (temp == 1) ? "yes" : "no");
|
|
#endif
|
|
}
|
|
|
|
if((temp == 0xffff) && (!pSiS->SiS_Pr->DDCPortMixup)) {
|
|
i = 3;
|
|
do {
|
|
temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 0, 0, NULL, pSiS->VBFlags2);
|
|
} while(((temp == 0) || (temp == 0xffff)) && i--);
|
|
|
|
if((temp == 0) || (temp == 0xffff)) {
|
|
if(TestDDC1(pScrn)) temp = 1;
|
|
}
|
|
}
|
|
|
|
if((temp) && (temp != 0xffff)) {
|
|
orSISIDXREG(SISCR,0x32,0x20);
|
|
ret = 1;
|
|
} else if(pSiS->ChipType >= SIS_330) {
|
|
andSISIDXREG(SISCR,0x32,~0x20);
|
|
ret = 0;
|
|
}
|
|
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
setSISIDXREG(SISCR,pSiS->myCR63,0xBF,CR63);
|
|
}
|
|
|
|
setSISIDXREG(SISCR,0x17,0x7F,CR17);
|
|
|
|
outSISIDXREG(SISSR,0x1F,SR1F);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Detect CRT1 */
|
|
void SISCRT1PreInit(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
UChar CR32;
|
|
UChar OtherDevices = 0;
|
|
|
|
pSiS->CRT1Detected = FALSE;
|
|
|
|
if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) {
|
|
pSiS->CRT1Detected = TRUE;
|
|
pSiS->CRT1off = 0;
|
|
return;
|
|
}
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) {
|
|
pSiS->CRT1Detected = TRUE;
|
|
pSiS->CRT1off = 0;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#ifdef SISMERGED
|
|
if((pSiS->MergedFB) && (!(pSiS->MergedFBAuto))) {
|
|
pSiS->CRT1Detected = TRUE;
|
|
pSiS->CRT1off = 0;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
inSISIDXREG(SISCR, 0x32, CR32);
|
|
|
|
if(pSiS->ChipType >= SIS_330) {
|
|
/* Works reliably on 330 and later */
|
|
pSiS->CRT1Detected = SiS_SISDetectCRT1(pScrn);
|
|
} else {
|
|
if(CR32 & 0x20) pSiS->CRT1Detected = TRUE;
|
|
else pSiS->CRT1Detected = SiS_SISDetectCRT1(pScrn);
|
|
}
|
|
|
|
if(CR32 & 0x5F) OtherDevices = 1;
|
|
|
|
if(pSiS->CRT1off == -1) {
|
|
if(!pSiS->CRT1Detected) {
|
|
|
|
/* No CRT1 detected. */
|
|
/* If other devices exist, switch it off */
|
|
if(OtherDevices) pSiS->CRT1off = 1;
|
|
else pSiS->CRT1off = 0;
|
|
|
|
} else {
|
|
|
|
/* CRT1 detected, leave/switch it on */
|
|
pSiS->CRT1off = 0;
|
|
|
|
}
|
|
}
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"%sCRT1/VGA detected\n",
|
|
pSiS->CRT1Detected ? "" : "No ");
|
|
}
|
|
|
|
/* Detect CRT2-LCD and LCD size */
|
|
void SISLCDPreInit(ScrnInfoPtr pScrn, Bool quiet)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
UChar CR32, CR36, CR37, CR7D=0, tmp;
|
|
|
|
pSiS->VBFlags &= ~(CRT2_LCD);
|
|
pSiS->VBLCDFlags = 0;
|
|
pSiS->LCDwidth = 0;
|
|
pSiS->LCDheight = 0;
|
|
|
|
if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return;
|
|
|
|
inSISIDXREG(SISCR, 0x32, CR32);
|
|
|
|
if(CR32 & 0x08) pSiS->VBFlags |= CRT2_LCD;
|
|
|
|
/* 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).
|
|
* Addendum: For DVI-I connected panels, this is not ideal.
|
|
* Therefore, we disregard an eventually detected secondary
|
|
* VGA if the user forced CRT2 type to LCD.
|
|
*
|
|
* 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->VBFlags2 & VB2_SISTMDSBRIDGE) &&
|
|
(!(pSiS->VBFlags2 & VB2_30xBDH)) &&
|
|
(pSiS->VESA != 1)) {
|
|
|
|
if(pSiS->forcecrt2redetection) {
|
|
pSiS->VBFlags &= ~CRT2_LCD;
|
|
/* Do NOT clear CR32[D3] here! */
|
|
}
|
|
|
|
if(!(pSiS->nocrt2ddcdetection)) {
|
|
if((!(pSiS->VBFlags & CRT2_LCD)) &&
|
|
( (!(CR32 & 0x10)) ||
|
|
(pSiS->ForceCRT2Type == CRT2_LCD) ) ) {
|
|
if(!quiet) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"%s LCD/plasma panel, sensing via DDC\n",
|
|
pSiS->forcecrt2redetection ?
|
|
"(Re)-detecting" : "BIOS detected no");
|
|
}
|
|
if(SiS_SenseLCDDDC(pSiS->SiS_Pr, pSiS)) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"DDC error during LCD panel detection\n");
|
|
} else {
|
|
inSISIDXREG(SISCR, 0x32, CR32);
|
|
if(CR32 & 0x08) {
|
|
pSiS->VBFlags |= CRT2_LCD;
|
|
pSiS->postVBCR32 |= 0x08;
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
|
"No LCD/plasma panel detected\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
|
|
if(pSiS->VBFlags & CRT2_LCD) {
|
|
inSISIDXREG(SISCR, 0x36, CR36);
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
if(pSiS->VBFlags2 & VB2_301) {
|
|
if((CR36 & 0x0f) < 0x0f) CR36 &= 0xf7;
|
|
}
|
|
}
|
|
if(pSiS->PRGB != -1) {
|
|
tmp = 0x37;
|
|
if((pSiS->VGAEngine == SIS_315_VGA) &&
|
|
(pSiS->ChipType < SIS_661) &&
|
|
(pSiS->ROM661New) &&
|
|
(!(pSiS->SiS_Pr->PanelSelfDetected))) {
|
|
tmp = 0x35;
|
|
}
|
|
if(pSiS->PRGB == 18) orSISIDXREG(SISCR, tmp, 0x01);
|
|
else if(pSiS->PRGB == 24) andSISIDXREG(SISCR, tmp, 0xfe);
|
|
}
|
|
inSISIDXREG(SISCR, 0x37, CR37);
|
|
if(pSiS->ChipType < SIS_661) {
|
|
inSISIDXREG(SISCR, 0x3C, CR7D);
|
|
} else {
|
|
inSISIDXREG(SISCR, 0x7D, CR7D);
|
|
}
|
|
if(pSiS->SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
|
|
pSiS->VBLCDFlags |= VB_LCD_BARCO1366;
|
|
pSiS->LCDwidth = 1360;
|
|
pSiS->LCDheight = 1024;
|
|
if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"Detected LCD panel (%dx%d, type %d, %sexpanding, RGB%d)\n",
|
|
pSiS->LCDwidth, pSiS->LCDheight,
|
|
((CR36 & 0xf0) >> 4),
|
|
(CR37 & 0x10) ? "" : "non-",
|
|
(CR37 & 0x01) ? 18 : 24);
|
|
} else if(pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) {
|
|
pSiS->VBLCDFlags |= VB_LCD_848x480;
|
|
pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 848;
|
|
pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 480;
|
|
pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
|
|
"Assuming LCD/plasma panel (848x480, expanding, RGB24)\n");
|
|
} else if(pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) {
|
|
pSiS->VBLCDFlags |= VB_LCD_856x480;
|
|
pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 856;
|
|
pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 480;
|
|
pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
|
|
"Assuming LCD/plasma panel (856x480, expanding, RGB24)\n");
|
|
} else if(pSiS->FSTN) {
|
|
pSiS->VBLCDFlags |= VB_LCD_320x240;
|
|
pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 320;
|
|
pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 240;
|
|
pSiS->VBLCDFlags &= ~VB_LCD_EXPANDING;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
|
|
"Assuming FSTN LCD panel (320x240, non-expanding)\n");
|
|
} else {
|
|
if(CR36 == 0) {
|
|
/* Old 650/301LV and ECS A907 BIOS versions "forget" to set CR36, CR37 */
|
|
if(pSiS->VGAEngine == SIS_315_VGA) {
|
|
if(pSiS->ChipType < SIS_661) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"BIOS provided invalid panel size, probing...\n");
|
|
if(pSiS->VBFlags2 & VB2_LVDS) pSiS->SiS_Pr->SiS_IF_DEF_LVDS = 1;
|
|
else pSiS->SiS_Pr->SiS_IF_DEF_LVDS = 0;
|
|
SiS_GetPanelID(pSiS->SiS_Pr);
|
|
inSISIDXREG(SISCR, 0x36, CR36);
|
|
inSISIDXREG(SISCR, 0x37, CR37);
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Broken BIOS, unable to determine panel size, disabling LCD\n");
|
|
pSiS->VBFlags &= ~CRT2_LCD;
|
|
return;
|
|
}
|
|
} else if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"BIOS provided invalid panel size, assuming 1024x768, RGB18\n");
|
|
setSISIDXREG(SISCR,0x36,0xf0,0x02);
|
|
setSISIDXREG(SISCR,0x37,0xee,0x01);
|
|
CR36 = 0x02;
|
|
inSISIDXREG(SISCR,0x37,CR37);
|
|
}
|
|
}
|
|
if((CR36 & 0x0f) == 0x0f) {
|
|
pSiS->VBLCDFlags |= VB_LCD_CUSTOM;
|
|
pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY;
|
|
pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX;
|
|
if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"Detected LCD/Plasma panel (max. X %d Y %d, pref. %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);
|
|
} else {
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
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;
|
|
if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
|
|
} else if((pSiS->ChipType >= 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->ChipType < 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;
|
|
if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING;
|
|
}
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"Detected LCD/plasma panel (%dx%d, %d, %sexp., RGB%d [%02x%02x%02x])\n",
|
|
pSiS->LCDwidth, pSiS->LCDheight,
|
|
((pSiS->VGAEngine == SIS_315_VGA) && (!pSiS->ROM661New)) ?
|
|
((CR36 & 0x0f) - 1) : ((CR36 & 0xf0) >> 4),
|
|
(CR37 & 0x10) ? "" : "non-",
|
|
(CR37 & 0x01) ? 18 : 24,
|
|
CR36, CR37, CR7D);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SiSSetupPseudoPanel(ScrnInfoPtr pScrn)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
int i;
|
|
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"No LCD detected, but forced to enable digital output\n");
|
|
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
|
"Will not be able to properly filter display modes!\n");
|
|
|
|
pSiS->VBFlags |= CRT2_LCD;
|
|
pSiS->SiS_Pr->SiS_CustomT = CUT_UNKNOWNLCD;
|
|
pSiS->SiS_Pr->CP_PrefClock = 0;
|
|
pSiS->SiS_Pr->CP_PreferredIndex = -1;
|
|
pSiS->VBLCDFlags |= (VB_LCD_UNKNOWN | VB_LCD_EXPANDING);
|
|
pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 2048;
|
|
pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 2048;
|
|
for(i=0; i<7; i++) pSiS->SiS_Pr->CP_DataValid[i] = FALSE;
|
|
pSiS->SiS_Pr->CP_HaveCustomData = FALSE;
|
|
pSiS->SiS_Pr->PanelSelfDetected = TRUE;
|
|
outSISIDXREG(SISCR,0x36,0x0f);
|
|
setSISIDXREG(SISCR,0x37,0x0e,0x10);
|
|
orSISIDXREG(SISCR,0x32,0x08);
|
|
}
|
|
|
|
/* Detect CRT2-TV connector type and PAL/NTSC flag */
|
|
void SISTVPreInit(ScrnInfoPtr pScrn, Bool quiet)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
UChar SR16, SR38, CR32, CR35=0, CR38=0, CR79, CR39;
|
|
int temp = 0;
|
|
|
|
if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return;
|
|
|
|
inSISIDXREG(SISCR, 0x32, CR32);
|
|
inSISIDXREG(SISCR, 0x35, CR35);
|
|
inSISIDXREG(SISSR, 0x16, SR16);
|
|
inSISIDXREG(SISSR, 0x38, SR38);
|
|
switch(pSiS->VGAEngine) {
|
|
case SIS_300_VGA:
|
|
if(pSiS->Chipset == PCI_CHIP_SIS630) temp = 0x35;
|
|
break;
|
|
case SIS_315_VGA:
|
|
temp = 0x38;
|
|
break;
|
|
}
|
|
if(temp) {
|
|
inSISIDXREG(SISCR, temp, CR38);
|
|
}
|
|
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"(vb.c: SISTVPreInit 1: CR32=%02x SR16=%02x SR38=%02x VBFlags 0x%x)\n",
|
|
CR32, SR16, SR38, pSiS->VBFlags);
|
|
#endif
|
|
|
|
if(CR32 & 0x47) pSiS->VBFlags |= CRT2_TV;
|
|
|
|
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 & 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->VBFlags2 & VB2_CHRONTEL))
|
|
pSiS->VBFlags |= (TV_CHSCART | TV_PAL);
|
|
else if((CR38 & 0x08) && (pSiS->VBFlags2 & VB2_CHRONTEL))
|
|
pSiS->VBFlags |= (TV_CHYPBPR525I | TV_NTSC);
|
|
|
|
if(pSiS->VBFlags & (TV_SCART | TV_SVIDEO | TV_AVIDEO)) {
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
/* Should be SR38, but this does not work. */
|
|
if(SR16 & 0x20)
|
|
pSiS->VBFlags |= TV_PAL;
|
|
else
|
|
pSiS->VBFlags |= TV_NTSC;
|
|
} else if(pSiS->Chipset == PCI_CHIP_SIS550) {
|
|
inSISIDXREG(SISCR, 0x7a, CR79);
|
|
if(CR79 & 0x08) {
|
|
inSISIDXREG(SISCR, 0x79, CR79);
|
|
CR79 >>= 5;
|
|
}
|
|
if(CR79 & 0x01) {
|
|
pSiS->VBFlags |= TV_PAL;
|
|
if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM;
|
|
else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN;
|
|
} else
|
|
pSiS->VBFlags |= TV_NTSC;
|
|
} else if(pSiS->Chipset == PCI_CHIP_SIS650) {
|
|
inSISIDXREG(SISCR, 0x79, CR79);
|
|
if(CR79 & 0x20) {
|
|
pSiS->VBFlags |= TV_PAL;
|
|
if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM;
|
|
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;
|
|
if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM;
|
|
else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN;
|
|
} else
|
|
pSiS->VBFlags |= TV_NTSC;
|
|
}
|
|
}
|
|
|
|
#ifdef TWDEBUG
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"(vb.c: SISTVPreInit 2: VBFlags 0x%x)\n", pSiS->VBFlags);
|
|
#endif
|
|
|
|
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->VBFlags2 & VB2_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, Bool quiet)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
UChar CR32;
|
|
|
|
/* CRT2-VGA only supported on these bridges */
|
|
if(!(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE))
|
|
return;
|
|
|
|
inSISIDXREG(SISCR, 0x32, CR32);
|
|
|
|
if(CR32 & 0x10) pSiS->VBFlags |= CRT2_VGA;
|
|
|
|
/* See the comment in initextx.c/SiS_SenseVGA2DDC() */
|
|
if(pSiS->SiS_Pr->DDCPortMixup) return;
|
|
|
|
#ifdef SISDUALHEAD
|
|
if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) {
|
|
#endif
|
|
|
|
if(pSiS->forcecrt2redetection) {
|
|
pSiS->VBFlags &= ~CRT2_VGA;
|
|
}
|
|
|
|
/* We don't trust the normal sensing method for VGA2 since
|
|
* it is performed by the BIOS during POST, and it is
|
|
* impossible to sense VGA2 if the bridge is disabled.
|
|
* Therefore, we try sensing VGA2 by DDC as well (if not
|
|
* detected otherwise and only if there is no LCD panel
|
|
* which is prone to be misdetected as a secondary VGA)
|
|
*/
|
|
if(!(pSiS->nocrt2ddcdetection)) {
|
|
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,
|
|
"Detected secondary VGA connection\n");
|
|
} else {
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"No secondary VGA connection detected\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#ifdef SISDUALHEAD
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static int
|
|
SISDoSense(ScrnInfoPtr pScrn, UShort type, UShort 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);
|
|
UChar backupP4_0d, backupP2_00, backupP2_4d, backupSR_1e, biosflag=0;
|
|
UShort svhs=0, svhs_c=0;
|
|
UShort cvbs=0, cvbs_c=0;
|
|
UShort vga2=0, vga2_c=0;
|
|
int myflag, result; /* , i; */
|
|
|
|
if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return;
|
|
|
|
#ifdef TWDEBUG
|
|
inSISIDXREG(SISCR,0x32,backupP2_4d);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"(vb.c: SISSense30c 1: CR32=%02x, VBFlags 0x%x)\n", backupP2_4d, pSiS->VBFlags);
|
|
#endif
|
|
|
|
if(pSiS->VBFlags2 & VB2_301) {
|
|
svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
|
|
inSISIDXREG(SISPART4,0x01,myflag);
|
|
if(myflag & 0x04) {
|
|
svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
|
|
}
|
|
} else if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) {
|
|
svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
|
|
} else if(pSiS->VBFlags2 & (VB2_301LV | VB2_302LV)) {
|
|
svhs = 0x0200; cvbs = 0x0100;
|
|
} else if(pSiS->VBFlags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
|
|
svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
|
|
} else return;
|
|
|
|
vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
|
|
if(pSiS->VBFlags2 & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
|
|
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->SiS_Pr->UseROM) {
|
|
if(pSiS->VGAEngine == SIS_300_VGA) {
|
|
if(pSiS->VBFlags2 & VB2_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);
|
|
if(pSiS->BIOS[0x6f] & 0x01) {
|
|
if(pSiS->VBFlags2 & VB2_SISUMC) vga2 = GETROMWORD(0x4d);
|
|
}
|
|
svhs = cvbs = GETROMWORD(0x65);
|
|
if(pSiS->BIOS[0x5d] & 0x04) biosflag |= 0x01;
|
|
}
|
|
}
|
|
/* No "else", some BIOSes carry wrong data */
|
|
}
|
|
|
|
if(pSiS->ChipType >= XGI_20) {
|
|
if(pSiS->HaveXGIBIOS) {
|
|
biosflag = pSiS->BIOS[0x58] & 0x03;
|
|
} else {
|
|
/* These boards have a s-video connector, but its
|
|
* pins are routed both the bridge's composite and
|
|
* svideo pins. This is for using the S-video plug
|
|
* for YPbPr output. Anyway, since a svideo connected
|
|
* TV would also been detected as a composite connected
|
|
* one, we don't check for composite if svideo is
|
|
* detected.
|
|
*/
|
|
biosflag &= ~0x02;
|
|
}
|
|
}
|
|
|
|
if(!(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) {
|
|
vga2 = vga2_c = 0;
|
|
}
|
|
|
|
inSISIDXREG(SISSR,0x1e,backupSR_1e);
|
|
orSISIDXREG(SISSR,0x1e,0x20);
|
|
|
|
inSISIDXREG(SISPART4,0x0d,backupP4_0d);
|
|
if(pSiS->VBFlags2 & VB2_30xCLV) {
|
|
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->VBFlags2 & VB2_SISYPBPRBRIDGE) {
|
|
outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
|
|
}
|
|
|
|
if(!(pSiS->VBFlags2 & VB2_30xCLV)) {
|
|
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->VBFlags2 & VB2_30xCLV) {
|
|
orSISIDXREG(SISPART4,0x0d,0x04);
|
|
}
|
|
|
|
if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) {
|
|
if(pSiS->SenseYPbPr) {
|
|
outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
|
|
SiS_DDC2Delay(pSiS->SiS_Pr, 0x2000);
|
|
/* New BIOS (2.x) uses vga2 sensing here for all bridges >301LV */
|
|
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->VBFlags2 & VB2_30xCLV) {
|
|
inSISIDXREG(SISPART2,0x00,biosflag);
|
|
if(biosflag & 0x20) {
|
|
for(myflag = 2; myflag > 0; myflag--) {
|
|
biosflag ^= 0x20;
|
|
outSISIDXREG(SISPART2,0x00,biosflag);
|
|
}
|
|
}
|
|
}
|
|
|
|
outSISIDXREG(SISPART2,0x00,backupP2_00);
|
|
|
|
#ifdef TWDEBUG
|
|
inSISIDXREG(SISCR,0x32,backupP2_4d);
|
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
|
"(vb.c: SISSense30c 2: CR32=0x%02x, VBFlags 0x%x)\n", backupP2_4d, pSiS->VBFlags);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
SISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet)
|
|
{
|
|
SISPtr pSiS = SISPTR(pScrn);
|
|
int temp1=0, temp2, i;
|
|
UChar 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, 0x0e,0x0b);
|
|
SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
|
|
}
|
|
/* Sense connected TV devices */
|
|
for(i = 0; i < 3; i++) {
|
|
SiS_SetCH700x(pSiS->SiS_Pr, 0x10, 0x01);
|
|
SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
|
|
SiS_SetCH700x(pSiS->SiS_Pr, 0x10, 0x00);
|
|
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, 0x49, 0x20);
|
|
|
|
SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
|
|
|
|
/* Sense connected TV devices */
|
|
temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20);
|
|
temp2 |= 0x01;
|
|
SiS_SetCH701x(pSiS->SiS_Pr, 0x20, temp2);
|
|
|
|
SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
|
|
|
|
temp2 ^= 0x01;
|
|
SiS_SetCH701x(pSiS->SiS_Pr, 0x20, temp2);
|
|
|
|
SiS_DDC2Delay(pSiS->SiS_Pr, 0x96);
|
|
|
|
temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20);
|
|
|
|
/* Restore Power register */
|
|
SiS_SetCH701x(pSiS->SiS_Pr, 0x49, temp1);
|
|
|
|
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);
|
|
ULong VBFlagsBackup = pSiS->VBFlags;
|
|
Bool backup1 = pSiS->forcecrt2redetection;
|
|
Bool backup2 = pSiS->nocrt2ddcdetection;
|
|
|
|
#ifdef SISDUALHEAD
|
|
if(pSiS->DualHeadMode) return FALSE;
|
|
#endif
|
|
|
|
pSiS->VBFlags &= ~(CRT2_DEFAULT |
|
|
CRT2_ENABLE |
|
|
TV_STANDARD |
|
|
TV_INTERFACE |
|
|
TV_YPBPRALL |
|
|
TV_YPBPRAR |
|
|
TV_CHSCART |
|
|
TV_CHYPBPR525I |
|
|
CRT1_LCDA |
|
|
DISPTYPE_CRT1);
|
|
|
|
/* At first, re-do the sensing for TV and VGA2 */
|
|
if(pSiS->VBFlags2 & VB2_SISBRIDGE) {
|
|
SISSense30x(pScrn, TRUE);
|
|
} else if(pSiS->VBFlags2 & VB2_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->VBFlags2 & VB2_SISTMDSBRIDGE) &&
|
|
(!(pSiS->VBFlags2 & VB2_30xBDH)) &&
|
|
(pSiS->VESA != 1) &&
|
|
(pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) {
|
|
SISLCDPreInit(pScrn, TRUE);
|
|
} else {
|
|
pSiS->VBFlags |= (pSiS->detectedCRT2Devices & CRT2_LCD);
|
|
}
|
|
|
|
/* Secondary VGA is only supported on these bridges: */
|
|
if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) {
|
|
SISCRT2PreInit(pScrn, TRUE);
|
|
}
|
|
|
|
pSiS->forcecrt2redetection = backup1;
|
|
pSiS->nocrt2ddcdetection = backup2;
|
|
|
|
pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA;
|
|
if(SISDetermineLCDACap(pScrn)) {
|
|
pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA;
|
|
}
|
|
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;
|
|
}
|
|
|
|
pSiS->VBFlagsInit = 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;
|
|
}
|
|
|
|
|