]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/video/i810/i810_main.c
[PATCH] i810fb: Fix suspend and resume hooks
[karo-tx-linux.git] / drivers / video / i810 / i810_main.c
index 7018ffffcbc4e391f8dbc8076a072ed59f865f82..d27cd19b7f70c179c8b16eb9dd5c19e1a81c0f17 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/pci_ids.h>
 #include <linux/resource.h>
 #include <linux/unistd.h>
+#include <linux/console.h>
 
 #include <asm/io.h>
 #include <asm/div64.h>
@@ -95,18 +96,18 @@ static struct pci_driver i810fb_driver = {
 static char *mode_option __devinitdata = NULL;
 static int vram       __devinitdata = 4;
 static int bpp        __devinitdata = 8;
-static int mtrr       __devinitdata = 0;
-static int accel      __devinitdata = 0;
-static int hsync1     __devinitdata = 0;
-static int hsync2     __devinitdata = 0;
-static int vsync1     __devinitdata = 0;
-static int vsync2     __devinitdata = 0;
-static int xres       __devinitdata = 640;
-static int yres       __devinitdata = 480;
-static int vyres      __devinitdata = 0;
-static int sync       __devinitdata = 0;
-static int ext_vga    __devinitdata = 0;
-static int dcolor     __devinitdata = 0;
+static int mtrr       __devinitdata;
+static int accel      __devinitdata;
+static int hsync1     __devinitdata;
+static int hsync2     __devinitdata;
+static int vsync1     __devinitdata;
+static int vsync2     __devinitdata;
+static int xres       __devinitdata;
+static int yres       __devinitdata;
+static int vyres      __devinitdata;
+static int sync       __devinitdata;
+static int extvga     __devinitdata;
+static int dcolor     __devinitdata;
 
 /*------------------------------------------------------------*/
 
@@ -776,7 +777,7 @@ static void i810_load_cursor_image(int width, int height, u8 *data,
 
 static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
        u8 __iomem *mmio = par->mmio_start_virtual;
        u8 red, green, blue, trans, temp;
 
@@ -949,8 +950,8 @@ static void set_color_bitfields(struct fb_var_screeninfo *var)
 static int i810_check_params(struct fb_var_screeninfo *var, 
                             struct fb_info *info)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
-       int line_length, vidmem, mode_valid = 0;
+       struct i810fb_par *par = info->par;
+       int line_length, vidmem, mode_valid = 0, retval = 0;
        u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
        /*
         *  Memory limit
@@ -1026,10 +1027,11 @@ static int i810_check_params(struct fb_var_screeninfo *var,
                        printk("i810fb: invalid video mode%s\n",
                               default_sync ? "" : ". Specifying "
                               "vsyncN/hsyncN parameters may help");
+                       retval = -EINVAL;
                }
        }
 
-       return 0;
+       return retval;
 }      
 
 /**
@@ -1042,7 +1044,7 @@ static int i810_check_params(struct fb_var_screeninfo *var,
  */
 static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
 
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
@@ -1153,7 +1155,7 @@ static void decode_var(const struct fb_var_screeninfo *var,
 static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, 
                            u8 *transp, struct fb_info *info)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
        u8 __iomem *mmio = par->mmio_start_virtual;
        u8 temp;
 
@@ -1192,7 +1194,7 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
 
 static int i810fb_open(struct fb_info *info, int user)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
        u32 count = atomic_read(&par->use_count);
        
        if (count == 0) {
@@ -1211,7 +1213,7 @@ static int i810fb_open(struct fb_info *info, int user)
 
 static int i810fb_release(struct fb_info *info, int user)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
        u32 count;
        
        count = atomic_read(&par->use_count);
@@ -1233,7 +1235,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
                            unsigned blue, unsigned transp, 
                            struct fb_info *info)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
        u8 __iomem *mmio = par->mmio_start_virtual;
        u8 temp;
        int i;
@@ -1327,7 +1329,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 static int i810fb_pan_display(struct fb_var_screeninfo *var, 
                              struct fb_info *info)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
        u32 total;
        
        total = var->xoffset * par->depth + 
@@ -1339,7 +1341,7 @@ static int i810fb_pan_display(struct fb_var_screeninfo *var,
 
 static int i810fb_blank (int blank_mode, struct fb_info *info)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
        u8 __iomem *mmio = par->mmio_start_virtual;
        int mode = 0, pwr, scr_off = 0;
        
@@ -1384,7 +1386,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info)
 
 static int i810fb_set_par(struct fb_info *info)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
 
        decode_var(&info->var, par);
        i810_load_regs(par);
@@ -1428,7 +1430,7 @@ static int i810fb_check_var(struct fb_var_screeninfo *var,
 
 static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-       struct i810fb_par *par = (struct i810fb_par *)info->par;
+       struct i810fb_par *par = info->par;
        u8 __iomem *mmio = par->mmio_start_virtual;
 
        if (!par->dev_flags & LOCKUP)
@@ -1515,36 +1517,29 @@ static struct fb_ops i810fb_ops __devinitdata = {
 static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
 {
        struct fb_info *info = pci_get_drvdata(dev);
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
-       int blank = 0, prev_state = par->cur_state;
-
-       if (state.event == prev_state)
-               return 0;
+       struct i810fb_par *par = info->par;
 
        par->cur_state = state.event;
 
-       switch (state.event) {
-       case 1:
-               blank = VESA_VSYNC_SUSPEND;
-               break;
-       case 2:
-               blank = VESA_HSYNC_SUSPEND;
-               break;
-       case 3:
-               blank = VESA_POWERDOWN;
-               break;
-       default:
-               return -EINVAL;
+       if (state.event == PM_EVENT_FREEZE) {
+               dev->dev.power.power_state = state;
+               return 0;
        }
-       info->fbops->fb_blank(blank, info);
 
-       if (!prev_state) { 
-               agp_unbind_memory(par->i810_gtt.i810_fb_memory);
-               agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
-               pci_disable_device(dev);
-       }
+       acquire_console_sem();
+       fb_set_suspend(info, 1);
+
+       if (info->fbops->fb_sync)
+               info->fbops->fb_sync(info);
+
+       i810fb_blank(FB_BLANK_POWERDOWN, info);
+       agp_unbind_memory(par->i810_gtt.i810_fb_memory);
+       agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
+
        pci_save_state(dev);
+       pci_disable_device(dev);
        pci_set_power_state(dev, pci_choose_state(dev, state));
+       release_console_sem();
 
        return 0;
 }
@@ -1552,23 +1547,29 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
 static int i810fb_resume(struct pci_dev *dev) 
 {
        struct fb_info *info = pci_get_drvdata(dev);
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
+       int cur_state = par->cur_state;
 
-       if (par->cur_state == 0)
+       par->cur_state = PM_EVENT_ON;
+
+       if (cur_state == PM_EVENT_FREEZE) {
+               pci_set_power_state(dev, PCI_D0);
                return 0;
+       }
 
-       pci_restore_state(dev);
+       acquire_console_sem();
        pci_set_power_state(dev, PCI_D0);
+       pci_restore_state(dev);
        pci_enable_device(dev);
+       pci_set_master(dev);
        agp_bind_memory(par->i810_gtt.i810_fb_memory,
                        par->fb.offset);
        agp_bind_memory(par->i810_gtt.i810_cursor_memory,
                        par->cursor_heap.offset);
-
+       i810fb_set_par(info);
+       fb_set_suspend (info, 0);
        info->fbops->fb_blank(VESA_NO_BLANKING, info);
-
-       par->cur_state = 0;
-
+       release_console_sem();
        return 0;
 }
 /***********************************************************************
@@ -1609,7 +1610,7 @@ static void __devinit i810_fix_offsets(struct i810fb_par *par)
 
 static int __devinit i810_alloc_agp_mem(struct fb_info *info)
 {
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
        int size;
        struct agp_bridge_data *bridge;
        
@@ -1724,12 +1725,21 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
        if (bpp < 8)
                bpp = 8;
        
+       par->i810fb_ops = i810fb_ops;
+
+       if (xres)
+               info->var.xres = xres;
+       else
+               info->var.xres = 640;
+
+       if (yres)
+               info->var.yres = yres;
+       else
+               info->var.yres = 480;
+
        if (!vyres) 
-               vyres = (vram << 20)/(xres*bpp >> 3);
+               vyres = (vram << 20)/(info->var.xres*bpp >> 3);
 
-       par->i810fb_ops = i810fb_ops;
-       info->var.xres = xres;
-       info->var.yres = yres;
        info->var.yres_virtual = vyres;
        info->var.bits_per_pixel = bpp;
 
@@ -1756,7 +1766,7 @@ static void __devinit i810_init_device(struct i810fb_par *par)
        i810_init_cursor(par);
 
        /* mvo: enable external vga-connector (for laptops) */
-       if (ext_vga) {
+       if (extvga) {
                i810_writel(HVSYNC, mmio, 0);
                i810_writel(PWR_CLKC, mmio, 3);
        }
@@ -1830,7 +1840,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
 {
        struct fb_videomode mode;
        struct fb_var_screeninfo var;
-       struct fb_monspecs *specs = NULL;
+       struct fb_monspecs *specs = &info->monspecs;
        int found = 0;
 #ifdef CONFIG_FB_I810_I2C
        int i;
@@ -1844,7 +1854,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
 #ifdef CONFIG_FB_I810_I2C
        i810_create_i2c_busses(par);
 
-       for (i = 0; i < 3; i++) {
+       for (i = 0; i < 4; i++) {
                err = i810_probe_i2c_connector(info, &par->edid, i+1);
                if (!err)
                        break;
@@ -1853,27 +1863,26 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
        if (!err)
                printk("i810fb_init_pci: DDC probe successful\n");
 
-       fb_edid_to_monspecs(par->edid, &info->monspecs);
+       fb_edid_to_monspecs(par->edid, specs);
 
-       if (info->monspecs.modedb == NULL)
+       if (specs->modedb == NULL)
                printk("i810fb_init_pci: Unable to get Mode Database\n");
 
-       specs = &info->monspecs;
        fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
                                 &info->modelist);
        if (specs->modedb != NULL) {
-               if (specs->misc & FB_MISC_1ST_DETAIL) {
-                       for (i = 0; i < specs->modedb_len; i++) {
-                               if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
-                                       mode = specs->modedb[i];
-                                       found = 1;
-                                       break;
-                               }
+               struct fb_videomode *m;
+
+               if (xres && yres) {
+                       if ((m = fb_find_best_mode(&var, &info->modelist))) {
+                               mode = *m;
+                               found  = 1;
                        }
                }
 
                if (!found) {
-                       mode = specs->modedb[0];
+                       m = fb_find_best_display(&info->monspecs, &info->modelist);
+                       mode = *m;
                        found = 1;
                }
 
@@ -1903,8 +1912,8 @@ static int __devinit i810fb_setup(char *options)
                        mtrr = 1;
                else if (!strncmp(this_opt, "accel", 5))
                        accel = 1;
-               else if (!strncmp(this_opt, "ext_vga", 7))
-                       ext_vga = 1;
+               else if (!strncmp(this_opt, "extvga", 6))
+                       extvga = 1;
                else if (!strncmp(this_opt, "sync", 4))
                        sync = 1;
                else if (!strncmp(this_opt, "vram:", 5))
@@ -2048,8 +2057,7 @@ static void i810fb_release_resource(struct fb_info *info,
                iounmap(par->mmio_start_virtual);
        if (par->aperture.virtual)
                iounmap(par->aperture.virtual);
-       if (par->edid)
-               kfree(par->edid);
+       kfree(par->edid);
        if (par->res_flags & FRAMEBUFFER_REQ)
                release_mem_region(par->aperture.physical,
                                   par->aperture.size);
@@ -2066,7 +2074,7 @@ static void i810fb_release_resource(struct fb_info *info,
 static void __exit i810fb_remove_pci(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
-       struct i810fb_par *par = (struct i810fb_par *) info->par;
+       struct i810fb_par *par = info->par;
 
        unregister_framebuffer(info);  
        i810fb_release_resource(info, par);
@@ -2133,8 +2141,8 @@ module_param(accel, bool, 0);
 MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
 module_param(mtrr, bool, 0);
 MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
-module_param(ext_vga, bool, 0);
-MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)");
+module_param(extvga, bool, 0);
+MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
 module_param(sync, bool, 0);
 MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
                 " (default = 0)");