RivaTuner dumps call the `how much memory have I got?' reg NV_PFB_CSTATUS
[nouveau] / src / nv_setup.c
1 /*
2  * Copyright 2003 NVIDIA, Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 #include "nv_include.h"
24
25 /*
26  * Override VGA I/O routines.
27  */
28 static void NVWriteCrtc(vgaHWPtr pVga, CARD8 index, CARD8 value)
29 {
30     NVPtr pNv = (NVPtr)pVga->MMIOBase;
31     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
32     VGA_WR08(ptr, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index);
33     VGA_WR08(ptr, pVga->IOBase + VGA_CRTC_DATA_OFFSET,  value);
34 }
35 static CARD8 NVReadCrtc(vgaHWPtr pVga, CARD8 index)
36 {
37     NVPtr pNv = (NVPtr)pVga->MMIOBase;
38     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
39     VGA_WR08(ptr, pVga->IOBase + VGA_CRTC_INDEX_OFFSET, index);
40     return (VGA_RD08(ptr, pVga->IOBase + VGA_CRTC_DATA_OFFSET));
41 }
42 static void NVWriteGr(vgaHWPtr pVga, CARD8 index, CARD8 value)
43 {
44     NVPtr pNv = (NVPtr)pVga->MMIOBase;
45     VGA_WR08(pNv->PVIO0, VGA_GRAPH_INDEX, index);
46     VGA_WR08(pNv->PVIO0, VGA_GRAPH_DATA,  value);
47 }
48 static CARD8 NVReadGr(vgaHWPtr pVga, CARD8 index)
49 {
50     NVPtr pNv = (NVPtr)pVga->MMIOBase;
51     VGA_WR08(pNv->PVIO0, VGA_GRAPH_INDEX, index);
52     return (VGA_RD08(pNv->PVIO0, VGA_GRAPH_DATA));
53 }
54 static void NVWriteSeq(vgaHWPtr pVga, CARD8 index, CARD8 value)
55 {
56     NVPtr pNv = (NVPtr)pVga->MMIOBase;
57     VGA_WR08(pNv->PVIO0, VGA_SEQ_INDEX, index);
58     VGA_WR08(pNv->PVIO0, VGA_SEQ_DATA,  value);
59 }
60 static CARD8 NVReadSeq(vgaHWPtr pVga, CARD8 index)
61 {
62     NVPtr pNv = (NVPtr)pVga->MMIOBase;
63     VGA_WR08(pNv->PVIO0, VGA_SEQ_INDEX, index);
64     return (VGA_RD08(pNv->PVIO0, VGA_SEQ_DATA));
65 }
66 static void NVWriteAttr(vgaHWPtr pVga, CARD8 index, CARD8 value)
67 {
68     NVPtr pNv = (NVPtr)pVga->MMIOBase;
69     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
70     volatile CARD8 tmp;
71
72     tmp = VGA_RD08(ptr, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
73     if (pVga->paletteEnabled)
74         index &= ~0x20;
75     else
76         index |= 0x20;
77     VGA_WR08(ptr, VGA_ATTR_INDEX,  index);
78     VGA_WR08(ptr, VGA_ATTR_DATA_W, value);
79 }
80 static CARD8 NVReadAttr(vgaHWPtr pVga, CARD8 index)
81 {
82     NVPtr pNv = (NVPtr)pVga->MMIOBase;
83     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
84     volatile CARD8 tmp;
85
86     tmp = VGA_RD08(ptr, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
87     if (pVga->paletteEnabled)
88         index &= ~0x20;
89     else
90         index |= 0x20;
91     VGA_WR08(ptr, VGA_ATTR_INDEX, index);
92     return (VGA_RD08(ptr, VGA_ATTR_DATA_R));
93 }
94 static void NVWriteMiscOut(vgaHWPtr pVga, CARD8 value)
95 {
96     NVPtr pNv = (NVPtr)pVga->MMIOBase;
97     VGA_WR08(pNv->PVIO0, VGA_MISC_OUT_W, value);
98 }
99 static CARD8 NVReadMiscOut(vgaHWPtr pVga)
100 {
101     NVPtr pNv = (NVPtr)pVga->MMIOBase;
102     return (VGA_RD08(pNv->PVIO0, VGA_MISC_OUT_R));
103 }
104 static void NVEnablePalette(vgaHWPtr pVga)
105 {
106     NVPtr pNv = (NVPtr)pVga->MMIOBase;
107     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
108     volatile CARD8 tmp;
109
110     tmp = VGA_RD08(ptr, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
111     VGA_WR08(ptr, VGA_ATTR_INDEX, 0x00);
112     pVga->paletteEnabled = TRUE;
113 }
114 static void NVDisablePalette(vgaHWPtr pVga)
115 {
116     NVPtr pNv = (NVPtr)pVga->MMIOBase;
117     volatile CARD8 *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
118     volatile CARD8 tmp;
119
120     tmp = VGA_RD08(ptr, pVga->IOBase + VGA_IN_STAT_1_OFFSET);
121     VGA_WR08(ptr, VGA_ATTR_INDEX, 0x20);
122     pVga->paletteEnabled = FALSE;
123 }
124 static void NVWriteDacMask(vgaHWPtr pVga, CARD8 value)
125 {
126     NVPtr pNv = (NVPtr)pVga->MMIOBase;
127     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
128     VGA_WR08(ptr, VGA_DAC_MASK, value);
129 }
130 static CARD8 NVReadDacMask(vgaHWPtr pVga)
131 {
132     NVPtr pNv = (NVPtr)pVga->MMIOBase;
133     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
134     return (VGA_RD08(ptr, VGA_DAC_MASK));
135 }
136 static void NVWriteDacReadAddr(vgaHWPtr pVga, CARD8 value)
137 {
138     NVPtr pNv = (NVPtr)pVga->MMIOBase;
139     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
140     VGA_WR08(ptr, VGA_DAC_READ_ADDR, value);
141 }
142 static void NVWriteDacWriteAddr(vgaHWPtr pVga, CARD8 value)
143 {
144     NVPtr pNv = (NVPtr)pVga->MMIOBase;
145     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
146     VGA_WR08(ptr, VGA_DAC_WRITE_ADDR, value);
147 }
148 static void NVWriteDacData(vgaHWPtr pVga, CARD8 value)
149 {
150     NVPtr pNv = (NVPtr)pVga->MMIOBase;
151     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
152     VGA_WR08(ptr, VGA_DAC_DATA, value);
153 }
154 static CARD8 NVReadDacData(vgaHWPtr pVga)
155 {
156     NVPtr pNv = (NVPtr)pVga->MMIOBase;
157     volatile CARD8 *ptr = pNv->cur_head ? pNv->PDIO1 : pNv->PDIO0;
158     return (VGA_RD08(ptr, VGA_DAC_DATA));
159 }
160
161 static Bool 
162 NVIsConnected (ScrnInfoPtr pScrn, int output)
163 {
164     NVPtr pNv = NVPTR(pScrn);
165     CARD32 reg52C, reg608, temp;
166     Bool present;
167
168     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
169                "Probing for analog device on output %s...\n", 
170                 output ? "B" : "A");
171
172     reg52C = NVReadRAMDAC(pNv, output, NV_RAMDAC_OUTPUT);
173     reg608 = NVReadRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL);
174
175     NVWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL, (reg608 & ~0x00010000));
176
177     NVWriteRAMDAC(pNv, output, NV_RAMDAC_OUTPUT, (reg52C & 0x0000FEEE));
178     usleep(1000);
179     
180     temp = NVReadRAMDAC(pNv, output, NV_RAMDAC_OUTPUT);
181     NVWriteRAMDAC(pNv, output, NV_RAMDAC_OUTPUT, temp | 1);
182
183     NVWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_DATA, 0x94050140);
184     temp = NVReadRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL);
185     NVWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
186
187     usleep(1000);
188
189     present = (NVReadRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
190
191     if(present)
192        xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "  ...found one\n");
193     else
194        xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "  ...can't find one\n");
195
196     temp = NVReadRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL);
197     NVWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
198
199     NVWriteRAMDAC(pNv, output, NV_RAMDAC_OUTPUT, reg52C);
200     NVWriteRAMDAC(pNv, output, NV_RAMDAC_TEST_CONTROL, reg608);
201
202     return present;
203 }
204
205 static void
206 NVSelectHeadRegisters(ScrnInfoPtr pScrn, int head)
207 {
208     NVPtr pNv = NVPTR(pScrn);
209
210     pNv->cur_head = head;
211 }
212
213 static xf86MonPtr 
214 NVProbeDDC (ScrnInfoPtr pScrn, int bus)
215 {
216     NVPtr pNv = NVPTR(pScrn);
217     xf86MonPtr MonInfo = NULL;
218
219     if(!pNv->I2C) return NULL;
220
221     pNv->DDCBase = bus ? 0x36 : 0x3e;
222
223     xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
224                "Probing for EDID on I2C bus %s...\n", bus ? "B" : "A");
225
226     if ((MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pNv->I2C))) {
227        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
228                   "DDC detected a %s:\n", MonInfo->features.input_type ?
229                   "DFP" : "CRT");
230        xf86PrintEDID( MonInfo );
231     } else {
232        xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
233                   "  ... none found\n");
234     }
235
236     return MonInfo;
237 }
238
239 static void store_initial_head_owner(ScrnInfoPtr pScrn)
240 {
241         NVPtr pNv = NVPTR(pScrn);
242
243         if (pNv->NVArch != 0x11) {
244                 pNv->vtOWNER = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_44);
245                 goto ownerknown;
246         }
247
248         /* reading CR44 is broken on nv11, so we attempt to infer it */
249         if (nvReadMC(pNv, NV_PBUS_DEBUG_1) & (1 << 28)) /* heads tied, restore both */
250                 pNv->vtOWNER = 0x4;
251         else {
252                 uint8_t slaved_on_A, slaved_on_B;
253                 bool tvA, tvB = false;
254
255                 NVLockVgaCrtcs(pNv, false);
256
257                 slaved_on_B = NVReadVgaCrtc(pNv, 1, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
258                 if (slaved_on_B)
259                         tvB = !(NVReadVgaCrtc(pNv, 1, NV_CIO_CRE_LCD__INDEX) & NV_CIO_CRE_LCD_LCD_SELECT);
260
261                 slaved_on_A = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
262                 if (slaved_on_A)
263                         tvA = !(NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_LCD__INDEX) & NV_CIO_CRE_LCD_LCD_SELECT);
264
265                 NVLockVgaCrtcs(pNv, true);
266
267                 if (slaved_on_A && !tvA)
268                         pNv->vtOWNER = 0x0;
269                 else if (slaved_on_B && !tvB)
270                         pNv->vtOWNER = 0x3;
271                 else if (slaved_on_A)
272                         pNv->vtOWNER = 0x0;
273                 else if (slaved_on_B)
274                         pNv->vtOWNER = 0x3;
275                 else
276                         pNv->vtOWNER = 0x0;
277         }
278
279 ownerknown:
280         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initial CRTC_OWNER is %d\n", pNv->vtOWNER);
281
282         /* we need to ensure the heads are not tied henceforth, or reading any
283          * 8 bit reg on head B will fail
284          * setting a single arbitrary head solves that */
285         NVSetOwner(pNv, 0);
286 }
287
288 static void nv4GetConfig (NVPtr pNv)
289 {
290         uint32_t reg_FB0 = nvReadFB(pNv, NV_PFB_BOOT_0);
291
292         if (reg_FB0 & 0x00000100)
293                 pNv->RamAmountKBytes = ((reg_FB0 >> 12) & 0x0F) * 1024 * 2 + 1024 * 2;
294         else
295                 switch (reg_FB0 & 0x00000003) {
296                 case 0:
297                         pNv->RamAmountKBytes = 1024 * 32;
298                         break;
299                 case 1:
300                         pNv->RamAmountKBytes = 1024 * 4;
301                         break;
302                 case 2:
303                         pNv->RamAmountKBytes = 1024 * 8;
304                         break;
305                 case 3:
306                 default:
307                         pNv->RamAmountKBytes = 1024 * 16;
308                         break;
309                 }
310
311         pNv->CrystalFreqKHz = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & 0x00000040) ? 14318 : 13500;
312         pNv->CURSOR         = &(pNv->PRAMIN[0x5E00]);
313         pNv->MinVClockFreqKHz = 12000;
314         pNv->MaxVClockFreqKHz = 350000;
315 }
316
317 static void nForce_check_dimms(ScrnInfoPtr pScrn)
318 {
319         uint16_t mem_ctrlr_pciid = PCI_SLOT_READ_LONG(3, 0x00) >> 16;
320
321         if ((mem_ctrlr_pciid == 0x1a9) || (mem_ctrlr_pciid == 0x1ab) || (mem_ctrlr_pciid == 0x1ed)) {
322                 uint32_t dimm[3];
323
324                 dimm[0] = (PCI_SLOT_READ_LONG(2, 0x40) >> 8) & 0x4f;
325                 dimm[1] = (PCI_SLOT_READ_LONG(2, 0x44) >> 8) & 0x4f;
326                 dimm[2] = (PCI_SLOT_READ_LONG(2, 0x48) >> 8) & 0x4f;
327
328                 if (dimm[0] + dimm[1] != dimm[2])
329                         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
330                                    "Your nForce DIMMs are not arranged in optimal banks!\n");
331         }
332 }
333
334 static void nv10GetConfig(ScrnInfoPtr pScrn)
335 {
336         NVPtr pNv = NVPTR(pScrn);
337         uint32_t implementation = pNv->Chipset & 0x0ff0;
338
339 #if X_BYTE_ORDER == X_BIG_ENDIAN
340         if (!(nvReadMC(pNv, 0x0004) & 0x01000001))
341                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
342                            "Card is in big endian mode, something is very wrong !\n");
343 #endif
344
345         if (implementation == CHIPSET_NFORCE) {
346                 pNv->RamAmountKBytes = (((PCI_SLOT_READ_LONG(1, 0x7c) >> 6) & 31) + 1) * 1024;
347                 nForce_check_dimms(pScrn);
348         } else if (implementation == CHIPSET_NFORCE2) {
349                 pNv->RamAmountKBytes = (((PCI_SLOT_READ_LONG(1, 0x84) >> 4) & 127) + 1) * 1024;
350                 nForce_check_dimms(pScrn);
351         } else
352                 pNv->RamAmountKBytes = (nvReadFB(pNv, NV_PFB_CSTATUS) & 0xFFF00000) >> 10;
353
354         if (pNv->RamAmountKBytes > 256*1024)
355                 pNv->RamAmountKBytes = 256*1024;
356
357         pNv->CrystalFreqKHz = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & (1 << 6)) ? 14318 : 13500;
358         if (pNv->twoHeads && implementation != CHIPSET_NV11)
359                 if (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & (1 << 22))
360                         pNv->CrystalFreqKHz = 27000;
361
362         pNv->CURSOR           = NULL;  /* can't set this here */
363         pNv->MinVClockFreqKHz = 12000;
364         pNv->MaxVClockFreqKHz = pNv->twoStagePLL ? 400000 : 350000;
365 }
366
367 void
368 NVCommonSetup(ScrnInfoPtr pScrn)
369 {
370         NVPtr pNv = NVPTR(pScrn);
371         vgaHWPtr pVga = VGAHWPTR(pScrn);
372         uint16_t implementation = pNv->Chipset & 0x0ff0;
373         bool tvA = false;
374         bool tvB = false;
375         xf86MonPtr monitorA, monitorB;
376         int FlatPanel = -1;   /* really means the CRTC is slaved */
377         bool Television = false;
378  
379     /*
380      * Override VGA I/O routines.
381      */
382     pVga->writeCrtc         = NVWriteCrtc;
383     pVga->readCrtc          = NVReadCrtc;
384     pVga->writeGr           = NVWriteGr;
385     pVga->readGr            = NVReadGr;
386     pVga->writeAttr         = NVWriteAttr;
387     pVga->readAttr          = NVReadAttr;
388     pVga->writeSeq          = NVWriteSeq;
389     pVga->readSeq           = NVReadSeq;
390     pVga->writeMiscOut      = NVWriteMiscOut;
391     pVga->readMiscOut       = NVReadMiscOut;
392     pVga->enablePalette     = NVEnablePalette;
393     pVga->disablePalette    = NVDisablePalette;
394     pVga->writeDacMask      = NVWriteDacMask;
395     pVga->readDacMask       = NVReadDacMask;
396     pVga->writeDacWriteAddr = NVWriteDacWriteAddr;
397     pVga->writeDacReadAddr  = NVWriteDacReadAddr;
398     pVga->writeDacData      = NVWriteDacData;
399     pVga->readDacData       = NVReadDacData;
400     /*
401      * Note: There are different pointers to the CRTC/AR and GR/SEQ registers.
402      * Bastardize the intended uses of these to make it work.
403      */
404     pVga->MMIOBase   = (CARD8 *)pNv;
405     pVga->MMIOOffset = 0;
406
407 #ifndef XSERVER_LIBPCIACCESS
408         pNv->REGS = xf86MapPciMem(pScrn->scrnIndex, 
409                         VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, 
410                         pNv->PciTag, pNv->IOAddress, 0x01000000);
411         pNv->FB_BAR = xf86MapPciMem(pScrn->scrnIndex,
412                         VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
413                         pNv->PciTag, pNv->VRAMPhysical, 0x10000);
414 #else
415         /* 0x01000000 is the size */
416         pci_device_map_range(pNv->PciInfo, pNv->IOAddress, 0x01000000, PCI_DEV_MAP_FLAG_WRITABLE, (void *)&pNv->REGS);
417         pci_device_map_range(pNv->PciInfo, pNv->VRAMPhysical, 0x10000, PCI_DEV_MAP_FLAG_WRITABLE, (void *)&pNv->FB_BAR);
418 #endif /* XSERVER_LIBPCIACCESS */
419
420         pNv->PRAMIN   = pNv->REGS + (NV_PRAMIN_OFFSET/4);
421         pNv->PGRAPH   = pNv->REGS + (NV_PGRAPH_OFFSET/4);
422
423         /* 8 bit registers */
424         pNv->PCIO0    = (uint8_t *)pNv->REGS + NV_PRMCIO0_OFFSET;
425         pNv->PDIO0    = (uint8_t *)pNv->REGS + NV_PRMDIO0_OFFSET;
426         pNv->PVIO0    = (uint8_t *)pNv->REGS + NV_PRMVIO0_OFFSET;
427         pNv->PCIO1    = pNv->PCIO0 + NV_PRMCIO_SIZE;
428         pNv->PDIO1    = pNv->PDIO0 + NV_PRMDIO_SIZE;
429         pNv->PVIO1    = pNv->PVIO0 + NV_PRMVIO_SIZE;
430
431         pNv->alphaCursor = (pNv->NVArch >= 0x11);
432
433         pNv->twoHeads = (pNv->Architecture >= NV_ARCH_10) &&
434                         (implementation != CHIPSET_NV10) &&
435                         (implementation != CHIPSET_NV15) &&
436                         (implementation != CHIPSET_NFORCE) &&
437                         (implementation != CHIPSET_NV20);
438
439         pNv->fpScaler = (pNv->FpScale && pNv->twoHeads && implementation != CHIPSET_NV11);
440
441         /* nv30 and nv35 have two stage PLLs, but use only one register; they are dealt with separately */
442         pNv->twoStagePLL = (implementation == CHIPSET_NV31) ||
443                            (implementation == CHIPSET_NV36) ||
444                            (pNv->Architecture >= NV_ARCH_40);
445
446         pNv->WaitVSyncPossible = (pNv->Architecture >= NV_ARCH_10) &&
447                                  (implementation != CHIPSET_NV10);
448
449         pNv->BlendingPossible = ((pNv->Chipset & 0xffff) > CHIPSET_NV04);
450
451     /* look for known laptop chips */
452     /* FIXME still probably missing some ids (for randr12, pre-nv40 mobile should be auto-detected) */
453     switch(pNv->Chipset & 0xffff) {
454     case 0x0098:
455     case 0x0099:
456     case 0x00C8:
457     case 0x00C9:
458     case 0x00CC:
459     case 0x0112:
460     case 0x0144:
461     case 0x0146:
462     case 0x0148:
463     case 0x0149:
464     case 0x0160:
465     case 0x0164:
466     case 0x0166:
467     case 0x0167:
468     case 0x0168:
469     case 0x0169:
470     case 0x016B:
471     case 0x016C:
472     case 0x016D:
473     case 0x0174:
474     case 0x0175:
475     case 0x0176:
476     case 0x0177:
477     case 0x0179:
478     case 0x017C:
479     case 0x017D:
480     case 0x0186:
481     case 0x0187:
482     case 0x018D:
483     case 0x01D6:
484     case 0x01D7:
485     case 0x01D8:
486     case 0x0228:
487     case 0x0244:
488     case 0x0286:
489     case 0x028C:
490     case 0x0297:
491     case 0x0298:
492     case 0x0299:
493     case 0x0316:
494     case 0x0317:
495     case 0x031A:
496     case 0x031B:
497     case 0x031C:
498     case 0x031D:
499     case 0x031E:
500     case 0x031F:
501     case 0x0324:
502     case 0x0325:
503     case 0x0328:
504     case 0x0329:
505     case 0x032C:
506     case 0x032D:
507     case 0x0347:
508     case 0x0348:
509     case 0x0349:
510     case 0x034B:
511     case 0x034C:
512     case 0x0397:
513     case 0x0398:
514     case 0x039B:
515         pNv->Mobile = TRUE;
516         break;
517     default:
518         break;
519     }
520
521         pNv->Television = FALSE;
522
523         if (pNv->twoHeads)
524                 store_initial_head_owner(pScrn);
525
526         /* Parse the bios to initialize the card */
527         NVParseBios(pScrn);
528
529         if (pNv->Architecture == NV_ARCH_04)
530                 nv4GetConfig(pNv);
531         else
532                 nv10GetConfig(pScrn);
533
534     if (!pNv->randr12_enable) {
535       
536         NVSelectHeadRegisters(pScrn, 0);
537         
538         NVLockUnlock(pScrn, 0);
539         
540         NVI2CInit(pScrn);
541         
542         
543         if(!pNv->twoHeads) {
544             pNv->crtc_active[0] = TRUE;
545             pNv->crtc_active[1] = FALSE;
546             if((monitorA = NVProbeDDC(pScrn, 0))) {
547                 FlatPanel = monitorA->features.input_type ? 1 : 0;
548                 
549                 /* NV4 doesn't support FlatPanels */
550                 if((pNv->Chipset & 0x0fff) <= CHIPSET_NV04)
551                     FlatPanel = 0;
552             } else {
553                 if(nvReadCurVGA(pNv, NV_CIO_CRE_PIXEL_INDEX) & 0x80) {
554                     if(!(nvReadCurVGA(pNv, NV_CIO_CRE_LCD__INDEX) & 0x01))
555                         Television = TRUE;
556                     FlatPanel = 1;
557                 } else {
558                     FlatPanel = 0;
559                 }
560                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
561                            "HW is currently programmed for %s\n",
562                            FlatPanel ? (Television ? "TV" : "DFP") : "CRT");
563             } 
564             
565             if(pNv->FlatPanel == -1) {
566                 pNv->FlatPanel = FlatPanel;
567                 pNv->Television = Television;
568             } else {
569                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
570                            "Forcing display type to %s as specified\n", 
571                            pNv->FlatPanel ? "DFP" : "CRT");
572             }
573         } else {
574             CARD8 outputAfromCRTC, outputBfromCRTC;
575             pNv->crtc_active[0] = FALSE;
576             pNv->crtc_active[1] = FALSE;
577             CARD8 slaved_on_A, slaved_on_B;
578             Bool analog_on_A, analog_on_B;
579             CARD32 oldhead;
580             CARD8 cr44;
581             
582             if(implementation != CHIPSET_NV11) {
583                 if(NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT) & 0x100)
584                     outputAfromCRTC = 1;
585                 else            
586                     outputAfromCRTC = 0;
587                 if(NVReadRAMDAC(pNv, 1, NV_RAMDAC_OUTPUT) & 0x100)
588                     outputBfromCRTC = 1;
589                 else
590                     outputBfromCRTC = 0;
591                 analog_on_A = NVIsConnected(pScrn, 0);
592                 analog_on_B = NVIsConnected(pScrn, 1);
593             } else {
594                 outputAfromCRTC = 0;
595                 outputBfromCRTC = 1;
596                 analog_on_A = FALSE;
597                 analog_on_B = FALSE;
598             }
599             
600             cr44 = pNv->vtOWNER;
601             
602             nvWriteCurVGA(pNv, NV_CIO_CRE_44, 3);
603             NVSelectHeadRegisters(pScrn, 1);
604             NVLockUnlock(pScrn, 0);
605             
606             slaved_on_B = nvReadCurVGA(pNv, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
607             if(slaved_on_B) {
608                 tvB = !(nvReadCurVGA(pNv, NV_CIO_CRE_LCD__INDEX) & 0x01);
609             }
610             
611             nvWriteCurVGA(pNv, NV_CIO_CRE_44, 0);
612             NVSelectHeadRegisters(pScrn, 0);
613             NVLockUnlock(pScrn, 0);
614             
615             slaved_on_A = nvReadCurVGA(pNv, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
616             if(slaved_on_A) {
617                 tvA = !(nvReadCurVGA(pNv, NV_CIO_CRE_LCD__INDEX) & 0x01);
618             }
619             
620             oldhead = NVReadCRTC(pNv, 0, NV_CRTC_FSEL);
621             NVWriteCRTC(pNv, 0, NV_CRTC_FSEL, oldhead | 0x00000010);
622             
623             monitorA = NVProbeDDC(pScrn, 0);
624             monitorB = NVProbeDDC(pScrn, 1);
625             
626             if(slaved_on_A && !tvA) {
627                 pNv->crtc_active[0] = TRUE;
628                 FlatPanel = 1;
629                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
630                            "CRTC 0 is currently programmed for DFP\n");
631             } else 
632                 if(slaved_on_B && !tvB) {
633                     pNv->crtc_active[1] = TRUE;
634                     FlatPanel = 1;
635                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
636                                "CRTC 1 is currently programmed for DFP\n");
637                 } else
638                     if(analog_on_A) {
639                         pNv->crtc_active[outputAfromCRTC] = TRUE;
640                         FlatPanel = 0;
641                         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
642                                    "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
643                     } else
644                         if(analog_on_B) {
645                             pNv->crtc_active[outputBfromCRTC] = TRUE;
646                             FlatPanel = 0;
647                             xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
648                                        "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
649                         } else
650                             if(slaved_on_A) {
651                                 pNv->crtc_active[0] = TRUE;
652                                 FlatPanel = 1;
653                                 Television = 1;
654                                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
655                                            "CRTC 0 is currently programmed for TV\n");
656                             } else
657                                 if(slaved_on_B) {
658                                     pNv->crtc_active[1] = TRUE;
659                                     FlatPanel = 1;
660                                     Television = 1;
661                                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
662                                                "CRTC 1 is currently programmed for TV\n");
663                                 } else
664                                     if(monitorA) {
665                                         FlatPanel = monitorA->features.input_type ? 1 : 0;
666                                     } else 
667                                         if(monitorB) {
668                                             FlatPanel = monitorB->features.input_type ? 1 : 0;
669                                         }
670             
671             if(pNv->FlatPanel == -1) {
672                 if(FlatPanel != -1) {
673                     pNv->FlatPanel = FlatPanel;
674                     pNv->Television = Television;
675                 } else {
676                     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
677                                "Unable to detect display type...\n");
678                     if(pNv->Mobile) {
679                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
680                                    "...On a laptop, assuming DFP\n");
681                         pNv->FlatPanel = 1;
682                     } else {
683                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
684                                    "...Using default of CRT\n");
685                         pNv->FlatPanel = 0;
686                     }
687                 }
688             } else {
689                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
690                            "Forcing display type to %s as specified\n", 
691                            pNv->FlatPanel ? "DFP" : "CRT");
692             }
693             
694                 if(!(pNv->crtc_active[0]) && !(pNv->crtc_active[1])) {
695                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
696                                 "Unable to detect which CRTC is used...\n");
697                         if(pNv->FlatPanel) {
698                                 pNv->crtc_active[1] = TRUE;
699                         } else {
700                                 pNv->crtc_active[0] = TRUE;
701                         }
702                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
703                         "...Defaulting to CRTCNumber %i\n", pNv->crtc_active[1]);
704                 }
705
706             if(monitorA) {
707                 if((monitorA->features.input_type && pNv->FlatPanel) ||
708                    (!monitorA->features.input_type && !pNv->FlatPanel))
709                 {
710                     if(monitorB) { 
711                         xfree(monitorB);
712                         monitorB = NULL;
713                     }
714                 } else {
715                     xfree(monitorA);
716                     monitorA = NULL;
717                 }
718             }
719             
720             if(monitorB) {
721                 if((monitorB->features.input_type && !pNv->FlatPanel) ||
722                    (!monitorB->features.input_type && pNv->FlatPanel)) 
723                 {
724                     xfree(monitorB);
725                 } else {
726                     monitorA = monitorB;
727                 }
728                 monitorB = NULL;
729             }
730             
731             if(implementation == CHIPSET_NV11)
732                 cr44 = pNv->crtc_active[1] * 0x3;
733             
734             NVWriteCRTC(pNv, 0, NV_CRTC_FSEL,  oldhead);
735
736             nvWriteCurVGA(pNv, NV_CIO_CRE_44, cr44);
737             NVSelectHeadRegisters(pScrn, pNv->crtc_active[1]);
738         }
739         
740         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
741                    "Using %s on CRTC %i\n",
742                    pNv->FlatPanel ? (pNv->Television ? "TV" : "DFP") : "CRT", 
743                    pNv->crtc_active[1]);
744         
745         if(pNv->FlatPanel && !pNv->Television) {
746             pNv->fpWidth = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HDISP_END) + 1;
747             pNv->fpHeight = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_VDISP_END) + 1;
748             pNv->fpSyncs = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL) & 0x30000033;
749             xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
750                        pNv->fpWidth, pNv->fpHeight);
751         }
752         
753         if(monitorA)
754             xf86SetDDCproperties(pScrn, monitorA);
755
756         if(!pNv->FlatPanel || (pScrn->depth != 24) || !pNv->twoHeads)
757             pNv->FPDither = FALSE;
758         
759         pNv->LVDS = FALSE;
760         if(pNv->FlatPanel && pNv->twoHeads) {
761             NVWriteRAMDAC(pNv, 0, NV_RAMDAC_FP_TMDS_CONTROL, 0x00010004);
762             if(NVReadRAMDAC(pNv, 0, NV_RAMDAC_FP_TMDS_DATA) & 1)
763                 pNv->LVDS = TRUE;
764             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel is %s\n", 
765                        pNv->LVDS ? "LVDS" : "TMDS");
766         }
767     }
768 }
769