s/#define ABC ;/#define ABC do { ; } while(0);/
[nouveau] / src / nv_setup.c
1  /***************************************************************************\
2 |*                                                                           *|
3 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
4 |*                                                                           *|
5 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
6 |*     international laws.  Users and possessors of this source code are     *|
7 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
8 |*     use this code in individual and commercial software.                  *|
9 |*                                                                           *|
10 |*     Any use of this source code must include,  in the user documenta-     *|
11 |*     tion and  internal comments to the code,  notices to the end user     *|
12 |*     as follows:                                                           *|
13 |*                                                                           *|
14 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
15 |*                                                                           *|
16 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
17 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
18 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
19 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
20 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
21 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
22 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
23 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
24 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
25 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
26 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
27 |*                                                                           *|
28 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
29 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
30 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
31 |*     computer  software  documentation,"  as such  terms  are  used in     *|
32 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
33 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
34 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
35 |*     all U.S. Government End Users  acquire the source code  with only     *|
36 |*     those rights set forth herein.                                        *|
37 |*                                                                           *|
38  \***************************************************************************/
39
40 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_setup.c,v 1.48 2005/09/14 02:28:03 mvojkovi Exp $ */
41
42 #include "nv_include.h"
43 #include "nvreg.h"
44
45 /*
46  * Override VGA I/O routines.
47  */
48 static void NVWriteCrtc(vgaHWPtr pVga, CARD8 index, CARD8 value)
49 {
50     NVPtr pNv = (NVPtr)pVga->MMIOBase;
51     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
52     VGA_WR08(ptr, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index);
53     VGA_WR08(ptr, pVga->IOBase + VGA_CRTC_DATA_OFFSET,  value);
54 }
55 static CARD8 NVReadCrtc(vgaHWPtr pVga, CARD8 index)
56 {
57     NVPtr pNv = (NVPtr)pVga->MMIOBase;
58     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
59     VGA_WR08(ptr, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index);
60     return (VGA_RD08(ptr, pVga->IOBase + VGA_CRTC_DATA_OFFSET));
61 }
62 static void NVWriteGr(vgaHWPtr pVga, CARD8 index, CARD8 value)
63 {
64     NVPtr pNv = (NVPtr)pVga->MMIOBase;
65     VGA_WR08(pNv->PVIO, VGA_GRAPH_INDEX, index);
66     VGA_WR08(pNv->PVIO, VGA_GRAPH_DATA,  value);
67 }
68 static CARD8 NVReadGr(vgaHWPtr pVga, CARD8 index)
69 {
70     NVPtr pNv = (NVPtr)pVga->MMIOBase;
71     VGA_WR08(pNv->PVIO, VGA_GRAPH_INDEX, index);
72     return (VGA_RD08(pNv->PVIO, VGA_GRAPH_DATA));
73 }
74 static void NVWriteSeq(vgaHWPtr pVga, CARD8 index, CARD8 value)
75 {
76     NVPtr pNv = (NVPtr)pVga->MMIOBase;
77     VGA_WR08(pNv->PVIO, VGA_SEQ_INDEX, index);
78     VGA_WR08(pNv->PVIO, VGA_SEQ_DATA,  value);
79 }
80 static CARD8 NVReadSeq(vgaHWPtr pVga, CARD8 index)
81 {
82     NVPtr pNv = (NVPtr)pVga->MMIOBase;
83     VGA_WR08(pNv->PVIO, VGA_SEQ_INDEX, index);
84     return (VGA_RD08(pNv->PVIO, VGA_SEQ_DATA));
85 }
86 static void NVWriteAttr(vgaHWPtr pVga, CARD8 index, CARD8 value)
87 {
88     NVPtr pNv = (NVPtr)pVga->MMIOBase;
89     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
90     volatile CARD8 tmp;
91
92     tmp = VGA_RD08(ptr, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
93     if (pVga->paletteEnabled)
94         index &= ~0x20;
95     else
96         index |= 0x20;
97     VGA_WR08(ptr, VGA_ATTR_INDEX,  index);
98     VGA_WR08(ptr, VGA_ATTR_DATA_W, value);
99 }
100 static CARD8 NVReadAttr(vgaHWPtr pVga, CARD8 index)
101 {
102     NVPtr pNv = (NVPtr)pVga->MMIOBase;
103     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
104     volatile CARD8 tmp;
105
106     tmp = VGA_RD08(ptr, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
107     if (pVga->paletteEnabled)
108         index &= ~0x20;
109     else
110         index |= 0x20;
111     VGA_WR08(ptr, VGA_ATTR_INDEX, index);
112     return (VGA_RD08(ptr, VGA_ATTR_DATA_R));
113 }
114 static void NVWriteMiscOut(vgaHWPtr pVga, CARD8 value)
115 {
116     NVPtr pNv = (NVPtr)pVga->MMIOBase;
117     VGA_WR08(pNv->PVIO, VGA_MISC_OUT_W, value);
118 }
119 static CARD8 NVReadMiscOut(vgaHWPtr pVga)
120 {
121     NVPtr pNv = (NVPtr)pVga->MMIOBase;
122     return (VGA_RD08(pNv->PVIO, VGA_MISC_OUT_R));
123 }
124 static void NVEnablePalette(vgaHWPtr pVga)
125 {
126     NVPtr pNv = (NVPtr)pVga->MMIOBase;
127     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
128     volatile CARD8 tmp;
129
130     tmp = VGA_RD08(ptr, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
131     VGA_WR08(ptr, VGA_ATTR_INDEX, 0x00);
132     pVga->paletteEnabled = TRUE;
133 }
134 static void NVDisablePalette(vgaHWPtr pVga)
135 {
136     NVPtr pNv = (NVPtr)pVga->MMIOBase;
137     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
138     volatile CARD8 tmp;
139
140     tmp = VGA_RD08(ptr, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
141     VGA_WR08(ptr, VGA_ATTR_INDEX, 0x20);
142     pVga->paletteEnabled = FALSE;
143 }
144 static void NVWriteDacMask(vgaHWPtr pVga, CARD8 value)
145 {
146     NVPtr pNv = (NVPtr)pVga->MMIOBase;
147     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
148     VGA_WR08(ptr, VGA_DAC_MASK, value);
149 }
150 static CARD8 NVReadDacMask(vgaHWPtr pVga)
151 {
152     NVPtr pNv = (NVPtr)pVga->MMIOBase;
153     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
154     return (VGA_RD08(ptr, VGA_DAC_MASK));
155 }
156 static void NVWriteDacReadAddr(vgaHWPtr pVga, CARD8 value)
157 {
158     NVPtr pNv = (NVPtr)pVga->MMIOBase;
159     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
160     VGA_WR08(ptr, VGA_DAC_READ_ADDR, value);
161 }
162 static void NVWriteDacWriteAddr(vgaHWPtr pVga, CARD8 value)
163 {
164     NVPtr pNv = (NVPtr)pVga->MMIOBase;
165     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
166     VGA_WR08(ptr, VGA_DAC_WRITE_ADDR, value);
167 }
168 static void NVWriteDacData(vgaHWPtr pVga, CARD8 value)
169 {
170     NVPtr pNv = (NVPtr)pVga->MMIOBase;
171     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
172     VGA_WR08(ptr, VGA_DAC_DATA, value);
173 }
174 static CARD8 NVReadDacData(vgaHWPtr pVga)
175 {
176     NVPtr pNv = (NVPtr)pVga->MMIOBase;
177     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
178     return (VGA_RD08(ptr, VGA_DAC_DATA));
179 }
180
181 static Bool 
182 NVIsConnected (ScrnInfoPtr pScrn, int output)
183 {
184     NVPtr pNv = NVPTR(pScrn);
185     CARD32 reg52C, reg608, temp;
186     Bool present;
187
188     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
189                "Probing for analog device on output %s...\n", 
190                 output ? "B" : "A");
191
192     reg52C = nvReadRAMDAC(pNv, output, NV_RAMDAC_OUTPUT);
193     reg608 = nvReadRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL);
194
195     nvWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL, (reg608 & ~0x00010000));
196
197     nvWriteRAMDAC(pNv, output, NV_RAMDAC_OUTPUT, (reg52C & 0x0000FEEE));
198     usleep(1000);
199     
200     temp = nvReadRAMDAC(pNv, output, NV_RAMDAC_OUTPUT);
201     nvWriteRAMDAC(pNv, output, NV_RAMDAC_OUTPUT, temp | 1);
202
203     nvWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_DATA, 0x94050140);
204     temp = nvReadRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL);
205     nvWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
206
207     usleep(1000);
208
209     present = (nvReadRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
210
211     if(present)
212        xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "  ...found one\n");
213     else
214        xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "  ...can't find one\n");
215
216     temp = nvReadRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL);
217     nvWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
218
219     nvWriteRAMDAC(pNv, output, NV_RAMDAC_OUTPUT, reg52C);
220     nvWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL, reg608);
221
222     return present;
223 }
224
225 static void
226 NVSelectHeadRegisters(ScrnInfoPtr pScrn, int head)
227 {
228     NVPtr pNv = NVPTR(pScrn);
229
230     pNv->cur_head = head;
231 }
232
233 static xf86MonPtr 
234 NVProbeDDC (ScrnInfoPtr pScrn, int bus)
235 {
236     NVPtr pNv = NVPTR(pScrn);
237     xf86MonPtr MonInfo = NULL;
238
239     if(!pNv->I2C) return NULL;
240
241     pNv->DDCBase = bus ? 0x36 : 0x3e;
242
243     xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
244                "Probing for EDID on I2C bus %s...\n", bus ? "B" : "A");
245
246     if ((MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pNv->I2C))) {
247        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
248                   "DDC detected a %s:\n", MonInfo->features.input_type ?
249                   "DFP" : "CRT");
250        xf86PrintEDID( MonInfo );
251     } else {
252        xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
253                   "  ... none found\n");
254     }
255
256     return MonInfo;
257 }
258
259 static void nv4GetConfig (NVPtr pNv)
260 {
261     CARD32 reg_FB0 = nvReadFB(pNv, 0x0);
262     if (reg_FB0 & 0x00000100) {
263         pNv->RamAmountKBytes = ((reg_FB0 >> 12) & 0x0F) * 1024 * 2
264                               + 1024 * 2;
265     } else {
266         switch (reg_FB0 & 0x00000003) {
267         case 0:
268             pNv->RamAmountKBytes = 1024 * 32;
269             break;
270         case 1:
271             pNv->RamAmountKBytes = 1024 * 4;
272             break;
273         case 2:
274             pNv->RamAmountKBytes = 1024 * 8;
275             break;
276         case 3:
277         default:
278             pNv->RamAmountKBytes = 1024 * 16;
279             break;
280         }
281     }
282     pNv->CrystalFreqKHz = (nvReadEXTDEV(pNv, 0x0000) & 0x00000040) ? 14318 : 13500;
283     pNv->CURSOR         = &(pNv->PRAMIN[0x1E00]);
284     pNv->MinVClockFreqKHz = 12000;
285     pNv->MaxVClockFreqKHz = 350000;
286 }
287
288 static void nv10GetConfig (NVPtr pNv)
289 {
290     CARD32 implementation = pNv->Chipset & 0x0ff0;
291
292 #if X_BYTE_ORDER == X_BIG_ENDIAN
293     /* turn on big endian register access */
294     if(!(nvReadMC(pNv, 0x0004) & 0x01000001)) {
295        xf86DrvMsg(0, X_ERROR, "Card is in big endian mode, something is very wrong !\n");
296     }
297 #endif
298
299         if (implementation == CHIPSET_NFORCE) {
300                 uint32_t amt;
301 #ifdef XSERVER_LIBPCIACCESS
302                 const struct pci_slot_match match[] = { {0, 0, 0, 1, 0} };
303                 struct pci_device_iterator *iterator = pci_slot_match_iterator_create(&match);
304                 /* assume one device to exist */
305                 struct pci_device *device = pci_device_next(iterator);
306                 PCI_DEV_READ_LONG(device, 0x7c, &amt);
307 #else
308                 amt = pciReadLong(pciTag(0, 0, 1), 0x7C);
309 #endif /* XSERVER_LIBPCIACCESS */
310                 pNv->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
311         } else if (implementation == CHIPSET_NFORCE2) {
312                 uint32_t amt; 
313 #ifdef XSERVER_LIBPCIACCESS
314                 const struct pci_slot_match match[] = { {0, 0, 0, 1, 0} };
315                 struct pci_device_iterator *iterator = pci_slot_match_iterator_create(&match);
316                 /* assume one device to exist */
317                 struct pci_device *device = pci_device_next(iterator);
318                 PCI_DEV_READ_LONG(device, 0x84, &amt);
319 #else
320                 amt = pciReadLong(pciTag(0, 0, 1), 0x84);
321 #endif /* XSERVER_LIBPCIACCESS */
322                 pNv->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
323         } else {
324                 pNv->RamAmountKBytes = (nvReadFB(pNv, 0x020C) & 0xFFF00000) >> 10;
325         }
326
327     if(pNv->RamAmountKBytes > 256*1024)
328         pNv->RamAmountKBytes = 256*1024;
329
330     pNv->CrystalFreqKHz = (nvReadEXTDEV(pNv, 0x0000) & (1 << 6)) ? 14318 : 13500;
331     
332     if(pNv->twoHeads && (implementation != CHIPSET_NV11))
333     {
334        if(nvReadEXTDEV(pNv, 0x0000) & (1 << 22))
335            pNv->CrystalFreqKHz = 27000;
336     }
337
338     pNv->CURSOR           = NULL;  /* can't set this here */
339     pNv->MinVClockFreqKHz = 12000;
340     pNv->MaxVClockFreqKHz = pNv->twoStagePLL ? 400000 : 350000;
341 }
342
343 void
344 NVCommonSetup(ScrnInfoPtr pScrn)
345 {
346     NVPtr pNv = NVPTR(pScrn);
347     vgaHWPtr pVga = VGAHWPTR(pScrn);
348     CARD16 implementation = pNv->Chipset & 0x0ff0;
349     xf86MonPtr monitorA, monitorB;
350     Bool tvA = FALSE;
351     Bool tvB = FALSE;
352     int FlatPanel = -1;   /* really means the CRTC is slaved */
353     Bool Television = FALSE;
354     
355     /*
356      * Override VGA I/O routines.
357      */
358     pVga->writeCrtc         = NVWriteCrtc;
359     pVga->readCrtc          = NVReadCrtc;
360     pVga->writeGr           = NVWriteGr;
361     pVga->readGr            = NVReadGr;
362     pVga->writeAttr         = NVWriteAttr;
363     pVga->readAttr          = NVReadAttr;
364     pVga->writeSeq          = NVWriteSeq;
365     pVga->readSeq           = NVReadSeq;
366     pVga->writeMiscOut      = NVWriteMiscOut;
367     pVga->readMiscOut       = NVReadMiscOut;
368     pVga->enablePalette     = NVEnablePalette;
369     pVga->disablePalette    = NVDisablePalette;
370     pVga->writeDacMask      = NVWriteDacMask;
371     pVga->readDacMask       = NVReadDacMask;
372     pVga->writeDacWriteAddr = NVWriteDacWriteAddr;
373     pVga->writeDacReadAddr  = NVWriteDacReadAddr;
374     pVga->writeDacData      = NVWriteDacData;
375     pVga->readDacData       = NVReadDacData;
376     /*
377      * Note: There are different pointers to the CRTC/AR and GR/SEQ registers.
378      * Bastardize the intended uses of these to make it work.
379      */
380     pVga->MMIOBase   = (CARD8 *)pNv;
381     pVga->MMIOOffset = 0;
382
383 #ifndef XSERVER_LIBPCIACCESS
384         pNv->REGS = xf86MapPciMem(pScrn->scrnIndex, 
385                         VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, 
386                         pNv->PciTag, pNv->IOAddress, 0x01000000);
387 #else
388         /* 0x01000000 is the size */
389         pci_device_map_range(pNv->PciInfo, pNv->IOAddress, 0x01000000, PCI_DEV_MAP_FLAG_WRITABLE, &(pNv->REGS));
390 #endif /* XSERVER_LIBPCIACCESS */
391
392     pNv->PRAMIN   = pNv->REGS + (NV_PRAMIN_OFFSET/4);
393         if (pNv->Architecture >= NV_ARCH_50) {
394                 pNv->NV50_PCRTC = pNv->REGS + (NV50_PCRTC_OFFSET/4);
395         }
396     pNv->PCRTC0   = pNv->REGS + (NV_PCRTC0_OFFSET/4);
397     pNv->PRAMDAC0 = pNv->REGS + (NV_PRAMDAC0_OFFSET/4);
398     pNv->PFB      = pNv->REGS + (NV_PFB_OFFSET/4);
399     pNv->PFIFO    = pNv->REGS + (NV_PFIFO_OFFSET/4);
400     pNv->PGRAPH   = pNv->REGS + (NV_PGRAPH_OFFSET/4);
401     pNv->PEXTDEV  = pNv->REGS + (NV_PEXTDEV_OFFSET/4);
402     pNv->PTIMER   = pNv->REGS + (NV_PTIMER_OFFSET/4);
403     pNv->PVIDEO   = pNv->REGS + (NV_PVIDEO_OFFSET/4);
404     pNv->PMC      = pNv->REGS + (NV_PMC_OFFSET/4);
405
406     pNv->PCRTC1   = pNv->PCRTC0 + 0x2000/4;
407     pNv->PRAMDAC1 = pNv->PRAMDAC0 + 0x2000/4;
408
409     /* 8 bit registers */
410     pNv->PCIO0    = (CARD8*)pNv->REGS + NV_PCIO0_OFFSET;
411     pNv->PDIO0    = (CARD8*)pNv->REGS + NV_PDIO0_OFFSET;
412     pNv->PVIO     = (CARD8*)pNv->REGS + NV_PVIO_OFFSET;
413     pNv->PROM     = (CARD8*)pNv->REGS + NV_PROM_OFFSET;
414
415     pNv->PCIO1    = pNv->PCIO0 + 0x2000;
416     pNv->PDIO1    = pNv->PDIO0 + 0x2000;
417
418     pNv->twoHeads =  (pNv->Architecture >= NV_ARCH_10) &&
419                      (implementation != CHIPSET_NV10) &&
420                      (implementation != CHIPSET_NV15) &&
421                      (implementation != CHIPSET_NFORCE) &&
422                      (implementation != CHIPSET_NV20);
423
424     pNv->fpScaler = (pNv->FpScale && pNv->twoHeads && (implementation!=CHIPSET_NV11));
425
426     pNv->twoStagePLL = (implementation == CHIPSET_NV31) ||
427                        (implementation == CHIPSET_NV36) ||
428                        (pNv->Architecture >= NV_ARCH_40);
429
430     pNv->WaitVSyncPossible = (pNv->Architecture >= NV_ARCH_10) &&
431                              (implementation != CHIPSET_NV10);
432
433     pNv->BlendingPossible = ((pNv->Chipset & 0xffff) > CHIPSET_NV04);
434
435     /* look for known laptop chips */
436     /* FIXME we could add some ids here (0x0164,0x0167,0x0168,0x01D6,0x01D7,0x01D8,0x0298,0x0299,0x0398) */
437     switch(pNv->Chipset & 0xffff) {
438     case 0x0112:
439     case 0x0174:
440     case 0x0175:
441     case 0x0176:
442     case 0x0177:
443     case 0x0179:
444     case 0x017C:
445     case 0x017D:
446     case 0x0186:
447     case 0x0187:
448     case 0x018D:
449     case 0x0228:
450     case 0x0286:
451     case 0x028C:
452     case 0x0316:
453     case 0x0317:
454     case 0x031A:
455     case 0x031B:
456     case 0x031C:
457     case 0x031D:
458     case 0x031E:
459     case 0x031F:
460     case 0x0324:
461     case 0x0325:
462     case 0x0328:
463     case 0x0329:
464     case 0x032C:
465     case 0x032D:
466     case 0x0347:
467     case 0x0348:
468     case 0x0349:
469     case 0x034B:
470     case 0x034C:
471     case 0x0160:
472     case 0x0166:
473     case 0x0169:
474     case 0x016B:
475     case 0x016C:
476     case 0x016D:
477     case 0x00C8:
478     case 0x00CC:
479     case 0x0144:
480     case 0x0146:
481     case 0x0148:
482     case 0x0098:
483     case 0x0099:
484         pNv->Mobile = TRUE;
485         break;
486     default:
487         break;
488     }
489
490     pNv->Television = FALSE;
491
492     /* Parse the bios to initialize the card */
493     NVSelectHeadRegisters(pScrn, 0);
494     NVParseBios(pScrn);
495
496         if(pNv->Architecture == NV_ARCH_04) {
497                 nv4GetConfig(pNv);
498         } else {
499                 nv10GetConfig(pNv);
500         }
501
502     if (!pNv->randr12_enable) {
503       
504         NVSelectHeadRegisters(pScrn, 0);
505         
506         NVLockUnlock(pNv, 0);
507         
508         NVI2CInit(pScrn);
509         
510         
511         if(!pNv->twoHeads) {
512             pNv->crtc_active[0] = TRUE;
513             pNv->crtc_active[1] = FALSE;
514             if((monitorA = NVProbeDDC(pScrn, 0))) {
515                 FlatPanel = monitorA->features.input_type ? 1 : 0;
516                 
517                 /* NV4 doesn't support FlatPanels */
518                 if((pNv->Chipset & 0x0fff) <= CHIPSET_NV04)
519                     FlatPanel = 0;
520             } else {
521                 if(nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
522                     if(!(nvReadVGA(pNv, NV_VGA_CRTCX_LCD) & 0x01)) 
523                         Television = TRUE;
524                     FlatPanel = 1;
525                 } else {
526                     FlatPanel = 0;
527                 }
528                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
529                            "HW is currently programmed for %s\n",
530                            FlatPanel ? (Television ? "TV" : "DFP") : "CRT");
531             } 
532             
533             if(pNv->FlatPanel == -1) {
534                 pNv->FlatPanel = FlatPanel;
535                 pNv->Television = Television;
536             } else {
537                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
538                            "Forcing display type to %s as specified\n", 
539                            pNv->FlatPanel ? "DFP" : "CRT");
540             }
541         } else {
542             CARD8 outputAfromCRTC, outputBfromCRTC;
543             pNv->crtc_active[0] = FALSE;
544             pNv->crtc_active[1] = FALSE;
545             CARD8 slaved_on_A, slaved_on_B;
546             Bool analog_on_A, analog_on_B;
547             CARD32 oldhead;
548             CARD8 cr44;
549             
550             if(implementation != CHIPSET_NV11) {
551                 if(nvReadRAMDAC0(pNv, NV_RAMDAC_OUTPUT) & 0x100)
552                     outputAfromCRTC = 1;
553                 else            
554                     outputAfromCRTC = 0;
555                 if(nvReadRAMDAC(pNv, 1, NV_RAMDAC_OUTPUT) & 0x100)
556                     outputBfromCRTC = 1;
557                 else
558                     outputBfromCRTC = 0;
559                 analog_on_A = NVIsConnected(pScrn, 0);
560                 analog_on_B = NVIsConnected(pScrn, 1);
561             } else {
562                 outputAfromCRTC = 0;
563                 outputBfromCRTC = 1;
564                 analog_on_A = FALSE;
565                 analog_on_B = FALSE;
566             }
567             
568             cr44 = nvReadVGA(pNv, NV_VGA_CRTCX_OWNER);
569             pNv->vtOWNER = cr44;
570             
571             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, 3);
572             NVSelectHeadRegisters(pScrn, 1);
573             NVLockUnlock(pNv, 0);
574             
575             slaved_on_B = nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL) & 0x80;
576             if(slaved_on_B) {
577                 tvB = !(nvReadVGA(pNv, NV_VGA_CRTCX_LCD) & 0x01);
578             }
579             
580             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, 0);
581             NVSelectHeadRegisters(pScrn, 0);
582             NVLockUnlock(pNv, 0);
583             
584             slaved_on_A = nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL) & 0x80; 
585             if(slaved_on_A) {
586                 tvA = !(nvReadVGA(pNv, NV_VGA_CRTCX_LCD) & 0x01);
587             }
588             
589             oldhead = nvReadCRTC0(pNv, NV_CRTC_FSEL);
590             nvWriteCRTC0(pNv, NV_CRTC_FSEL, oldhead | 0x00000010);
591             
592             monitorA = NVProbeDDC(pScrn, 0);
593             monitorB = NVProbeDDC(pScrn, 1);
594             
595             if(slaved_on_A && !tvA) {
596                 pNv->crtc_active[0] = TRUE;
597                 FlatPanel = 1;
598                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
599                            "CRTC 0 is currently programmed for DFP\n");
600             } else 
601                 if(slaved_on_B && !tvB) {
602                     pNv->crtc_active[1] = TRUE;
603                     FlatPanel = 1;
604                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
605                                "CRTC 1 is currently programmed for DFP\n");
606                 } else
607                     if(analog_on_A) {
608                         pNv->crtc_active[outputAfromCRTC] = TRUE;
609                         FlatPanel = 0;
610                         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
611                                    "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
612                     } else
613                         if(analog_on_B) {
614                             pNv->crtc_active[outputBfromCRTC] = TRUE;
615                             FlatPanel = 0;
616                             xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
617                                        "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
618                         } else
619                             if(slaved_on_A) {
620                                 pNv->crtc_active[0] = TRUE;
621                                 FlatPanel = 1;
622                                 Television = 1;
623                                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
624                                            "CRTC 0 is currently programmed for TV\n");
625                             } else
626                                 if(slaved_on_B) {
627                                     pNv->crtc_active[1] = TRUE;
628                                     FlatPanel = 1;
629                                     Television = 1;
630                                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
631                                                "CRTC 1 is currently programmed for TV\n");
632                                 } else
633                                     if(monitorA) {
634                                         FlatPanel = monitorA->features.input_type ? 1 : 0;
635                                     } else 
636                                         if(monitorB) {
637                                             FlatPanel = monitorB->features.input_type ? 1 : 0;
638                                         }
639             
640             if(pNv->FlatPanel == -1) {
641                 if(FlatPanel != -1) {
642                     pNv->FlatPanel = FlatPanel;
643                     pNv->Television = Television;
644                 } else {
645                     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
646                                "Unable to detect display type...\n");
647                     if(pNv->Mobile) {
648                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
649                                    "...On a laptop, assuming DFP\n");
650                         pNv->FlatPanel = 1;
651                     } else {
652                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
653                                    "...Using default of CRT\n");
654                         pNv->FlatPanel = 0;
655                     }
656                 }
657             } else {
658                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
659                            "Forcing display type to %s as specified\n", 
660                            pNv->FlatPanel ? "DFP" : "CRT");
661             }
662             
663                 if(!(pNv->crtc_active[0]) && !(pNv->crtc_active[1])) {
664                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
665                                 "Unable to detect which CRTC is used...\n");
666                         if(pNv->FlatPanel) {
667                                 pNv->crtc_active[1] = TRUE;
668                         } else {
669                                 pNv->crtc_active[0] = TRUE;
670                         }
671                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
672                         "...Defaulting to CRTCNumber %i\n", pNv->crtc_active[1]);
673                 }
674
675             if(monitorA) {
676                 if((monitorA->features.input_type && pNv->FlatPanel) ||
677                    (!monitorA->features.input_type && !pNv->FlatPanel))
678                 {
679                     if(monitorB) { 
680                         xfree(monitorB);
681                         monitorB = NULL;
682                     }
683                 } else {
684                     xfree(monitorA);
685                     monitorA = NULL;
686                 }
687             }
688             
689             if(monitorB) {
690                 if((monitorB->features.input_type && !pNv->FlatPanel) ||
691                    (!monitorB->features.input_type && pNv->FlatPanel)) 
692                 {
693                     xfree(monitorB);
694                 } else {
695                     monitorA = monitorB;
696                 }
697                 monitorB = NULL;
698             }
699             
700             if(implementation == CHIPSET_NV11)
701                 cr44 = pNv->crtc_active[1] * 0x3;
702             
703             nvWriteCRTC0(pNv, NV_CRTC_FSEL,  oldhead);
704
705             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, cr44);
706             NVSelectHeadRegisters(pScrn, pNv->crtc_active[1]);
707         }
708         
709         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
710                    "Using %s on CRTC %i\n",
711                    pNv->FlatPanel ? (pNv->Television ? "TV" : "DFP") : "CRT", 
712                    pNv->crtc_active[1]);
713         
714         if(pNv->FlatPanel && !pNv->Television) {
715             pNv->fpWidth = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HDISP_END) + 1;
716             pNv->fpHeight = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_VDISP_END) + 1;
717             pNv->fpSyncs = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL) & 0x30000033;
718             xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
719                        pNv->fpWidth, pNv->fpHeight);
720         }
721         
722         if(monitorA)
723             xf86SetDDCproperties(pScrn, monitorA);
724
725         if(!pNv->FlatPanel || (pScrn->depth != 24) || !pNv->twoHeads)
726             pNv->FPDither = FALSE;
727         
728         pNv->LVDS = FALSE;
729         if(pNv->FlatPanel && pNv->twoHeads) {
730             nvWriteRAMDAC0(pNv, NV_RAMDAC_FP_TMDS_CONTROL, 0x00010004);
731             if(nvReadRAMDAC0(pNv, NV_RAMDAC_FP_TMDS_DATA) & 1)
732                 pNv->LVDS = TRUE;
733             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel is %s\n", 
734                        pNv->LVDS ? "LVDS" : "TMDS");
735         }
736     }
737 }
738