Undo last commit and move it to drm.
[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, NV_PFB_BOOT_0);
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, NV_PEXTDEV_BOOT_0) & 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, NV_PFB_020C) & 0xFFF00000) >> 10;
325         }
326
327     if(pNv->RamAmountKBytes > 256*1024)
328         pNv->RamAmountKBytes = 256*1024;
329
330     pNv->CrystalFreqKHz = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & (1 << 6)) ? 14318 : 13500;
331     
332     if(pNv->twoHeads && (implementation != CHIPSET_NV11))
333     {
334        if(nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & (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, (void *)&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         /* Don't mess with pre-randr12 situations. */
432         if (pNv->NVArch == 0x30 && pNv->randr12_enable)
433                 pNv->twoStagePLL = TRUE;
434
435     pNv->WaitVSyncPossible = (pNv->Architecture >= NV_ARCH_10) &&
436                              (implementation != CHIPSET_NV10);
437
438     pNv->BlendingPossible = ((pNv->Chipset & 0xffff) > CHIPSET_NV04);
439
440     /* look for known laptop chips */
441     /* FIXME still probably missing some ids (for randr12, pre-nv40 mobile should be auto-detected) */
442     switch(pNv->Chipset & 0xffff) {
443     case 0x0098:
444     case 0x0099:
445     case 0x00C8:
446     case 0x00C9:
447     case 0x00CC:
448     case 0x0112:
449     case 0x0144:
450     case 0x0146:
451     case 0x0148:
452     case 0x0149:
453     case 0x0160:
454     case 0x0164:
455     case 0x0166:
456     case 0x0167:
457     case 0x0168:
458     case 0x0169:
459     case 0x016B:
460     case 0x016C:
461     case 0x016D:
462     case 0x0174:
463     case 0x0175:
464     case 0x0176:
465     case 0x0177:
466     case 0x0179:
467     case 0x017C:
468     case 0x017D:
469     case 0x0186:
470     case 0x0187:
471     case 0x018D:
472     case 0x01D6:
473     case 0x01D7:
474     case 0x01D8:
475     case 0x0228:
476     case 0x0244:
477     case 0x0286:
478     case 0x028C:
479     case 0x0297:
480     case 0x0298:
481     case 0x0299:
482     case 0x0316:
483     case 0x0317:
484     case 0x031A:
485     case 0x031B:
486     case 0x031C:
487     case 0x031D:
488     case 0x031E:
489     case 0x031F:
490     case 0x0324:
491     case 0x0325:
492     case 0x0328:
493     case 0x0329:
494     case 0x032C:
495     case 0x032D:
496     case 0x0347:
497     case 0x0348:
498     case 0x0349:
499     case 0x034B:
500     case 0x034C:
501     case 0x0397:
502     case 0x0398:
503     case 0x039B:
504         pNv->Mobile = TRUE;
505         break;
506     default:
507         break;
508     }
509
510         pNv->Television = FALSE;
511
512         if (pNv->twoHeads) {
513                 pNv->vtOWNER = NVReadVGA(pNv, 0, NV_VGA_CRTCX_OWNER);
514                 if (pNv->NVArch == 0x11) {      /* reading OWNER is broken on nv11 */
515                         if (nvReadMC(pNv, NV_PBUS_DEBUG_1) & (1 << 28)) /* heads tied, restore both */
516                                 pNv->vtOWNER = 0x04;
517                         else {
518                                 NVLockUnlockHead(pScrn, 1, FALSE); /* implicit owner set */
519
520                                 uint8_t slaved_on_B = NVReadVGA(pNv, 1, NV_VGA_CRTCX_PIXEL) & 0x80;
521                                 if (slaved_on_B)
522                                         tvB = !(NVReadVGA(pNv, 1, NV_VGA_CRTCX_LCD) & 0x01);
523
524                                 NVLockUnlockHead(pScrn, 0, FALSE);
525
526                                 uint8_t slaved_on_A = NVReadVGA(pNv, 0, NV_VGA_CRTCX_PIXEL) & 0x80;
527                                 if (slaved_on_A)
528                                         tvA = !(NVReadVGA(pNv, 0, NV_VGA_CRTCX_LCD) & 0x01);
529
530                                 if (slaved_on_A && !tvA)
531                                         pNv->vtOWNER = 0x0;
532                                 else if (slaved_on_B && !tvB)
533                                         pNv->vtOWNER = 0x3;
534                                 else if (slaved_on_A)
535                                         pNv->vtOWNER = 0x0;
536                                 else if (slaved_on_B)
537                                         pNv->vtOWNER = 0x3;
538                                 else
539                                         pNv->vtOWNER = 0x0;
540                         }
541                 }
542
543                 ErrorF("Initial CRTC_OWNER is %d\n", pNv->vtOWNER);
544         }
545
546     /* Parse the bios to initialize the card */
547     NVParseBios(pScrn);
548
549         if(pNv->Architecture == NV_ARCH_04) {
550                 nv4GetConfig(pNv);
551         } else {
552                 nv10GetConfig(pNv);
553         }
554
555     if (!pNv->randr12_enable) {
556       
557         NVSelectHeadRegisters(pScrn, 0);
558         
559         NVLockUnlock(pNv, 0);
560         
561         NVI2CInit(pScrn);
562         
563         
564         if(!pNv->twoHeads) {
565             pNv->crtc_active[0] = TRUE;
566             pNv->crtc_active[1] = FALSE;
567             if((monitorA = NVProbeDDC(pScrn, 0))) {
568                 FlatPanel = monitorA->features.input_type ? 1 : 0;
569                 
570                 /* NV4 doesn't support FlatPanels */
571                 if((pNv->Chipset & 0x0fff) <= CHIPSET_NV04)
572                     FlatPanel = 0;
573             } else {
574                 if(nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
575                     if(!(nvReadVGA(pNv, NV_VGA_CRTCX_LCD) & 0x01)) 
576                         Television = TRUE;
577                     FlatPanel = 1;
578                 } else {
579                     FlatPanel = 0;
580                 }
581                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
582                            "HW is currently programmed for %s\n",
583                            FlatPanel ? (Television ? "TV" : "DFP") : "CRT");
584             } 
585             
586             if(pNv->FlatPanel == -1) {
587                 pNv->FlatPanel = FlatPanel;
588                 pNv->Television = Television;
589             } else {
590                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
591                            "Forcing display type to %s as specified\n", 
592                            pNv->FlatPanel ? "DFP" : "CRT");
593             }
594         } else {
595             CARD8 outputAfromCRTC, outputBfromCRTC;
596             pNv->crtc_active[0] = FALSE;
597             pNv->crtc_active[1] = FALSE;
598             CARD8 slaved_on_A, slaved_on_B;
599             Bool analog_on_A, analog_on_B;
600             CARD32 oldhead;
601             CARD8 cr44;
602             
603             if(implementation != CHIPSET_NV11) {
604                 if(nvReadRAMDAC0(pNv, NV_RAMDAC_OUTPUT) & 0x100)
605                     outputAfromCRTC = 1;
606                 else            
607                     outputAfromCRTC = 0;
608                 if(nvReadRAMDAC(pNv, 1, NV_RAMDAC_OUTPUT) & 0x100)
609                     outputBfromCRTC = 1;
610                 else
611                     outputBfromCRTC = 0;
612                 analog_on_A = NVIsConnected(pScrn, 0);
613                 analog_on_B = NVIsConnected(pScrn, 1);
614             } else {
615                 outputAfromCRTC = 0;
616                 outputBfromCRTC = 1;
617                 analog_on_A = FALSE;
618                 analog_on_B = FALSE;
619             }
620             
621             cr44 = pNv->vtOWNER;
622             
623             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, 3);
624             NVSelectHeadRegisters(pScrn, 1);
625             NVLockUnlock(pNv, 0);
626             
627             slaved_on_B = nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL) & 0x80;
628             if(slaved_on_B) {
629                 tvB = !(nvReadVGA(pNv, NV_VGA_CRTCX_LCD) & 0x01);
630             }
631             
632             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, 0);
633             NVSelectHeadRegisters(pScrn, 0);
634             NVLockUnlock(pNv, 0);
635             
636             slaved_on_A = nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL) & 0x80; 
637             if(slaved_on_A) {
638                 tvA = !(nvReadVGA(pNv, NV_VGA_CRTCX_LCD) & 0x01);
639             }
640             
641             oldhead = nvReadCRTC0(pNv, NV_CRTC_FSEL);
642             nvWriteCRTC0(pNv, NV_CRTC_FSEL, oldhead | 0x00000010);
643             
644             monitorA = NVProbeDDC(pScrn, 0);
645             monitorB = NVProbeDDC(pScrn, 1);
646             
647             if(slaved_on_A && !tvA) {
648                 pNv->crtc_active[0] = TRUE;
649                 FlatPanel = 1;
650                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
651                            "CRTC 0 is currently programmed for DFP\n");
652             } else 
653                 if(slaved_on_B && !tvB) {
654                     pNv->crtc_active[1] = TRUE;
655                     FlatPanel = 1;
656                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
657                                "CRTC 1 is currently programmed for DFP\n");
658                 } else
659                     if(analog_on_A) {
660                         pNv->crtc_active[outputAfromCRTC] = TRUE;
661                         FlatPanel = 0;
662                         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
663                                    "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
664                     } else
665                         if(analog_on_B) {
666                             pNv->crtc_active[outputBfromCRTC] = TRUE;
667                             FlatPanel = 0;
668                             xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
669                                        "CRTC %i appears to have a CRT attached\n", pNv->crtc_active[1]);
670                         } else
671                             if(slaved_on_A) {
672                                 pNv->crtc_active[0] = TRUE;
673                                 FlatPanel = 1;
674                                 Television = 1;
675                                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
676                                            "CRTC 0 is currently programmed for TV\n");
677                             } else
678                                 if(slaved_on_B) {
679                                     pNv->crtc_active[1] = TRUE;
680                                     FlatPanel = 1;
681                                     Television = 1;
682                                     xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
683                                                "CRTC 1 is currently programmed for TV\n");
684                                 } else
685                                     if(monitorA) {
686                                         FlatPanel = monitorA->features.input_type ? 1 : 0;
687                                     } else 
688                                         if(monitorB) {
689                                             FlatPanel = monitorB->features.input_type ? 1 : 0;
690                                         }
691             
692             if(pNv->FlatPanel == -1) {
693                 if(FlatPanel != -1) {
694                     pNv->FlatPanel = FlatPanel;
695                     pNv->Television = Television;
696                 } else {
697                     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
698                                "Unable to detect display type...\n");
699                     if(pNv->Mobile) {
700                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
701                                    "...On a laptop, assuming DFP\n");
702                         pNv->FlatPanel = 1;
703                     } else {
704                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
705                                    "...Using default of CRT\n");
706                         pNv->FlatPanel = 0;
707                     }
708                 }
709             } else {
710                 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
711                            "Forcing display type to %s as specified\n", 
712                            pNv->FlatPanel ? "DFP" : "CRT");
713             }
714             
715                 if(!(pNv->crtc_active[0]) && !(pNv->crtc_active[1])) {
716                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
717                                 "Unable to detect which CRTC is used...\n");
718                         if(pNv->FlatPanel) {
719                                 pNv->crtc_active[1] = TRUE;
720                         } else {
721                                 pNv->crtc_active[0] = TRUE;
722                         }
723                         xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
724                         "...Defaulting to CRTCNumber %i\n", pNv->crtc_active[1]);
725                 }
726
727             if(monitorA) {
728                 if((monitorA->features.input_type && pNv->FlatPanel) ||
729                    (!monitorA->features.input_type && !pNv->FlatPanel))
730                 {
731                     if(monitorB) { 
732                         xfree(monitorB);
733                         monitorB = NULL;
734                     }
735                 } else {
736                     xfree(monitorA);
737                     monitorA = NULL;
738                 }
739             }
740             
741             if(monitorB) {
742                 if((monitorB->features.input_type && !pNv->FlatPanel) ||
743                    (!monitorB->features.input_type && pNv->FlatPanel)) 
744                 {
745                     xfree(monitorB);
746                 } else {
747                     monitorA = monitorB;
748                 }
749                 monitorB = NULL;
750             }
751             
752             if(implementation == CHIPSET_NV11)
753                 cr44 = pNv->crtc_active[1] * 0x3;
754             
755             nvWriteCRTC0(pNv, NV_CRTC_FSEL,  oldhead);
756
757             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, cr44);
758             NVSelectHeadRegisters(pScrn, pNv->crtc_active[1]);
759         }
760         
761         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
762                    "Using %s on CRTC %i\n",
763                    pNv->FlatPanel ? (pNv->Television ? "TV" : "DFP") : "CRT", 
764                    pNv->crtc_active[1]);
765         
766         if(pNv->FlatPanel && !pNv->Television) {
767             pNv->fpWidth = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HDISP_END) + 1;
768             pNv->fpHeight = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_VDISP_END) + 1;
769             pNv->fpSyncs = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL) & 0x30000033;
770             xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
771                        pNv->fpWidth, pNv->fpHeight);
772         }
773         
774         if(monitorA)
775             xf86SetDDCproperties(pScrn, monitorA);
776
777         if(!pNv->FlatPanel || (pScrn->depth != 24) || !pNv->twoHeads)
778             pNv->FPDither = FALSE;
779         
780         pNv->LVDS = FALSE;
781         if(pNv->FlatPanel && pNv->twoHeads) {
782             nvWriteRAMDAC0(pNv, NV_RAMDAC_FP_TMDS_CONTROL, 0x00010004);
783             if(nvReadRAMDAC0(pNv, NV_RAMDAC_FP_TMDS_DATA) & 1)
784                 pNv->LVDS = TRUE;
785             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel is %s\n", 
786                        pNv->LVDS ? "LVDS" : "TMDS");
787         }
788     }
789 }
790