1/* 2 * Video bridge detection and configuration for 300, 315 and 330 series 3 * 4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1) Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2) Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3) The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Author: Thomas Winischhofer <thomas@winischhofer.net> 29 * 30 */ 31 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36#include "sis.h" 37#define SIS_NEED_inSISREG 38#define SIS_NEED_inSISIDXREG 39#define SIS_NEED_outSISIDXREG 40#define SIS_NEED_orSISIDXREG 41#define SIS_NEED_andSISIDXREG 42#define SIS_NEED_setSISIDXREG 43#include "sis_regs.h" 44#include "sis_dac.h" 45 46void SISCRT1PreInit(ScrnInfoPtr pScrn); 47void SISLCDPreInit(ScrnInfoPtr pScrn, Bool quiet); 48void SISTVPreInit(ScrnInfoPtr pScrn, Bool quiet); 49void SISCRT2PreInit(ScrnInfoPtr pScrn, Bool quiet); 50Bool SISRedetectCRT2Type(ScrnInfoPtr pScrn); 51void SISSense30x(ScrnInfoPtr pScrn, Bool quiet); 52void SISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet); 53void SiSSetupPseudoPanel(ScrnInfoPtr pScrn); 54 55extern Bool SISDetermineLCDACap(ScrnInfoPtr pScrn); 56extern void SISSaveDetectedDevices(ScrnInfoPtr pScrn); 57extern void SISWaitRetraceCRT1(ScrnInfoPtr pScrn); 58extern UChar SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, UShort offset, UChar value); 59 60/* From init.c, init301.c ---- (use their data types) */ 61extern BOOLEAN SiS_GetPanelID(struct SiS_Private *SiS_Pr); 62extern unsigned short SiS_SenseLCDDDC(struct SiS_Private *SiS_Pr, SISPtr pSiS); 63extern unsigned short SiS_SenseVGA2DDC(struct SiS_Private *SiS_Pr, SISPtr pSiS); 64 65typedef struct _SiS_LCD_StStruct 66{ 67 ULong VBLCD_lcdflag; 68 UShort LCDwidth; 69 UShort LCDheight; 70} SiS_LCD_StStruct; 71 72static const SiS_LCD_StStruct SiS300_LCD_Type[]= 73{ 74 { VB_LCD_1024x768, 1024, 768 }, /* 0 - invalid */ 75 { VB_LCD_800x600, 800, 600 }, /* 1 */ 76 { VB_LCD_1024x768, 1024, 768 }, /* 2 */ 77 { VB_LCD_1280x1024,1280, 1024 }, /* 3 */ 78 { VB_LCD_1280x960, 1280, 960 }, /* 4 */ 79 { VB_LCD_640x480, 640, 480 }, /* 5 */ 80 { VB_LCD_1024x600, 1024, 600 }, /* 6 */ 81 { VB_LCD_1152x768, 1152, 768 }, /* 7 */ 82 { VB_LCD_1024x768, 1024, 768 }, /* 8 */ 83 { VB_LCD_1024x768, 1024, 768 }, /* 9 */ 84 { VB_LCD_1280x768, 1280, 768 }, /* a */ 85 { VB_LCD_1024x768, 1024, 768 }, /* b */ 86 { VB_LCD_1024x768, 1024, 768 }, /* c */ 87 { VB_LCD_1024x768, 1024, 768 }, /* d */ 88 { VB_LCD_320x480, 320, 480 }, /* e */ 89 { VB_LCD_CUSTOM, 0, 0 } /* f */ 90}; 91 92static const SiS_LCD_StStruct SiS315_LCD_Type[]= 93{ 94 { VB_LCD_1024x768, 1024, 768 }, /* 0 - invalid */ 95 { VB_LCD_800x600, 800, 600 }, /* 1 */ 96 { VB_LCD_1024x768, 1024, 768 }, /* 2 */ 97 { VB_LCD_1280x1024,1280, 1024 }, /* 3 */ 98 { VB_LCD_640x480, 640, 480 }, /* 4 */ 99 { VB_LCD_1024x600, 1024, 600 }, /* 5 */ 100 { VB_LCD_1152x864, 1152, 864 }, /* 6 */ 101 { VB_LCD_1280x960, 1280, 960 }, /* 7 */ 102 { VB_LCD_1152x768, 1152, 768 }, /* 8 */ 103 { VB_LCD_1400x1050,1400, 1050 }, /* 9 */ 104 { VB_LCD_1280x768, 1280, 768 }, /* a */ 105 { VB_LCD_1600x1200,1600, 1200 }, /* b */ 106 { VB_LCD_640x480_2, 640, 480 }, /* c FSTN */ 107 { VB_LCD_640x480_3, 640, 480 }, /* d FSTN */ 108 { VB_LCD_320x480, 320, 480 }, /* e */ 109 { VB_LCD_CUSTOM, 0, 0 } /* f */ 110}; 111 112static const SiS_LCD_StStruct SiS661_LCD_Type[]= 113{ 114 { VB_LCD_1024x768, 1024, 768 }, /* 0 - invalid */ 115 { VB_LCD_800x600, 800, 600 }, /* 1 */ 116 { VB_LCD_1024x768, 1024, 768 }, /* 2 */ 117 { VB_LCD_1280x1024,1280, 1024 }, /* 3 */ 118 { VB_LCD_640x480, 640, 480 }, /* 4 */ 119 { VB_LCD_1024x600, 1024, 600 }, /* 5 - temp */ 120 { VB_LCD_1152x864, 1152, 864 }, /* 6 - temp */ 121 { VB_LCD_1280x960, 1280, 960 }, /* 7 */ 122 { VB_LCD_1280x854, 1280, 854 }, /* 8 */ 123 { VB_LCD_1400x1050,1400, 1050 }, /* 9 */ 124 { VB_LCD_1280x768, 1280, 768 }, /* a */ 125 { VB_LCD_1600x1200,1600, 1200 }, /* b */ 126 { VB_LCD_1280x800, 1280, 800 }, /* c */ 127 { VB_LCD_1680x1050,1680, 1050 }, /* d */ 128 { VB_LCD_1280x720, 1280, 720 }, /* e */ 129 { VB_LCD_CUSTOM, 0, 0 } /* f */ 130}; 131 132static Bool 133TestDDC1(ScrnInfoPtr pScrn) 134{ 135 SISPtr pSiS = SISPTR(pScrn); 136 UShort old; 137 int count = 48; 138 139 old = SiS_ReadDDC1Bit(pSiS->SiS_Pr); 140 do { 141 if(old != SiS_ReadDDC1Bit(pSiS->SiS_Pr)) break; 142 } while(count--); 143 return (count == -1) ? FALSE : TRUE; 144} 145 146static int 147SiS_SISDetectCRT1(ScrnInfoPtr pScrn) 148{ 149 SISPtr pSiS = SISPTR(pScrn); 150 UShort temp = 0xffff; 151 UChar SR1F, CR63=0, CR17; 152 int i, ret = 0; 153 Bool mustwait = FALSE; 154 155 inSISIDXREG(SISSR,0x1F,SR1F); 156 setSISIDXREG(SISSR,0x1F,0x3f,0x04); 157 if(SR1F & 0xc0) mustwait = TRUE; 158 159 if(pSiS->VGAEngine == SIS_315_VGA) { 160 inSISIDXREG(SISCR,pSiS->myCR63,CR63); 161 CR63 &= 0x40; 162 andSISIDXREG(SISCR,pSiS->myCR63,0xbf); 163 } 164 165 inSISIDXREG(SISCR,0x17,CR17); 166 CR17 &= 0x80; 167 if(!CR17) { 168 orSISIDXREG(SISCR,0x17,0x80); 169 mustwait = TRUE; 170 outSISIDXREG(SISSR, 0x00, 0x01); 171 outSISIDXREG(SISSR, 0x00, 0x03); 172 } 173 174 if(mustwait) { 175 for(i=0; i < 10; i++) SISWaitRetraceCRT1(pScrn); 176 } 177 178 if(pSiS->ChipType >= SIS_330) { 179 int watchdog; 180 if(pSiS->ChipType >= SIS_340) { 181 outSISIDXREG(SISCR, 0x57, 0x4a); 182 } else { 183 outSISIDXREG(SISCR, 0x57, 0x5f); 184 } 185 orSISIDXREG(SISCR, 0x53, 0x02); 186 watchdog = 655360; 187 while((!((inSISREG(SISINPSTAT)) & 0x01)) && --watchdog); 188 watchdog = 655360; 189 while(((inSISREG(SISINPSTAT)) & 0x01) && --watchdog); 190 if((inSISREG(SISMISCW)) & 0x10) temp = 1; 191 andSISIDXREG(SISCR, 0x53, 0xfd); 192 outSISIDXREG(SISCR, 0x57, 0x00); 193#ifdef TWDEBUG 194 xf86DrvMsg(0, X_INFO, "330: Found CRT1: %s\n", (temp == 1) ? "yes" : "no"); 195#endif 196 } 197 198 if((temp == 0xffff) && (!pSiS->SiS_Pr->DDCPortMixup)) { 199 i = 3; 200 do { 201 temp = SiS_HandleDDC(pSiS->SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 0, 0, NULL, pSiS->VBFlags2); 202 } while(((temp == 0) || (temp == 0xffff)) && i--); 203 204 if((temp == 0) || (temp == 0xffff)) { 205 if(TestDDC1(pScrn)) temp = 1; 206 } 207 } 208 209 if((temp) && (temp != 0xffff)) { 210 orSISIDXREG(SISCR,0x32,0x20); 211 ret = 1; 212 } else if(pSiS->ChipType >= SIS_330) { 213 andSISIDXREG(SISCR,0x32,~0x20); 214 ret = 0; 215 } 216 217 if(pSiS->VGAEngine == SIS_315_VGA) { 218 setSISIDXREG(SISCR,pSiS->myCR63,0xBF,CR63); 219 } 220 221 setSISIDXREG(SISCR,0x17,0x7F,CR17); 222 223 outSISIDXREG(SISSR,0x1F,SR1F); 224 225 return ret; 226} 227 228/* Detect CRT1 */ 229void SISCRT1PreInit(ScrnInfoPtr pScrn) 230{ 231 SISPtr pSiS = SISPTR(pScrn); 232 UChar CR32; 233 UChar OtherDevices = 0; 234 235 pSiS->CRT1Detected = FALSE; 236 237 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) { 238 pSiS->CRT1Detected = TRUE; 239 pSiS->CRT1off = 0; 240 return; 241 } 242 243#ifdef SISDUALHEAD 244 if(pSiS->DualHeadMode) { 245 pSiS->CRT1Detected = TRUE; 246 pSiS->CRT1off = 0; 247 return; 248 } 249#endif 250 251#ifdef SISMERGED 252 if((pSiS->MergedFB) && (!(pSiS->MergedFBAuto))) { 253 pSiS->CRT1Detected = TRUE; 254 pSiS->CRT1off = 0; 255 return; 256 } 257#endif 258 259 inSISIDXREG(SISCR, 0x32, CR32); 260 261 if(pSiS->ChipType >= SIS_330) { 262 /* Works reliably on 330 and later */ 263 pSiS->CRT1Detected = SiS_SISDetectCRT1(pScrn); 264 } else { 265 if(CR32 & 0x20) pSiS->CRT1Detected = TRUE; 266 else pSiS->CRT1Detected = SiS_SISDetectCRT1(pScrn); 267 } 268 269 if(CR32 & 0x5F) OtherDevices = 1; 270 271 if(pSiS->CRT1off == -1) { 272 if(!pSiS->CRT1Detected) { 273 274 /* No CRT1 detected. */ 275 /* If other devices exist, switch it off */ 276 if(OtherDevices) pSiS->CRT1off = 1; 277 else pSiS->CRT1off = 0; 278 279 } else { 280 281 /* CRT1 detected, leave/switch it on */ 282 pSiS->CRT1off = 0; 283 284 } 285 } 286 287 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 288 "%sCRT1/VGA detected\n", 289 pSiS->CRT1Detected ? "" : "No "); 290} 291 292/* Detect CRT2-LCD and LCD size */ 293void SISLCDPreInit(ScrnInfoPtr pScrn, Bool quiet) 294{ 295 SISPtr pSiS = SISPTR(pScrn); 296 UChar CR32, CR36, CR37, CR7D=0, tmp; 297 298 pSiS->VBFlags &= ~(CRT2_LCD); 299 pSiS->VBLCDFlags = 0; 300 pSiS->LCDwidth = 0; 301 pSiS->LCDheight = 0; 302 303 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return; 304 305 inSISIDXREG(SISCR, 0x32, CR32); 306 307 if(CR32 & 0x08) pSiS->VBFlags |= CRT2_LCD; 308 309 /* If no panel has been detected by the BIOS during booting, 310 * we try to detect it ourselves at this point. We do that 311 * if forcecrt2redetection was given, too. 312 * This is useful on machines with DVI connectors where the 313 * panel was connected after booting. This is only supported 314 * on the 315/330 series and the 301/30xB/C bridge (because the 315 * 30xLV don't seem to have a DDC port and operate only LVDS 316 * panels which mostly don't support DDC). We only do this if 317 * there was no secondary VGA detected by the BIOS, because LCD 318 * and VGA2 share the same DDC channel and might be misdetected 319 * as the wrong type (especially if the LCD panel only supports 320 * EDID Version 1). 321 * Addendum: For DVI-I connected panels, this is not ideal. 322 * Therefore, we disregard an eventually detected secondary 323 * VGA if the user forced CRT2 type to LCD. 324 * 325 * By default, CRT2 redetection is forced since 12/09/2003, as 326 * I encountered numerous panels which deliver more or less 327 * bogus DDC data confusing the BIOS. Since our DDC detection 328 * is waaaay better, we prefer it instead of the primitive 329 * and buggy BIOS method. 330 * 331 */ 332#ifdef SISDUALHEAD 333 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 334#endif 335 if((pSiS->VGAEngine == SIS_315_VGA) && 336 (pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 337 (!(pSiS->VBFlags2 & VB2_30xBDH)) && 338 (pSiS->VESA != 1)) { 339 340 if(pSiS->forcecrt2redetection) { 341 pSiS->VBFlags &= ~CRT2_LCD; 342 /* Do NOT clear CR32[D3] here! */ 343 } 344 345 if(!(pSiS->nocrt2ddcdetection)) { 346 if((!(pSiS->VBFlags & CRT2_LCD)) && 347 ( (!(CR32 & 0x10)) || 348 (pSiS->ForceCRT2Type == CRT2_LCD) ) ) { 349 if(!quiet) { 350 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 351 "%s LCD/plasma panel, sensing via DDC\n", 352 pSiS->forcecrt2redetection ? 353 "(Re)-detecting" : "BIOS detected no"); 354 } 355 if(SiS_SenseLCDDDC(pSiS->SiS_Pr, pSiS)) { 356 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 357 "DDC error during LCD panel detection\n"); 358 } else { 359 inSISIDXREG(SISCR, 0x32, CR32); 360 if(CR32 & 0x08) { 361 pSiS->VBFlags |= CRT2_LCD; 362 pSiS->postVBCR32 |= 0x08; 363 } else { 364 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 365 "No LCD/plasma panel detected\n"); 366 } 367 } 368 } 369 } 370 371 } 372#ifdef SISDUALHEAD 373 } 374#endif 375 376 if(pSiS->VBFlags & CRT2_LCD) { 377 inSISIDXREG(SISCR, 0x36, CR36); 378 if(pSiS->VGAEngine == SIS_300_VGA) { 379 if(pSiS->VBFlags2 & VB2_301) { 380 if((CR36 & 0x0f) < 0x0f) CR36 &= 0xf7; 381 } 382 } 383 if(pSiS->PRGB != -1) { 384 tmp = 0x37; 385 if((pSiS->VGAEngine == SIS_315_VGA) && 386 (pSiS->ChipType < SIS_661) && 387 (pSiS->ROM661New) && 388 (!(pSiS->SiS_Pr->PanelSelfDetected))) { 389 tmp = 0x35; 390 } 391 if(pSiS->PRGB == 18) orSISIDXREG(SISCR, tmp, 0x01); 392 else if(pSiS->PRGB == 24) andSISIDXREG(SISCR, tmp, 0xfe); 393 } 394 inSISIDXREG(SISCR, 0x37, CR37); 395 if(pSiS->ChipType < SIS_661) { 396 inSISIDXREG(SISCR, 0x3C, CR7D); 397 } else { 398 inSISIDXREG(SISCR, 0x7D, CR7D); 399 } 400 if(pSiS->SiS_Pr->SiS_CustomT == CUT_BARCO1366) { 401 pSiS->VBLCDFlags |= VB_LCD_BARCO1366; 402 pSiS->LCDwidth = 1360; 403 pSiS->LCDheight = 1024; 404 if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 405 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 406 "Detected LCD panel (%dx%d, type %d, %sexpanding, RGB%d)\n", 407 pSiS->LCDwidth, pSiS->LCDheight, 408 ((CR36 & 0xf0) >> 4), 409 (CR37 & 0x10) ? "" : "non-", 410 (CR37 & 0x01) ? 18 : 24); 411 } else if(pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL848) { 412 pSiS->VBLCDFlags |= VB_LCD_848x480; 413 pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 848; 414 pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 480; 415 pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 416 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 417 "Assuming LCD/plasma panel (848x480, expanding, RGB24)\n"); 418 } else if(pSiS->SiS_Pr->SiS_CustomT == CUT_PANEL856) { 419 pSiS->VBLCDFlags |= VB_LCD_856x480; 420 pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 856; 421 pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 480; 422 pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 423 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 424 "Assuming LCD/plasma panel (856x480, expanding, RGB24)\n"); 425 } else if(pSiS->FSTN) { 426 pSiS->VBLCDFlags |= VB_LCD_320x240; 427 pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 320; 428 pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 240; 429 pSiS->VBLCDFlags &= ~VB_LCD_EXPANDING; 430 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 431 "Assuming FSTN LCD panel (320x240, non-expanding)\n"); 432 } else { 433 if(CR36 == 0) { 434 /* Old 650/301LV and ECS A907 BIOS versions "forget" to set CR36, CR37 */ 435 if(pSiS->VGAEngine == SIS_315_VGA) { 436 if(pSiS->ChipType < SIS_661) { 437 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 438 "BIOS provided invalid panel size, probing...\n"); 439 if(pSiS->VBFlags2 & VB2_LVDS) pSiS->SiS_Pr->SiS_IF_DEF_LVDS = 1; 440 else pSiS->SiS_Pr->SiS_IF_DEF_LVDS = 0; 441 SiS_GetPanelID(pSiS->SiS_Pr); 442 inSISIDXREG(SISCR, 0x36, CR36); 443 inSISIDXREG(SISCR, 0x37, CR37); 444 } else { 445 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 446 "Broken BIOS, unable to determine panel size, disabling LCD\n"); 447 pSiS->VBFlags &= ~CRT2_LCD; 448 return; 449 } 450 } else if(pSiS->VGAEngine == SIS_300_VGA) { 451 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 452 "BIOS provided invalid panel size, assuming 1024x768, RGB18\n"); 453 setSISIDXREG(SISCR,0x36,0xf0,0x02); 454 setSISIDXREG(SISCR,0x37,0xee,0x01); 455 CR36 = 0x02; 456 inSISIDXREG(SISCR,0x37,CR37); 457 } 458 } 459 if((CR36 & 0x0f) == 0x0f) { 460 pSiS->VBLCDFlags |= VB_LCD_CUSTOM; 461 pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY; 462 pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX; 463 if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 464 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 465 "Detected LCD/Plasma panel (max. X %d Y %d, pref. %dx%d, RGB%d)\n", 466 pSiS->SiS_Pr->CP_MaxX, pSiS->SiS_Pr->CP_MaxY, 467 pSiS->SiS_Pr->CP_PreferredX, pSiS->SiS_Pr->CP_PreferredY, 468 (CR37 & 0x01) ? 18 : 24); 469 } else { 470 if(pSiS->VGAEngine == SIS_300_VGA) { 471 pSiS->VBLCDFlags |= SiS300_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag; 472 pSiS->LCDheight = SiS300_LCD_Type[(CR36 & 0x0f)].LCDheight; 473 pSiS->LCDwidth = SiS300_LCD_Type[(CR36 & 0x0f)].LCDwidth; 474 if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 475 } else if((pSiS->ChipType >= SIS_661) || (pSiS->ROM661New)) { 476 pSiS->VBLCDFlags |= SiS661_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag; 477 pSiS->LCDheight = SiS661_LCD_Type[(CR36 & 0x0f)].LCDheight; 478 pSiS->LCDwidth = SiS661_LCD_Type[(CR36 & 0x0f)].LCDwidth; 479 if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 480 if(pSiS->ChipType < SIS_661) { 481 if(!(pSiS->SiS_Pr->PanelSelfDetected)) { 482 inSISIDXREG(SISCR,0x35,tmp); 483 CR37 &= 0xfc; 484 CR37 |= (tmp & 0x01); 485 } 486 } 487 } else { 488 pSiS->VBLCDFlags |= SiS315_LCD_Type[(CR36 & 0x0f)].VBLCD_lcdflag; 489 pSiS->LCDheight = SiS315_LCD_Type[(CR36 & 0x0f)].LCDheight; 490 pSiS->LCDwidth = SiS315_LCD_Type[(CR36 & 0x0f)].LCDwidth; 491 if(CR37 & 0x10) pSiS->VBLCDFlags |= VB_LCD_EXPANDING; 492 } 493 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 494 "Detected LCD/plasma panel (%dx%d, %d, %sexp., RGB%d [%02x%02x%02x])\n", 495 pSiS->LCDwidth, pSiS->LCDheight, 496 ((pSiS->VGAEngine == SIS_315_VGA) && (!pSiS->ROM661New)) ? 497 ((CR36 & 0x0f) - 1) : ((CR36 & 0xf0) >> 4), 498 (CR37 & 0x10) ? "" : "non-", 499 (CR37 & 0x01) ? 18 : 24, 500 CR36, CR37, CR7D); 501 } 502 } 503 } 504} 505 506void SiSSetupPseudoPanel(ScrnInfoPtr pScrn) 507{ 508 SISPtr pSiS = SISPTR(pScrn); 509 int i; 510 511 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 512 "No LCD detected, but forced to enable digital output\n"); 513 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 514 "Will not be able to properly filter display modes!\n"); 515 516 pSiS->VBFlags |= CRT2_LCD; 517 pSiS->SiS_Pr->SiS_CustomT = CUT_UNKNOWNLCD; 518 pSiS->SiS_Pr->CP_PrefClock = 0; 519 pSiS->SiS_Pr->CP_PreferredIndex = -1; 520 pSiS->VBLCDFlags |= (VB_LCD_UNKNOWN | VB_LCD_EXPANDING); 521 pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = 2048; 522 pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = 2048; 523 for(i=0; i<7; i++) pSiS->SiS_Pr->CP_DataValid[i] = FALSE; 524 pSiS->SiS_Pr->CP_HaveCustomData = FALSE; 525 pSiS->SiS_Pr->PanelSelfDetected = TRUE; 526 outSISIDXREG(SISCR,0x36,0x0f); 527 setSISIDXREG(SISCR,0x37,0x0e,0x10); 528 orSISIDXREG(SISCR,0x32,0x08); 529} 530 531/* Detect CRT2-TV connector type and PAL/NTSC flag */ 532void SISTVPreInit(ScrnInfoPtr pScrn, Bool quiet) 533{ 534 SISPtr pSiS = SISPTR(pScrn); 535 UChar SR16, SR38, CR32, CR35=0, CR38=0, CR79, CR39; 536 int temp = 0; 537 538 if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return; 539 540 inSISIDXREG(SISCR, 0x32, CR32); 541 inSISIDXREG(SISCR, 0x35, CR35); 542 inSISIDXREG(SISSR, 0x16, SR16); 543 inSISIDXREG(SISSR, 0x38, SR38); 544 switch(pSiS->VGAEngine) { 545 case SIS_300_VGA: 546 if(pSiS->Chipset == PCI_CHIP_SIS630) temp = 0x35; 547 break; 548 case SIS_315_VGA: 549 temp = 0x38; 550 break; 551 } 552 if(temp) { 553 inSISIDXREG(SISCR, temp, CR38); 554 } 555 556#ifdef TWDEBUG 557 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 558 "(vb.c: SISTVPreInit 1: CR32=%02x SR16=%02x SR38=%02x VBFlags 0x%x)\n", 559 CR32, SR16, SR38, pSiS->VBFlags); 560#endif 561 562 if(CR32 & 0x47) pSiS->VBFlags |= CRT2_TV; 563 564 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 565 if(CR32 & 0x80) pSiS->VBFlags |= CRT2_TV; 566 } else { 567 CR32 &= 0x7f; 568 } 569 570 if(CR32 & 0x01) 571 pSiS->VBFlags |= TV_AVIDEO; 572 else if(CR32 & 0x02) 573 pSiS->VBFlags |= TV_SVIDEO; 574 else if(CR32 & 0x04) 575 pSiS->VBFlags |= TV_SCART; 576 else if((CR32 & 0x40) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) 577 pSiS->VBFlags |= (TV_HIVISION | TV_PAL); 578 else if((CR32 & 0x80) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) { 579 pSiS->VBFlags |= TV_YPBPR; 580 if(pSiS->NewCRLayout) { 581 if(CR38 & 0x04) { 582 switch(CR35 & 0xE0) { 583 case 0x20: pSiS->VBFlags |= TV_YPBPR525P; break; 584 case 0x40: pSiS->VBFlags |= TV_YPBPR750P; break; 585 case 0x60: pSiS->VBFlags |= TV_YPBPR1080I; break; 586 default: pSiS->VBFlags |= TV_YPBPR525I; 587 } 588 } else pSiS->VBFlags |= TV_YPBPR525I; 589 inSISIDXREG(SISCR,0x39,CR39); 590 CR39 &= 0x03; 591 if(CR39 == 0x00) pSiS->VBFlags |= TV_YPBPR43LB; 592 else if(CR39 == 0x01) pSiS->VBFlags |= TV_YPBPR43; 593 else if(CR39 == 0x02) pSiS->VBFlags |= TV_YPBPR169; 594 else pSiS->VBFlags |= TV_YPBPR43; 595 } else if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR) { 596 if(CR38 & 0x08) { 597 switch(CR38 & 0x30) { 598 case 0x10: pSiS->VBFlags |= TV_YPBPR525P; break; 599 case 0x20: pSiS->VBFlags |= TV_YPBPR750P; break; 600 case 0x30: pSiS->VBFlags |= TV_YPBPR1080I; break; 601 default: pSiS->VBFlags |= TV_YPBPR525I; 602 } 603 } else pSiS->VBFlags |= TV_YPBPR525I; 604 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPRAR) { 605 inSISIDXREG(SISCR,0x3B,CR39); 606 CR39 &= 0x03; 607 if(CR39 == 0x00) pSiS->VBFlags |= TV_YPBPR43LB; 608 else if(CR39 == 0x01) pSiS->VBFlags |= TV_YPBPR169; 609 else if(CR39 == 0x03) pSiS->VBFlags |= TV_YPBPR43; 610 } 611 } 612 } else if((CR38 & 0x04) && (pSiS->VBFlags2 & VB2_CHRONTEL)) 613 pSiS->VBFlags |= (TV_CHSCART | TV_PAL); 614 else if((CR38 & 0x08) && (pSiS->VBFlags2 & VB2_CHRONTEL)) 615 pSiS->VBFlags |= (TV_CHYPBPR525I | TV_NTSC); 616 617 if(pSiS->VBFlags & (TV_SCART | TV_SVIDEO | TV_AVIDEO)) { 618 if(pSiS->VGAEngine == SIS_300_VGA) { 619 /* Should be SR38, but this does not work. */ 620 if(SR16 & 0x20) 621 pSiS->VBFlags |= TV_PAL; 622 else 623 pSiS->VBFlags |= TV_NTSC; 624 } else if(pSiS->Chipset == PCI_CHIP_SIS550) { 625 inSISIDXREG(SISCR, 0x7a, CR79); 626 if(CR79 & 0x08) { 627 inSISIDXREG(SISCR, 0x79, CR79); 628 CR79 >>= 5; 629 } 630 if(CR79 & 0x01) { 631 pSiS->VBFlags |= TV_PAL; 632 if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM; 633 else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN; 634 } else 635 pSiS->VBFlags |= TV_NTSC; 636 } else if(pSiS->Chipset == PCI_CHIP_SIS650) { 637 inSISIDXREG(SISCR, 0x79, CR79); 638 if(CR79 & 0x20) { 639 pSiS->VBFlags |= TV_PAL; 640 if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM; 641 else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN; 642 } else 643 pSiS->VBFlags |= TV_NTSC; 644 } else if(pSiS->NewCRLayout) { 645 if(SR38 & 0x01) { 646 pSiS->VBFlags |= TV_PAL; 647 if(CR35 & 0x04) pSiS->VBFlags |= TV_PALM; 648 else if(CR35 & 0x08) pSiS->VBFlags |= TV_PALN; 649 } else { 650 pSiS->VBFlags |= TV_NTSC; 651 if(CR35 & 0x02) pSiS->VBFlags |= TV_NTSCJ; 652 } 653 } else { /* 315, 330 */ 654 if(SR38 & 0x01) { 655 pSiS->VBFlags |= TV_PAL; 656 if(CR38 & 0x40) pSiS->VBFlags |= TV_PALM; 657 else if(CR38 & 0x80) pSiS->VBFlags |= TV_PALN; 658 } else 659 pSiS->VBFlags |= TV_NTSC; 660 } 661 } 662 663#ifdef TWDEBUG 664 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 665 "(vb.c: SISTVPreInit 2: VBFlags 0x%x)\n", pSiS->VBFlags); 666#endif 667 668 if((pSiS->VBFlags & (TV_SCART|TV_SVIDEO|TV_AVIDEO)) && !quiet) { 669 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected default TV standard %s\n", 670 (pSiS->VBFlags & TV_NTSC) ? 671 ((pSiS->VBFlags & TV_NTSCJ) ? "NTSCJ" : "NTSC") : 672 ((pSiS->VBFlags & TV_PALM) ? "PALM" : 673 ((pSiS->VBFlags & TV_PALN) ? "PALN" : "PAL"))); 674 } 675 676 if((pSiS->VBFlags & TV_HIVISION) && !quiet) { 677 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "BIOS reports HiVision TV\n"); 678 } 679 680 if((pSiS->VBFlags2 & VB2_CHRONTEL) && (pSiS->VBFlags & (TV_CHSCART|TV_CHYPBPR525I)) && !quiet) { 681 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chrontel: %s forced\n", 682 (pSiS->VBFlags & TV_CHSCART) ? "SCART (PAL)" : "YPbPr (480i)"); 683 } 684 685 if((pSiS->VBFlags & TV_YPBPR) && !quiet) { 686 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected YPbPr TV (by default %s)\n", 687 (pSiS->VBFlags & TV_YPBPR525I) ? "480i" : 688 ((pSiS->VBFlags & TV_YPBPR525P) ? "480p" : 689 ((pSiS->VBFlags & TV_YPBPR750P) ? "720p" : "1080i"))); 690 } 691} 692 693/* Detect CRT2-VGA */ 694void SISCRT2PreInit(ScrnInfoPtr pScrn, Bool quiet) 695{ 696 SISPtr pSiS = SISPTR(pScrn); 697 UChar CR32; 698 699 /* CRT2-VGA only supported on these bridges */ 700 if(!(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) 701 return; 702 703 inSISIDXREG(SISCR, 0x32, CR32); 704 705 if(CR32 & 0x10) pSiS->VBFlags |= CRT2_VGA; 706 707 /* See the comment in initextx.c/SiS_SenseVGA2DDC() */ 708 if(pSiS->SiS_Pr->DDCPortMixup) return; 709 710#ifdef SISDUALHEAD 711 if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) { 712#endif 713 714 if(pSiS->forcecrt2redetection) { 715 pSiS->VBFlags &= ~CRT2_VGA; 716 } 717 718 /* We don't trust the normal sensing method for VGA2 since 719 * it is performed by the BIOS during POST, and it is 720 * impossible to sense VGA2 if the bridge is disabled. 721 * Therefore, we try sensing VGA2 by DDC as well (if not 722 * detected otherwise and only if there is no LCD panel 723 * which is prone to be misdetected as a secondary VGA) 724 */ 725 if(!(pSiS->nocrt2ddcdetection)) { 726 if(!(pSiS->VBFlags & (CRT2_VGA | CRT2_LCD))) { 727 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 728 "%s secondary VGA, sensing via DDC\n", 729 pSiS->forcecrt2redetection ? 730 "Forced re-detection of" : "BIOS detected no"); 731 if(SiS_SenseVGA2DDC(pSiS->SiS_Pr, pSiS)) { 732 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 733 "DDC error during secondary VGA detection\n"); 734 } else { 735 inSISIDXREG(SISCR, 0x32, CR32); 736 if(CR32 & 0x10) { 737 pSiS->VBFlags |= CRT2_VGA; 738 pSiS->postVBCR32 |= 0x10; 739 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 740 "Detected secondary VGA connection\n"); 741 } else { 742 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 743 "No secondary VGA connection detected\n"); 744 } 745 } 746 } 747 } 748#ifdef SISDUALHEAD 749 } 750#endif 751} 752 753static int 754SISDoSense(ScrnInfoPtr pScrn, UShort type, UShort test) 755{ 756 SISPtr pSiS = SISPTR(pScrn); 757 int temp, mytest, result, i, j; 758 759#ifdef TWDEBUG 760 xf86DrvMsg(0, X_INFO, "Sense: %x %x\n", type, test); 761#endif 762 763 for(j = 0; j < 10; j++) { 764 result = 0; 765 for(i = 0; i < 3; i++) { 766 mytest = test; 767 outSISIDXREG(SISPART4,0x11,(type & 0x00ff)); 768 temp = (type >> 8) | (mytest & 0x00ff); 769 setSISIDXREG(SISPART4,0x10,0xe0,temp); 770 SiS_DDC2Delay(pSiS->SiS_Pr, 0x1500); 771 mytest >>= 8; 772 mytest &= 0x7f; 773 inSISIDXREG(SISPART4,0x03,temp); 774 temp ^= 0x0e; 775 temp &= mytest; 776 if(temp == mytest) result++; 777#if 1 778 outSISIDXREG(SISPART4,0x11,0x00); 779 andSISIDXREG(SISPART4,0x10,0xe0); 780 SiS_DDC2Delay(pSiS->SiS_Pr, 0x1000); 781#endif 782 } 783 if((result == 0) || (result >= 2)) break; 784 } 785 return(result); 786} 787 788#define GETROMWORD(w) (pSiS->BIOS[w] | (pSiS->BIOS[w+1] << 8)) 789 790/* Sense connected devices on 30x */ 791void 792SISSense30x(ScrnInfoPtr pScrn, Bool quiet) 793{ 794 SISPtr pSiS = SISPTR(pScrn); 795 UChar backupP4_0d, backupP2_00, backupP2_4d, backupSR_1e, biosflag=0; 796 UShort svhs=0, svhs_c=0; 797 UShort cvbs=0, cvbs_c=0; 798 UShort vga2=0, vga2_c=0; 799 int myflag, result; /* , i; */ 800 801 if(!(pSiS->VBFlags2 & VB2_SISBRIDGE)) return; 802 803#ifdef TWDEBUG 804 inSISIDXREG(SISCR,0x32,backupP2_4d); 805 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 806 "(vb.c: SISSense30c 1: CR32=%02x, VBFlags 0x%x)\n", backupP2_4d, pSiS->VBFlags); 807#endif 808 809 if(pSiS->VBFlags2 & VB2_301) { 810 svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1; 811 inSISIDXREG(SISPART4,0x01,myflag); 812 if(myflag & 0x04) { 813 svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd; 814 } 815 } else if(pSiS->VBFlags2 & (VB2_301B | VB2_302B)) { 816 svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190; 817 } else if(pSiS->VBFlags2 & (VB2_301LV | VB2_302LV)) { 818 svhs = 0x0200; cvbs = 0x0100; 819 } else if(pSiS->VBFlags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) { 820 svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190; 821 } else return; 822 823 vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804; 824 if(pSiS->VBFlags2 & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) { 825 svhs_c = 0x0408; cvbs_c = 0x0808; 826 } 827 biosflag = 2; 828 829 if(pSiS->Chipset == PCI_CHIP_SIS300) { 830 inSISIDXREG(SISSR,0x3b,myflag); 831 if(!(myflag & 0x01)) vga2 = vga2_c = 0; 832 } 833 834 if(pSiS->SiS_Pr->UseROM) { 835 if(pSiS->VGAEngine == SIS_300_VGA) { 836 if(pSiS->VBFlags2 & VB2_301) { 837 inSISIDXREG(SISPART4,0x01,myflag); 838 if(!(myflag & 0x04)) { 839 vga2 = GETROMWORD(0xf8); svhs = GETROMWORD(0xfa); cvbs = GETROMWORD(0xfc); 840 } 841 } 842 biosflag = pSiS->BIOS[0xfe]; 843 } else if((pSiS->Chipset == PCI_CHIP_SIS660) || 844 (pSiS->Chipset == PCI_CHIP_SIS340)) { 845 if(pSiS->ROM661New) { 846 biosflag = 2; 847 vga2 = GETROMWORD(0x63); 848 if(pSiS->BIOS[0x6f] & 0x01) { 849 if(pSiS->VBFlags2 & VB2_SISUMC) vga2 = GETROMWORD(0x4d); 850 } 851 svhs = cvbs = GETROMWORD(0x65); 852 if(pSiS->BIOS[0x5d] & 0x04) biosflag |= 0x01; 853 } 854 } 855 /* No "else", some BIOSes carry wrong data */ 856 } 857 858 if(pSiS->ChipType >= XGI_20) { 859 if(pSiS->HaveXGIBIOS) { 860 biosflag = pSiS->BIOS[0x58] & 0x03; 861 } else { 862 /* These boards have a s-video connector, but its 863 * pins are routed both the bridge's composite and 864 * svideo pins. This is for using the S-video plug 865 * for YPbPr output. Anyway, since a svideo connected 866 * TV would also been detected as a composite connected 867 * one, we don't check for composite if svideo is 868 * detected. 869 */ 870 biosflag &= ~0x02; 871 } 872 } 873 874 if(!(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE)) { 875 vga2 = vga2_c = 0; 876 } 877 878 inSISIDXREG(SISSR,0x1e,backupSR_1e); 879 orSISIDXREG(SISSR,0x1e,0x20); 880 881 inSISIDXREG(SISPART4,0x0d,backupP4_0d); 882 if(pSiS->VBFlags2 & VB2_30xCLV) { 883 setSISIDXREG(SISPART4,0x0d,~0x07,0x01); 884 } else { 885 orSISIDXREG(SISPART4,0x0d,0x04); 886 } 887 SiS_DDC2Delay(pSiS->SiS_Pr, 0x2000); 888 889 inSISIDXREG(SISPART2,0x00,backupP2_00); 890 outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc)); 891 892 inSISIDXREG(SISPART2,0x4d,backupP2_4d); 893 if(pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE) { 894 outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10)); 895 } 896 897 if(!(pSiS->VBFlags2 & VB2_30xCLV)) { 898 SISDoSense(pScrn, 0, 0); 899 } 900 901 andSISIDXREG(SISCR, 0x32, ~0x14); 902 pSiS->postVBCR32 &= ~0x14; 903 904 if(vga2_c || vga2) { 905 if(SISDoSense(pScrn, vga2, vga2_c)) { 906 if(biosflag & 0x01) { 907 if(!quiet) { 908 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 909 "SiS30x: Detected TV connected to SCART output\n"); 910 } 911 pSiS->VBFlags |= TV_SCART; 912 orSISIDXREG(SISCR, 0x32, 0x04); 913 pSiS->postVBCR32 |= 0x04; 914 } else { 915 if(!quiet) { 916 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 917 "SiS30x: Detected secondary VGA connection\n"); 918 } 919 pSiS->VBFlags |= VGA2_CONNECTED; 920 orSISIDXREG(SISCR, 0x32, 0x10); 921 pSiS->postVBCR32 |= 0x10; 922 } 923 } 924 if(biosflag & 0x01) pSiS->SiS_SD_Flags |= SiS_SD_VBHASSCART; 925 } 926 927 andSISIDXREG(SISCR, 0x32, 0x3f); 928 pSiS->postVBCR32 &= 0x3f; 929 930 if(pSiS->VBFlags2 & VB2_30xCLV) { 931 orSISIDXREG(SISPART4,0x0d,0x04); 932 } 933 934 if((pSiS->VGAEngine == SIS_315_VGA) && (pSiS->VBFlags2 & VB2_SISYPBPRBRIDGE)) { 935 if(pSiS->SenseYPbPr) { 936 outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10)); 937 SiS_DDC2Delay(pSiS->SiS_Pr, 0x2000); 938 /* New BIOS (2.x) uses vga2 sensing here for all bridges >301LV */ 939 if((result = SISDoSense(pScrn, svhs, 0x0604))) { 940 if((result = SISDoSense(pScrn, cvbs, 0x0804))) { 941 if(!quiet) { 942 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 943 "SiS30x: Detected TV connected to YPbPr component output\n"); 944 } 945 orSISIDXREG(SISCR,0x32,0x80); 946 pSiS->VBFlags |= TV_YPBPR; 947 pSiS->postVBCR32 |= 0x80; 948 } 949 } 950 outSISIDXREG(SISPART2,0x4d,backupP2_4d); 951 } 952 } 953 954 andSISIDXREG(SISCR, 0x32, ~0x03); 955 pSiS->postVBCR32 &= ~0x03; 956 957 if(!(pSiS->VBFlags & TV_YPBPR)) { 958 959 if((result = SISDoSense(pScrn, svhs, svhs_c))) { 960 if(!quiet) { 961 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 962 "SiS30x: Detected TV connected to SVIDEO output\n"); 963 } 964 pSiS->VBFlags |= TV_SVIDEO; 965 orSISIDXREG(SISCR, 0x32, 0x02); 966 pSiS->postVBCR32 |= 0x02; 967 } 968 969 if((biosflag & 0x02) || (!result)) { 970 if(SISDoSense(pScrn, cvbs, cvbs_c)) { 971 if(!quiet) { 972 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 973 "SiS30x: Detected TV connected to COMPOSITE output\n"); 974 } 975 pSiS->VBFlags |= TV_AVIDEO; 976 orSISIDXREG(SISCR, 0x32, 0x01); 977 pSiS->postVBCR32 |= 0x01; 978 } 979 } 980 981 } 982 983 SISDoSense(pScrn, 0, 0); 984 985 outSISIDXREG(SISPART2,0x00,backupP2_00); 986 outSISIDXREG(SISPART4,0x0d,backupP4_0d); 987 outSISIDXREG(SISSR,0x1e,backupSR_1e); 988 989 if(pSiS->VBFlags2 & VB2_30xCLV) { 990 inSISIDXREG(SISPART2,0x00,biosflag); 991 if(biosflag & 0x20) { 992 for(myflag = 2; myflag > 0; myflag--) { 993 biosflag ^= 0x20; 994 outSISIDXREG(SISPART2,0x00,biosflag); 995 } 996 } 997 } 998 999 outSISIDXREG(SISPART2,0x00,backupP2_00); 1000 1001#ifdef TWDEBUG 1002 inSISIDXREG(SISCR,0x32,backupP2_4d); 1003 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1004 "(vb.c: SISSense30c 2: CR32=0x%02x, VBFlags 0x%x)\n", backupP2_4d, pSiS->VBFlags); 1005#endif 1006} 1007 1008void 1009SISSenseChrontel(ScrnInfoPtr pScrn, Bool quiet) 1010{ 1011 SISPtr pSiS = SISPTR(pScrn); 1012 int temp1=0, temp2, i; 1013 UChar test[3]; 1014 1015 if(pSiS->SiS_Pr->SiS_IF_DEF_CH70xx == 1) { 1016 1017 /* Chrontel 700x */ 1018 1019 /* Read power status */ 1020 temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x0e); /* Power status */ 1021 if((temp1 & 0x03) != 0x03) { 1022 /* Power all outputs */ 1023 SiS_SetCH700x(pSiS->SiS_Pr, 0x0e,0x0b); 1024 SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 1025 } 1026 /* Sense connected TV devices */ 1027 for(i = 0; i < 3; i++) { 1028 SiS_SetCH700x(pSiS->SiS_Pr, 0x10, 0x01); 1029 SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 1030 SiS_SetCH700x(pSiS->SiS_Pr, 0x10, 0x00); 1031 SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 1032 temp1 = SiS_GetCH700x(pSiS->SiS_Pr, 0x10); 1033 if(!(temp1 & 0x08)) test[i] = 0x02; 1034 else if(!(temp1 & 0x02)) test[i] = 0x01; 1035 else test[i] = 0; 1036 SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 1037 } 1038 1039 if(test[0] == test[1]) temp1 = test[0]; 1040 else if(test[0] == test[2]) temp1 = test[0]; 1041 else if(test[1] == test[2]) temp1 = test[1]; 1042 else { 1043 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1044 "Chrontel: TV detection unreliable - test results varied\n"); 1045 temp1 = test[2]; 1046 } 1047 1048 } else if(pSiS->SiS_Pr->SiS_IF_DEF_CH70xx == 2) { 1049 1050 /* Chrontel 701x */ 1051 1052 /* Backup Power register */ 1053 temp1 = SiS_GetCH701x(pSiS->SiS_Pr, 0x49); 1054 1055 /* Enable TV path */ 1056 SiS_SetCH701x(pSiS->SiS_Pr, 0x49, 0x20); 1057 1058 SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 1059 1060 /* Sense connected TV devices */ 1061 temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20); 1062 temp2 |= 0x01; 1063 SiS_SetCH701x(pSiS->SiS_Pr, 0x20, temp2); 1064 1065 SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 1066 1067 temp2 ^= 0x01; 1068 SiS_SetCH701x(pSiS->SiS_Pr, 0x20, temp2); 1069 1070 SiS_DDC2Delay(pSiS->SiS_Pr, 0x96); 1071 1072 temp2 = SiS_GetCH701x(pSiS->SiS_Pr, 0x20); 1073 1074 /* Restore Power register */ 1075 SiS_SetCH701x(pSiS->SiS_Pr, 0x49, temp1); 1076 1077 temp1 = 0; 1078 if(temp2 & 0x02) temp1 |= 0x01; 1079 if(temp2 & 0x10) temp1 |= 0x01; 1080 if(temp2 & 0x04) temp1 |= 0x02; 1081 1082 if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04; 1083 1084 } 1085 1086 switch(temp1) { 1087 case 0x01: 1088 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1089 "Chrontel: Detected TV connected to COMPOSITE output\n"); 1090 pSiS->VBFlags |= TV_AVIDEO; 1091 orSISIDXREG(SISCR, 0x32, 0x01); 1092 andSISIDXREG(SISCR, 0x32, ~0x06); 1093 pSiS->postVBCR32 |= 0x01; 1094 pSiS->postVBCR32 &= ~0x06; 1095 break; 1096 case 0x02: 1097 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1098 "Chrontel: Detected TV connected to SVIDEO output\n"); 1099 pSiS->VBFlags |= TV_SVIDEO; 1100 orSISIDXREG(SISCR, 0x32, 0x02); 1101 andSISIDXREG(SISCR, 0x32, ~0x05); 1102 pSiS->postVBCR32 |= 0x02; 1103 pSiS->postVBCR32 &= ~0x05; 1104 break; 1105 case 0x04: 1106 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1107 "Chrontel: Detected TV connected to SCART or YPBPR output\n"); 1108 if(pSiS->chtvtype == -1) { 1109 if(!quiet) { 1110 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1111 "Chrontel: Use CHTVType option to select either SCART or YPBPR525I\n"); 1112 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1113 "Chrontel: Using SCART by default\n"); 1114 } 1115 pSiS->chtvtype = 1; 1116 } 1117 if(pSiS->chtvtype) 1118 pSiS->VBFlags |= TV_CHSCART; 1119 else 1120 pSiS->VBFlags |= TV_CHYPBPR525I; 1121 break; 1122 default: 1123 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1124 "Chrontel: No TV detected.\n"); 1125 andSISIDXREG(SISCR, 0x32, ~0x07); 1126 pSiS->postVBCR32 &= ~0x07; 1127 } 1128} 1129 1130/* Redetect CRT2 devices. Calling this requires a reset 1131 * of the current display mode if TRUE is returned. 1132 */ 1133Bool SISRedetectCRT2Type(ScrnInfoPtr pScrn) 1134{ 1135 SISPtr pSiS = SISPTR(pScrn); 1136 ULong VBFlagsBackup = pSiS->VBFlags; 1137 Bool backup1 = pSiS->forcecrt2redetection; 1138 Bool backup2 = pSiS->nocrt2ddcdetection; 1139 1140#ifdef SISDUALHEAD 1141 if(pSiS->DualHeadMode) return FALSE; 1142#endif 1143 1144 pSiS->VBFlags &= ~(CRT2_DEFAULT | 1145 CRT2_ENABLE | 1146 TV_STANDARD | 1147 TV_INTERFACE | 1148 TV_YPBPRALL | 1149 TV_YPBPRAR | 1150 TV_CHSCART | 1151 TV_CHYPBPR525I | 1152 CRT1_LCDA | 1153 DISPTYPE_CRT1); 1154 1155 /* At first, re-do the sensing for TV and VGA2 */ 1156 if(pSiS->VBFlags2 & VB2_SISBRIDGE) { 1157 SISSense30x(pScrn, TRUE); 1158 } else if(pSiS->VBFlags2 & VB2_CHRONTEL) { 1159 SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x9c); 1160 SISSenseChrontel(pScrn, TRUE); 1161 SiS_SetChrontelGPIO(pSiS->SiS_Pr, 0x00); 1162 } 1163 1164 SISTVPreInit(pScrn, TRUE); 1165 1166 pSiS->forcecrt2redetection = TRUE; 1167 pSiS->nocrt2ddcdetection = FALSE; 1168 1169 /* We only re-detect LCD for the TMDS-SiS-bridges. LVDS 1170 * is practically never being hot-plugged (and even if, 1171 * there is no way of detecting this). 1172 */ 1173 if((pSiS->VGAEngine == SIS_315_VGA) && 1174 (pSiS->VBFlags2 & VB2_SISTMDSBRIDGE) && 1175 (!(pSiS->VBFlags2 & VB2_30xBDH)) && 1176 (pSiS->VESA != 1) && 1177 (pSiS->SiS_Pr->SiS_CustomT != CUT_UNKNOWNLCD)) { 1178 SISLCDPreInit(pScrn, TRUE); 1179 } else { 1180 pSiS->VBFlags |= (pSiS->detectedCRT2Devices & CRT2_LCD); 1181 } 1182 1183 /* Secondary VGA is only supported on these bridges: */ 1184 if(pSiS->VBFlags2 & VB2_SISVGA2BRIDGE) { 1185 SISCRT2PreInit(pScrn, TRUE); 1186 } 1187 1188 pSiS->forcecrt2redetection = backup1; 1189 pSiS->nocrt2ddcdetection = backup2; 1190 1191 pSiS->SiS_SD_Flags &= ~SiS_SD_SUPPORTLCDA; 1192 if(SISDetermineLCDACap(pScrn)) { 1193 pSiS->SiS_SD_Flags |= SiS_SD_SUPPORTLCDA; 1194 } 1195 SISSaveDetectedDevices(pScrn); 1196 1197 pSiS->VBFlags = VBFlagsBackup; 1198 1199 /* If LCD disappeared, don't use it and don't advertise LCDA support. Duh! */ 1200 if(!(pSiS->detectedCRT2Devices & CRT2_LCD)) { 1201 pSiS->SiS_SD_Flags &= ~(SiS_SD_SUPPORTLCDA); 1202 if(pSiS->VBFlags & CRT2_LCD) { 1203 /* If CRT2 was LCD, disable CRT2 and adapt display mode flags */ 1204 pSiS->VBFlags &= ~(CRT2_LCD | DISPLAY_MODE); 1205 /* Switch on CRT1 as an emergency measure */ 1206 pSiS->VBFlags |= (SINGLE_MODE | DISPTYPE_CRT1); 1207 pSiS->CRT1off = 0; 1208 } 1209 /* If CRT1 was LCD, switch to CRT1-VGA. No need to adapt display mode flags. */ 1210 pSiS->VBFlags &= ~(CRT1_LCDA); 1211 pSiS->VBFlags_backup = pSiS->VBFlags; 1212 } 1213 1214 pSiS->VBFlagsInit = pSiS->VBFlags; 1215 1216 /* Save new detection result registers to write them back in EnterVT() */ 1217 inSISIDXREG(SISCR,0x32,pSiS->myCR32); 1218 inSISIDXREG(SISCR,0x36,pSiS->myCR36); 1219 inSISIDXREG(SISCR,0x37,pSiS->myCR37); 1220 1221 return TRUE; 1222} 1223 1224 1225