diff options
Diffstat (limited to 'drivers/video/fbdev/savage/savagefb_driver.c')
| -rw-r--r-- | drivers/video/fbdev/savage/savagefb_driver.c | 89 |
1 files changed, 58 insertions, 31 deletions
diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c index 3c8ae87f0ea7..ac41f8f37589 100644 --- a/drivers/video/fbdev/savage/savagefb_driver.c +++ b/drivers/video/fbdev/savage/savagefb_driver.c @@ -41,6 +41,7 @@ * */ +#include <linux/aperture.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -868,6 +869,9 @@ static int savagefb_check_var(struct fb_var_screeninfo *var, DBG("savagefb_check_var"); + if (!var->pixclock) + return -EINVAL; + var->transp.offset = 0; var->transp.length = 0; switch (var->bits_per_pixel) { @@ -1640,6 +1644,7 @@ static const struct fb_ops savagefb_ops = { .owner = THIS_MODULE, .fb_open = savagefb_open, .fb_release = savagefb_release, + __FB_DEFAULT_IOMEM_OPS_RDWR, .fb_check_var = savagefb_check_var, .fb_set_par = savagefb_set_par, .fb_setcolreg = savagefb_setcolreg, @@ -1651,10 +1656,9 @@ static const struct fb_ops savagefb_ops = { .fb_imageblit = savagefb_imageblit, .fb_sync = savagefb_sync, #else - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, + __FB_DEFAULT_IOMEM_OPS_DRAW, #endif + __FB_DEFAULT_IOMEM_OPS_MMAP, }; /* --------------------------------------------------------------------- */ @@ -1859,8 +1863,7 @@ static int savage_init_hw(struct savagefb_par *par) vga_out8(0x3d4, 0x68, par); /* memory control 1 */ if ((vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6)) RamSavage4[1] = 8; - - /*FALLTHROUGH*/ + fallthrough; case S3_SAVAGE2000: videoRam = RamSavage4[(config1 & 0xE0) >> 5] * 1024; @@ -2135,8 +2138,7 @@ static int savage_init_fb_info(struct fb_info *info, struct pci_dev *dev, info->var.accel_flags = 0; info->fbops = &savagefb_ops; - info->flags = FBINFO_DEFAULT | - FBINFO_HWACCEL_YPAN | + info->flags = FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_XPAN; info->pseudo_palette = par->pseudo_palette; @@ -2157,6 +2159,8 @@ static int savage_init_fb_info(struct fb_info *info, struct pci_dev *dev, info->flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; + else + kfree(info->pixmap.addr); } #endif return err; @@ -2169,11 +2173,16 @@ static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id) struct fb_info *info; struct savagefb_par *par; u_int h_sync, v_sync; + unsigned char __maybe_unused *edid; int err, lpitch; int video_len; DBG("savagefb_probe"); + err = aperture_remove_conflicting_pci_devices(dev, "savagefb"); + if (err) + return err; + info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev); if (!info) return -ENOMEM; @@ -2211,9 +2220,9 @@ static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id) INIT_LIST_HEAD(&info->modelist); #if defined(CONFIG_FB_SAVAGE_I2C) savagefb_create_i2c_busses(info); - savagefb_probe_i2c_connector(info, &par->edid); - fb_edid_to_monspecs(par->edid, &info->monspecs); - kfree(par->edid); + savagefb_probe_i2c_connector(info, &edid); + fb_edid_to_monspecs(edid, &info->monspecs); + kfree(edid); fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len, &info->modelist); @@ -2267,7 +2276,10 @@ static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id) if (info->var.xres_virtual > 0x1000) info->var.xres_virtual = 0x1000; #endif - savagefb_check_var(&info->var, info); + err = savagefb_check_var(&info->var, info); + if (err) + goto failed; + savagefb_set_fix(info); /* @@ -2346,9 +2358,9 @@ static void savagefb_remove(struct pci_dev *dev) } } -static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg) +static int savagefb_suspend_late(struct device *dev, pm_message_t mesg) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct savagefb_par *par = info->par; DBG("savagefb_suspend"); @@ -2356,7 +2368,7 @@ static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg) if (mesg.event == PM_EVENT_PRETHAW) mesg.event = PM_EVENT_FREEZE; par->pm_state = mesg.event; - dev->dev.power.power_state = mesg; + dev->power.power_state = mesg; /* * For PM_EVENT_FREEZE, do not power down so the console @@ -2374,17 +2386,29 @@ static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg) savagefb_blank(FB_BLANK_POWERDOWN, info); savage_set_default_par(par, &par->save); savage_disable_mmio(par); - pci_save_state(dev); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, mesg)); console_unlock(); return 0; } -static int savagefb_resume(struct pci_dev* dev) +static int __maybe_unused savagefb_suspend(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + return savagefb_suspend_late(dev, PMSG_SUSPEND); +} + +static int __maybe_unused savagefb_hibernate(struct device *dev) +{ + return savagefb_suspend_late(dev, PMSG_HIBERNATE); +} + +static int __maybe_unused savagefb_freeze(struct device *dev) +{ + return savagefb_suspend_late(dev, PMSG_FREEZE); +} + +static int __maybe_unused savagefb_resume(struct device *dev) +{ + struct fb_info *info = dev_get_drvdata(dev); struct savagefb_par *par = info->par; int cur_state = par->pm_state; @@ -2396,20 +2420,11 @@ static int savagefb_resume(struct pci_dev* dev) * The adapter was not powered down coming back from a * PM_EVENT_FREEZE. */ - if (cur_state == PM_EVENT_FREEZE) { - pci_set_power_state(dev, PCI_D0); + if (cur_state == PM_EVENT_FREEZE) return 0; - } console_lock(); - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - - if (pci_enable_device(dev)) - DBG("err"); - - pci_set_master(dev); savage_enable_mmio(par); savage_init_hw(par); savagefb_set_par(info); @@ -2420,6 +2435,16 @@ static int savagefb_resume(struct pci_dev* dev) return 0; } +static const struct dev_pm_ops savagefb_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = savagefb_suspend, + .resume = savagefb_resume, + .freeze = savagefb_freeze, + .thaw = savagefb_resume, + .poweroff = savagefb_hibernate, + .restore = savagefb_resume, +#endif +}; static const struct pci_device_id savagefb_devices[] = { {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128, @@ -2500,8 +2525,7 @@ static struct pci_driver savagefb_driver = { .name = "savagefb", .id_table = savagefb_devices, .probe = savagefb_probe, - .suspend = savagefb_suspend, - .resume = savagefb_resume, + .driver.pm = &savagefb_pm_ops, .remove = savagefb_remove, }; @@ -2537,6 +2561,9 @@ static int __init savagefb_init(void) DBG("savagefb_init"); + if (fb_modesetting_disabled("savagefb")) + return -ENODEV; + if (fb_get_options("savagefb", &option)) return -ENODEV; |
