Merge branch 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
[powerpc.git] / drivers / video / fbmem.c
index 2822526..08d4e11 100644 (file)
@@ -354,59 +354,59 @@ static void fb_rotate_logo(struct fb_info *info, u8 *dst,
        if (rotate == FB_ROTATE_UD) {
                fb_rotate_logo_ud(image->data, dst, image->width,
                                  image->height);
-               image->dx = info->var.xres - image->width;
-               image->dy = info->var.yres - image->height;
+               image->dx = info->var.xres - image->width - image->dx;
+               image->dy = info->var.yres - image->height - image->dy;
        } else if (rotate == FB_ROTATE_CW) {
                fb_rotate_logo_cw(image->data, dst, image->width,
                                  image->height);
                tmp = image->width;
                image->width = image->height;
                image->height = tmp;
-               image->dx = info->var.xres - image->width;
+               tmp = image->dy;
+               image->dy = image->dx;
+               image->dx = info->var.xres - image->width - tmp;
        } else if (rotate == FB_ROTATE_CCW) {
                fb_rotate_logo_ccw(image->data, dst, image->width,
                                   image->height);
                tmp = image->width;
                image->width = image->height;
                image->height = tmp;
-               image->dy = info->var.yres - image->height;
+               tmp = image->dx;
+               image->dx = image->dy;
+               image->dy = info->var.yres - image->height - tmp;
        }
 
        image->data = dst;
 }
 
 static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
-                           int rotate)
+                           int rotate, unsigned int num)
 {
-       int x;
+       unsigned int x;
 
        if (rotate == FB_ROTATE_UR) {
-               for (x = 0; x < num_online_cpus() &&
-                            x * (fb_logo.logo->width + 8) <=
-                            info->var.xres - fb_logo.logo->width; x++) {
+               for (x = 0;
+                    x < num && image->dx + image->width <= info->var.xres;
+                    x++) {
                        info->fbops->fb_imageblit(info, image);
-                       image->dx += fb_logo.logo->width + 8;
+                       image->dx += image->width + 8;
                }
        } else if (rotate == FB_ROTATE_UD) {
-               for (x = 0; x < num_online_cpus() &&
-                            x * (fb_logo.logo->width + 8) <=
-                            info->var.xres - fb_logo.logo->width; x++) {
+               for (x = 0; x < num && image->dx >= 0; x++) {
                        info->fbops->fb_imageblit(info, image);
-                       image->dx -= fb_logo.logo->width + 8;
+                       image->dx -= image->width + 8;
                }
        } else if (rotate == FB_ROTATE_CW) {
-               for (x = 0; x < num_online_cpus() &&
-                            x * (fb_logo.logo->width + 8) <=
-                            info->var.yres - fb_logo.logo->width; x++) {
+               for (x = 0;
+                    x < num && image->dy + image->height <= info->var.yres;
+                    x++) {
                        info->fbops->fb_imageblit(info, image);
-                       image->dy += fb_logo.logo->width + 8;
+                       image->dy += image->height + 8;
                }
        } else if (rotate == FB_ROTATE_CCW) {
-               for (x = 0; x < num_online_cpus() &&
-                            x * (fb_logo.logo->width + 8) <=
-                            info->var.yres - fb_logo.logo->width; x++) {
+               for (x = 0; x < num && image->dy >= 0; x++) {
                        info->fbops->fb_imageblit(info, image);
-                       image->dy -= fb_logo.logo->width + 8;
+                       image->dy -= image->height + 8;
                }
        }
 }
@@ -418,7 +418,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
 
        memset(&fb_logo, 0, sizeof(struct logo_data));
 
-       if (info->flags & FBINFO_MISC_TILEBLITTING)
+       if (info->flags & FBINFO_MISC_TILEBLITTING ||
+           info->flags & FBINFO_MODULE)
                return 0;
 
        if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -483,7 +484,8 @@ int fb_show_logo(struct fb_info *info, int rotate)
        struct fb_image image;
 
        /* Return if the frame buffer is not mapped or suspended */
-       if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING)
+       if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING ||
+           info->flags & FBINFO_MODULE)
                return 0;
 
        image.depth = 8;
@@ -532,7 +534,7 @@ int fb_show_logo(struct fb_info *info, int rotate)
                        fb_rotate_logo(info, logo_rotate, &image, rotate);
        }
 
-       fb_do_show_logo(info, &image, rotate);
+       fb_do_show_logo(info, &image, rotate, num_online_cpus());
 
        kfree(palette);
        if (saved_pseudo_palette != NULL)
@@ -586,7 +588,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
                return -EPERM;
 
        if (info->fbops->fb_read)
-               return info->fbops->fb_read(file, buf, count, ppos);
+               return info->fbops->fb_read(info, buf, count, ppos);
        
        total_size = info->screen_size;
 
@@ -661,7 +663,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
                return -EPERM;
 
        if (info->fbops->fb_write)
-               return info->fbops->fb_write(file, buf, count, ppos);
+               return info->fbops->fb_write(info, buf, count, ppos);
        
        total_size = info->screen_size;
 
@@ -771,14 +773,37 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
         return 0;
 }
 
