X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Fnvidia%2Fnvidia.c;fp=drivers%2Fvideo%2Fnvidia%2Fnvidia.c;h=093ab9977c7ce843bc222e478d142c0aa57ff0d9;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=47733f58153bd4d8bb856dcc69d98e4e86492a95;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 47733f581..093ab9977 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_MTRR #include #endif @@ -29,6 +30,7 @@ #include #endif #ifdef CONFIG_PMAC_BACKLIGHT +#include #include #endif @@ -138,6 +140,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 +288,18 @@ 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, PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280, + 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, @@ -384,6 +400,14 @@ 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_6800B_GT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x021d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x021e, @@ -403,12 +427,14 @@ MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl); /* command line data, set in nvidiafb_setup() */ static int flatpanel __devinitdata = -1; /* Autodetect later */ +static int fpdither __devinitdata = -1; static int forceCRTC __devinitdata = -1; static int hwcur __devinitdata = 0; 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 @@ -476,7 +502,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; @@ -516,9 +542,9 @@ static struct backlight_controller nvidia_backlight_controller = { static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8, u16 bg, u16 fg, u32 w, u32 h) { + u32 *data = (u32 *) data8; int i, j, k = 0; u32 b, tmp; - u32 *data = (u32 *) data8; w = (w + 1) & ~1; @@ -593,6 +619,30 @@ static int nvidia_panel_tweak(struct nvidia_par *par, return tweak; } +static void nvidia_vga_protect(struct nvidia_par *par, int on) +{ + unsigned char tmp; + + if (on) { + /* + * Turn off screen and disable sequencer. + */ + tmp = NVReadSeq(par, 0x01); + + NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ + NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ + } else { + /* + * Reenable sequencer, then turn on screen. + */ + + tmp = NVReadSeq(par, 0x01); + + NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ + NVWriteSeq(par, 0x00, 0x03); /* End Reset */ + } +} + static void nvidia_save_vga(struct nvidia_par *par, struct _riva_hw_state *state) { @@ -619,38 +669,56 @@ static void nvidia_save_vga(struct nvidia_par *par, NVTRACE_LEAVE(); } -static void nvidia_write_regs(struct nvidia_par *par) +#undef DUMP_REG + +static void nvidia_write_regs(struct nvidia_par *par, + struct _riva_hw_state *state) { - struct _riva_hw_state *state = &par->ModeReg; int i; NVTRACE_ENTER(); - NVWriteCrtc(par, 0x11, 0x00); - - NVLockUnlock(par, 0); NVLoadStateExt(par, state); NVWriteMiscOut(par, state->misc_output); + for (i = 1; i < NUM_SEQ_REGS; i++) { +#ifdef DUMP_REG + printk(" SEQ[%02x] = %08x\n", i, state->seq[i]); +#endif + NVWriteSeq(par, i, state->seq[i]); + } + + /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */ + NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80); + for (i = 0; i < NUM_CRT_REGS; i++) { switch (i) { case 0x19: case 0x20 ... 0x40: break; default: +#ifdef DUMP_REG + printk("CRTC[%02x] = %08x\n", i, state->crtc[i]); +#endif NVWriteCrtc(par, i, state->crtc[i]); } } - for (i = 0; i < NUM_ATC_REGS; i++) - NVWriteAttr(par, i, state->attr[i]); - - for (i = 0; i < NUM_GRC_REGS; i++) + for (i = 0; i < NUM_GRC_REGS; i++) { +#ifdef DUMP_REG + printk(" GRA[%02x] = %08x\n", i, state->gra[i]); +#endif NVWriteGr(par, i, state->gra[i]); + } + + for (i = 0; i < NUM_ATC_REGS; i++) { +#ifdef DUMP_REG + printk("ATTR[%02x] = %08x\n", i, state->attr[i]); +#endif + NVWriteAttr(par, i, state->attr[i]); + } - for (i = 0; i < NUM_SEQ_REGS; i++) - NVWriteSeq(par, i, state->seq[i]); NVTRACE_LEAVE(); } @@ -658,7 +726,7 @@ static int nvidia_calc_regs(struct fb_info *info) { struct nvidia_par *par = info->par; struct _riva_hw_state *state = &par->ModeReg; - int i, depth = fb_get_color_depth(&info->var); + int i, depth = fb_get_color_depth(&info->var, &info->fix); int h_display = info->var.xres / 8 - 1; int h_start = (info->var.xres + info->var.right_margin) / 8 - 1; int h_end = (info->var.xres + info->var.right_margin + @@ -860,7 +928,7 @@ static void nvidia_init_vga(struct fb_info *info) for (i = 0; i < 0x10; i++) state->attr[i] = i; state->attr[0x10] = 0x41; - state->attr[0x11] = 0x01; + state->attr[0x11] = 0xff; state->attr[0x12] = 0x0f; state->attr[0x13] = 0x00; state->attr[0x14] = 0x00; @@ -890,11 +958,11 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct nvidia_par *par = info->par; u8 data[MAX_CURS * MAX_CURS / 8]; - u16 fg, bg; int i, set = cursor->set; + u16 fg, bg; if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS) - return soft_cursor(info, cursor); + return -ENXIO; NVShowHideCursor(par, 0); @@ -931,21 +999,18 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor) if (src) { switch (cursor->rop) { case ROP_XOR: - for (i = 0; i < s_pitch * cursor->image.height; - i++) + for (i = 0; i < s_pitch * cursor->image.height; i++) src[i] = dat[i] ^ msk[i]; break; case ROP_COPY: default: - for (i = 0; i < s_pitch * cursor->image.height; - i++) + for (i = 0; i < s_pitch * cursor->image.height; i++) src[i] = dat[i] & msk[i]; break; } - fb_sysmove_buf_aligned(info, &info->pixmap, data, - d_pitch, src, s_pitch, - cursor->image.height); + fb_pad_aligned_buffer(data, d_pitch, src, s_pitch, + cursor->image.height); bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) | ((info->cmap.green[bg_idx] & 0xf8) << 2) | @@ -977,13 +1042,24 @@ static int nvidiafb_set_par(struct fb_info *info) NVTRACE_ENTER(); NVLockUnlock(par, 1); - if (!par->FlatPanel || (info->var.bits_per_pixel != 24) || - !par->twoHeads) + if (!par->FlatPanel || !par->twoHeads) par->FPDither = 0; + if (par->FPDither < 0) { + if ((par->Chipset & 0x0ff0) == 0x0110) + par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x0528) + & 0x00010000); + else + par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1); + printk(KERN_INFO PFX "Flat panel dithering %s\n", + par->FPDither ? "enabled" : "disabled"); + } + + info->fix.visual = (info->var.bits_per_pixel == 8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; + nvidia_init_vga(info); nvidia_calc_regs(info); - nvidia_write_regs(par); NVLockUnlock(par, 0); if (par->twoHeads) { @@ -992,12 +1068,25 @@ static int nvidiafb_set_par(struct fb_info *info) NVLockUnlock(par, 0); } - NVWriteCrtc(par, 0x11, 0x00); + nvidia_vga_protect(par, 1); + + nvidia_write_regs(par, &par->ModeReg); + NVSetStartAddress(par, 0); + +#if defined (__BIG_ENDIAN) + /* turn on LFB swapping */ + { + unsigned char tmp; + + VGA_WR08(par->PCIO, 0x3d4, 0x46); + tmp = VGA_RD08(par->PCIO, 0x3d5); + tmp |= (1 << 7); + VGA_WR08(par->PCIO, 0x3d5, tmp); + } +#endif + info->fix.line_length = (info->var.xres_virtual * info->var.bits_per_pixel) >> 3; - info->fix.visual = (info->var.bits_per_pixel == 8) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; - if (info->var.accel_flags) { info->fbops->fb_imageblit = nvidiafb_imageblit; info->fbops->fb_fillrect = nvidiafb_fillrect; @@ -1017,7 +1106,7 @@ static int nvidiafb_set_par(struct fb_info *info) par->cursor_reset = 1; - NVWriteCrtc(par, 0x11, 0xff); + nvidia_vga_protect(par, 0); NVTRACE_LEAVE(); return 0; @@ -1228,7 +1317,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); @@ -1267,7 +1356,7 @@ static int nvidiafb_blank(int blank, struct fb_info *info) NVWriteCrtc(par, 0x1a, vesa); #ifdef CONFIG_PMAC_BACKLIGHT - if (par->FlatPanel && _machine == _MACH_Pmac) { + if (par->FlatPanel && machine_is(powermac)) { set_backlight_enable(!blank); } #endif @@ -1291,6 +1380,57 @@ static struct fb_ops nvidia_fb_ops = { .fb_sync = nvidiafb_sync, }; +#ifdef CONFIG_PM +static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct nvidia_par *par = info->par; + + acquire_console_sem(); + par->pm_state = state.event; + + if (state.event == PM_EVENT_FREEZE) { + dev->dev.power.power_state = state; + } else { + fb_set_suspend(info, 1); + nvidiafb_blank(FB_BLANK_POWERDOWN, info); + nvidia_write_regs(par, &par->SavedReg); + pci_save_state(dev); + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + } + + release_console_sem(); + return 0; +} + +static int nvidiafb_resume(struct pci_dev *dev) +{ + struct fb_info *info = pci_get_drvdata(dev); + struct nvidia_par *par = info->par; + + acquire_console_sem(); + pci_set_power_state(dev, PCI_D0); + + if (par->pm_state != PM_EVENT_FREEZE) { + pci_restore_state(dev); + pci_enable_device(dev); + pci_set_master(dev); + } + + par->pm_state = PM_EVENT_ON; + nvidiafb_set_par(info); + fb_set_suspend (info, 0); + nvidiafb_blank(FB_BLANK_UNBLANK, info); + + release_console_sem(); + return 0; +} +#else +#define nvidiafb_suspend NULL +#define nvidiafb_resume NULL +#endif + static int __devinit nvidia_set_fbinfo(struct fb_info *info) { struct fb_monspecs *specs = &info->monspecs; @@ -1309,29 +1449,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); - if (specs->modedb != NULL) { - /* get preferred timing */ - if (specs->misc & FB_MISC_1ST_DETAIL) { - int i; - - for (i = 0; i < specs->modedb_len; i++) { - if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { - modedb = specs->modedb[i]; - break; - } - } - } else { - /* otherwise, get first mode in database */ - modedb = specs->modedb[0]; - } + switch (bpp) { + case 0 ... 8: + bpp = 8; + break; + case 9 ... 16: + bpp = 16; + break; + default: + bpp = 32; + break; + } - fb_videomode_to_var(&nvidiafb_default_var, &modedb); - nvidiafb_default_var.bits_per_pixel = 8; + 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 = 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, 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) ? @@ -1348,11 +1495,13 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) info->pixmap.scan_align = 4; info->pixmap.buf_align = 4; + info->pixmap.access_align = 32; info->pixmap.size = 8 * 1024; info->pixmap.flags = FB_PIXMAP_SYSTEM; if (!hwcur) - info->fbops->fb_cursor = soft_cursor; + info->fbops->fb_cursor = NULL; + info->var.accel_flags = (!noaccel); switch (par->Architecture) { @@ -1378,11 +1527,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 */ @@ -1415,6 +1587,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 */ @@ -1443,7 +1617,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); @@ -1463,26 +1637,10 @@ 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); - -#ifdef CONFIG_PCI_NAMES - printk(KERN_INFO PFX "%s\n", pd->pretty_name); -#endif - - 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"); + par->FPDither = fpdither; par->CRTCnumber = forceCRTC; par->FpScale = (!noscale); @@ -1504,7 +1662,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; @@ -1515,10 +1685,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; @@ -1567,28 +1742,29 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, info->fix.id, par->FbMapSize / (1024 * 1024), info->fix.smem_start); #ifdef CONFIG_PMAC_BACKLIGHT - if (par->FlatPanel && _machine == _MACH_Pmac) + if (par->FlatPanel && machine_is(powermac)) register_backlight_controller(&nvidia_backlight_controller, par, "mnca"); #endif 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; } @@ -1598,8 +1774,6 @@ static void __exit nvidiafb_remove(struct pci_dev *pd) struct nvidia_par *par = info->par; NVTRACE_ENTER(); - if (!info) - return; unregister_framebuffer(info); #ifdef CONFIG_MTRR @@ -1661,6 +1835,10 @@ static int __devinit nvidiafb_setup(char *options) } else if (!strncmp(this_opt, "nomtrr", 6)) { nomtrr = 1; #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; } @@ -1672,8 +1850,10 @@ static int __devinit nvidiafb_setup(char *options) static struct pci_driver nvidiafb_driver = { .name = "nvidiafb", .id_table = nvidiafb_pci_tbl, - .probe = nvidiafb_probe, - .remove = __exit_p(nvidiafb_remove), + .probe = nvidiafb_probe, + .suspend = nvidiafb_suspend, + .resume = nvidiafb_resume, + .remove = __exit_p(nvidiafb_remove), }; /* ------------------------------------------------------------------------- * @@ -1707,7 +1887,11 @@ module_exit(nvidiafb_exit); module_param(flatpanel, int, 0); MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. " - "(0 or 1=enabled) (default=0)"); + "(0=disabled, 1=enabled, -1=autodetect) (default=-1)"); +module_param(fpdither, int, 0); +MODULE_PARM_DESC(fpdither, + "Enables dithering of flat panel for 6 bits panels. " + "(0=disabled, 1=enabled, -1=autodetect) (default=-1)"); module_param(hwcur, int, 0); MODULE_PARM_DESC(hwcur, "Enables hardware cursor implementation. (0 or 1=enabled) " @@ -1732,6 +1916,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) "