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