]> err.no Git - linux-2.6/blobdiff - drivers/video/fbmem.c
Merge branch 'fixes' of git://git.linux-nfs.org/pub/linux/nfs-2.6
[linux-2.6] / drivers / video / fbmem.c
index c4ce3e44327ee02df5527a095a92db48b86874c6..38c2e2558f5e34ac8285ca91253b204e9ae4cc51 100644 (file)
@@ -773,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 = ∩︀
+       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);
@@ -798,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;
 
@@ -841,7 +875,9 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
                        }
                }
        }
-       return 0;
+
+ done:
+       return ret;
 }
 
 int
@@ -1200,6 +1236,10 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
        pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
 #elif defined(__arm__) || defined(__sh__) || defined(__m32r__)
        vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+#elif defined(__avr32__)
+       vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
+                                     & ~_PAGE_CACHABLE)
+                                    | (_PAGE_BUFFER | _PAGE_DIRTY));
 #elif defined(__ia64__)
        if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
                vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);