[PATCH] nvidiafb: Add support for Geforce4 MX 4000
[deliverable/linux.git] / drivers / video / nvidia / nvidia.c
index 0b40a2a721c180609c15b16e82e3209b195a846e..a7c4e5e8ead63781420bdb9d0a8c203d8f97a915 100644 (file)
@@ -138,6 +138,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
@@ -284,6 +286,16 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_NVIDIA, 0x0252,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        {PCI_VENDOR_ID_NVIDIA, 0x0313,
@@ -418,6 +430,7 @@ static int noaccel __devinitdata = 0;
 static int noscale __devinitdata = 0;
 static int paneltweak __devinitdata = 0;
 static int vram __devinitdata = 0;
+static int bpp __devinitdata = 8;
 #ifdef CONFIG_MTRR
 static int nomtrr __devinitdata = 0;
 #endif
@@ -485,7 +498,7 @@ static int nvidia_backlight_levels[] = {
 
 static int nvidia_set_backlight_enable(int on, int level, void *data)
 {
-       struct nvidia_par *par = (struct nvidia_par *)data;
+       struct nvidia_par *par = data;
        u32 tmp_pcrt, tmp_pmc, fpcontrol;
 
        tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
@@ -1301,7 +1314,7 @@ static int nvidiafb_pan_display(struct fb_var_screeninfo *var,
        struct nvidia_par *par = info->par;
        u32 total;
 
-       total = info->var.yoffset * info->fix.line_length + info->var.xoffset;
+       total = var->yoffset * info->fix.line_length + var->xoffset;
 
        NVSetStartAddress(par, total);
 
@@ -1382,24 +1395,36 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
                                 info->monspecs.modedb_len, &info->modelist);
        fb_var_to_videomode(&modedb, &nvidiafb_default_var);
 
+       switch (bpp) {
+       case 0 ... 8:
+               bpp = 8;
+               break;
+       case 9 ... 16:
+               bpp = 16;
+               break;
+       default:
+               bpp = 32;
+               break;
+       }
+
        if (specs->modedb != NULL) {
                struct fb_videomode *modedb;
 
                modedb = fb_find_best_display(specs, &info->modelist);
                fb_videomode_to_var(&nvidiafb_default_var, modedb);
-               nvidiafb_default_var.bits_per_pixel = 8;
+               nvidiafb_default_var.bits_per_pixel = bpp;
        } else if (par->fpWidth && par->fpHeight) {
                char buf[16];
 
                memset(buf, 0, 16);
                snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
                fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
-                            specs->modedb_len, &modedb, 8);
+                            specs->modedb_len, &modedb, bpp);
        }
 
        if (mode_option)
                fb_find_mode(&nvidiafb_default_var, info, mode_option,
-                            specs->modedb, specs->modedb_len, &modedb, 8);
+                            specs->modedb, specs->modedb_len, &modedb, bpp);
 
        info->var = nvidiafb_default_var;
        info->fix.visual = (info->var.bits_per_pixel == 8) ?
@@ -1448,11 +1473,34 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
        return nvidiafb_check_var(&info->var, info);
 }
 
