Back to home page

OSCL-LXR

 
 

    


0001  /***************************************************************************\
0002 |*                                                                           *|
0003 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
0004 |*                                                                           *|
0005 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
0006 |*     international laws.  Users and possessors of this source code are     *|
0007 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
0008 |*     use this code in individual and commercial software.                  *|
0009 |*                                                                           *|
0010 |*     Any use of this source code must include,  in the user documenta-     *|
0011 |*     tion and  internal comments to the code,  notices to the end user     *|
0012 |*     as follows:                                                           *|
0013 |*                                                                           *|
0014 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
0015 |*                                                                           *|
0016 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
0017 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
0018 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
0019 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
0020 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
0021 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
0022 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
0023 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
0024 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
0025 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
0026 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
0027 |*                                                                           *|
0028 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
0029 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
0030 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
0031 |*     computer  software  documentation,"  as such  terms  are  used in     *|
0032 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
0033 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
0034 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
0035 |*     all U.S. Government End Users  acquire the source code  with only     *|
0036 |*     those rights set forth herein.                                        *|
0037 |*                                                                           *|
0038  \***************************************************************************/
0039 
0040 /*
0041  * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
0042  * XFree86 'nv' driver, this source code is provided under MIT-style licensing
0043  * where the source code is provided "as is" without warranty of any kind.
0044  * The only usage restriction is for the copyright notices to be retained
0045  * whenever code is used.
0046  *
0047  * Antonino Daplas <adaplas@pol.net> 2005-03-11
0048  */
0049 
0050 #include <video/vga.h>
0051 #include <linux/delay.h>
0052 #include <linux/pci.h>
0053 #include <linux/slab.h>
0054 #include "nv_type.h"
0055 #include "nv_local.h"
0056 #include "nv_proto.h"
0057 /*
0058  * Override VGA I/O routines.
0059  */
0060 void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value)
0061 {
0062     VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
0063     VGA_WR08(par->PCIO, par->IOBase + 0x05, value);
0064 }
0065 u8 NVReadCrtc(struct nvidia_par *par, u8 index)
0066 {
0067     VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
0068     return (VGA_RD08(par->PCIO, par->IOBase + 0x05));
0069 }
0070 void NVWriteGr(struct nvidia_par *par, u8 index, u8 value)
0071 {
0072     VGA_WR08(par->PVIO, VGA_GFX_I, index);
0073     VGA_WR08(par->PVIO, VGA_GFX_D, value);
0074 }
0075 u8 NVReadGr(struct nvidia_par *par, u8 index)
0076 {
0077     VGA_WR08(par->PVIO, VGA_GFX_I, index);
0078     return (VGA_RD08(par->PVIO, VGA_GFX_D));
0079 }
0080 void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value)
0081 {
0082     VGA_WR08(par->PVIO, VGA_SEQ_I, index);
0083     VGA_WR08(par->PVIO, VGA_SEQ_D, value);
0084 }
0085 u8 NVReadSeq(struct nvidia_par *par, u8 index)
0086 {
0087     VGA_WR08(par->PVIO, VGA_SEQ_I, index);
0088     return (VGA_RD08(par->PVIO, VGA_SEQ_D));
0089 }
0090 void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value)
0091 {
0092 
0093     VGA_RD08(par->PCIO, par->IOBase + 0x0a);
0094     if (par->paletteEnabled)
0095         index &= ~0x20;
0096     else
0097         index |= 0x20;
0098     VGA_WR08(par->PCIO, VGA_ATT_IW, index);
0099     VGA_WR08(par->PCIO, VGA_ATT_W, value);
0100 }
0101 u8 NVReadAttr(struct nvidia_par *par, u8 index)
0102 {
0103     VGA_RD08(par->PCIO, par->IOBase + 0x0a);
0104     if (par->paletteEnabled)
0105         index &= ~0x20;
0106     else
0107         index |= 0x20;
0108     VGA_WR08(par->PCIO, VGA_ATT_IW, index);
0109     return (VGA_RD08(par->PCIO, VGA_ATT_R));
0110 }
0111 void NVWriteMiscOut(struct nvidia_par *par, u8 value)
0112 {
0113     VGA_WR08(par->PVIO, VGA_MIS_W, value);
0114 }
0115 u8 NVReadMiscOut(struct nvidia_par *par)
0116 {
0117     return (VGA_RD08(par->PVIO, VGA_MIS_R));
0118 }
0119 void NVWriteDacMask(struct nvidia_par *par, u8 value)
0120 {
0121     VGA_WR08(par->PDIO, VGA_PEL_MSK, value);
0122 }
0123 void NVWriteDacReadAddr(struct nvidia_par *par, u8 value)
0124 {
0125     VGA_WR08(par->PDIO, VGA_PEL_IR, value);
0126 }
0127 void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value)
0128 {
0129     VGA_WR08(par->PDIO, VGA_PEL_IW, value);
0130 }
0131 void NVWriteDacData(struct nvidia_par *par, u8 value)
0132 {
0133     VGA_WR08(par->PDIO, VGA_PEL_D, value);
0134 }
0135 u8 NVReadDacData(struct nvidia_par *par)
0136 {
0137     return (VGA_RD08(par->PDIO, VGA_PEL_D));
0138 }
0139 
0140 static int NVIsConnected(struct nvidia_par *par, int output)
0141 {
0142     volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
0143     u32 reg52C, reg608, dac0_reg608 = 0;
0144     int present;
0145 
0146     if (output) {
0147         dac0_reg608 = NV_RD32(PRAMDAC, 0x0608);
0148         PRAMDAC += 0x800;
0149     }
0150 
0151     reg52C = NV_RD32(PRAMDAC, 0x052C);
0152     reg608 = NV_RD32(PRAMDAC, 0x0608);
0153 
0154     NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
0155 
0156     NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
0157     msleep(1);
0158     NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
0159 
0160     NV_WR32(par->PRAMDAC0, 0x0610, 0x94050140);
0161     NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) |
0162         0x00001000);
0163 
0164     msleep(1);
0165 
0166     present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0;
0167 
0168     if (present)
0169         printk("nvidiafb: CRTC%i analog found\n", output);
0170     else
0171         printk("nvidiafb: CRTC%i analog not found\n", output);
0172 
0173     if (output)
0174         NV_WR32(par->PRAMDAC0, 0x0608, dac0_reg608);
0175 
0176     NV_WR32(PRAMDAC, 0x052C, reg52C);
0177     NV_WR32(PRAMDAC, 0x0608, reg608);
0178 
0179     return present;
0180 }
0181 
0182 static void NVSelectHeadRegisters(struct nvidia_par *par, int head)
0183 {
0184     if (head) {
0185         par->PCIO = par->PCIO0 + 0x2000;
0186         par->PCRTC = par->PCRTC0 + 0x800;
0187         par->PRAMDAC = par->PRAMDAC0 + 0x800;
0188         par->PDIO = par->PDIO0 + 0x2000;
0189     } else {
0190         par->PCIO = par->PCIO0;
0191         par->PCRTC = par->PCRTC0;
0192         par->PRAMDAC = par->PRAMDAC0;
0193         par->PDIO = par->PDIO0;
0194     }
0195 }
0196 
0197 static void nv4GetConfig(struct nvidia_par *par)
0198 {
0199     if (NV_RD32(par->PFB, 0x0000) & 0x00000100) {
0200         par->RamAmountKBytes =
0201             ((NV_RD32(par->PFB, 0x0000) >> 12) & 0x0F) * 1024 * 2 +
0202             1024 * 2;
0203     } else {
0204         switch (NV_RD32(par->PFB, 0x0000) & 0x00000003) {
0205         case 0:
0206             par->RamAmountKBytes = 1024 * 32;
0207             break;
0208         case 1:
0209             par->RamAmountKBytes = 1024 * 4;
0210             break;
0211         case 2:
0212             par->RamAmountKBytes = 1024 * 8;
0213             break;
0214         case 3:
0215         default:
0216             par->RamAmountKBytes = 1024 * 16;
0217             break;
0218         }
0219     }
0220     par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & 0x00000040) ?
0221         14318 : 13500;
0222     par->CURSOR = &par->PRAMIN[0x1E00];
0223     par->MinVClockFreqKHz = 12000;
0224     par->MaxVClockFreqKHz = 350000;
0225 }
0226 
0227 static void nv10GetConfig(struct nvidia_par *par)
0228 {
0229     struct pci_dev *dev;
0230     u32 implementation = par->Chipset & 0x0ff0;
0231 
0232 #ifdef __BIG_ENDIAN
0233     /* turn on big endian register access */
0234     if (!(NV_RD32(par->PMC, 0x0004) & 0x01000001)) {
0235         NV_WR32(par->PMC, 0x0004, 0x01000001);
0236         mb();
0237     }
0238 #endif
0239 
0240     dev = pci_get_domain_bus_and_slot(pci_domain_nr(par->pci_dev->bus),
0241                       0, 1);
0242     if ((par->Chipset & 0xffff) == 0x01a0) {
0243         u32 amt;
0244 
0245         pci_read_config_dword(dev, 0x7c, &amt);
0246         par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
0247     } else if ((par->Chipset & 0xffff) == 0x01f0) {
0248         u32 amt;
0249 
0250         pci_read_config_dword(dev, 0x84, &amt);
0251         par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
0252     } else {
0253         par->RamAmountKBytes =
0254             (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10;
0255     }
0256     pci_dev_put(dev);
0257 
0258     par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ?
0259         14318 : 13500;
0260 
0261     if (par->twoHeads && (implementation != 0x0110)) {
0262         if (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 22))
0263             par->CrystalFreqKHz = 27000;
0264     }
0265 
0266     par->CURSOR = NULL; /* can't set this here */
0267     par->MinVClockFreqKHz = 12000;
0268     par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
0269 }
0270 
0271 int NVCommonSetup(struct fb_info *info)
0272 {
0273     struct nvidia_par *par = info->par;
0274     struct fb_var_screeninfo *var;
0275     u16 implementation = par->Chipset & 0x0ff0;
0276     u8 *edidA = NULL, *edidB = NULL;
0277     struct fb_monspecs *monitorA, *monitorB;
0278     struct fb_monspecs *monA = NULL, *monB = NULL;
0279     int mobile = 0;
0280     int tvA = 0;
0281     int tvB = 0;
0282     int FlatPanel = -1; /* really means the CRTC is slaved */
0283     int Television = 0;
0284     int err = 0;
0285 
0286     var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
0287     monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
0288     monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
0289 
0290     if (!var || !monitorA || !monitorB) {
0291         err = -ENOMEM;
0292         goto done;
0293     }
0294 
0295     par->PRAMIN = par->REGS + (0x00710000 / 4);
0296     par->PCRTC0 = par->REGS + (0x00600000 / 4);
0297     par->PRAMDAC0 = par->REGS + (0x00680000 / 4);
0298     par->PFB = par->REGS + (0x00100000 / 4);
0299     par->PFIFO = par->REGS + (0x00002000 / 4);
0300     par->PGRAPH = par->REGS + (0x00400000 / 4);
0301     par->PEXTDEV = par->REGS + (0x00101000 / 4);
0302     par->PTIMER = par->REGS + (0x00009000 / 4);
0303     par->PMC = par->REGS + (0x00000000 / 4);
0304     par->FIFO = par->REGS + (0x00800000 / 4);
0305 
0306     /* 8 bit registers */
0307     par->PCIO0 = (u8 __iomem *) par->REGS + 0x00601000;
0308     par->PDIO0 = (u8 __iomem *) par->REGS + 0x00681000;
0309     par->PVIO = (u8 __iomem *) par->REGS + 0x000C0000;
0310 
0311     par->twoHeads = (par->Architecture >= NV_ARCH_10) &&
0312         (implementation != 0x0100) &&
0313         (implementation != 0x0150) &&
0314         (implementation != 0x01A0) && (implementation != 0x0200);
0315 
0316     par->fpScaler = (par->FpScale && par->twoHeads &&
0317              (implementation != 0x0110));
0318 
0319     par->twoStagePLL = (implementation == 0x0310) ||
0320         (implementation == 0x0340) || (par->Architecture >= NV_ARCH_40);
0321 
0322     par->WaitVSyncPossible = (par->Architecture >= NV_ARCH_10) &&
0323         (implementation != 0x0100);
0324 
0325     par->BlendingPossible = ((par->Chipset & 0xffff) != 0x0020);
0326 
0327     /* look for known laptop chips */
0328     switch (par->Chipset & 0xffff) {
0329     case 0x0112:
0330     case 0x0174:
0331     case 0x0175:
0332     case 0x0176:
0333     case 0x0177:
0334     case 0x0179:
0335     case 0x017C:
0336     case 0x017D:
0337     case 0x0186:
0338     case 0x0187:
0339     case 0x018D:
0340     case 0x01D7:
0341     case 0x0228:
0342     case 0x0286:
0343     case 0x028C:
0344     case 0x0316:
0345     case 0x0317:
0346     case 0x031A:
0347     case 0x031B:
0348     case 0x031C:
0349     case 0x031D:
0350     case 0x031E:
0351     case 0x031F:
0352     case 0x0324:
0353     case 0x0325:
0354     case 0x0328:
0355     case 0x0329:
0356     case 0x032C:
0357     case 0x032D:
0358     case 0x0347:
0359     case 0x0348:
0360     case 0x0349:
0361     case 0x034B:
0362     case 0x034C:
0363     case 0x0160:
0364     case 0x0166:
0365     case 0x0169:
0366     case 0x016B:
0367     case 0x016C:
0368     case 0x016D:
0369     case 0x00C8:
0370     case 0x00CC:
0371     case 0x0144:
0372     case 0x0146:
0373     case 0x0147:
0374     case 0x0148:
0375     case 0x0098:
0376     case 0x0099:
0377         mobile = 1;
0378         break;
0379     default:
0380         break;
0381     }
0382 
0383     if (par->Architecture == NV_ARCH_04)
0384         nv4GetConfig(par);
0385     else
0386         nv10GetConfig(par);
0387 
0388     NVSelectHeadRegisters(par, 0);
0389 
0390     NVLockUnlock(par, 0);
0391 
0392     par->IOBase = (NVReadMiscOut(par) & 0x01) ? 0x3d0 : 0x3b0;
0393 
0394     par->Television = 0;
0395 
0396     nvidia_create_i2c_busses(par);
0397     if (!par->twoHeads) {
0398         par->CRTCnumber = 0;
0399         if (nvidia_probe_i2c_connector(info, 1, &edidA))
0400             nvidia_probe_of_connector(info, 1, &edidA);
0401         if (edidA && !fb_parse_edid(edidA, var)) {
0402             printk("nvidiafb: EDID found from BUS1\n");
0403             monA = monitorA;
0404             fb_edid_to_monspecs(edidA, monA);
0405             FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
0406 
0407             /* NV4 doesn't support FlatPanels */
0408             if ((par->Chipset & 0x0fff) <= 0x0020)
0409                 FlatPanel = 0;
0410         } else {
0411             VGA_WR08(par->PCIO, 0x03D4, 0x28);
0412             if (VGA_RD08(par->PCIO, 0x03D5) & 0x80) {
0413                 VGA_WR08(par->PCIO, 0x03D4, 0x33);
0414                 if (!(VGA_RD08(par->PCIO, 0x03D5) & 0x01))
0415                     Television = 1;
0416                 FlatPanel = 1;
0417             } else {
0418                 FlatPanel = 0;
0419             }
0420             printk("nvidiafb: HW is currently programmed for %s\n",
0421                    FlatPanel ? (Television ? "TV" : "DFP") :
0422                    "CRT");
0423         }
0424 
0425         if (par->FlatPanel == -1) {
0426             par->FlatPanel = FlatPanel;
0427             par->Television = Television;
0428         } else {
0429             printk("nvidiafb: Forcing display type to %s as "
0430                    "specified\n", par->FlatPanel ? "DFP" : "CRT");
0431         }
0432     } else {
0433         u8 outputAfromCRTC, outputBfromCRTC;
0434         int CRTCnumber = -1;
0435         u8 slaved_on_A, slaved_on_B;
0436         int analog_on_A, analog_on_B;
0437         u32 oldhead;
0438         u8 cr44;
0439 
0440         if (implementation != 0x0110) {
0441             if (NV_RD32(par->PRAMDAC0, 0x0000052C) & 0x100)
0442                 outputAfromCRTC = 1;
0443             else
0444                 outputAfromCRTC = 0;
0445             if (NV_RD32(par->PRAMDAC0, 0x0000252C) & 0x100)
0446                 outputBfromCRTC = 1;
0447             else
0448                 outputBfromCRTC = 0;
0449             analog_on_A = NVIsConnected(par, 0);
0450             analog_on_B = NVIsConnected(par, 1);
0451         } else {
0452             outputAfromCRTC = 0;
0453             outputBfromCRTC = 1;
0454             analog_on_A = 0;
0455             analog_on_B = 0;
0456         }
0457 
0458         VGA_WR08(par->PCIO, 0x03D4, 0x44);
0459         cr44 = VGA_RD08(par->PCIO, 0x03D5);
0460 
0461         VGA_WR08(par->PCIO, 0x03D5, 3);
0462         NVSelectHeadRegisters(par, 1);
0463         NVLockUnlock(par, 0);
0464 
0465         VGA_WR08(par->PCIO, 0x03D4, 0x28);
0466         slaved_on_B = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
0467         if (slaved_on_B) {
0468             VGA_WR08(par->PCIO, 0x03D4, 0x33);
0469             tvB = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
0470         }
0471 
0472         VGA_WR08(par->PCIO, 0x03D4, 0x44);
0473         VGA_WR08(par->PCIO, 0x03D5, 0);
0474         NVSelectHeadRegisters(par, 0);
0475         NVLockUnlock(par, 0);
0476 
0477         VGA_WR08(par->PCIO, 0x03D4, 0x28);
0478         slaved_on_A = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
0479         if (slaved_on_A) {
0480             VGA_WR08(par->PCIO, 0x03D4, 0x33);
0481             tvA = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
0482         }
0483 
0484         oldhead = NV_RD32(par->PCRTC0, 0x00000860);
0485         NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
0486 
0487         if (nvidia_probe_i2c_connector(info, 1, &edidA))
0488             nvidia_probe_of_connector(info, 1, &edidA);
0489         if (edidA && !fb_parse_edid(edidA, var)) {
0490             printk("nvidiafb: EDID found from BUS1\n");
0491             monA = monitorA;
0492             fb_edid_to_monspecs(edidA, monA);
0493         }
0494 
0495         if (nvidia_probe_i2c_connector(info, 2, &edidB))
0496             nvidia_probe_of_connector(info, 2, &edidB);
0497         if (edidB && !fb_parse_edid(edidB, var)) {
0498             printk("nvidiafb: EDID found from BUS2\n");
0499             monB = monitorB;
0500             fb_edid_to_monspecs(edidB, monB);
0501         }
0502 
0503         if (slaved_on_A && !tvA) {
0504             CRTCnumber = 0;
0505             FlatPanel = 1;
0506             printk("nvidiafb: CRTC 0 is currently programmed for "
0507                    "DFP\n");
0508         } else if (slaved_on_B && !tvB) {
0509             CRTCnumber = 1;
0510             FlatPanel = 1;
0511             printk("nvidiafb: CRTC 1 is currently programmed "
0512                    "for DFP\n");
0513         } else if (analog_on_A) {
0514             CRTCnumber = outputAfromCRTC;
0515             FlatPanel = 0;
0516             printk("nvidiafb: CRTC %i appears to have a "
0517                    "CRT attached\n", CRTCnumber);
0518         } else if (analog_on_B) {
0519             CRTCnumber = outputBfromCRTC;
0520             FlatPanel = 0;
0521             printk("nvidiafb: CRTC %i appears to have a "
0522                    "CRT attached\n", CRTCnumber);
0523         } else if (slaved_on_A) {
0524             CRTCnumber = 0;
0525             FlatPanel = 1;
0526             Television = 1;
0527             printk("nvidiafb: CRTC 0 is currently programmed "
0528                    "for TV\n");
0529         } else if (slaved_on_B) {
0530             CRTCnumber = 1;
0531             FlatPanel = 1;
0532             Television = 1;
0533             printk("nvidiafb: CRTC 1 is currently programmed for "
0534                    "TV\n");
0535         } else if (monA) {
0536             FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
0537         } else if (monB) {
0538             FlatPanel = (monB->input & FB_DISP_DDI) ? 1 : 0;
0539         }
0540 
0541         if (par->FlatPanel == -1) {
0542             if (FlatPanel != -1) {
0543                 par->FlatPanel = FlatPanel;
0544                 par->Television = Television;
0545             } else {
0546                 printk("nvidiafb: Unable to detect display "
0547                        "type...\n");
0548                 if (mobile) {
0549                     printk("...On a laptop, assuming "
0550                            "DFP\n");
0551                     par->FlatPanel = 1;
0552                 } else {
0553                     printk("...Using default of CRT\n");
0554                     par->FlatPanel = 0;
0555                 }
0556             }
0557         } else {
0558             printk("nvidiafb: Forcing display type to %s as "
0559                    "specified\n", par->FlatPanel ? "DFP" : "CRT");
0560         }
0561 
0562         if (par->CRTCnumber == -1) {
0563             if (CRTCnumber != -1)
0564                 par->CRTCnumber = CRTCnumber;
0565             else {
0566                 printk("nvidiafb: Unable to detect which "
0567                        "CRTCNumber...\n");
0568                 if (par->FlatPanel)
0569                     par->CRTCnumber = 1;
0570                 else
0571                     par->CRTCnumber = 0;
0572                 printk("...Defaulting to CRTCNumber %i\n",
0573                        par->CRTCnumber);
0574             }
0575         } else {
0576             printk("nvidiafb: Forcing CRTCNumber %i as "
0577                    "specified\n", par->CRTCnumber);
0578         }
0579 
0580         if (monA) {
0581             if (((monA->input & FB_DISP_DDI) &&
0582                  par->FlatPanel) ||
0583                 ((!(monA->input & FB_DISP_DDI)) &&
0584                  !par->FlatPanel)) {
0585                 if (monB) {
0586                     fb_destroy_modedb(monB->modedb);
0587                     monB = NULL;
0588                 }
0589             } else {
0590                 fb_destroy_modedb(monA->modedb);
0591                 monA = NULL;
0592             }
0593         }
0594 
0595         if (monB) {
0596             if (((monB->input & FB_DISP_DDI) &&
0597                  !par->FlatPanel) ||
0598                 ((!(monB->input & FB_DISP_DDI)) &&
0599                  par->FlatPanel)) {
0600                 fb_destroy_modedb(monB->modedb);
0601                 monB = NULL;
0602             } else
0603                 monA = monB;
0604         }
0605 
0606         if (implementation == 0x0110)
0607             cr44 = par->CRTCnumber * 0x3;
0608 
0609         NV_WR32(par->PCRTC0, 0x00000860, oldhead);
0610 
0611         VGA_WR08(par->PCIO, 0x03D4, 0x44);
0612         VGA_WR08(par->PCIO, 0x03D5, cr44);
0613         NVSelectHeadRegisters(par, par->CRTCnumber);
0614     }
0615 
0616     printk("nvidiafb: Using %s on CRTC %i\n",
0617            par->FlatPanel ? (par->Television ? "TV" : "DFP") : "CRT",
0618            par->CRTCnumber);
0619 
0620     if (par->FlatPanel && !par->Television) {
0621         par->fpWidth = NV_RD32(par->PRAMDAC, 0x0820) + 1;
0622         par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1;
0623         par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033;
0624 
0625         printk("nvidiafb: Panel size is %i x %i\n", par->fpWidth, par->fpHeight);
0626     }
0627 
0628     if (monA)
0629         info->monspecs = *monA;
0630 
0631     if (!par->FlatPanel || !par->twoHeads)
0632         par->FPDither = 0;
0633 
0634     par->LVDS = 0;
0635     if (par->FlatPanel && par->twoHeads) {
0636         NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004);
0637         if (NV_RD32(par->PRAMDAC0, 0x08b4) & 1)
0638             par->LVDS = 1;
0639         printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS");
0640     }
0641 
0642     kfree(edidA);
0643     kfree(edidB);
0644 done:
0645     kfree(var);
0646     kfree(monitorA);
0647     kfree(monitorB);
0648     return err;
0649 }