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