Rename relevant functions, sizes and offsets to PRM.IO from P.IO, in keeping with...
[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 nv4GetConfig (NVPtr pNv)
240 {
241         uint32_t reg_FB0 = nvReadFB(pNv, NV_PFB_BOOT_0);
242
243         if (reg_FB0 & 0x00000100)
244                 pNv->RamAmountKBytes = ((reg_FB0 >> 12) & 0x0F) * 1024 * 2 + 1024 * 2;
245         else
246                 switch (reg_FB0 & 0x00000003) {
247                 case 0:
248                         pNv->RamAmountKBytes = 1024 * 32;
249                         break;
250                 case 1:
251                         pNv->RamAmountKBytes = 1024 * 4;
252                         break;
253                 case 2:
254                         pNv->RamAmountKBytes = 1024 * 8;
255                         break;
256                 case 3:
257                 default:
258                         pNv->RamAmountKBytes = 1024 * 16;
259                         break;
260                 }
261
262         pNv->CrystalFreqKHz = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & 0x00000040) ? 14318 : 13500;
263         pNv->CURSOR         = &(pNv->PRAMIN[0x5E00]);
264         pNv->MinVClockFreqKHz = 12000;
265         pNv->MaxVClockFreqKHz = 350000;
266 }
267
268 static void nForce_check_dimms(ScrnInfoPtr pScrn)
269 {
270         uint16_t mem_ctrlr_pciid = PCI_SLOT_READ_LONG(3, 0x00) >> 16;
271
272         if ((mem_ctrlr_pciid == 0x1a9) || (mem_ctrlr_pciid == 0x1ab) || (mem_ctrlr_pciid == 0x1ed)) {
273                 uint32_t dimm[3];
274
275                 dimm[0] = (PCI_SLOT_READ_LONG(2, 0x40) >> 8) & 0x4f;
276                 dimm[1] = (PCI_SLOT_READ_LONG(2, 0x44) >> 8) & 0x4f;
277                 dimm[2] = (PCI_SLOT_READ_LONG(2, 0x48) >> 8) & 0x4f;
278
279                 if (dimm[0] + dimm[1] != dimm[2])
280                         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
281                                    "Your nForce DIMMs are not arranged in optimal banks!\n");
282         }
283 }
284
285 static void nv10GetConfig(ScrnInfoPtr pScrn)
286 {
287         NVPtr pNv = NVPTR(pScrn);
288         uint32_t implementation = pNv->Chipset & 0x0ff0;
289
290 #if X_BYTE_ORDER == X_BIG_ENDIAN
291         if (!(nvReadMC(pNv, 0x0004) & 0x01000001))
292                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
293                            "Card is in big endian mode, something is very wrong !\n");
294 #endif
295
296         if (implementation == CHIPSET_NFORCE) {
297                 pNv->RamAmountKBytes = (((PCI_SLOT_READ_LONG(1, 0x7c) >> 6) & 31) + 1) * 1024;
298                 nForce_check_dimms(pScrn);
299         } else if (implementation == CHIPSET_NFORCE2) {
300                 pNv->RamAmountKBytes = (((PCI_SLOT_READ_LONG(1, 0x84) >> 4) & 127) + 1) * 1024;
301                 nForce_check_dimms(pScrn);
302         } else
303                 pNv->RamAmountKBytes = (nvReadFB(pNv, NV_PFB_020C) & 0xFFF00000) >> 10;
304
305         if (pNv->RamAmountKBytes > 256*1024)
306                 pNv->RamAmountKBytes = 256*1024;
307
308         pNv->CrystalFreqKHz = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & (1 << 6)) ? 14318 : 13500;
309         if (pNv->twoHeads && implementation != CHIPSET_NV11)
310                 if (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & (1 << 22))
311                         pNv->CrystalFreqKHz = 27000;
312
313         pNv->CURSOR           = NULL;  /* can't set this here */
314         pNv->MinVClockFreqKHz = 12000;
315         pNv->MaxVClockFreqKHz = pNv->twoStagePLL ? 400000 : 350000;
316 }
317
318 void
319 NVCommonSetup(ScrnInfoPtr pScrn)
320 {
321         NVPtr pNv = NVPTR(pScrn);
322         vgaHWPtr pVga = VGAHWPTR(pScrn);
323         uint16_t implementation = pNv->Chipset & 0x0ff0;
324         bool tvA = false;
325         bool tvB = false;
326         xf86MonPtr monitorA, monitorB;
327         int FlatPanel = -1;   /* really means the CRTC is slaved */
328         bool Television = false;
329  
330     /*
331      * Override VGA I/O routines.
332      */
333     pVga->writeCrtc         = NVWriteCrtc;
334     pVga->readCrtc          = NVReadCrtc;
335     pVga->writeGr           = NVWriteGr;
336     pVga->readGr            = NVReadGr;
337     pVga->writeAttr         = NVWriteAttr;
338     pVga->readAttr          = NVReadAttr;
339     pVga->writeSeq          = NVWriteSeq;
340     pVga->readSeq           = NVReadSeq;
341     pVga->writeMiscOut      = NVWriteMiscOut;
342     pVga->readMiscOut       = NVReadMiscOut;
343     pVga->enablePalette     = NVEnablePalette;
344     pVga->disablePalette    = NVDisablePalette;
345     pVga->writeDacMask      = NVWriteDacMask;
346     pVga->readDacMask       = NVReadDacMask;
347     pVga->writeDacWriteAddr = NVWriteDacWriteAddr;
348     pVga->writeDacReadAddr  = NVWriteDacReadAddr;
349     pVga->writeDacData      = NVWriteDacData;
350     pVga->readDacData       = NVReadDacData;
351     /*
352      * Note: There are different pointers to the CRTC/AR and GR/SEQ registers.
353      * Bastardize the intended uses of these to make it work.
354      */
355     pVga->MMIOBase   = (CARD8 *)pNv;
356     pVga->MMIOOffset = 0;
357
358 #ifndef XSERVER_LIBPCIACCESS
359         pNv->REGS = xf86MapPciMem(pScrn->scrnIndex, 
360                         VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, 
361                         pNv->PciTag, pNv->IOAddress, 0x01000000);
362         pNv->FB_BAR = xf86MapPciMem(pScrn->scrnIndex,
363                         VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
364                         pNv->PciTag, pNv->VRAMPhysical, 0x10000);
365 #else
366         /* 0x01000000 is the size */
367         pci_device_map_range(pNv->PciInfo, pNv->IOAddress, 0x01000000, PCI_DEV_MAP_FLAG_WRITABLE, (void *)&pNv->REGS);
368         pci_device_map_range(pNv->PciInfo, pNv->VRAMPhysical, 0x10000, PCI_DEV_MAP_FLAG_WRITABLE, (void *)&pNv->FB_BAR);
369 #endif /* XSERVER_LIBPCIACCESS */
370
371         pNv->PRAMIN   = pNv->REGS + (NV_PRAMIN_OFFSET/4);
372         pNv->PGRAPH   = pNv->REGS + (NV_PGRAPH_OFFSET/4);
373
374         /* 8 bit registers */
375         pNv->PCIO0    = (uint8_t *)pNv->REGS + NV_PRMCIO0_OFFSET;
376         pNv->PDIO0    = (uint8_t *)pNv->REGS + NV_PRMDIO0_OFFSET;
377         pNv->PVIO0    = (uint8_t *)pNv->REGS + NV_PRMVIO0_OFFSET;
378         pNv->PCIO1    = pNv->PCIO0 + NV_PRMCIO_SIZE;
379         pNv->PDIO1    = pNv->PDIO0 + NV_PRMDIO_SIZE;
380         pNv->PVIO1    = pNv->PVIO0 + NV_PRMVIO_SIZE;
381
382         pNv->alphaCursor = (pNv->NVArch >= 0x11);
383
384         pNv->twoHeads = (pNv->Architecture >= NV_ARCH_10) &&
385                         (implementation != CHIPSET_NV10) &&
386                         (implementation != CHIPSET_NV15) &&
387                         (implementation != CHIPSET_NFORCE) &&
388                         (implementation != CHIPSET_NV20);
389
390         pNv->fpScaler = (pNv->FpScale && pNv->twoHeads && implementation != CHIPSET_NV11);
391
392         /* nv30 and nv35 have two stage PLLs, but use only one register; they are dealt with separately */
393         pNv->twoStagePLL = (implementation == CHIPSET_NV31) ||
394                            (implementation == CHIPSET_NV36) ||
395                            (pNv->Architecture >= NV_ARCH_40);
396
397         pNv->WaitVSyncPossible = (pNv->Architecture >= NV_ARCH_10) &&
398                                  (implementation != CHIPSET_NV10);
399
400         pNv->BlendingPossible = ((pNv->Chipset & 0xffff) > CHIPSET_NV04);
401
402     /* look for known laptop chips */
403     /* FIXME still probably missing some ids (for randr12, pre-nv40 mobile should be auto-detected) */
404     switch(pNv->Chipset & 0xffff) {
405     case 0x0098:
406     case 0x0099:
407     case 0x00C8:
408     case 0x00C9:
409     case 0x00CC:
410     case 0x0112:
411     case 0x0144:
412     case 0x0146:
413     case 0x0148:
414     case 0x0149:
415     case 0x0160:
416     case 0x0164:
417     case 0x0166:
418     case 0x0167:
419     case 0x0168:
420     case 0x0169:
421     case 0x016B:
422     case 0x016C:
423     case 0x016D:
424     case 0x0174:
425     case 0x0175:
426     case 0x0176:
427     case 0x0177:
428     case 0x0179:
429     case 0x017C:
430     case 0x017D:
431     case 0x0186:
432     case 0x0187:
433     case 0x018D:
434     case 0x01D6:
435     case 0x01D7:
436     case 0x01D8:
437     case 0x0228:
438     case 0x0244:
439     case 0x0286:
440     case 0x028C:
441     case 0x0297:
442     case 0x0298:
443     case 0x0299:
444     case 0x0316:
445     case 0x0317:
446     case 0x031A:
447     case 0x031B:
448     case 0x031C:
449     case 0x031D:
450     case 0x031E:
451     case 0x031F:
452     case 0x0324:
453     case 0x0325:
454     case 0x0328:
455     case 0x0329:
456     case 0x032C:
457     case 0x032D:
458     case 0x0347:
459     case 0x0348:
460     case 0x0349:
461     case 0x034B:
462     case 0x034C:
463     case 0x0397:
464     case 0x0398:
465     case 0x039B:
466         pNv->Mobile = TRUE;
467         break;
468     default:
469         break;
470     }
471
472         pNv->Television = FALSE;
473
474         if (pNv->twoHeads) {
475                 pNv->vtOWNER = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_44);
476                 if (pNv->NVArch == 0x11) {      /* reading OWNER is broken on nv11 */
477                         if (nvReadMC(pNv, NV_PBUS_DEBUG_1) & (1 << 28)) /* heads tied, restore both */
478                                 pNv->vtOWNER = 0x04;
479                         else {
480                                 uint8_t slaved_on_A, slaved_on_B;
481
482                                 NVSetOwner(pNv, 1);
483                                 NVLockVgaCrtc(pNv, 1, false);
484
485                                 slaved_on_B = NVReadVgaCrtc(pNv, 1, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
486                                 if (slaved_on_B)
487                                         tvB = !(NVReadVgaCrtc(pNv, 1, NV_CIO_CRE_LCD__INDEX) & 0x01);
488
489                                 NVSetOwner(pNv, 0);
490                                 NVLockVgaCrtc(pNv, 0, false);
491
492                                 slaved_on_A = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
493                                 if (slaved_on_A)
494                                         tvA = !(NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_LCD__INDEX) & 0x01);
495
496                                 if (slaved_on_A && !tvA)
497                                         pNv->vtOWNER = 0x0;
498                                 else if (slaved_on_B && !tvB)
499                                         pNv->vtOWNER = 0x3;
500                                 else if (slaved_on_A)
501                                         pNv->vtOWNER = 0x0;
502                                 else if (slaved_on_B)
503                                         pNv->vtOWNER = 0x3;
504                                 else
505                                         pNv->vtOWNER = 0x0;
506                         }
507                 }
508
509                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initial CRTC_OWNER is %d\n", pNv->vtOWNER);
510         }
511
512         /* Parse the bios to initialize the card */
513         NVParseBios(pScrn);
514
515         if (pNv->Architecture == NV_ARCH_04)
516                 nv4GetConfig(pNv);
517         else
518                 nv10GetConfig(pScrn);
519
520     if (!pNv->randr12_enable) {
521       
522         NVSelectHeadRegisters(pScrn, 0);
523         
524         NVLockUnlock(pScrn, 0);
525         
526         NVI2CInit(pScrn);
527         
528         
529         if(!pNv->twoHeads) {
530             pNv->crtc_active[0] = TRUE;
531             pNv->crtc_active[1] = FALSE;
532             if((monitorA = NVProbeDDC(pScrn, 0))) {
533                 FlatPanel = monitorA->features.input_type ? 1 : 0;
534                 
535                 /* NV4 doesn't support FlatPanels */
536                 if((pNv->Chipset & 0x0fff) <= CHIPSET_NV04)
537                     FlatPanel = 0;
538             } else {
539                 if(nvReadCurVGA(pNv, NV_CIO_CRE_PIXEL_INDEX) & 0x80) {
540                     if(!(nvReadCurVGA(pNv, NV_CIO_CRE_LCD__INDEX) & 0x01))
541                         Television = TRUE;
542                     FlatPanel = 1;
543                 } else {
544                     FlatPanel = 0;
545                 }
546                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
547                            "HW is currently programmed for %s\n",
548                            FlatPanel ? (Television ? "TV" : "DFP") : "CRT");
549             } 
550             
551             if(pNv->FlatPanel == -1) {
552                 pNv->FlatPanel = FlatPanel;
553                 pNv->Television = Television;
554             } else {
555                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
556                            "Forcing display type to %s as specified\n", 
557                            pNv->FlatPanel ? "DFP" : "CRT");
558             }
559         } else {
560             CARD8 outputAfromCRTC, outputBfromCRTC;
561             pNv->crtc_active[0] = FALSE;
562             pNv->crtc_active[1] = FALSE;
563             CARD8 slaved_on_A, slaved_on_B;
564             Bool analog_on_A, analog_on_B;
565             CARD32 oldhead;
566             CARD8 cr44;
567             
568             if(implementation != CHIPSET_NV11) {
569                 if(NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT) & 0x100)
570                     outputAfromCRTC = 1;
571                 else            
572                     outputAfromCRTC = 0;
573                 if(NVReadRAMDAC(pNv, 1, NV_RAMDAC_OUTPUT) & 0x100)
574                     outputBfromCRTC = 1;
575                 else
576                     outputBfromCRTC = 0;
577                 analog_on_A = NVIsConnected(pScrn, 0);
578                 analog_on_B = NVIsConnected(pScrn, 1);
579             } else {
580                 outputAfromCRTC = 0;
581                 outputBfromCRTC = 1;
582                 analog_on_A = FALSE;
583                 analog_on_B = FALSE;
584             }
585             
586             cr44 = pNv->vtOWNER;
587             
588             nvWriteCurVGA(pNv, NV_CIO_CRE_44, 3);
589             NVSelectHeadRegisters(pScrn, 1);
590             NVLockUnlock(pScrn, 0);
591             
592             slaved_on_B = nvReadCurVGA(pNv, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
593             if(slaved_on_B) {
594                 tvB = !(nvReadCurVGA(pNv, NV_CIO_CRE_LCD__INDEX) & 0x01);
595             }
596             
597             nvWriteCurVGA(pNv, NV_CIO_CRE_44, 0);
598             NVSelectHeadRegisters(pScrn, 0);
599             NVLockUnlock(pScrn, 0);
600             
601             slaved_on_A = nvReadCurVGA(pNv, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
602             if(slaved_on_A) {
603                 tvA = !(nvReadCurVGA(pNv, NV_CIO_CRE_LCD__INDEX) & 0x01);
604             }
605             
606             oldhead = NVReadCRTC(pNv, 0, NV_CRTC_FSEL);
607             NVWriteCRTC(pNv, 0, NV_CRTC_FSEL, oldhead | 0x00000010);
608             
609             monitorA = NVProbeDDC(pScrn, 0);
610             monitorB = NVProbeDDC(pScrn, 1);
611             
612             if(slaved_on_A && !tvA) {
613                 pNv->crtc_active[0] = TRUE;
614                 FlatPanel = 1;
615                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
616                            "CRTC 0 is currently programmed for DFP\n");
617             } else 
618                 if(slaved_on_B && !tvB) {
619                     pNv->crtc_active[1] = TRUE;
620                     FlatPanel = 1;
621                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
622                                "CRTC 1 is currently programmed for DFP\n");
623                 } else
624                     if(analog_on_A) {
625                         pNv->crtc_active[outputAfromCRTC] = TRUE;
626                         FlatPanel = 0;
627                         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
628                                    "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
629                     } else
630                         if(analog_on_B) {
631                             pNv->crtc_active[outputBfromCRTC] = TRUE;
632                             FlatPanel = 0;
633                             xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
634                                        "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
635                         } else
636                             if(slaved_on_A) {
637                                 pNv->crtc_active[0] = TRUE;
638                                 FlatPanel = 1;
639                                 Television = 1;
640                                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
641                                            "CRTC 0 is currently programmed for TV\n");
642                             } else
643                                 if(slaved_on_B) {
644                                     pNv->crtc_active[1] = TRUE;
645                                     FlatPanel = 1;
646                                     Television = 1;
647                                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
648                                                "CRTC 1 is currently programmed for TV\n");
649                                 } else
650                                     if(monitorA) {
651                                         FlatPanel = monitorA->features.input_type ? 1 : 0;
652                                     } else 
653                                         if(monitorB) {
654                                             FlatPanel = monitorB->features.input_type ? 1 : 0;
655                                         }
656             
657             if(pNv->FlatPanel == -1) {
658                 if(FlatPanel != -1) {
659                     pNv->FlatPanel = FlatPanel;
660                     pNv->Television = Television;
661                 } else {
662                     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
663                                "Unable to detect display type...\n");
664                     if(pNv->Mobile) {
665                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
666                                    "...On a laptop, assuming DFP\n");
667                         pNv->FlatPanel = 1;
668                     } else {
669                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
670                                    "...Using default of CRT\n");
671                         pNv->FlatPanel = 0;
672                     }
673                 }
674             } else {
675                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
676                            "Forcing display type to %s as specified\n", 
677                            pNv->FlatPanel ? "DFP" : "CRT");
678             }
679             
680                 if(!(pNv->crtc_active[0]) && !(pNv->crtc_active[1])) {
681                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
682                                 "Unable to detect which CRTC is used...\n");
683                         if(pNv->FlatPanel) {
684                                 pNv->crtc_active[1] = TRUE;
685                         } else {
686                                 pNv->crtc_active[0] = TRUE;
687                         }
688                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
689                         "...Defaulting to CRTCNumber %i\n", pNv->crtc_active[1]);
690                 }
691
692             if(monitorA) {
693                 if((monitorA->features.input_type && pNv->FlatPanel) ||
694                    (!monitorA->features.input_type && !pNv->FlatPanel))
695                 {
696                     if(monitorB) { 
697                         xfree(monitorB);
698                         monitorB = NULL;
699                     }
700                 } else {
701                     xfree(monitorA);
702                     monitorA = NULL;
703                 }
704             }
705             
706             if(monitorB) {
707                 if((monitorB->features.input_type && !pNv->FlatPanel) ||
708                    (!monitorB->features.input_type && pNv->FlatPanel)) 
709                 {
710                     xfree(monitorB);
711                 } else {
712                     monitorA = monitorB;
713                 }
714                 monitorB = NULL;
715             }
716             
717             if(implementation == CHIPSET_NV11)
718                 cr44 = pNv->crtc_active[1] * 0x3;
719             
720             NVWriteCRTC(pNv, 0, NV_CRTC_FSEL,  oldhead);
721
722             nvWriteCurVGA(pNv, NV_CIO_CRE_44, cr44);
723             NVSelectHeadRegisters(pScrn, pNv->crtc_active[1]);
724         }
725         
726         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
727                    "Using %s on CRTC %i\n",
728                    pNv->FlatPanel ? (pNv->Television ? "TV" : "DFP") : "CRT", 
729                    pNv->crtc_active[1]);
730         
731         if(pNv->FlatPanel && !pNv->Television) {
732             pNv->fpWidth = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HDISP_END) + 1;
733             pNv->fpHeight = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_VDISP_END) + 1;
734             pNv->fpSyncs = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL) & 0x30000033;
735             xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
736                        pNv->fpWidth, pNv->fpHeight);
737         }
738         
739         if(monitorA)
740             xf86SetDDCproperties(pScrn, monitorA);
741
742         if(!pNv->FlatPanel || (pScrn->depth != 24) || !pNv->twoHeads)
743             pNv->FPDither = FALSE;
744         
745         pNv->LVDS = FALSE;
746         if(pNv->FlatPanel && pNv->twoHeads) {
747             NVWriteRAMDAC(pNv, 0, NV_RAMDAC_FP_TMDS_CONTROL, 0x00010004);
748             if(NVReadRAMDAC(pNv, 0, NV_RAMDAC_FP_TMDS_DATA) & 1)
749                 pNv->LVDS = TRUE;
750             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel is %s\n", 
751                        pNv->LVDS ? "LVDS" : "TMDS");
752         }
753     }
754 }
755