xenocara/driver/xf86-video-sis/src/sis_vb.c
2006-11-26 20:12:30 +00:00

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;
}