-static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
+static u32 __devinit nvidia_get_chipset(struct fb_info *info)
+{
+       struct nvidia_par *par = info->par;
+       u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
+
+       printk("nvidiafb: PCI id - %x\n", id);
+       if ((id & 0xfff0) == 0x00f0) {
+               /* pci-e */
+               printk("nvidiafb: PCI-E card\n");
+               id = NV_RD32(par->REGS, 0x1800);
+
+               if ((id & 0x0000ffff) == 0x000010DE)
+                       id = 0x10DE0000 | (id >> 16);
+               else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */
+                       id = 0x10DE0000 | ((id << 8) & 0x0000ff00) |
+                            ((id >> 8) & 0x000000ff);
+       }
+
+       printk("nvidiafb: Actual id - %x\n", id);
+       return id;
+}
+
+static u32 __devinit nvidia_get_arch(struct fb_info *info)
 {
+       struct nvidia_par *par = info->par;
        u32 arch = 0;
 
-       switch (pd->device & 0x0ff0) {
+       switch (par->Chipset & 0x0ff0) {
        case 0x0100:            /* GeForce 256 */
        case 0x0110:            /* GeForce2 MX */
        case 0x0150:            /* GeForce2 */
@@ -1485,6 +1533,8 @@ static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
        case 0x0210:
        case 0x0220:
        case 0x0230:
+       case 0x0290:
+       case 0x0390:
                arch = NV_ARCH_40;
                break;
        case 0x0020:            /* TNT, TNT2 */
@@ -1513,7 +1563,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
        if (!info)
                goto err_out;
 
-       par = (struct nvidia_par *)info->par;
+       par = info->par;
        par->pci_dev = pd;
 
        info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
@@ -1533,18 +1583,6 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
                goto err_out_request;
        }
 
-       par->Architecture = nvidia_get_arch(pd);
-
-       par->Chipset = (pd->vendor << 16) | pd->device;
-       printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
-
-       if (par->Architecture == 0) {
-               printk(KERN_ERR PFX "unknown NV_ARCH\n");
-               goto err_out_free_base0;
-       }
-
-       sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
-
        par->FlatPanel = flatpanel;
        if (flatpanel == 1)
                printk(KERN_INFO PFX "flatpanel support enabled\n");
@@ -1570,7 +1608,19 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
                goto err_out_free_base0;
        }
 
-       NVCommonSetup(info);
+       par->Chipset = nvidia_get_chipset(info);
+       printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
+       par->Architecture = nvidia_get_arch(info);
+
+       if (par->Architecture == 0) {
+               printk(KERN_ERR PFX "unknown NV_ARCH\n");
+               goto err_out_arch;
+       }
+
+       sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+
+       if (NVCommonSetup(info))
+               goto err_out_arch;
 
        par->FbAddress = nvidiafb_fix.smem_start;
        par->FbMapSize = par->RamAmountKBytes * 1024;
@@ -1581,10 +1631,15 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
        if (par->FbMapSize > 64 * 1024 * 1024)
                par->FbMapSize = 64 * 1024 * 1024;
 
-       par->FbUsableSize = par->FbMapSize - (128 * 1024);
+       if(par->Architecture >= NV_ARCH_40)
+               par->FbUsableSize = par->FbMapSize - (560 * 1024);
+       else
+               par->FbUsableSize = par->FbMapSize - (128 * 1024);
        par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
            16 * 1024;
        par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
+       par->CursorStart = par->FbUsableSize + (32 * 1024);
+
        info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
        info->screen_size = par->FbUsableSize;
        nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
@@ -1640,21 +1695,22 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
        NVTRACE_LEAVE();
        return 0;
 
-      err_out_iounmap_fb:
+err_out_iounmap_fb:
        iounmap(info->screen_base);
-      err_out_free_base1:
+err_out_free_base1:
        fb_destroy_modedb(info->monspecs.modedb);
        nvidia_delete_i2c_busses(par);
+err_out_arch:
        iounmap(par->REGS);
-      err_out_free_base0:
+err_out_free_base0:
        pci_release_regions(pd);
-      err_out_request:
+err_out_request:
        pci_disable_device(pd);
-      err_out_enable:
+err_out_enable:
        kfree(info->pixmap.addr);
-      err_out_kfree:
+err_out_kfree:
        framebuffer_release(info);
-      err_out:
+err_out:
        return -ENODEV;
 }
 
@@ -1729,6 +1785,8 @@ static int __devinit nvidiafb_setup(char *options)
 #endif
                } else if (!strncmp(this_opt, "fpdither:", 9)) {
                        fpdither = simple_strtol(this_opt+9, NULL, 0);
+               } else if (!strncmp(this_opt, "bpp:", 4)) {
+                       bpp = simple_strtoul(this_opt+4, NULL, 0);
                } else
                        mode_option = this_opt;
        }
@@ -1804,6 +1862,11 @@ module_param(vram, int, 0);
 MODULE_PARM_DESC(vram,
                 "amount of framebuffer memory to remap in MiB"
                 "(default=0 - remap entire memory)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
+module_param(bpp, int, 0);
+MODULE_PARM_DESC(bpp, "pixel width in bits"
+                "(default=8)");
 #ifdef CONFIG_MTRR
 module_param(nomtrr, bool, 0);
 MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
This page took 0.040776 seconds and 5 git commands to generate.