diff options
Diffstat (limited to 'drivers/video/nvidia')
-rw-r--r-- | drivers/video/nvidia/nv_hw.c | 82 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_i2c.c | 12 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_proto.h | 2 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_setup.c | 37 | ||||
-rw-r--r-- | drivers/video/nvidia/nvidia.c | 117 |
5 files changed, 187 insertions, 63 deletions
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c index b989358437b3..99c3a8e6a237 100644 --- a/drivers/video/nvidia/nv_hw.c +++ b/drivers/video/nvidia/nv_hw.c @@ -52,6 +52,7 @@ #include <linux/pci.h> #include "nv_type.h" #include "nv_local.h" +#include "nv_proto.h" void NVLockUnlock(struct nvidia_par *par, int Lock) { @@ -848,7 +849,7 @@ void NVCalcStateExt(struct nvidia_par *par, int width, int hDisplaySize, int height, int dotClock, int flags) { - int pixelDepth, VClk; + int pixelDepth, VClk = 0; /* * Save mode parameters. */ @@ -938,15 +939,24 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) if (par->Architecture == NV_ARCH_04) { NV_WR32(par->PFB, 0x0200, state->config); - } else if ((par->Chipset & 0xfff0) == 0x0090) { - for (i = 0; i < 15; i++) { - NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0); - NV_WR32(par->PFB, 0x0604 + (i * 0x10), par->FbMapSize - 1); - } - } else { + } else if ((par->Architecture < NV_ARCH_40) || + (par->Chipset & 0xfff0) == 0x0040) { for (i = 0; i < 8; i++) { NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0); - NV_WR32(par->PFB, 0x0244 + (i * 0x10), par->FbMapSize - 1); + NV_WR32(par->PFB, 0x0244 + (i * 0x10), + par->FbMapSize - 1); + } + } else { + int regions = 12; + + if (((par->Chipset & 0xfff0) == 0x0090) || + ((par->Chipset & 0xfff0) == 0x01D0) || + ((par->Chipset & 0xfff0) == 0x0290)) + regions = 15; + for(i = 0; i < regions; i++) { + NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0); + NV_WR32(par->PFB, 0x0604 + (i * 0x10), + par->FbMapSize - 1); } } @@ -1182,11 +1192,17 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF); } else { if (par->Architecture >= NV_ARCH_40) { + u32 tmp; + NV_WR32(par->PGRAPH, 0x0084, 0x401287c0); NV_WR32(par->PGRAPH, 0x008C, 0x60de8051); NV_WR32(par->PGRAPH, 0x0090, 0x00008000); NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f); + tmp = NV_RD32(par->REGS, 0x1540) & 0xff; + for(i = 0; tmp && !(tmp & 1); tmp >>= 1, i++); + NV_WR32(par->PGRAPH, 0x5000, i); + if ((par->Chipset & 0xfff0) == 0x0040) { NV_WR32(par->PGRAPH, 0x09b0, 0x83280fff); @@ -1211,6 +1227,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) 0xffff7fff); break; case 0x00C0: + case 0x0120: NV_WR32(par->PGRAPH, 0x0828, 0x007596ff); NV_WR32(par->PGRAPH, 0x082C, @@ -1245,6 +1262,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) 0x00100000); break; case 0x0090: + case 0x0290: NV_WR32(par->PRAMDAC, 0x0608, NV_RD32(par->PRAMDAC, 0x0608) | 0x00100000); @@ -1310,14 +1328,44 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) } } - if ((par->Chipset & 0xfff0) == 0x0090) { - for (i = 0; i < 60; i++) - NV_WR32(par->PGRAPH, 0x0D00 + i, - NV_RD32(par->PFB, 0x0600 + i)); + if ((par->Architecture < NV_ARCH_40) || + ((par->Chipset & 0xfff0) == 0x0040)) { + for (i = 0; i < 32; i++) { + NV_WR32(par->PGRAPH, 0x0900 + i*4, + NV_RD32(par->PFB, 0x0240 +i*4)); + NV_WR32(par->PGRAPH, 0x6900 + i*4, + NV_RD32(par->PFB, 0x0240 +i*4)); + } } else { - for (i = 0; i < 32; i++) - NV_WR32(par->PGRAPH, 0x0900 + i, - NV_RD32(par->PFB, 0x0240 + i)); + if (((par->Chipset & 0xfff0) == 0x0090) || + ((par->Chipset & 0xfff0) == 0x01D0) || + ((par->Chipset & 0xfff0) == 0x0290)) { + for (i = 0; i < 60; i++) { + NV_WR32(par->PGRAPH, + 0x0D00 + i*4, + NV_RD32(par->PFB, + 0x0600 + i*4)); + NV_WR32(par->PGRAPH, + 0x6900 + i*4, + NV_RD32(par->PFB, + 0x0600 + i*4)); + } + } else { + for (i = 0; i < 48; i++) { + NV_WR32(par->PGRAPH, + 0x0900 + i*4, + NV_RD32(par->PFB, + 0x0600 + i*4)); + if(((par->Chipset & 0xfff0) + != 0x0160) && + ((par->Chipset & 0xfff0) + != 0x0220)) + NV_WR32(par->PGRAPH, + 0x6900 + i*4, + NV_RD32(par->PFB, + 0x0600 + i*4)); + } + } } if (par->Architecture >= NV_ARCH_40) { @@ -1338,7 +1386,9 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) NV_WR32(par->PGRAPH, 0x0868, par->FbMapSize - 1); } else { - if((par->Chipset & 0xfff0) == 0x0090) { + if ((par->Chipset & 0xfff0) == 0x0090 || + (par->Chipset & 0xfff0) == 0x01D0 || + (par->Chipset & 0xfff0) == 0x0290) { NV_WR32(par->PGRAPH, 0x0DF0, NV_RD32(par->PFB, 0x0200)); NV_WR32(par->PGRAPH, 0x0DF4, diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index 12f2884d3f0b..bd9eca05e146 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c @@ -46,7 +46,7 @@ static void nvidia_gpio_setscl(void *data, int state) static void nvidia_gpio_setsda(void *data, int state) { - struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data; + struct nvidia_i2c_chan *chan = data; struct nvidia_par *par = chan->par; u32 val; @@ -64,7 +64,7 @@ static void nvidia_gpio_setsda(void *data, int state) static int nvidia_gpio_getscl(void *data) { - struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data; + struct nvidia_i2c_chan *chan = data; struct nvidia_par *par = chan->par; u32 val = 0; @@ -79,7 +79,7 @@ static int nvidia_gpio_getscl(void *data) static int nvidia_gpio_getsda(void *data) { - struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data; + struct nvidia_i2c_chan *chan = data; struct nvidia_par *par = chan->par; u32 val = 0; @@ -136,13 +136,13 @@ void nvidia_create_i2c_busses(struct nvidia_par *par) par->chan[2].par = par; par->chan[0].ddc_base = 0x3e; - nvidia_setup_i2c_bus(&par->chan[0], "BUS1"); + nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0"); par->chan[1].ddc_base = 0x36; - nvidia_setup_i2c_bus(&par->chan[1], "BUS2"); + nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1"); par->chan[2].ddc_base = 0x50; - nvidia_setup_i2c_bus(&par->chan[2], "BUS3"); + nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2"); } void nvidia_delete_i2c_busses(struct nvidia_par *par) diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h index 3353103e8b0b..b149a690ee0f 100644 --- a/drivers/video/nvidia/nv_proto.h +++ b/drivers/video/nvidia/nv_proto.h @@ -4,7 +4,7 @@ #define __NV_PROTO_H__ /* in nv_setup.c */ -void NVCommonSetup(struct fb_info *info); +int NVCommonSetup(struct fb_info *info); void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value); u8 NVReadCrtc(struct nvidia_par *par, u8 index); void NVWriteGr(struct nvidia_par *par, u8 index, u8 value); diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index 1f06a9f1bd0f..a18a9aebf05f 100644 --- a/drivers/video/nvidia/nv_setup.c +++ b/drivers/video/nvidia/nv_setup.c @@ -285,28 +285,34 @@ static void nv10GetConfig(struct nvidia_par *par) par->CrystalFreqKHz = 27000; } - par->CursorStart = (par->RamAmountKBytes - 96) * 1024; par->CURSOR = NULL; /* can't set this here */ par->MinVClockFreqKHz = 12000; par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000; } -void NVCommonSetup(struct fb_info *info) +int NVCommonSetup(struct fb_info *info) { struct nvidia_par *par = info->par; - struct fb_var_screeninfo var; + struct fb_var_screeninfo *var; u16 implementation = par->Chipset & 0x0ff0; u8 *edidA = NULL, *edidB = NULL; - struct fb_monspecs monitorA, monitorB; + struct fb_monspecs *monitorA, *monitorB; struct fb_monspecs *monA = NULL, *monB = NULL; int mobile = 0; int tvA = 0; int tvB = 0; int FlatPanel = -1; /* really means the CRTC is slaved */ int Television = 0; + int err = 0; - memset(&monitorA, 0, sizeof(struct fb_monspecs)); - memset(&monitorB, 0, sizeof(struct fb_monspecs)); + var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); + monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL); + monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL); + + if (!var || !monitorA || !monitorB) { + err = -ENOMEM; + goto done; + } par->PRAMIN = par->REGS + (0x00710000 / 4); par->PCRTC0 = par->REGS + (0x00600000 / 4); @@ -382,6 +388,8 @@ void NVCommonSetup(struct fb_info *info) case 0x0146: case 0x0147: case 0x0148: + case 0x0098: + case 0x0099: mobile = 1; break; default: @@ -406,9 +414,9 @@ void NVCommonSetup(struct fb_info *info) par->CRTCnumber = 0; if (nvidia_probe_i2c_connector(info, 1, &edidA)) nvidia_probe_of_connector(info, 1, &edidA); - if (edidA && !fb_parse_edid(edidA, &var)) { + if (edidA && !fb_parse_edid(edidA, var)) { printk("nvidiafb: EDID found from BUS1\n"); - monA = &monitorA; + monA = monitorA; fb_edid_to_monspecs(edidA, monA); FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0; @@ -494,17 +502,17 @@ void NVCommonSetup(struct fb_info *info) if (nvidia_probe_i2c_connector(info, 1, &edidA)) nvidia_probe_of_connector(info, 1, &edidA); - if (edidA && !fb_parse_edid(edidA, &var)) { + if (edidA && !fb_parse_edid(edidA, var)) { printk("nvidiafb: EDID found from BUS1\n"); - monA = &monitorA; + monA = monitorA; fb_edid_to_monspecs(edidA, monA); } if (nvidia_probe_i2c_connector(info, 2, &edidB)) nvidia_probe_of_connector(info, 2, &edidB); - if (edidB && !fb_parse_edid(edidB, &var)) { + if (edidB && !fb_parse_edid(edidB, var)) { printk("nvidiafb: EDID found from BUS2\n"); - monB = &monitorB; + monB = monitorB; fb_edid_to_monspecs(edidB, monB); } @@ -639,4 +647,9 @@ void NVCommonSetup(struct fb_info *info) kfree(edidA); kfree(edidB); +done: + kfree(var); + kfree(monitorA); + kfree(monitorB); + return err; } diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index bee09c6e48f6..dbcb8962e57d 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -284,6 +284,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 +428,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 +496,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; @@ -1382,24 +1393,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 +1471,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 +1531,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 +1561,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 +1581,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 +1606,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 +1629,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 +1693,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 +1783,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 +1860,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) " |