+static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
+                        u32 activate)
+{
+       struct fb_event event;
+       struct fb_blit_caps caps, fbcaps;
+       int err = 0;
+
+       memset(&caps, 0, sizeof(caps));
+       memset(&fbcaps, 0, sizeof(fbcaps));
+       caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
+       event.info = info;
+       event.data = &caps;
+       fb_notifier_call_chain(FB_EVENT_GET_REQ, &event);
+       info->fbops->fb_get_caps(info, &fbcaps, var);
+
+       if (((fbcaps.x ^ caps.x) & caps.x) ||
+           ((fbcaps.y ^ caps.y) & caps.y) ||
+           (fbcaps.len < caps.len))
+               err = -EINVAL;
+
+       return err;
+}
+
 int
 fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
 {
-       int err, flags = info->flags;
+       int flags = info->flags;
+       int ret = 0;
 
        if (var->activate & FB_ACTIVATE_INV_MODE) {
                struct fb_videomode mode1, mode2;
-               int ret = 0;
 
                fb_var_to_videomode(&mode1, var);
                fb_var_to_videomode(&mode2, &info->var);
@@ -796,40 +821,51 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
                if (!ret)
                    fb_delete_videomode(&mode1, &info->modelist);
 
-               return ret;
+
+               ret = (ret) ? -EINVAL : 0;
+               goto done;
        }
 
        if ((var->activate & FB_ACTIVATE_FORCE) ||
            memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
+               u32 activate = var->activate;
+
                if (!info->fbops->fb_check_var) {
                        *var = info->var;
-                       return 0;
+                       goto done;
                }
 
-               if ((err = info->fbops->fb_check_var(var, info)))
-                       return err;
+               ret = info->fbops->fb_check_var(var, info);
+
+               if (ret)
+                       goto done;
 
                if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
                        struct fb_videomode mode;
-                       int err = 0;
+
+                       if (info->fbops->fb_get_caps) {
+                               ret = fb_check_caps(info, var, activate);
+
+                               if (ret)
+                                       goto done;
+                       }
 
                        info->var = *var;
+
                        if (info->fbops->fb_set_par)
                                info->fbops->fb_set_par(info);
 
                        fb_pan_display(info, &info->var);
-
                        fb_set_cmap(&info->cmap, info);
-
                        fb_var_to_videomode(&mode, &info->var);
 
                        if (info->modelist.prev && info->modelist.next &&
                            !list_empty(&info->modelist))
-                               err = fb_add_videomode(&mode, &info->modelist);
+                               ret = fb_add_videomode(&mode, &info->modelist);
 
-                       if (!err && (flags & FBINFO_MISC_USEREVENT)) {
+                       if (!ret && (flags & FBINFO_MISC_USEREVENT)) {
                                struct fb_event event;
-                               int evnt = (var->activate & FB_ACTIVATE_ALL) ?
+                               int evnt = (activate & FB_ACTIVATE_ALL) ?
                                        FB_EVENT_MODE_CHANGE_ALL :
                                        FB_EVENT_MODE_CHANGE;
 
@@ -839,7 +875,9 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
                        }
                }
        }
-       return 0;
+
+ done:
+       return ret;
 }
 
 int
@@ -1266,6 +1304,9 @@ static const struct file_operations fb_fops = {
 #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
        .get_unmapped_area = get_fb_unmapped_area,
 #endif
+#ifdef CONFIG_FB_DEFERRED_IO
+       .fsync =        fb_deferred_io_fsync,
+#endif
 };
 
 struct class *fb_class;
@@ -1316,6 +1357,12 @@ register_framebuffer(struct fb_info *fb_info)
        }       
        fb_info->pixmap.offset = 0;
 
+       if (!fb_info->pixmap.blit_x)
+               fb_info->pixmap.blit_x = ~(u32)0;
+
+       if (!fb_info->pixmap.blit_y)
+               fb_info->pixmap.blit_y = ~(u32)0;
+
        if (!fb_info->modelist.prev || !fb_info->modelist.next)
                INIT_LIST_HEAD(&fb_info->modelist);