diff options
Diffstat (limited to 'drivers/video/fbmem.c')
-rw-r--r-- | drivers/video/fbmem.c | 95 |
1 files changed, 75 insertions, 20 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 01072f4b3e8f..776f7fcd2fbf 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/linux_logo.h> | 27 | #include <linux/linux_logo.h> |
28 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
29 | #include <linux/seq_file.h> | ||
29 | #include <linux/console.h> | 30 | #include <linux/console.h> |
30 | #ifdef CONFIG_KMOD | 31 | #ifdef CONFIG_KMOD |
31 | #include <linux/kmod.h> | 32 | #include <linux/kmod.h> |
@@ -632,27 +633,51 @@ int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } | |||
632 | int fb_show_logo(struct fb_info *info, int rotate) { return 0; } | 633 | int fb_show_logo(struct fb_info *info, int rotate) { return 0; } |
633 | #endif /* CONFIG_LOGO */ | 634 | #endif /* CONFIG_LOGO */ |
634 | 635 | ||
635 | static int fbmem_read_proc(char *buf, char **start, off_t offset, | 636 | static void *fb_seq_start(struct seq_file *m, loff_t *pos) |
636 | int len, int *eof, void *private) | ||
637 | { | 637 | { |
638 | struct fb_info **fi; | 638 | return (*pos < FB_MAX) ? pos : NULL; |
639 | int clen; | 639 | } |
640 | 640 | ||
641 | clen = 0; | 641 | static void *fb_seq_next(struct seq_file *m, void *v, loff_t *pos) |
642 | for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && clen < 4000; | 642 | { |
643 | fi++) | 643 | (*pos)++; |
644 | if (*fi) | 644 | return (*pos < FB_MAX) ? pos : NULL; |
645 | clen += sprintf(buf + clen, "%d %s\n", | 645 | } |
646 | (*fi)->node, | 646 | |
647 | (*fi)->fix.id); | 647 | static void fb_seq_stop(struct seq_file *m, void *v) |
648 | *start = buf + offset; | 648 | { |
649 | if (clen > offset) | 649 | } |
650 | clen -= offset; | 650 | |
651 | else | 651 | static int fb_seq_show(struct seq_file *m, void *v) |
652 | clen = 0; | 652 | { |
653 | return clen < len ? clen : len; | 653 | int i = *(loff_t *)v; |
654 | struct fb_info *fi = registered_fb[i]; | ||
655 | |||
656 | if (fi) | ||
657 | seq_printf(m, "%d %s\n", fi->node, fi->fix.id); | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static const struct seq_operations proc_fb_seq_ops = { | ||
662 | .start = fb_seq_start, | ||
663 | .next = fb_seq_next, | ||
664 | .stop = fb_seq_stop, | ||
665 | .show = fb_seq_show, | ||
666 | }; | ||
667 | |||
668 | static int proc_fb_open(struct inode *inode, struct file *file) | ||
669 | { | ||
670 | return seq_open(file, &proc_fb_seq_ops); | ||
654 | } | 671 | } |
655 | 672 | ||
673 | static const struct file_operations fb_proc_fops = { | ||
674 | .owner = THIS_MODULE, | ||
675 | .open = proc_fb_open, | ||
676 | .read = seq_read, | ||
677 | .llseek = seq_lseek, | ||
678 | .release = seq_release, | ||
679 | }; | ||
680 | |||
656 | static ssize_t | 681 | static ssize_t |
657 | fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 682 | fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) |
658 | { | 683 | { |
@@ -1057,7 +1082,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
1057 | case FBIOPUT_CON2FBMAP: | 1082 | case FBIOPUT_CON2FBMAP: |
1058 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) | 1083 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
1059 | return - EFAULT; | 1084 | return - EFAULT; |
1060 | if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES) | 1085 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) |
1061 | return -EINVAL; | 1086 | return -EINVAL; |
1062 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) | 1087 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) |
1063 | return -EINVAL; | 1088 | return -EINVAL; |
@@ -1352,6 +1377,32 @@ static const struct file_operations fb_fops = { | |||
1352 | 1377 | ||
1353 | struct class *fb_class; | 1378 | struct class *fb_class; |
1354 | EXPORT_SYMBOL(fb_class); | 1379 | EXPORT_SYMBOL(fb_class); |
1380 | |||
1381 | static int fb_check_foreignness(struct fb_info *fi) | ||
1382 | { | ||
1383 | const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN; | ||
1384 | |||
1385 | fi->flags &= ~FBINFO_FOREIGN_ENDIAN; | ||
1386 | |||
1387 | #ifdef __BIG_ENDIAN | ||
1388 | fi->flags |= foreign_endian ? 0 : FBINFO_BE_MATH; | ||
1389 | #else | ||
1390 | fi->flags |= foreign_endian ? FBINFO_BE_MATH : 0; | ||
1391 | #endif /* __BIG_ENDIAN */ | ||
1392 | |||
1393 | if (fi->flags & FBINFO_BE_MATH && !fb_be_math(fi)) { | ||
1394 | pr_err("%s: enable CONFIG_FB_BIG_ENDIAN to " | ||
1395 | "support this framebuffer\n", fi->fix.id); | ||
1396 | return -ENOSYS; | ||
1397 | } else if (!(fi->flags & FBINFO_BE_MATH) && fb_be_math(fi)) { | ||
1398 | pr_err("%s: enable CONFIG_FB_LITTLE_ENDIAN to " | ||
1399 | "support this framebuffer\n", fi->fix.id); | ||
1400 | return -ENOSYS; | ||
1401 | } | ||
1402 | |||
1403 | return 0; | ||
1404 | } | ||
1405 | |||
1355 | /** | 1406 | /** |
1356 | * register_framebuffer - registers a frame buffer device | 1407 | * register_framebuffer - registers a frame buffer device |
1357 | * @fb_info: frame buffer info structure | 1408 | * @fb_info: frame buffer info structure |
@@ -1371,6 +1422,10 @@ register_framebuffer(struct fb_info *fb_info) | |||
1371 | 1422 | ||
1372 | if (num_registered_fb == FB_MAX) | 1423 | if (num_registered_fb == FB_MAX) |
1373 | return -ENXIO; | 1424 | return -ENXIO; |
1425 | |||
1426 | if (fb_check_foreignness(fb_info)) | ||
1427 | return -ENOSYS; | ||
1428 | |||
1374 | num_registered_fb++; | 1429 | num_registered_fb++; |
1375 | for (i = 0 ; i < FB_MAX; i++) | 1430 | for (i = 0 ; i < FB_MAX; i++) |
1376 | if (!registered_fb[i]) | 1431 | if (!registered_fb[i]) |
@@ -1503,7 +1558,7 @@ void fb_set_suspend(struct fb_info *info, int state) | |||
1503 | static int __init | 1558 | static int __init |
1504 | fbmem_init(void) | 1559 | fbmem_init(void) |
1505 | { | 1560 | { |
1506 | create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL); | 1561 | proc_create("fb", 0, NULL, &fb_proc_fops); |
1507 | 1562 | ||
1508 | if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) | 1563 | if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) |
1509 | printk("unable to get major %d for fb devs\n", FB_MAJOR); | 1564 | printk("unable to get major %d for fb devs\n", FB_MAJOR); |