1/* 2 * Video bridge detection and configuration for 300, 315 and 330 series 3 * 4 * Copyright (C) 2001-2004 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 EXPRESSED 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 "xf86.h" 37#include "compiler.h" 38#include "xf86PciInfo.h" 39 40#include "xgi.h" 41#include "xgi_regs.h" 42#include "xgi_vb.h" 43#include "xgi_dac.h" 44#include "vb_def.h" 45 46extern unsigned char XGI_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, unsigned char value); 47 48static Bool 49TestDDC1(ScrnInfoPtr pScrn) 50{ 51/* XGIPtr pXGI = XGIPTR(pScrn); 52 unsigned short old; */ 53 int count = 48; 54/* 55 old = XGI_ReadDDC1Bit(pXGI->XGI_Pr); 56 do { 57 if(old != XGI_ReadDDC1Bit(pXGI->XGI_Pr)) break; 58 } while(count--); 59*/ 60 return (count == -1) ? FALSE : TRUE; 61} 62 63static int 64XGI_XGIDetectCRT1(ScrnInfoPtr pScrn) 65{ 66 XGIPtr pXGI = XGIPTR(pScrn); 67 unsigned short temp = 0xffff; 68 unsigned char SR1F, CR17; 69 int i, ret = 0; 70 Bool mustwait = FALSE; 71 72 inXGIIDXREG(XGISR,0x1F,SR1F); 73 orXGIIDXREG(XGISR,0x1F,0x04); 74 andXGIIDXREG(XGISR,0x1F,0x3F); 75 if(SR1F & 0xc0) mustwait = TRUE; 76 77 inXGIIDXREG(XGICR,0x17,CR17); 78 CR17 &= 0x80; 79 if(!CR17) { 80 orXGIIDXREG(XGICR,0x17,0x80); 81 mustwait = TRUE; 82 outXGIIDXREG(XGISR, 0x00, 0x01); 83 outXGIIDXREG(XGISR, 0x00, 0x03); 84 } 85 86 if(mustwait) { 87 for(i=0; i < 10; i++) XGI_WaitBeginRetrace(pXGI->RelIO); 88 } 89 90 if((temp == 0) || (temp == 0xffff)) { 91 if(TestDDC1(pScrn)) temp = 1; 92 } 93 94 if((temp) && (temp != 0xffff)) { 95 orXGIIDXREG(XGICR,0x32,0x20); 96 ret = 1; 97 } 98 99 setXGIIDXREG(XGICR,0x17,0x7F,CR17); 100 101 outXGIIDXREG(XGISR,0x1F,SR1F); 102 103 return ret; 104} 105 106/* Detect CRT1 */ 107void XGICRT1PreInit(ScrnInfoPtr pScrn) 108{ 109 XGIPtr pXGI = XGIPTR(pScrn); 110 unsigned char CR32; 111 unsigned char CRT1Detected; 112 113 if (!(pXGI->XGI_Pr->VBType & VB_XGIVB) || IS_DUAL_HEAD(pXGI) 114#ifdef XGIMERGED 115 || ((pXGI->MergedFB) && (!(pXGI->MergedFBAuto))) 116#endif 117 ) { 118 pXGI->CRT1off = 0; 119 return; 120 } 121 122 inXGIIDXREG(XGICR, 0x32, CR32); 123 124 CRT1Detected = (CR32 & 0x20) ? 1 : XGI_XGIDetectCRT1(pScrn); 125 126 if (pXGI->CRT1off == -1) { 127 const int OtherDevices = ((CR32 & 0x5F) != 0); 128 129 /* If no CRT1 detected and other devices exist, switch CRT1 off. 130 * Otherwise, switch it on. 131 */ 132 pXGI->CRT1off = (!CRT1Detected && OtherDevices) ? 1 : 0; 133 } 134 135 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 136 "%sCRT1 (VGA) connection detected\n", 137 CRT1Detected ? "" : "No "); 138} 139 140/* Detect CRT2-LCD and LCD size */ 141void XGILCDPreInit(ScrnInfoPtr pScrn) 142{ 143 XGIPtr pXGI = XGIPTR(pScrn); 144 unsigned char CR32; 145 146 pXGI->LCDwidth = 0; 147 148 /* if(!(pXGI->XGI_Pr->VBType & VB_XGIVB)) return; */ 149 150 inXGIIDXREG(XGICR, 0x32, CR32); 151 152 if(CR32 & 0x08) pXGI->VBFlags |= CRT2_LCD; 153 if( pXGI->xgi_HwDevExt.jChipType == XG21) 154 { 155 pXGI->VBFlags |= CRT2_LCD; 156 CR32 |= 0x08 ; 157 outXGIIDXREG(XGICR, 0x32, CR32); 158 } 159 160 /* If no panel has been detected by the BIOS during booting, 161 * we try to detect it ourselves at this point. We do that 162 * if forcecrt2redetection was given, too. 163 * This is useful on machines with DVI connectors where the 164 * panel was connected after booting. This is only supported 165 * on the 315/330 series and the 301/30xB/C bridge (because the 166 * 30xLV don't seem to have a DDC port and operate only LVDS 167 * panels which mostly don't support DDC). We only do this if 168 * there was no secondary VGA detected by the BIOS, because LCD 169 * and VGA2 share the same DDC channel and might be misdetected 170 * as the wrong type (especially if the LCD panel only supports 171 * EDID Version 1). 172 * 173 * By default, CRT2 redetection is forced since 12/09/2003, as 174 * I encountered numerous panels which deliver more or less 175 * bogus DDC data confusing the BIOS. Since our DDC detection 176 * is waaaay better, we prefer it instead of the primitive 177 * and buggy BIOS method. 178 */ 179 if (!IS_DUAL_HEAD(pXGI) || !IS_SECOND_HEAD(pXGI)) { 180 181 } 182} 183 184/* Detect CRT2-TV connector type and PAL/NTSC flag */ 185void XGITVPreInit(ScrnInfoPtr pScrn) 186{ 187 XGIPtr pXGI = XGIPTR(pScrn); 188 unsigned char SR16, SR38, CR32, CR35=0, CR38=0, CR39; 189 int temp = 0; 190 191 if(!(pXGI->XGI_Pr->VBType & VB_XGIVB)) return; 192 193 inXGIIDXREG(XGICR, 0x32, CR32); 194 inXGIIDXREG(XGICR, 0x35, CR35); 195 inXGIIDXREG(XGISR, 0x16, SR16); 196 inXGIIDXREG(XGISR, 0x38, SR38); 197 198 if(temp) { 199 inXGIIDXREG(XGICR, temp, CR38); 200 } 201 202#ifdef TWDEBUG 203 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 204 "(vb.c: CR32=%02x SR16=%02x SR38=%02x)\n", 205 CR32, SR16, SR38); 206#endif 207 208 if(CR32 & 0x47) pXGI->VBFlags |= CRT2_TV; 209 210 if(pXGI->XGI_SD_Flags & XGI_SD_SUPPORTYPBPR) { 211 if(CR32 & 0x80) pXGI->VBFlags |= CRT2_TV; 212 } else { 213 CR32 &= 0x7f; 214 } 215 216 if(CR32 & 0x01) 217 pXGI->VBFlags |= TV_AVIDEO; 218 else if(CR32 & 0x02) 219 pXGI->VBFlags |= TV_SVIDEO; 220 else if(CR32 & 0x04) 221 pXGI->VBFlags |= TV_SCART; 222 else if((CR32 & 0x40) && (pXGI->XGI_SD_Flags & XGI_SD_SUPPORTHIVISION)) 223 pXGI->VBFlags |= (TV_HIVISION | TV_PAL); 224 else if((CR32 & 0x80) && (pXGI->XGI_SD_Flags & XGI_SD_SUPPORTYPBPR)) { 225 pXGI->VBFlags |= TV_YPBPR; 226 if(pXGI->XGI_SD_Flags & XGI_SD_SUPPORTYPBPR) { 227 if(CR38 & 0x08) { 228 switch(CR38 & 0x30) { 229 case 0x10: pXGI->VBFlags |= TV_YPBPR525P; break; 230 case 0x20: pXGI->VBFlags |= TV_YPBPR750P; break; 231 case 0x30: pXGI->VBFlags |= TV_YPBPR1080I; break; 232 default: pXGI->VBFlags |= TV_YPBPR525I; 233 } 234 } else pXGI->VBFlags |= TV_YPBPR525I; 235 if(pXGI->XGI_SD_Flags & XGI_SD_SUPPORTYPBPRAR) { 236 inXGIIDXREG(XGICR,0x3B,CR39); 237 CR39 &= 0x03; 238 if(CR39 == 0x00) pXGI->VBFlags |= TV_YPBPR43LB; 239 else if(CR39 == 0x01) pXGI->VBFlags |= TV_YPBPR169; 240 else if(CR39 == 0x03) pXGI->VBFlags |= TV_YPBPR43; 241 } 242 } 243 } 244 245 246 if(pXGI->VBFlags & (TV_SCART|TV_SVIDEO|TV_AVIDEO)) { 247 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected default TV standard %s\n", 248 (pXGI->VBFlags & TV_NTSC) ? 249 ((pXGI->VBFlags & TV_NTSCJ) ? "NTSCJ" : "NTSC") : 250 ((pXGI->VBFlags & TV_PALM) ? "PALM" : 251 ((pXGI->VBFlags & TV_PALN) ? "PALN" : "PAL"))); 252 } 253 254 if(pXGI->VBFlags & TV_HIVISION) { 255 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "BIOS reports HiVision TV\n"); 256 } 257 258 259 if(pXGI->VBFlags & TV_YPBPR) { 260 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected YPbPr TV (by default %s)\n", 261 (pXGI->VBFlags & TV_YPBPR525I) ? "480i" : 262 ((pXGI->VBFlags & TV_YPBPR525P) ? "480p" : 263 ((pXGI->VBFlags & TV_YPBPR750P) ? "720p" : "1080i"))); 264 } 265} 266 267 268 269/* Detect CRT2 */ 270void XGICRT2PreInit(ScrnInfoPtr pScrn) 271{ 272 XGIPtr pXGI = XGIPTR(pScrn); 273 unsigned char CR32; 274 unsigned char CRT2Detected = 0; 275 276 inXGIIDXREG(XGICR, 0x32, CR32); 277 278 if(CR32 & 0x10) 279 { 280 pXGI->VBFlags =pXGI->VBFlags | CRT2_VGA; 281 CRT2Detected = 1; 282 } 283 284 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,"%sCRT2 (VGA) connection detected\n", CRT2Detected ? "" : "No "); 285} 286 287 288