aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbmem.c')
-rw-r--r--drivers/video/fbmem.c131
1 files changed, 91 insertions, 40 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 28225265159a..38c2e2558f5e 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -354,59 +354,59 @@ static void fb_rotate_logo(struct fb_info *info, u8 *dst,
354 if (rotate == FB_ROTATE_UD) { 354 if (rotate == FB_ROTATE_UD) {
355 fb_rotate_logo_ud(image->data, dst, image->width, 355 fb_rotate_logo_ud(image->data, dst, image->width,
356 image->height); 356 image->height);
357 image->dx = info->var.xres - image->width; 357 image->dx = info->var.xres - image->width - image->dx;
358 image->dy = info->var.yres - image->height; 358 image->dy = info->var.yres - image->height - image->dy;
359 } else if (rotate == FB_ROTATE_CW) { 359 } else if (rotate == FB_ROTATE_CW) {
360 fb_rotate_logo_cw(image->data, dst, image->width, 360 fb_rotate_logo_cw(image->data, dst, image->width,
361 image->height); 361 image->height);
362 tmp = image->width; 362 tmp = image->width;
363 image->width = image->height; 363 image->width = image->height;
364 image->height = tmp; 364 image->height = tmp;
365 image->dx = info->var.xres - image->width; 365 tmp = image->dy;
366 image->dy = image->dx;
367 image->dx = info->var.xres - image->width - tmp;
366 } else if (rotate == FB_ROTATE_CCW) { 368 } else if (rotate == FB_ROTATE_CCW) {
367 fb_rotate_logo_ccw(image->data, dst, image->width, 369 fb_rotate_logo_ccw(image->data, dst, image->width,
368 image->height); 370 image->height);
369 tmp = image->width; 371 tmp = image->width;
370 image->width = image->height; 372 image->width = image->height;
371 image->height = tmp; 373 image->height = tmp;
372 image->dy = info->var.yres - image->height; 374 tmp = image->dx;
375 image->dx = image->dy;
376 image->dy = info->var.yres - image->height - tmp;
373 } 377 }
374 378
375 image->data = dst; 379 image->data = dst;
376} 380}
377 381
378static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, 382static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
379 int rotate) 383 int rotate, unsigned int num)
380{ 384{
381 int x; 385 unsigned int x;
382 386
383 if (rotate == FB_ROTATE_UR) { 387 if (rotate == FB_ROTATE_UR) {
384 for (x = 0; x < num_online_cpus() && 388 for (x = 0;
385 x * (fb_logo.logo->width + 8) <= 389 x < num && image->dx + image->width <= info->var.xres;
386 info->var.xres - fb_logo.logo->width; x++) { 390 x++) {
387 info->fbops->fb_imageblit(info, image); 391 info->fbops->fb_imageblit(info, image);
388 image->dx += fb_logo.logo->width + 8; 392 image->dx += image->width + 8;
389 } 393 }
390 } else if (rotate == FB_ROTATE_UD) { 394 } else if (rotate == FB_ROTATE_UD) {
391 for (x = 0; x < num_online_cpus() && 395 for (x = 0; x < num && image->dx >= 0; x++) {
392 x * (fb_logo.logo->width + 8) <=
393 info->var.xres - fb_logo.logo->width; x++) {
394 info->fbops->fb_imageblit(info, image); 396 info->fbops->fb_imageblit(info, image);
395 image->dx -= fb_logo.logo->width + 8; 397 image->dx -= image->width + 8;
396 } 398 }
397 } else if (rotate == FB_ROTATE_CW) { 399 } else if (rotate == FB_ROTATE_CW) {
398 for (x = 0; x < num_online_cpus() && 400 for (x = 0;
399 x * (fb_logo.logo->width + 8) <= 401 x < num && image->dy + image->height <= info->var.yres;
400 info->var.yres - fb_logo.logo->width; x++) { 402 x++) {
401 info->fbops->fb_imageblit(info, image); 403 info->fbops->fb_imageblit(info, image);
402 image->dy += fb_logo.logo->width + 8; 404 image->dy += image->height + 8;
403 } 405 }
404 } else if (rotate == FB_ROTATE_CCW) { 406 } else if (rotate == FB_ROTATE_CCW) {
405 for (x = 0; x < num_online_cpus() && 407 for (x = 0; x < num && image->dy >= 0; x++) {
406 x * (fb_logo.logo->width + 8) <=
407 info->var.yres - fb_logo.logo->width; x++) {
408 info->fbops->fb_imageblit(info, image); 408 info->fbops->fb_imageblit(info, image);
409 image->dy -= fb_logo.logo->width + 8; 409 image->dy -= image->height + 8;
410 } 410 }
411 } 411 }
412} 412}
@@ -418,7 +418,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
418 418
419 memset(&fb_logo, 0, sizeof(struct logo_data)); 419 memset(&fb_logo, 0, sizeof(struct logo_data));
420 420
421 if (info->flags & FBINFO_MISC_TILEBLITTING) 421 if (info->flags & FBINFO_MISC_TILEBLITTING ||
422 info->flags & FBINFO_MODULE)
422 return 0; 423 return 0;
423 424
424 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { 425 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -483,7 +484,8 @@ int fb_show_logo(struct fb_info *info, int rotate)
483 struct fb_image image; 484 struct fb_image image;
484 485
485 /* Return if the frame buffer is not mapped or suspended */ 486 /* Return if the frame buffer is not mapped or suspended */
486 if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) 487 if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING ||
488 info->flags & FBINFO_MODULE)
487 return 0; 489 return 0;
488 490
489 image.depth = 8; 491 image.depth = 8;
@@ -532,7 +534,7 @@ int fb_show_logo(struct fb_info *info, int rotate)
532 fb_rotate_logo(info, logo_rotate, &image, rotate); 534 fb_rotate_logo(info, logo_rotate, &image, rotate);
533 } 535 }
534 536
535 fb_do_show_logo(info, &image, rotate); 537 fb_do_show_logo(info, &image, rotate, num_online_cpus());
536 538
537 kfree(palette); 539 kfree(palette);
538 if (saved_pseudo_palette != NULL) 540 if (saved_pseudo_palette != NULL)
@@ -586,7 +588,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
586 return -EPERM; 588 return -EPERM;
587 589
588 if (info->fbops->fb_read) 590 if (info->fbops->fb_read)
589 return info->fbops->fb_read(file, buf, count, ppos); 591 return info->fbops->fb_read(info, buf, count, ppos);
590 592
591 total_size = info->screen_size; 593 total_size = info->screen_size;
592 594
@@ -661,7 +663,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
661 return -EPERM; 663 return -EPERM;
662 664
663 if (info->fbops->fb_write) 665 if (info->fbops->fb_write)
664 return info->fbops->fb_write(file, buf, count, ppos); 666 return info->fbops->fb_write(info, buf, count, ppos);
665 667
666 total_size = info->screen_size; 668 total_size = info->screen_size;
667 669
@@ -771,14 +773,37 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
771 return 0; 773 return 0;
772} 774}
773 775
776static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
777 u32 activate)
778{
779 struct fb_event event;
780 struct fb_blit_caps caps, fbcaps;
781 int err = 0;
782
783 memset(&caps, 0, sizeof(caps));
784 memset(&fbcaps, 0, sizeof(fbcaps));
785 caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
786 event.info = info;
787 event.data = &caps;
788 fb_notifier_call_chain(FB_EVENT_GET_REQ, &event);
789 info->fbops->fb_get_caps(info, &fbcaps, var);
790
791 if (((fbcaps.x ^ caps.x) & caps.x) ||
792 ((fbcaps.y ^ caps.y) & caps.y) ||
793 (fbcaps.len < caps.len))
794 err = -EINVAL;
795
796 return err;
797}
798
774int 799int
775fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) 800fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
776{ 801{
777 int err, flags = info->flags; 802 int flags = info->flags;
803 int ret = 0;
778 804
779 if (var->activate & FB_ACTIVATE_INV_MODE) { 805 if (var->activate & FB_ACTIVATE_INV_MODE) {
780 struct fb_videomode mode1, mode2; 806 struct fb_videomode mode1, mode2;
781 int ret = 0;
782 807
783 fb_var_to_videomode(&mode1, var); 808 fb_var_to_videomode(&mode1, var);
784 fb_var_to_videomode(&mode2, &info->var); 809 fb_var_to_videomode(&mode2, &info->var);
@@ -796,40 +821,51 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
796 if (!ret) 821 if (!ret)
797 fb_delete_videomode(&mode1, &info->modelist); 822 fb_delete_videomode(&mode1, &info->modelist);
798 823
799 return ret; 824
825 ret = (ret) ? -EINVAL : 0;
826 goto done;
800 } 827 }
801 828
802 if ((var->activate & FB_ACTIVATE_FORCE) || 829 if ((var->activate & FB_ACTIVATE_FORCE) ||
803 memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { 830 memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
831 u32 activate = var->activate;
832
804 if (!info->fbops->fb_check_var) { 833 if (!info->fbops->fb_check_var) {
805 *var = info->var; 834 *var = info->var;
806 return 0; 835 goto done;
807 } 836 }
808 837
809 if ((err = info->fbops->fb_check_var(var, info))) 838 ret = info->fbops->fb_check_var(var, info);
810 return err; 839
840 if (ret)
841 goto done;
811 842
812 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { 843 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
813 struct fb_videomode mode; 844 struct fb_videomode mode;
814 int err = 0; 845
846 if (info->fbops->fb_get_caps) {
847 ret = fb_check_caps(info, var, activate);
848
849 if (ret)
850 goto done;
851 }
815 852
816 info->var = *var; 853 info->var = *var;
854
817 if (info->fbops->fb_set_par) 855 if (info->fbops->fb_set_par)
818 info->fbops->fb_set_par(info); 856 info->fbops->fb_set_par(info);
819 857
820 fb_pan_display(info, &info->var); 858 fb_pan_display(info, &info->var);
821
822 fb_set_cmap(&info->cmap, info); 859 fb_set_cmap(&info->cmap, info);
823
824 fb_var_to_videomode(&mode, &info->var); 860 fb_var_to_videomode(&mode, &info->var);
825 861
826 if (info->modelist.prev && info->modelist.next && 862 if (info->modelist.prev && info->modelist.next &&
827 !list_empty(&info->modelist)) 863 !list_empty(&info->modelist))
828 err = fb_add_videomode(&mode, &info->modelist); 864 ret = fb_add_videomode(&mode, &info->modelist);
829 865
830 if (!err && (flags & FBINFO_MISC_USEREVENT)) { 866 if (!ret && (flags & FBINFO_MISC_USEREVENT)) {
831 struct fb_event event; 867 struct fb_event event;
832 int evnt = (var->activate & FB_ACTIVATE_ALL) ? 868 int evnt = (activate & FB_ACTIVATE_ALL) ?
833 FB_EVENT_MODE_CHANGE_ALL : 869 FB_EVENT_MODE_CHANGE_ALL :
834 FB_EVENT_MODE_CHANGE; 870 FB_EVENT_MODE_CHANGE;
835 871
@@ -839,7 +875,9 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
839 } 875 }
840 } 876 }
841 } 877 }
842 return 0; 878
879 done:
880 return ret;
843} 881}
844 882
845int 883int
@@ -1198,6 +1236,10 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
1198 pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; 1236 pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
1199#elif defined(__arm__) || defined(__sh__) || defined(__m32r__) 1237#elif defined(__arm__) || defined(__sh__) || defined(__m32r__)
1200 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 1238 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1239#elif defined(__avr32__)
1240 vma->vm_page_prot = __pgprot((pgprot_val(vma->vm_page_prot)
1241 & ~_PAGE_CACHABLE)
1242 | (_PAGE_BUFFER | _PAGE_DIRTY));
1201#elif defined(__ia64__) 1243#elif defined(__ia64__)
1202 if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start)) 1244 if (efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
1203 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 1245 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
@@ -1266,6 +1308,9 @@ static const struct file_operations fb_fops = {
1266#ifdef HAVE_ARCH_FB_UNMAPPED_AREA 1308#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
1267 .get_unmapped_area = get_fb_unmapped_area, 1309 .get_unmapped_area = get_fb_unmapped_area,
1268#endif 1310#endif
1311#ifdef CONFIG_FB_DEFERRED_IO
1312 .fsync = fb_deferred_io_fsync,
1313#endif
1269}; 1314};
1270 1315
1271struct class *fb_class; 1316struct class *fb_class;
@@ -1316,6 +1361,12 @@ register_framebuffer(struct fb_info *fb_info)
1316 } 1361 }
1317 fb_info->pixmap.offset = 0; 1362 fb_info->pixmap.offset = 0;
1318 1363
1364 if (!fb_info->pixmap.blit_x)
1365 fb_info->pixmap.blit_x = ~(u32)0;
1366
1367 if (!fb_info->pixmap.blit_y)
1368 fb_info->pixmap.blit_y = ~(u32)0;
1369
1319 if (!fb_info->modelist.prev || !fb_info->modelist.next) 1370 if (!fb_info->modelist.prev || !fb_info->modelist.next)
1320 INIT_LIST_HEAD(&fb_info->modelist); 1371 INIT_LIST_HEAD(&fb_info->modelist);
1321 1372