diff vidix/sis_bridge.c @ 22850:9a1e26fef45b

Move driver files directly into the vidix directory.
author diego
date Sun, 01 Apr 2007 00:02:43 +0000
parents
children d76307ffcb77
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vidix/sis_bridge.c	Sun Apr 01 00:02:43 2007 +0000
@@ -0,0 +1,827 @@
+/**
+    Video bridge detection for SiS 300 and 310/325 series chips.
+
+    Copyright 2003 Jake Page, Sugar Media.
+
+    Based on SiS Xv driver:
+    Copyright 2002-2003 by Thomas Winischhofer, Vienna, Austria.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+**/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "../libdha/libdha.h"
+#include "sis_regs.h"
+#include "sis_defs.h"
+
+
+static void sis_ddc2_delay(unsigned short delaytime)
+{
+    unsigned short i;
+    int temp;
+
+    for (i = 0; i < delaytime; i++) {
+	inSISIDXREG(SISSR, 0x05, temp);
+    }
+}
+
+
+static int sis_do_sense(int tempbl, int tempbh, int tempcl, int tempch)
+{
+    int temp;
+
+    outSISIDXREG(SISPART4, 0x11, tempbl);
+    temp = tempbh | tempcl;
+    setSISIDXREG(SISPART4, 0x10, 0xe0, temp);
+    //usleep(200000);
+    sis_ddc2_delay(0x1000);
+    tempch &= 0x7f;
+    inSISIDXREG(SISPART4, 0x03, temp);
+    temp ^= 0x0e;
+    temp &= tempch;
+    return (temp == tempch);
+}
+
+
+/* sense connected devices on 30x bridge */
+static void sis_sense_30x(void)
+{
+    unsigned char backupP4_0d, backupP2_00, biosflag;
+    unsigned char testsvhs_tempbl, testsvhs_tempbh;
+    unsigned char testsvhs_tempcl, testsvhs_tempch;
+    unsigned char testcvbs_tempbl, testcvbs_tempbh;
+    unsigned char testcvbs_tempcl, testcvbs_tempch;
+    unsigned char testvga2_tempbl, testvga2_tempbh;
+    unsigned char testvga2_tempcl, testvga2_tempch;
+    int myflag, result = 0, i, j, haveresult;
+    unsigned short temp;
+
+    inSISIDXREG(SISPART4, 0x0d, backupP4_0d);
+    outSISIDXREG(SISPART4, 0x0d, (backupP4_0d | 0x04));
+
+    inSISIDXREG(SISPART2, 0x00, backupP2_00);
+    outSISIDXREG(SISPART2, 0x00, (backupP2_00 | 0x1c));
+
+    sis_do_sense(0, 0, 0, 0);
+
+    if ((sis_vga_engine == SIS_315_VGA) ||
+	(sis_device_id == DEVICE_SIS_300)) {
+#if 0
+	if (0 /*pSiS->sishw_ext.UseROM */ ) {
+	    if (sis_vga_engine == SIS_300_VGA)
+		temp = 0xfe;
+	    else {
+		temp = 0xf3;
+		if (sis_device_id == DEVICE_SIS_330)
+		    temp = 0x11b;
+	    }
+	    if (pSiS->BIOS[temp] & 0x08) {
+		if (sis_verbose > 1) {
+		    printf
+			("[SiS] SiS30x: Video bridge has DVI-I TMDS/VGA combo connector\n");
+		}
+		orSISIDXREG(SISCR, 0x32, 0x80);
+	    } else {
+		andSISIDXREG(SISCR, 0x32, 0x7f);
+	    }
+	}
+#endif
+    }
+
+    if (sis_vga_engine == SIS_300_VGA) {
+	if (0 /*pSiS->sishw_ext.UseROM */ ) {
+#if 0
+	    testvga2_tempbh = pSiS->BIOS[0xf9];
+	    testvga2_tempbl = pSiS->BIOS[0xf8];
+	    testsvhs_tempbh = pSiS->BIOS[0xfb];
+	    testsvhs_tempbl = pSiS->BIOS[0xfa];
+	    testcvbs_tempbh = pSiS->BIOS[0xfd];
+	    testcvbs_tempbl = pSiS->BIOS[0xfc];
+	    biosflag = pSiS->BIOS[0xfe];
+#endif
+	} else {
+	    testvga2_tempbh = 0x00;
+	    testvga2_tempbl = 0xd1;
+	    testsvhs_tempbh = 0x00;
+	    testsvhs_tempbl = 0xb9;
+	    testcvbs_tempbh = 0x00;
+	    testcvbs_tempbl = 0xb3;
+	    biosflag = 0;
+	}
+	if (sis_vbflags & (VB_301B | VB_302B | VB_301LV | VB_302LV)) {
+	    testvga2_tempbh = 0x01;
+	    testvga2_tempbl = 0x90;
+	    testsvhs_tempbh = 0x01;
+	    testsvhs_tempbl = 0x6b;
+	    testcvbs_tempbh = 0x01;
+	    testcvbs_tempbl = 0x74;
+	}
+	inSISIDXREG(SISPART4, 0x01, myflag);
+	if (myflag & 0x04) {
+	    testvga2_tempbh = 0x00;
+	    testvga2_tempbl = 0xfd;
+	    testsvhs_tempbh = 0x00;
+	    testsvhs_tempbl = 0xdd;
+	    testcvbs_tempbh = 0x00;
+	    testcvbs_tempbl = 0xee;
+	}
+	testvga2_tempch = 0x0e;
+	testvga2_tempcl = 0x08;
+	testsvhs_tempch = 0x06;
+	testsvhs_tempcl = 0x04;
+	testcvbs_tempch = 0x08;
+	testcvbs_tempcl = 0x04;
+
+	if (sis_device_id == DEVICE_SIS_300) {
+	    inSISIDXREG(SISSR, 0x3b, myflag);
+	    if (!(myflag & 0x01)) {
+		testvga2_tempbh = 0x00;
+		testvga2_tempbl = 0x00;
+		testvga2_tempch = 0x00;
+		testvga2_tempcl = 0x00;
+	    }
+	}
+    } else {
+	if (0 /*pSiS->sishw_ext.UseROM */ ) {
+#if 0
+	    if (sis_device_id == DEVICE_SIS_330) {
+		testvga2_tempbh = pSiS->BIOS[0xe6];
+		testvga2_tempbl = pSiS->BIOS[0xe5];
+		testsvhs_tempbh = pSiS->BIOS[0xe8];
+		testsvhs_tempbl = pSiS->BIOS[0xe7];
+		testcvbs_tempbh = pSiS->BIOS[0xea];
+		testcvbs_tempbl = pSiS->BIOS[0xe9];
+		biosflag = pSiS->BIOS[0x11b];
+	    } else {
+		testvga2_tempbh = pSiS->BIOS[0xbe];
+		testvga2_tempbl = pSiS->BIOS[0xbd];
+		testsvhs_tempbh = pSiS->BIOS[0xc0];
+		testsvhs_tempbl = pSiS->BIOS[0xbf];
+		testcvbs_tempbh = pSiS->BIOS[0xc2];
+		testcvbs_tempbl = pSiS->BIOS[0xc1];
+		biosflag = pSiS->BIOS[0xf3];
+	    }
+#endif
+	} else {
+	    testvga2_tempbh = 0x00;
+	    testvga2_tempbl = 0xd1;
+	    testsvhs_tempbh = 0x00;
+	    testsvhs_tempbl = 0xb9;
+	    testcvbs_tempbh = 0x00;
+	    testcvbs_tempbl = 0xb3;
+	    biosflag = 0;
+	}
+
+	if (sis_vbflags & (VB_301B | VB_302B | VB_301LV | VB_302LV)) {
+	    if (0 /*pSiS->sishw_ext.UseROM */ ) {
+#if 0
+		if (sis_device_id == DEVICE_SIS_330) {
+		    testvga2_tempbh = pSiS->BIOS[0xec];
+		    testvga2_tempbl = pSiS->BIOS[0xeb];
+		    testsvhs_tempbh = pSiS->BIOS[0xee];
+		    testsvhs_tempbl = pSiS->BIOS[0xed];
+		    testcvbs_tempbh = pSiS->BIOS[0xf0];
+		    testcvbs_tempbl = pSiS->BIOS[0xef];
+		} else {
+		    testvga2_tempbh = pSiS->BIOS[0xc4];
+		    testvga2_tempbl = pSiS->BIOS[0xc3];
+		    testsvhs_tempbh = pSiS->BIOS[0xc6];
+		    testsvhs_tempbl = pSiS->BIOS[0xc5];
+		    testcvbs_tempbh = pSiS->BIOS[0xc8];
+		    testcvbs_tempbl = pSiS->BIOS[0xc7];
+		}
+#endif
+	    } else {
+		if (sis_vbflags & (VB_301B | VB_302B)) {
+		    testvga2_tempbh = 0x01;
+		    testvga2_tempbl = 0x90;
+		    testsvhs_tempbh = 0x01;
+		    testsvhs_tempbl = 0x6b;
+		    testcvbs_tempbh = 0x01;
+		    testcvbs_tempbl = 0x74;
+		} else {
+		    testvga2_tempbh = 0x00;
+		    testvga2_tempbl = 0x00;
+		    testsvhs_tempbh = 0x02;
+		    testsvhs_tempbl = 0x00;
+		    testcvbs_tempbh = 0x01;
+		    testcvbs_tempbl = 0x00;
+		}
+	    }
+	}
+	if (sis_vbflags & (VB_301 | VB_301B | VB_302B)) {
+	    inSISIDXREG(SISPART4, 0x01, myflag);
+	    if (myflag & 0x04) {
+		testvga2_tempbh = 0x00;
+		testvga2_tempbl = 0xfd;
+		testsvhs_tempbh = 0x00;
+		testsvhs_tempbl = 0xdd;
+		testcvbs_tempbh = 0x00;
+		testcvbs_tempbl = 0xee;
+	    }
+	}
+	if (sis_vbflags & (VB_301LV | VB_302LV)) {
+	    /* TW: No VGA2 or SCART on LV bridges */
+	    testvga2_tempbh = 0x00;
+	    testvga2_tempbl = 0x00;
+	    testvga2_tempch = 0x00;
+	    testvga2_tempcl = 0x00;
+	    testsvhs_tempch = 0x04;
+	    testsvhs_tempcl = 0x08;
+	    testcvbs_tempch = 0x08;
+	    testcvbs_tempcl = 0x08;
+	} else {
+	    testvga2_tempch = 0x0e;
+	    testvga2_tempcl = 0x08;
+	    testsvhs_tempch = 0x06;
+	    testsvhs_tempcl = 0x04;
+	    testcvbs_tempch = 0x08;
+	    testcvbs_tempcl = 0x04;
+	}
+    }
+
+    /* XXX: ?? andSISIDXREG(SISCR, 0x32, ~0x14); */
+    /* pSiS->postVBCR32 &= ~0x14; */
+
+    /* scan for VGA2/SCART */
+    if (testvga2_tempch || testvga2_tempcl ||
+	testvga2_tempbh || testvga2_tempbl) {
+
+	haveresult = 0;
+	for (j = 0; j < 10; j++) {
+	    result = 0;
+	    for (i = 0; i < 3; i++) {
+		if (sis_do_sense(testvga2_tempbl, testvga2_tempbh,
+				 testvga2_tempcl, testvga2_tempch))
+		    result++;
+	    }
+	    if ((result == 0) || (result >= 2))
+		break;
+	}
+	if (result) {
+	    if (biosflag & 0x01) {
+		if (sis_verbose > 1) {
+		    printf
+			("[SiS] SiS30x: Detected TV connected to SCART output\n");
+		}
+		sis_vbflags |= TV_SCART;
+		orSISIDXREG(SISCR, 0x32, 0x04);
+		/*pSiS->postVBCR32 |= 0x04; */
+	    } else {
+		if (sis_verbose > 1) {
+		    printf
+			("[SiS] SiS30x: Detected secondary VGA connection\n");
+		}
+		sis_vbflags |= VGA2_CONNECTED;
+		orSISIDXREG(SISCR, 0x32, 0x10);
+		/*pSiS->postVBCR32 |= 0x10; */
+	    }
+	}
+    }
+
+    /* scanning for TV */
+
+    /* XXX: ?? andSISIDXREG(SISCR, 0x32, ~0x03); */
+    /* pSiS->postVBCR32 &= ~0x03; */
+
+    result = sis_do_sense(testsvhs_tempbl, testsvhs_tempbh,
+			  testsvhs_tempcl, testsvhs_tempch);
+
+
+    haveresult = 0;
+    for (j = 0; j < 10; j++) {
+	result = 0;
+	for (i = 0; i < 3; i++) {
+	    if (sis_do_sense(testsvhs_tempbl, testsvhs_tempbh,
+			     testsvhs_tempcl, testsvhs_tempch))
+		result++;
+	}
+	if ((result == 0) || (result >= 2))
+	    break;
+    }
+    if (result) {
+	if (sis_verbose > 1) {
+	    printf
+		("[SiS] SiS30x: Detected TV connected to SVIDEO output\n");
+	}
+	/* TW: So we can be sure that there IS a SVIDEO output */
+	sis_vbflags |= TV_SVIDEO;
+	orSISIDXREG(SISCR, 0x32, 0x02);
+	//pSiS->postVBCR32 |= 0x02;
+    }
+
+    if ((biosflag & 0x02) || (!(result))) {
+	haveresult = 0;
+	for (j = 0; j < 10; j++) {
+	    result = 0;
+	    for (i = 0; i < 3; i++) {
+		if (sis_do_sense(testcvbs_tempbl, testcvbs_tempbh,
+				 testcvbs_tempcl, testcvbs_tempch))
+		    result++;
+	    }
+	    if ((result == 0) || (result >= 2))
+		break;
+	}
+	if (result) {
+	    if (sis_verbose > 1) {
+		printf
+		    ("[SiS] SiS30x: Detected TV connected to COMPOSITE output\n");
+	    }
+	    sis_vbflags |= TV_AVIDEO;
+	    orSISIDXREG(SISCR, 0x32, 0x01);
+	    //pSiS->postVBCR32 |= 0x01;
+	}
+    }
+
+    sis_do_sense(0, 0, 0, 0);
+
+    outSISIDXREG(SISPART2, 0x00, backupP2_00);
+    outSISIDXREG(SISPART4, 0x0d, backupP4_0d);
+}
+
+
+static void sis_detect_crt1(void)
+{
+    unsigned char CR32;
+    unsigned char CRT1Detected = 0;
+    unsigned char OtherDevices = 0;
+
+    if (!(sis_vbflags & VB_VIDEOBRIDGE)) {
+	sis_crt1_off = 0;
+	return;
+    }
+
+    inSISIDXREG(SISCR, 0x32, CR32);
+
+    if (CR32 & 0x20)
+	CRT1Detected = 1;
+    if (CR32 & 0x5F)
+	OtherDevices = 1;
+
+    if (sis_crt1_off == -1) {
+	if (!CRT1Detected) {
+	    /* BIOS detected no CRT1. */
+	    /* If other devices exist, switch it off */
+	    if (OtherDevices)
+		sis_crt1_off = 1;
+	    else
+		sis_crt1_off = 0;
+	} else {
+	    /* BIOS detected CRT1, leave/switch it on */
+	    sis_crt1_off = 0;
+	}
+    }
+    if (sis_verbose > 0) {
+	printf("[SiS] %sCRT1 connection detected\n",
+	       sis_crt1_off ? "No " : "");
+    }
+}
+
+
+static void sis_detect_lcd(void)
+{
+    unsigned char CR32, CR36, CR37;
+
+    if (!(sis_vbflags & VB_VIDEOBRIDGE)) {
+	return;
+    }
+
+    inSISIDXREG(SISCR, 0x32, CR32);
+
+    if (CR32 & 0x08)
+	sis_vbflags |= CRT2_LCD;
+
+    /* DDC detection of LCD - not supported yet */
+
+    /* Get other misc info about LCD - not supported */
+}
+
+
+static void sis_detect_tv(void)
+{
+    unsigned char SR16, SR38, CR32, CR38 = 0, CR79;
+    int temp = 0;
+
+    if (!(sis_vbflags & VB_VIDEOBRIDGE))
+	return;
+
+    inSISIDXREG(SISCR, 0x32, CR32);
+    inSISIDXREG(SISSR, 0x16, SR16);
+    inSISIDXREG(SISSR, 0x38, SR38);
+    switch (sis_vga_engine) {
+    case SIS_300_VGA:
+	if (sis_device_id == DEVICE_SIS_630_VGA)
+	    temp = 0x35;
+	break;
+    case SIS_315_VGA:
+	temp = 0x38;
+	break;
+    }
+    if (temp) {
+	inSISIDXREG(SISCR, temp, CR38);
+    }
+
+    if (CR32 & 0x47)
+	sis_vbflags |= CRT2_TV;
+
+    if (CR32 & 0x04)
+	sis_vbflags |= TV_SCART;
+    else if (CR32 & 0x02)
+	sis_vbflags |= TV_SVIDEO;
+    else if (CR32 & 0x01)
+	sis_vbflags |= TV_AVIDEO;
+    else if (CR32 & 0x40)
+	sis_vbflags |= (TV_SVIDEO | TV_HIVISION);
+    else if ((CR38 & 0x04) && (sis_vbflags & (VB_301LV | VB_302LV)))
+	sis_vbflags |= TV_HIVISION_LV;
+    else if ((CR38 & 0x04) && (sis_vbflags & VB_CHRONTEL))
+	sis_vbflags |= (TV_CHSCART | TV_PAL);
+    else if ((CR38 & 0x08) && (sis_vbflags & VB_CHRONTEL))
+	sis_vbflags |= (TV_CHHDTV | TV_NTSC);
+
+    if (sis_vbflags & (TV_SCART | TV_SVIDEO | TV_AVIDEO | TV_HIVISION)) {
+	if (sis_vga_engine == SIS_300_VGA) {
+	    /* TW: Should be SR38 here as well, but this
+	     *     does not work. Looks like a BIOS bug (2.04.5c).
+	     */
+	    if (SR16 & 0x20)
+		sis_vbflags |= TV_PAL;
+	    else
+		sis_vbflags |= TV_NTSC;
+	} else if ((sis_device_id == DEVICE_SIS_550_VGA)) {
+	    inSISIDXREG(SISCR, 0x79, CR79);
+	    if (CR79 & 0x08) {
+		inSISIDXREG(SISCR, 0x79, CR79);
+		CR79 >>= 5;
+	    }
+	    if (CR79 & 0x01) {
+		sis_vbflags |= TV_PAL;
+		if (CR38 & 0x40)
+		    sis_vbflags |= TV_PALM;
+		else if (CR38 & 0x80)
+		    sis_vbflags |= TV_PALN;
+	    } else
+		sis_vbflags |= TV_NTSC;
+	} else if ((sis_device_id == DEVICE_SIS_650_VGA)) {
+	    inSISIDXREG(SISCR, 0x79, CR79);
+	    if (CR79 & 0x20) {
+		sis_vbflags |= TV_PAL;
+		if (CR38 & 0x40)
+		    sis_vbflags |= TV_PALM;
+		else if (CR38 & 0x80)
+		    sis_vbflags |= TV_PALN;
+	    } else
+		sis_vbflags |= TV_NTSC;
+	} else {		/* 315, 330 */
+	    if (SR38 & 0x01) {
+		sis_vbflags |= TV_PAL;
+		if (CR38 & 0x40)
+		    sis_vbflags |= TV_PALM;
+		else if (CR38 & 0x80)
+		    sis_vbflags |= TV_PALN;
+	    } else
+		sis_vbflags |= TV_NTSC;
+	}
+    }
+
+    if (sis_vbflags &
+	(TV_SCART | TV_SVIDEO | TV_AVIDEO | TV_HIVISION | TV_CHSCART |
+	 TV_CHHDTV)) {
+	if (sis_verbose > 0) {
+	    printf("[SiS] %sTV standard %s\n",
+		   (sis_vbflags & (TV_CHSCART | TV_CHHDTV)) ? "Using " :
+		   "Detected default ",
+		   (sis_vbflags & TV_NTSC) ? ((sis_vbflags & TV_CHHDTV) ?
+					      "480i HDTV" : "NTSC")
+		   : ((sis_vbflags & TV_PALM) ? "PALM"
+		      : ((sis_vbflags & TV_PALN) ? "PALN" : "PAL")));
+	}
+    }
+
+}
+
+
+static void sis_detect_crt2(void)
+{
+    unsigned char CR32;
+
+    if (!(sis_vbflags & VB_VIDEOBRIDGE))
+	return;
+
+    /* CRT2-VGA not supported on LVDS and 30xLV */
+    if (sis_vbflags & (VB_LVDS | VB_301LV | VB_302LV))
+	return;
+
+    inSISIDXREG(SISCR, 0x32, CR32);
+
+    if (CR32 & 0x10)
+	sis_vbflags |= CRT2_VGA;
+
+#if 0
+    if (!(pSiS->nocrt2ddcdetection)) {
+	if (sis_vbflags & (VB_301B | VB_302B)) {
+	    if (!(sis_vbflags & (CRT2_VGA | CRT2_LCD))) {
+		printf
+		    ("[SiS] BIOS detected no secondary VGA, sensing via DDC\n");
+		if (SiS_SenseVGA2DDC(pSiS->SiS_Pr, pSiS)) {
+		    printf
+			("[SiS] DDC error during secondary VGA detection\n");
+		} else {
+		    inSISIDXREG(SISCR, 0x32, CR32);
+		    if (CR32 & 0x10) {
+			sis_vbflags |= CRT2_VGA;
+			/*pSiS->postVBCR32 |= 0x10; */
+			printf
+			    ("[SiS] Detected secondary VGA connection\n");
+		    } else {
+			printf
+			    ("[SiS] No secondary VGA connection detected\n");
+		    }
+		}
+	    }
+	}
+    }
+#endif
+
+}
+
+
+/* Preinit: detect video bridge and sense connected devs */
+static void sis_detect_video_bridge(void)
+{
+    int temp, temp1, temp2;
+
+
+    sis_vbflags = 0;
+
+    if (sis_vga_engine != SIS_300_VGA && sis_vga_engine != SIS_315_VGA)
+	return;
+
+    inSISIDXREG(SISPART4, 0x00, temp);
+    temp &= 0x0F;
+    if (temp == 1) {
+	inSISIDXREG(SISPART4, 0x01, temp1);
+	temp1 &= 0xff;
+	if (temp1 >= 0xE0) {
+	    sis_vbflags |= VB_302LV;
+	    //pSiS->sishw_ext.ujVBChipID = VB_CHIP_302LV;
+	    if (sis_verbose > 1) {
+		printf
+		    ("[SiS] Detected SiS302LV video bridge (ID 1; Revision 0x%x)\n",
+		     temp1);
+	    }
+
+	} else if (temp1 >= 0xD0) {
+	    sis_vbflags |= VB_301LV;
+	    //pSiS->sishw_ext.ujVBChipID = VB_CHIP_301LV;
+	    if (sis_verbose > 1) {
+		printf
+		    ("[SiS] Detected SiS301LV video bridge (ID 1; Revision 0x%x)\n",
+		     temp1);
+	    }
+	} else if (temp1 >= 0xB0) {
+	    sis_vbflags |= VB_301B;
+	    //pSiS->sishw_ext.ujVBChipID = VB_CHIP_301B;
+	    inSISIDXREG(SISPART4, 0x23, temp2);
+	    if (!(temp2 & 0x02))
+		sis_vbflags |= VB_30xBDH;
+	    if (sis_verbose > 1) {
+		printf
+		    ("[SiS] Detected SiS301B%s video bridge (Revision 0x%x)\n",
+		     (temp2 & 0x02) ? "" : " (DH)", temp1);
+	    }
+	} else {
+	    sis_vbflags |= VB_301;
+	    //pSiS->sishw_ext.ujVBChipID = VB_CHIP_301;
+	    if (sis_verbose > 1) {
+		printf
+		    ("[SiS] Detected SiS301 video bridge (Revision 0x%x)\n",
+		     temp1);
+	    }
+	}
+
+	sis_sense_30x();
+
+    } else if (temp == 2) {
+
+	inSISIDXREG(SISPART4, 0x01, temp1);
+	temp1 &= 0xff;
+	if (temp1 >= 0xE0) {
+	    sis_vbflags |= VB_302LV;
+	    //pSiS->sishw_ext.ujVBChipID = VB_CHIP_302LV;
+	    if (sis_verbose > 1) {
+		printf
+		    ("[SiS] Detected SiS302LV video bridge (ID 2; Revision 0x%x)\n",
+		     temp1);
+	    }
+	} else if (temp1 >= 0xD0) {
+	    sis_vbflags |= VB_301LV;
+	    //pSiS->sishw_ext.ujVBChipID = VB_CHIP_301LV;
+	    if (sis_verbose > 1) {
+		printf
+		    ("[SiS] Detected SiS301LV video bridge (ID 2; Revision 0x%x)\n",
+		     temp1);
+	    }
+	} else {
+	    sis_vbflags |= VB_302B;
+	    //pSiS->sishw_ext.ujVBChipID = VB_CHIP_302B;
+	    inSISIDXREG(SISPART4, 0x23, temp2);
+	    if (!(temp & 0x02))
+		sis_vbflags |= VB_30xBDH;
+	    if (sis_verbose > 1) {
+		printf
+		    ("[SiS] Detected SiS302B%s video bridge (Revision 0x%x)\n",
+		     (temp2 & 0x02) ? "" : " (DH)", temp1);
+	    }
+	}
+
+	sis_sense_30x();
+
+    } else if (temp == 3) {
+	if (sis_verbose > 1) {
+	    printf("[SiS] Detected SiS303 video bridge - not supported\n");
+	}
+    } else {
+	/* big scary mess of code to handle unknown or Chrontel LVDS */
+	/* skipping it for now */
+	if (sis_verbose > 1) {
+	    printf
+		("[SiS] Detected Chrontel video bridge - not supported\n");
+	}
+    }
+
+    /* this is probably not relevant to video overlay driver... */
+    /* detects if brdige uses LCDA for low res text modes */
+    if (sis_vga_engine == SIS_315_VGA) {
+	if (sis_vbflags & (VB_302B | VB_301LV | VB_302LV)) {
+#if 0
+	    if (pSiS->sisfblcda != 0xff) {
+		if ((pSiS->sisfblcda & 0x03) == 0x03) {
+		    //pSiS->SiS_Pr->SiS_UseLCDA = TRUE;
+		    sis_vbflags |= VB_USELCDA;
+		}
+	    } else
+#endif
+	    {
+		inSISIDXREG(SISCR, 0x34, temp);
+		if (temp <= 0x13) {
+		    inSISIDXREG(SISCR, 0x38, temp);
+		    if ((temp & 0x03) == 0x03) {
+			//pSiS->SiS_Pr->SiS_UseLCDA = TRUE;
+			sis_vbflags |= VB_USELCDA;
+		    } else {
+			inSISIDXREG(SISCR, 0x30, temp);
+			if (temp & 0x20) {
+			    inSISIDXREG(SISPART1, 0x13, temp);
+			    if (temp & 0x40) {
+				//pSiS->SiS_Pr->SiS_UseLCDA = TRUE;
+				sis_vbflags |= VB_USELCDA;
+			    }
+			}
+		    }
+		}
+	    }
+	    if (sis_vbflags & VB_USELCDA) {
+		/* printf("Bridge uses LCDA for low resolution and text modes\n"); */
+	    }
+	}
+    }
+
+
+}
+
+
+/* detect video bridge type and sense connected devices */
+void sis_init_video_bridge(void)
+{
+
+    sis_detect_video_bridge();
+
+    sis_detect_crt1();
+    //sis_detect_lcd();
+    sis_detect_tv();
+    sis_detect_crt2();
+
+    sis_detected_crt2_devices =
+	sis_vbflags & (CRT2_LCD | CRT2_TV | CRT2_VGA);
+
+    // force crt2 type
+    if (sis_force_crt2_type == CRT2_DEFAULT) {
+	if (sis_vbflags & CRT2_VGA)
+	    sis_force_crt2_type = CRT2_VGA;
+	else if (sis_vbflags & CRT2_LCD)
+	    sis_force_crt2_type = CRT2_LCD;
+	else if (sis_vbflags & CRT2_TV)
+	    sis_force_crt2_type = CRT2_TV;
+    }
+
+    switch (sis_force_crt2_type) {
+    case CRT2_TV:
+	sis_vbflags = sis_vbflags & ~(CRT2_LCD | CRT2_VGA);
+	if (sis_vbflags & VB_VIDEOBRIDGE)
+	    sis_vbflags = sis_vbflags | CRT2_TV;
+	else
+	    sis_vbflags = sis_vbflags & ~(CRT2_TV);
+	break;
+    case CRT2_LCD:
+	sis_vbflags = sis_vbflags & ~(CRT2_TV | CRT2_VGA);
+	if ((sis_vbflags & VB_VIDEOBRIDGE) /* XXX: && (pSiS->VBLCDFlags) */
+	    )
+	    sis_vbflags = sis_vbflags | CRT2_LCD;
+	else {
+	    sis_vbflags = sis_vbflags & ~(CRT2_LCD);
+	    if (sis_verbose > 0) {
+		printf
+		    ("[SiS] Can't force CRT2 to LCD, no panel detected\n");
+	    }
+	}
+	break;
+    case CRT2_VGA:
+	if (sis_vbflags & VB_LVDS) {
+	    if (sis_verbose > 0) {
+		printf("[SiS] LVDS does not support secondary VGA\n");
+	    }
+	    break;
+	}
+	if (sis_vbflags & (VB_301LV | VB_302LV)) {
+	    if (sis_verbose > 0) {
+		printf
+		    ("[SiS] SiS30xLV bridge does not support secondary VGA\n");
+	    }
+	    break;
+	}
+	sis_vbflags = sis_vbflags & ~(CRT2_TV | CRT2_LCD);
+	if (sis_vbflags & VB_VIDEOBRIDGE)
+	    sis_vbflags = sis_vbflags | CRT2_VGA;
+	else
+	    sis_vbflags = sis_vbflags & ~(CRT2_VGA);
+	break;
+    default:
+	sis_vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
+    }
+
+    /* CRT2 gamma correction?? */
+
+    /* other force modes: */
+    /*  have a 'force tv type' (svideo, composite, scart) option? */
+    /*  have a 'force crt1 type' (to turn it off, etc??) */
+
+    /* TW: Check if CRT1 used (or needed; this eg. if no CRT2 detected) */
+    if (sis_vbflags & VB_VIDEOBRIDGE) {
+
+	/* TW: No CRT2 output? Then we NEED CRT1!
+	 *     We also need CRT1 if depth = 8 and bridge=LVDS|630+301B
+	 */
+	if ((!(sis_vbflags & (CRT2_VGA | CRT2_LCD | CRT2_TV))) || (	/*(pScrn->bitsPerPixel == 8) && */
+								      ((sis_vbflags & (VB_LVDS | VB_CHRONTEL)) || ((sis_vga_engine == SIS_300_VGA) && (sis_vbflags & VB_301B))))) {
+	    sis_crt1_off = 0;
+	}
+	/* TW: No CRT2 output? Then we can't use hw overlay on CRT2 */
+	if (!(sis_vbflags & (CRT2_VGA | CRT2_LCD | CRT2_TV)))
+	    sis_overlay_on_crt1 = 1;
+
+    } else {			/* TW: no video bridge? */
+
+	/* Then we NEED CRT1... */
+	sis_crt1_off = 0;
+	/* ... and can't use CRT2 for overlay output */
+	sis_overlay_on_crt1 = 1;
+    }
+
+    /* tvstandard options ? */
+
+    // determine using CRT1 or CRT2?
+    /* -> NO dualhead right now... */
+    if (sis_vbflags & DISPTYPE_DISP2) {
+	if (sis_crt1_off) {
+	    sis_vbflags |= VB_DISPMODE_SINGLE;
+	    /* TW: No CRT1? Then we use the video overlay on CRT2 */
+	    sis_overlay_on_crt1 = 0;
+	} else			/* TW: CRT1 and CRT2 - mirror or dual head ----- */
+	    sis_vbflags |= (VB_DISPMODE_MIRROR | DISPTYPE_CRT1);
+    } else {			/* TW: CRT1 only ------------------------------- */
+	sis_vbflags |= (VB_DISPMODE_SINGLE | DISPTYPE_CRT1);
+    }
+
+    if (sis_verbose > 0) {
+	printf("[SiS] Using hardware overlay on CRT%d\n",
+	       sis_overlay_on_crt1 ? 1 : 2);
+    }
+
+}