randr12: Lots of misc fixes.
[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->PVIO0, VGA_GRAPH_INDEX, index);
66     VGA_WR08(pNv->PVIO0, VGA_GRAPH_DATA,  value);
67 }
68 static CARD8 NVReadGr(vgaHWPtr pVga, CARD8 index)
69 {
70     NVPtr pNv = (NVPtr)pVga->MMIOBase;
71     VGA_WR08(pNv->PVIO0, VGA_GRAPH_INDEX, index);
72     return (VGA_RD08(pNv->PVIO0, 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->PVIO0, VGA_SEQ_INDEX, index);
78     VGA_WR08(pNv->PVIO0, VGA_SEQ_DATA,  value);
79 }
80 static CARD8 NVReadSeq(vgaHWPtr pVga, CARD8 index)
81 {
82     NVPtr pNv = (NVPtr)pVga->MMIOBase;
83     VGA_WR08(pNv->PVIO0, VGA_SEQ_INDEX, index);
84     return (VGA_RD08(pNv->PVIO0, 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->PVIO0, VGA_MISC_OUT_W, value);
118 }
119 static CARD8 NVReadMiscOut(vgaHWPtr pVga)
120 {
121     NVPtr pNv = (NVPtr)pVga->MMIOBase;
122     return (VGA_RD08(pNv->PVIO0, 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->PVIO0     = (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     pNv->PVIO1    = pNv->PVIO0 + 0x2000;
418
419     pNv->twoHeads =  (pNv->Architecture >= NV_ARCH_10) &&
420                      (implementation != CHIPSET_NV10) &&
421                      (implementation != CHIPSET_NV15) &&
422                      (implementation != CHIPSET_NFORCE) &&
423                      (implementation != CHIPSET_NV20);
424
425     pNv->fpScaler = (pNv->FpScale && pNv->twoHeads && (implementation!=CHIPSET_NV11));
426
427     pNv->twoStagePLL = (implementation == CHIPSET_NV31) ||
428                        (implementation == CHIPSET_NV36) ||
429                        (pNv->Architecture >= NV_ARCH_40);
430
431     pNv->WaitVSyncPossible = (pNv->Architecture >= NV_ARCH_10) &&
432                              (implementation != CHIPSET_NV10);
433
434     pNv->BlendingPossible = ((pNv->Chipset & 0xffff) > CHIPSET_NV04);
435
436     /* look for known laptop chips */
437     /* FIXME we could add some ids here (0x0164,0x0167,0x0168,0x01D6,0x01D7,0x01D8,0x0298,0x0299,0x0398) */
438     switch(pNv->Chipset & 0xffff) {
439     case 0x0112:
440     case 0x0174:
441     case 0x0175:
442     case 0x0176:
443     case 0x0177:
444     case 0x0179:
445     case 0x017C:
446     case 0x017D:
447     case 0x0186:
448     case 0x0187:
449     case 0x018D:
450     case 0x0228:
451     case 0x0286:
452     case 0x028C:
453     case 0x0316:
454     case 0x0317:
455     case 0x031A:
456     case 0x031B:
457     case 0x031C:
458     case 0x031D:
459     case 0x031E:
460     case 0x031F:
461     case 0x0324:
462     case 0x0325:
463     case 0x0328:
464     case 0x0329:
465     case 0x032C:
466     case 0x032D:
467     case 0x0347:
468     case 0x0348:
469     case 0x0349:
470     case 0x034B:
471     case 0x034C:
472     case 0x0160:
473     case 0x0166:
474     case 0x0169:
475     case 0x016B:
476     case 0x016C:
477     case 0x016D:
478     case 0x00C8:
479     case 0x00CC:
480     case 0x0144:
481     case 0x0146:
482     case 0x0148:
483     case 0x0098:
484     case 0x0099:
485         pNv->Mobile = TRUE;
486         break;
487     default:
488         break;
489     }
490
491     pNv->Television = FALSE;
492
493     /* Parse the bios to initialize the card */
494     NVSelectHeadRegisters(pScrn, 0);
495     NVParseBios(pScrn);
496
497         if(pNv->Architecture == NV_ARCH_04) {
498                 nv4GetConfig(pNv);
499         } else {
500                 nv10GetConfig(pNv);
501         }
502
503     if (!pNv->randr12_enable) {
504       
505         NVSelectHeadRegisters(pScrn, 0);
506         
507         NVLockUnlock(pNv, 0);
508         
509         NVI2CInit(pScrn);
510         
511         
512         if(!pNv->twoHeads) {
513             pNv->crtc_active[0] = TRUE;
514             pNv->crtc_active[1] = FALSE;
515             if((monitorA = NVProbeDDC(pScrn, 0))) {
516                 FlatPanel = monitorA->features.input_type ? 1 : 0;
517                 
518                 /* NV4 doesn't support FlatPanels */
519                 if((pNv->Chipset & 0x0fff) <= CHIPSET_NV04)
520                     FlatPanel = 0;
521             } else {
522                 if(nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
523                     if(!(nvReadVGA(pNv, NV_VGA_CRTCX_LCD) & 0x01)) 
524                         Television = TRUE;
525                     FlatPanel = 1;
526                 } else {
527                     FlatPanel = 0;
528                 }
529                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
530                            "HW is currently programmed for %s\n",
531                            FlatPanel ? (Television ? "TV" : "DFP") : "CRT");
532             } 
533             
534             if(pNv->FlatPanel == -1) {
535                 pNv->FlatPanel = FlatPanel;
536                 pNv->Television = Television;
537             } else {
538                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
539                            "Forcing display type to %s as specified\n", 
540                            pNv->FlatPanel ? "DFP" : "CRT");
541             }
542         } else {
543             CARD8 outputAfromCRTC, outputBfromCRTC;
544             pNv->crtc_active[0] = FALSE;
545             pNv->crtc_active[1] = FALSE;
546             CARD8 slaved_on_A, slaved_on_B;
547             Bool analog_on_A, analog_on_B;
548             CARD32 oldhead;
549             CARD8 cr44;
550             
551             if(implementation != CHIPSET_NV11) {
552                 if(nvReadRAMDAC0(pNv, NV_RAMDAC_OUTPUT) & 0x100)
553                     outputAfromCRTC = 1;
554                 else            
555                     outputAfromCRTC = 0;
556                 if(nvReadRAMDAC(pNv, 1, NV_RAMDAC_OUTPUT) & 0x100)
557                     outputBfromCRTC = 1;
558                 else
559                     outputBfromCRTC = 0;
560                 analog_on_A = NVIsConnected(pScrn, 0);
561                 analog_on_B = NVIsConnected(pScrn, 1);
562             } else {
563                 outputAfromCRTC = 0;
564                 outputBfromCRTC = 1;
565                 analog_on_A = FALSE;
566                 analog_on_B = FALSE;
567             }
568             
569             cr44 = nvReadVGA(pNv, NV_VGA_CRTCX_OWNER);
570             pNv->vtOWNER = cr44;
571             
572             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, 3);
573             NVSelectHeadRegisters(pScrn, 1);
574             NVLockUnlock(pNv, 0);
575             
576             slaved_on_B = nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL) & 0x80;
577             if(slaved_on_B) {
578                 tvB = !(nvReadVGA(pNv, NV_VGA_CRTCX_LCD) & 0x01);
579             }
580             
581             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, 0);
582             NVSelectHeadRegisters(pScrn, 0);
583             NVLockUnlock(pNv, 0);
584             
585             slaved_on_A = nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL) & 0x80; 
586             if(slaved_on_A) {
587                 tvA = !(nvReadVGA(pNv, NV_VGA_CRTCX_LCD) & 0x01);
588             }
589             
590             oldhead = nvReadCRTC0(pNv, NV_CRTC_FSEL);
591             nvWriteCRTC0(pNv, NV_CRTC_FSEL, oldhead | 0x00000010);
592             
593             monitorA = NVProbeDDC(pScrn, 0);
594             monitorB = NVProbeDDC(pScrn, 1);
595             
596             if(slaved_on_A && !tvA) {
597                 pNv->crtc_active[0] = TRUE;
598                 FlatPanel = 1;
599                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
600                            "CRTC 0 is currently programmed for DFP\n");
601             } else 
602                 if(slaved_on_B && !tvB) {
603                     pNv->crtc_active[1] = TRUE;
604                     FlatPanel = 1;
605                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
606                                "CRTC 1 is currently programmed for DFP\n");
607                 } else
608                     if(analog_on_A) {
609                         pNv->crtc_active[outputAfromCRTC] = TRUE;
610                         FlatPanel = 0;
611                         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
612                                    "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
613                     } else
614                         if(analog_on_B) {
615                             pNv->crtc_active[outputBfromCRTC] = TRUE;
616                             FlatPanel = 0;
617                             xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
618                                        "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
619                         } else
620                             if(slaved_on_A) {
621                                 pNv->crtc_active[0] = TRUE;
622                                 FlatPanel = 1;
623                                 Television = 1;
624                                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
625                                            "CRTC 0 is currently programmed for TV\n");
626                             } else
627                                 if(slaved_on_B) {
628                                     pNv->crtc_active[1] = TRUE;
629                                     FlatPanel = 1;
630                                     Television = 1;
631                                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
632                                                "CRTC 1 is currently programmed for TV\n");
633                                 } else
634                                     if(monitorA) {
635                                         FlatPanel = monitorA->features.input_type ? 1 : 0;
636                                     } else 
637                                         if(monitorB) {
638                                             FlatPanel = monitorB->features.input_type ? 1 : 0;
639                                         }
640             
641             if(pNv->FlatPanel == -1) {
642                 if(FlatPanel != -1) {
643                     pNv->FlatPanel = FlatPanel;
644                     pNv->Television = Television;
645                 } else {
646                     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
647                                "Unable to detect display type...\n");
648                     if(pNv->Mobile) {
649                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
650                                    "...On a laptop, assuming DFP\n");
651                         pNv->FlatPanel = 1;
652                     } else {
653                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
654                                    "...Using default of CRT\n");
655                         pNv->FlatPanel = 0;
656                     }
657                 }
658             } else {
659                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
660                            "Forcing display type to %s as specified\n", 
661                            pNv->FlatPanel ? "DFP" : "CRT");
662             }
663             
664                 if(!(pNv->crtc_active[0]) && !(pNv->crtc_active[1])) {
665                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
666                                 "Unable to detect which CRTC is used...\n");
667                         if(pNv->FlatPanel) {
668                                 pNv->crtc_active[1] = TRUE;
669                         } else {
670                                 pNv->crtc_active[0] = TRUE;
671                         }
672                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
673                         "...Defaulting to CRTCNumber %i\n", pNv->crtc_active[1]);
674                 }
675
676             if(monitorA) {
677                 if((monitorA->features.input_type && pNv->FlatPanel) ||
678                    (!monitorA->features.input_type && !pNv->FlatPanel))
679                 {
680                     if(monitorB) { 
681                         xfree(monitorB);
682                         monitorB = NULL;
683                     }
684                 } else {
685                     xfree(monitorA);
686                     monitorA = NULL;
687                 }
688             }
689             
690             if(monitorB) {
691                 if((monitorB->features.input_type && !pNv->FlatPanel) ||
692                    (!monitorB->features.input_type && pNv->FlatPanel)) 
693                 {
694                     xfree(monitorB);
695                 } else {
696                     monitorA = monitorB;
697                 }
698                 monitorB = NULL;
699             }
700             
701             if(implementation == CHIPSET_NV11)
702                 cr44 = pNv->crtc_active[1] * 0x3;
703             
704             nvWriteCRTC0(pNv, NV_CRTC_FSEL,  oldhead);
705
706             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, cr44);
707             NVSelectHeadRegisters(pScrn, pNv->crtc_active[1]);
708         }
709         
710         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
711                    "Using %s on CRTC %i\n",
712                    pNv->FlatPanel ? (pNv->Television ? "TV" : "DFP") : "CRT", 
713                    pNv->crtc_active[1]);
714         
715         if(pNv->FlatPanel && !pNv->Television) {
716             pNv->fpWidth = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HDISP_END) + 1;
717             pNv->fpHeight = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_VDISP_END) + 1;
718             pNv->fpSyncs = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL) & 0x30000033;
719             xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
720                        pNv->fpWidth, pNv->fpHeight);
721         }
722         
723         if(monitorA)
724             xf86SetDDCproperties(pScrn, monitorA);
725
726         if(!pNv->FlatPanel || (pScrn->depth != 24) || !pNv->twoHeads)
727             pNv->FPDither = FALSE;
728         
729         pNv->LVDS = FALSE;
730         if(pNv->FlatPanel && pNv->twoHeads) {
731             nvWriteRAMDAC0(pNv, NV_RAMDAC_FP_TMDS_CONTROL, 0x00010004);
732             if(nvReadRAMDAC0(pNv, NV_RAMDAC_FP_TMDS_DATA) & 1)
733                 pNv->LVDS = TRUE;
734             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel is %s\n", 
735                        pNv->LVDS ? "LVDS" : "TMDS");
736         }
737     }
738 }
739