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