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