• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /*
41  * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
42  * XFree86 'nv' driver, this source code is provided under MIT-style licensing
43  * where the source code is provided "as is" without warranty of any kind.
44  * The only usage restriction is for the copyright notices to be retained
45  * whenever code is used.
46  *
47  * Antonino Daplas <adaplas@pol.net> 2005-03-11
48  */
49 
50 #include <video/vga.h>
51 #include <linux/delay.h>
52 #include <linux/pci.h>
53 #include <linux/slab.h>
54 #include "nv_type.h"
55 #include "nv_local.h"
56 #include "nv_proto.h"
57 /*
58  * Override VGA I/O routines.
59  */
NVWriteCrtc(struct nvidia_par * par,u8 index,u8 value)60 void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value)
61 {
62 	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
63 	VGA_WR08(par->PCIO, par->IOBase + 0x05, value);
64 }
NVReadCrtc(struct nvidia_par * par,u8 index)65 u8 NVReadCrtc(struct nvidia_par *par, u8 index)
66 {
67 	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
68 	return (VGA_RD08(par->PCIO, par->IOBase + 0x05));
69 }
NVWriteGr(struct nvidia_par * par,u8 index,u8 value)70 void NVWriteGr(struct nvidia_par *par, u8 index, u8 value)
71 {
72 	VGA_WR08(par->PVIO, VGA_GFX_I, index);
73 	VGA_WR08(par->PVIO, VGA_GFX_D, value);
74 }
NVReadGr(struct nvidia_par * par,u8 index)75 u8 NVReadGr(struct nvidia_par *par, u8 index)
76 {
77 	VGA_WR08(par->PVIO, VGA_GFX_I, index);
78 	return (VGA_RD08(par->PVIO, VGA_GFX_D));
79 }
NVWriteSeq(struct nvidia_par * par,u8 index,u8 value)80 void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value)
81 {
82 	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
83 	VGA_WR08(par->PVIO, VGA_SEQ_D, value);
84 }
NVReadSeq(struct nvidia_par * par,u8 index)85 u8 NVReadSeq(struct nvidia_par *par, u8 index)
86 {
87 	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
88 	return (VGA_RD08(par->PVIO, VGA_SEQ_D));
89 }
NVWriteAttr(struct nvidia_par * par,u8 index,u8 value)90 void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value)
91 {
92 	volatile u8 tmp;
93 
94 	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
95 	if (par->paletteEnabled)
96 		index &= ~0x20;
97 	else
98 		index |= 0x20;
99 	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
100 	VGA_WR08(par->PCIO, VGA_ATT_W, value);
101 }
NVReadAttr(struct nvidia_par * par,u8 index)102 u8 NVReadAttr(struct nvidia_par *par, u8 index)
103 {
104 	volatile u8 tmp;
105 
106 	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
107 	if (par->paletteEnabled)
108 		index &= ~0x20;
109 	else
110 		index |= 0x20;
111 	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
112 	return (VGA_RD08(par->PCIO, VGA_ATT_R));
113 }
NVWriteMiscOut(struct nvidia_par * par,u8 value)114 void NVWriteMiscOut(struct nvidia_par *par, u8 value)
115 {
116 	VGA_WR08(par->PVIO, VGA_MIS_W, value);
117 }
NVReadMiscOut(struct nvidia_par * par)118 u8 NVReadMiscOut(struct nvidia_par *par)
119 {
120 	return (VGA_RD08(par->PVIO, VGA_MIS_R));
121 }
NVWriteDacMask(struct nvidia_par * par,u8 value)122 void NVWriteDacMask(struct nvidia_par *par, u8 value)
123 {
124 	VGA_WR08(par->PDIO, VGA_PEL_MSK, value);
125 }
NVWriteDacReadAddr(struct nvidia_par * par,u8 value)126 void NVWriteDacReadAddr(struct nvidia_par *par, u8 value)
127 {
128 	VGA_WR08(par->PDIO, VGA_PEL_IR, value);
129 }
NVWriteDacWriteAddr(struct nvidia_par * par,u8 value)130 void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value)
131 {
132 	VGA_WR08(par->PDIO, VGA_PEL_IW, value);
133 }
NVWriteDacData(struct nvidia_par * par,u8 value)134 void NVWriteDacData(struct nvidia_par *par, u8 value)
135 {
136 	VGA_WR08(par->PDIO, VGA_PEL_D, value);
137 }
NVReadDacData(struct nvidia_par * par)138 u8 NVReadDacData(struct nvidia_par *par)
139 {
140 	return (VGA_RD08(par->PDIO, VGA_PEL_D));
141 }
142 
NVIsConnected(struct nvidia_par * par,int output)143 static int NVIsConnected(struct nvidia_par *par, int output)
144 {
145 	volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
146 	u32 reg52C, reg608, dac0_reg608 = 0;
147 	int present;
148 
149 	if (output) {
150 	    dac0_reg608 = NV_RD32(PRAMDAC, 0x0608);
151 	    PRAMDAC += 0x800;
152 	}
153 
154 	reg52C = NV_RD32(PRAMDAC, 0x052C);
155 	reg608 = NV_RD32(PRAMDAC, 0x0608);
156 
157 	NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
158 
159 	NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
160 	msleep(1);
161 	NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
162 
163 	NV_WR32(par->PRAMDAC0, 0x0610, 0x94050140);
164 	NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) |
165 		0x00001000);
166 
167 	msleep(1);
168 
169 	present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0;
170 
171 	if (present)
172 		printk("nvidiafb: CRTC%i analog found\n", output);
173 	else
174 		printk("nvidiafb: CRTC%i analog not found\n", output);
175 
176 	if (output)
177 	    NV_WR32(par->PRAMDAC0, 0x0608, dac0_reg608);
178 
179 	NV_WR32(PRAMDAC, 0x052C, reg52C);
180 	NV_WR32(PRAMDAC, 0x0608, reg608);
181 
182 	return present;
183 }
184 
NVSelectHeadRegisters(struct nvidia_par * par,int head)185 static void NVSelectHeadRegisters(struct nvidia_par *par, int head)
186 {
187 	if (head) {
188 		par->PCIO = par->PCIO0 + 0x2000;
189 		par->PCRTC = par->PCRTC0 + 0x800;
190 		par->PRAMDAC = par->PRAMDAC0 + 0x800;
191 		par->PDIO = par->PDIO0 + 0x2000;
192 	} else {
193 		par->PCIO = par->PCIO0;
194 		par->PCRTC = par->PCRTC0;
195 		par->PRAMDAC = par->PRAMDAC0;
196 		par->PDIO = par->PDIO0;
197 	}
198 }
199 
nv4GetConfig(struct nvidia_par * par)200 static void nv4GetConfig(struct nvidia_par *par)
201 {
202 	if (NV_RD32(par->PFB, 0x0000) & 0x00000100) {
203 		par->RamAmountKBytes =
204 		    ((NV_RD32(par->PFB, 0x0000) >> 12) & 0x0F) * 1024 * 2 +
205 		    1024 * 2;
206 	} else {
207 		switch (NV_RD32(par->PFB, 0x0000) & 0x00000003) {
208 		case 0:
209 			par->RamAmountKBytes = 1024 * 32;
210 			break;
211 		case 1:
212 			par->RamAmountKBytes = 1024 * 4;
213 			break;
214 		case 2:
215 			par->RamAmountKBytes = 1024 * 8;
216 			break;
217 		case 3:
218 		default:
219 			par->RamAmountKBytes = 1024 * 16;
220 			break;
221 		}
222 	}
223 	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & 0x00000040) ?
224 	    14318 : 13500;
225 	par->CURSOR = &par->PRAMIN[0x1E00];
226 	par->MinVClockFreqKHz = 12000;
227 	par->MaxVClockFreqKHz = 350000;
228 }
229 
nv10GetConfig(struct nvidia_par * par)230 static void nv10GetConfig(struct nvidia_par *par)
231 {
232 	struct pci_dev *dev;
233 	u32 implementation = par->Chipset & 0x0ff0;
234 
235 #ifdef __BIG_ENDIAN
236 	/* turn on big endian register access */
237 	if (!(NV_RD32(par->PMC, 0x0004) & 0x01000001)) {
238 		NV_WR32(par->PMC, 0x0004, 0x01000001);
239 		mb();
240 	}
241 #endif
242 
243 	dev = pci_get_domain_bus_and_slot(pci_domain_nr(par->pci_dev->bus),
244 					  0, 1);
245 	if ((par->Chipset & 0xffff) == 0x01a0) {
246 		u32 amt;
247 
248 		pci_read_config_dword(dev, 0x7c, &amt);
249 		par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
250 	} else if ((par->Chipset & 0xffff) == 0x01f0) {
251 		u32 amt;
252 
253 		pci_read_config_dword(dev, 0x84, &amt);
254 		par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
255 	} else {
256 		par->RamAmountKBytes =
257 		    (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10;
258 	}
259 	pci_dev_put(dev);
260 
261 	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ?
262 	    14318 : 13500;
263 
264 	if (par->twoHeads && (implementation != 0x0110)) {
265 		if (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 22))
266 			par->CrystalFreqKHz = 27000;
267 	}
268 
269 	par->CURSOR = NULL;	/* can't set this here */
270 	par->MinVClockFreqKHz = 12000;
271 	par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
272 }
273 
NVCommonSetup(struct fb_info * info)274 int NVCommonSetup(struct fb_info *info)
275 {
276 	struct nvidia_par *par = info->par;
277 	struct fb_var_screeninfo *var;
278 	u16 implementation = par->Chipset & 0x0ff0;
279 	u8 *edidA = NULL, *edidB = NULL;
280 	struct fb_monspecs *monitorA, *monitorB;
281 	struct fb_monspecs *monA = NULL, *monB = NULL;
282 	int mobile = 0;
283 	int tvA = 0;
284 	int tvB = 0;
285 	int FlatPanel = -1;	/* really means the CRTC is slaved */
286 	int Television = 0;
287 	int err = 0;
288 
289 	var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
290 	monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
291 	monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
292 
293 	if (!var || !monitorA || !monitorB) {
294 		err = -ENOMEM;
295 		goto done;
296 	}
297 
298 	par->PRAMIN = par->REGS + (0x00710000 / 4);
299 	par->PCRTC0 = par->REGS + (0x00600000 / 4);
300 	par->PRAMDAC0 = par->REGS + (0x00680000 / 4);
301 	par->PFB = par->REGS + (0x00100000 / 4);
302 	par->PFIFO = par->REGS + (0x00002000 / 4);
303 	par->PGRAPH = par->REGS + (0x00400000 / 4);
304 	par->PEXTDEV = par->REGS + (0x00101000 / 4);
305 	par->PTIMER = par->REGS + (0x00009000 / 4);
306 	par->PMC = par->REGS + (0x00000000 / 4);
307 	par->FIFO = par->REGS + (0x00800000 / 4);
308 
309 	/* 8 bit registers */
310 	par->PCIO0 = (u8 __iomem *) par->REGS + 0x00601000;
311 	par->PDIO0 = (u8 __iomem *) par->REGS + 0x00681000;
312 	par->PVIO = (u8 __iomem *) par->REGS + 0x000C0000;
313 
314 	par->twoHeads = (par->Architecture >= NV_ARCH_10) &&
315 	    (implementation != 0x0100) &&
316 	    (implementation != 0x0150) &&
317 	    (implementation != 0x01A0) && (implementation != 0x0200);
318 
319 	par->fpScaler = (par->FpScale && par->twoHeads &&
320 			 (implementation != 0x0110));
321 
322 	par->twoStagePLL = (implementation == 0x0310) ||
323 	    (implementation == 0x0340) || (par->Architecture >= NV_ARCH_40);
324 
325 	par->WaitVSyncPossible = (par->Architecture >= NV_ARCH_10) &&
326 	    (implementation != 0x0100);
327 
328 	par->BlendingPossible = ((par->Chipset & 0xffff) != 0x0020);
329 
330 	/* look for known laptop chips */
331 	switch (par->Chipset & 0xffff) {
332 	case 0x0112:
333 	case 0x0174:
334 	case 0x0175:
335 	case 0x0176:
336 	case 0x0177:
337 	case 0x0179:
338 	case 0x017C:
339 	case 0x017D:
340 	case 0x0186:
341 	case 0x0187:
342 	case 0x018D:
343 	case 0x01D7:
344 	case 0x0228:
345 	case 0x0286:
346 	case 0x028C:
347 	case 0x0316:
348 	case 0x0317:
349 	case 0x031A:
350 	case 0x031B:
351 	case 0x031C:
352 	case 0x031D:
353 	case 0x031E:
354 	case 0x031F:
355 	case 0x0324:
356 	case 0x0325:
357 	case 0x0328:
358 	case 0x0329:
359 	case 0x032C:
360 	case 0x032D:
361 	case 0x0347:
362 	case 0x0348:
363 	case 0x0349:
364 	case 0x034B:
365 	case 0x034C:
366 	case 0x0160:
367 	case 0x0166:
368 	case 0x0169:
369 	case 0x016B:
370 	case 0x016C:
371 	case 0x016D:
372 	case 0x00C8:
373 	case 0x00CC:
374 	case 0x0144:
375 	case 0x0146:
376 	case 0x0147:
377 	case 0x0148:
378 	case 0x0098:
379 	case 0x0099:
380 		mobile = 1;
381 		break;
382 	default:
383 		break;
384 	}
385 
386 	if (par->Architecture == NV_ARCH_04)
387 		nv4GetConfig(par);
388 	else
389 		nv10GetConfig(par);
390 
391 	NVSelectHeadRegisters(par, 0);
392 
393 	NVLockUnlock(par, 0);
394 
395 	par->IOBase = (NVReadMiscOut(par) & 0x01) ? 0x3d0 : 0x3b0;
396 
397 	par->Television = 0;
398 
399 	nvidia_create_i2c_busses(par);
400 	if (!par->twoHeads) {
401 		par->CRTCnumber = 0;
402 		if (nvidia_probe_i2c_connector(info, 1, &edidA))
403 			nvidia_probe_of_connector(info, 1, &edidA);
404 		if (edidA && !fb_parse_edid(edidA, var)) {
405 			printk("nvidiafb: EDID found from BUS1\n");
406 			monA = monitorA;
407 			fb_edid_to_monspecs(edidA, monA);
408 			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
409 
410 			/* NV4 doesn't support FlatPanels */
411 			if ((par->Chipset & 0x0fff) <= 0x0020)
412 				FlatPanel = 0;
413 		} else {
414 			VGA_WR08(par->PCIO, 0x03D4, 0x28);
415 			if (VGA_RD08(par->PCIO, 0x03D5) & 0x80) {
416 				VGA_WR08(par->PCIO, 0x03D4, 0x33);
417 				if (!(VGA_RD08(par->PCIO, 0x03D5) & 0x01))
418 					Television = 1;
419 				FlatPanel = 1;
420 			} else {
421 				FlatPanel = 0;
422 			}
423 			printk("nvidiafb: HW is currently programmed for %s\n",
424 			       FlatPanel ? (Television ? "TV" : "DFP") :
425 			       "CRT");
426 		}
427 
428 		if (par->FlatPanel == -1) {
429 			par->FlatPanel = FlatPanel;
430 			par->Television = Television;
431 		} else {
432 			printk("nvidiafb: Forcing display type to %s as "
433 			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
434 		}
435 	} else {
436 		u8 outputAfromCRTC, outputBfromCRTC;
437 		int CRTCnumber = -1;
438 		u8 slaved_on_A, slaved_on_B;
439 		int analog_on_A, analog_on_B;
440 		u32 oldhead;
441 		u8 cr44;
442 
443 		if (implementation != 0x0110) {
444 			if (NV_RD32(par->PRAMDAC0, 0x0000052C) & 0x100)
445 				outputAfromCRTC = 1;
446 			else
447 				outputAfromCRTC = 0;
448 			if (NV_RD32(par->PRAMDAC0, 0x0000252C) & 0x100)
449 				outputBfromCRTC = 1;
450 			else
451 				outputBfromCRTC = 0;
452 			analog_on_A = NVIsConnected(par, 0);
453 			analog_on_B = NVIsConnected(par, 1);
454 		} else {
455 			outputAfromCRTC = 0;
456 			outputBfromCRTC = 1;
457 			analog_on_A = 0;
458 			analog_on_B = 0;
459 		}
460 
461 		VGA_WR08(par->PCIO, 0x03D4, 0x44);
462 		cr44 = VGA_RD08(par->PCIO, 0x03D5);
463 
464 		VGA_WR08(par->PCIO, 0x03D5, 3);
465 		NVSelectHeadRegisters(par, 1);
466 		NVLockUnlock(par, 0);
467 
468 		VGA_WR08(par->PCIO, 0x03D4, 0x28);
469 		slaved_on_B = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
470 		if (slaved_on_B) {
471 			VGA_WR08(par->PCIO, 0x03D4, 0x33);
472 			tvB = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
473 		}
474 
475 		VGA_WR08(par->PCIO, 0x03D4, 0x44);
476 		VGA_WR08(par->PCIO, 0x03D5, 0);
477 		NVSelectHeadRegisters(par, 0);
478 		NVLockUnlock(par, 0);
479 
480 		VGA_WR08(par->PCIO, 0x03D4, 0x28);
481 		slaved_on_A = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
482 		if (slaved_on_A) {
483 			VGA_WR08(par->PCIO, 0x03D4, 0x33);
484 			tvA = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
485 		}
486 
487 		oldhead = NV_RD32(par->PCRTC0, 0x00000860);
488 		NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
489 
490 		if (nvidia_probe_i2c_connector(info, 1, &edidA))
491 			nvidia_probe_of_connector(info, 1, &edidA);
492 		if (edidA && !fb_parse_edid(edidA, var)) {
493 			printk("nvidiafb: EDID found from BUS1\n");
494 			monA = monitorA;
495 			fb_edid_to_monspecs(edidA, monA);
496 		}
497 
498 		if (nvidia_probe_i2c_connector(info, 2, &edidB))
499 			nvidia_probe_of_connector(info, 2, &edidB);
500 		if (edidB && !fb_parse_edid(edidB, var)) {
501 			printk("nvidiafb: EDID found from BUS2\n");
502 			monB = monitorB;
503 			fb_edid_to_monspecs(edidB, monB);
504 		}
505 
506 		if (slaved_on_A && !tvA) {
507 			CRTCnumber = 0;
508 			FlatPanel = 1;
509 			printk("nvidiafb: CRTC 0 is currently programmed for "
510 			       "DFP\n");
511 		} else if (slaved_on_B && !tvB) {
512 			CRTCnumber = 1;
513 			FlatPanel = 1;
514 			printk("nvidiafb: CRTC 1 is currently programmed "
515 			       "for DFP\n");
516 		} else if (analog_on_A) {
517 			CRTCnumber = outputAfromCRTC;
518 			FlatPanel = 0;
519 			printk("nvidiafb: CRTC %i appears to have a "
520 			       "CRT attached\n", CRTCnumber);
521 		} else if (analog_on_B) {
522 			CRTCnumber = outputBfromCRTC;
523 			FlatPanel = 0;
524 			printk("nvidiafb: CRTC %i appears to have a "
525 			       "CRT attached\n", CRTCnumber);
526 		} else if (slaved_on_A) {
527 			CRTCnumber = 0;
528 			FlatPanel = 1;
529 			Television = 1;
530 			printk("nvidiafb: CRTC 0 is currently programmed "
531 			       "for TV\n");
532 		} else if (slaved_on_B) {
533 			CRTCnumber = 1;
534 			FlatPanel = 1;
535 			Television = 1;
536 			printk("nvidiafb: CRTC 1 is currently programmed for "
537 			       "TV\n");
538 		} else if (monA) {
539 			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
540 		} else if (monB) {
541 			FlatPanel = (monB->input & FB_DISP_DDI) ? 1 : 0;
542 		}
543 
544 		if (par->FlatPanel == -1) {
545 			if (FlatPanel != -1) {
546 				par->FlatPanel = FlatPanel;
547 				par->Television = Television;
548 			} else {
549 				printk("nvidiafb: Unable to detect display "
550 				       "type...\n");
551 				if (mobile) {
552 					printk("...On a laptop, assuming "
553 					       "DFP\n");
554 					par->FlatPanel = 1;
555 				} else {
556 					printk("...Using default of CRT\n");
557 					par->FlatPanel = 0;
558 				}
559 			}
560 		} else {
561 			printk("nvidiafb: Forcing display type to %s as "
562 			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
563 		}
564 
565 		if (par->CRTCnumber == -1) {
566 			if (CRTCnumber != -1)
567 				par->CRTCnumber = CRTCnumber;
568 			else {
569 				printk("nvidiafb: Unable to detect which "
570 				       "CRTCNumber...\n");
571 				if (par->FlatPanel)
572 					par->CRTCnumber = 1;
573 				else
574 					par->CRTCnumber = 0;
575 				printk("...Defaulting to CRTCNumber %i\n",
576 				       par->CRTCnumber);
577 			}
578 		} else {
579 			printk("nvidiafb: Forcing CRTCNumber %i as "
580 			       "specified\n", par->CRTCnumber);
581 		}
582 
583 		if (monA) {
584 			if (((monA->input & FB_DISP_DDI) &&
585 			     par->FlatPanel) ||
586 			    ((!(monA->input & FB_DISP_DDI)) &&
587 			     !par->FlatPanel)) {
588 				if (monB) {
589 					fb_destroy_modedb(monB->modedb);
590 					monB = NULL;
591 				}
592 			} else {
593 				fb_destroy_modedb(monA->modedb);
594 				monA = NULL;
595 			}
596 		}
597 
598 		if (monB) {
599 			if (((monB->input & FB_DISP_DDI) &&
600 			     !par->FlatPanel) ||
601 			    ((!(monB->input & FB_DISP_DDI)) &&
602 			     par->FlatPanel)) {
603 				fb_destroy_modedb(monB->modedb);
604 				monB = NULL;
605 			} else
606 				monA = monB;
607 		}
608 
609 		if (implementation == 0x0110)
610 			cr44 = par->CRTCnumber * 0x3;
611 
612 		NV_WR32(par->PCRTC0, 0x00000860, oldhead);
613 
614 		VGA_WR08(par->PCIO, 0x03D4, 0x44);
615 		VGA_WR08(par->PCIO, 0x03D5, cr44);
616 		NVSelectHeadRegisters(par, par->CRTCnumber);
617 	}
618 
619 	printk("nvidiafb: Using %s on CRTC %i\n",
620 	       par->FlatPanel ? (par->Television ? "TV" : "DFP") : "CRT",
621 	       par->CRTCnumber);
622 
623 	if (par->FlatPanel && !par->Television) {
624 		par->fpWidth = NV_RD32(par->PRAMDAC, 0x0820) + 1;
625 		par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1;
626 		par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033;
627 
628 		printk("nvidiafb: Panel size is %i x %i\n", par->fpWidth, par->fpHeight);
629 	}
630 
631 	if (monA)
632 		info->monspecs = *monA;
633 
634 	if (!par->FlatPanel || !par->twoHeads)
635 		par->FPDither = 0;
636 
637 	par->LVDS = 0;
638 	if (par->FlatPanel && par->twoHeads) {
639 		NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004);
640 		if (NV_RD32(par->PRAMDAC0, 0x08b4) & 1)
641 			par->LVDS = 1;
642 		printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS");
643 	}
644 
645 	kfree(edidA);
646 	kfree(edidB);
647 done:
648 	kfree(var);
649 	kfree(monitorA);
650 	kfree(monitorB);
651 	return err;
652 }
653