2 * linux/drivers/video/fbmem.c
4 * Copyright (C) 1994 Martin Schaller
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
11 #include <linux/config.h>
12 #include <linux/module.h>
14 #include <linux/types.h>
15 #include <linux/errno.h>
16 #include <linux/sched.h>
17 #include <linux/smp_lock.h>
18 #include <linux/kernel.h>
19 #include <linux/major.h>
20 #include <linux/malloc.h>
21 #include <linux/mman.h>
22 #include <linux/tty.h>
23 #include <linux/console.h>
24 #include <linux/init.h>
25 #include <linux/proc_fs.h>
27 #include <linux/kmod.h>
29 #include <linux/devfs_fs_kernel.h>
31 #if defined(__mc68000__) || defined(CONFIG_APUS)
32 #include <asm/setup.h>
36 #include <asm/uaccess.h>
38 #include <asm/pgtable.h>
41 #include <video/fbcon.h>
44 * Frame buffer device initialization and setup routines
47 extern int acornfb_init(void);
48 extern int acornfb_setup(char*);
49 extern int amifb_init(void);
50 extern int amifb_setup(char*);
51 extern int atafb_init(void);
52 extern int atafb_setup(char*);
53 extern int macfb_init(void);
54 extern int macfb_setup(char*);
55 extern int cyberfb_init(void);
56 extern int cyberfb_setup(char*);
57 extern int pm2fb_init(void);
58 extern int pm2fb_setup(char*);
59 extern int cyber2000fb_init(void);
60 extern int cyber2000fb_setup(char*);
61 extern int retz3fb_init(void);
62 extern int retz3fb_setup(char*);
63 extern int clgenfb_init(void);
64 extern int clgenfb_setup(char*);
65 extern int hitfb_init(void);
66 extern int hitfb_setup(char*);
67 extern int vfb_init(void);
68 extern int vfb_setup(char*);
69 extern int offb_init(void);
70 extern int atyfb_init(void);
71 extern int atyfb_setup(char*);
72 extern int aty128fb_init(void);
73 extern int aty128fb_setup(char*);
74 extern int igafb_init(void);
75 extern int igafb_setup(char*);
76 extern int imsttfb_init(void);
77 extern int imsttfb_setup(char*);
78 extern int dnfb_init(void);
79 extern int tgafb_init(void);
80 extern int tgafb_setup(char*);
81 extern int virgefb_init(void);
82 extern int virgefb_setup(char*);
83 extern int resolver_video_setup(char*);
84 extern int s3triofb_init(void);
85 extern int vesafb_init(void);
86 extern int vesafb_setup(char*);
87 extern int vga16fb_init(void);
88 extern int vga16fb_setup(char*);
89 extern int hgafb_init(void);
90 extern int hgafb_setup(char*);
91 extern int matroxfb_init(void);
92 extern int matroxfb_setup(char*);
93 extern int hpfb_init(void);
94 extern int hpfb_setup(char*);
95 extern int sbusfb_init(void);
96 extern int sbusfb_setup(char*);
97 extern int control_init(void);
98 extern int control_setup(char*);
99 extern int platinum_init(void);
100 extern int platinum_setup(char*);
101 extern int valkyriefb_init(void);
102 extern int valkyriefb_setup(char*);
103 extern int chips_init(void);
104 extern int g364fb_init(void);
105 extern int sa1100fb_init(void);
106 extern int sa1100fb_setup(char*);
107 extern int fm2fb_init(void);
108 extern int fm2fb_setup(char*);
109 extern int q40fb_init(void);
110 extern int sun3fb_init(void);
111 extern int sun3fb_setup(char *);
112 extern int sgivwfb_init(void);
113 extern int sgivwfb_setup(char*);
114 extern int rivafb_init(void);
115 extern int rivafb_setup(char*);
116 extern int tdfxfb_init(void);
117 extern int tdfxfb_setup(char*);
118 extern int sisfb_init(void);
119 extern int sisfb_setup(char*);
125 } fb_drivers
[] __initdata
= {
127 #ifdef CONFIG_FB_SBUS
129 * Sbusfb must be initialized _before_ other frame buffer devices that
132 { "sbus", sbusfb_init
, sbusfb_setup
},
136 * Chipset specific drivers that use resource management
139 #ifdef CONFIG_FB_RETINAZ3
140 { "retz3", retz3fb_init
, retz3fb_setup
},
142 #ifdef CONFIG_FB_AMIGA
143 { "amifb", amifb_init
, amifb_setup
},
145 #ifdef CONFIG_FB_CYBER
146 { "cyber", cyberfb_init
, cyberfb_setup
},
148 #ifdef CONFIG_FB_CYBER2000
149 { "cyber2000", cyber2000fb_init
, cyber2000fb_setup
},
152 { "pm2fb", pm2fb_init
, pm2fb_setup
},
154 #ifdef CONFIG_FB_CLGEN
155 { "clgen", clgenfb_init
, clgenfb_setup
},
158 { "atyfb", atyfb_init
, atyfb_setup
},
160 #ifdef CONFIG_FB_MATROX
161 { "matrox", matroxfb_init
, matroxfb_setup
},
163 #ifdef CONFIG_FB_ATY128
164 { "aty128fb", aty128fb_init
, aty128fb_setup
},
166 #ifdef CONFIG_FB_VIRGE
167 { "virge", virgefb_init
, virgefb_setup
},
169 #ifdef CONFIG_FB_RIVA
170 { "riva", rivafb_init
, rivafb_setup
},
172 #ifdef CONFIG_FB_CONTROL
173 { "controlfb", control_init
, control_setup
},
175 #ifdef CONFIG_FB_PLATINUM
176 { "platinumfb", platinum_init
, platinum_setup
},
178 #ifdef CONFIG_FB_VALKYRIE
179 { "valkyriefb", valkyriefb_init
, valkyriefb_setup
},
181 #ifdef CONFIG_FB_CT65550
182 { "chipsfb", chips_init
, NULL
},
184 #ifdef CONFIG_FB_IMSTT
185 { "imsttfb", imsttfb_init
, imsttfb_setup
},
187 #ifdef CONFIG_FB_S3TRIO
188 { "s3trio", s3triofb_init
, NULL
},
191 { "fm2fb", fm2fb_init
, fm2fb_setup
},
194 { "sisfb", sisfb_init
, sisfb_setup
},
198 * Generic drivers that are used as fallbacks
200 * These depend on resource management and must be initialized
201 * _after_ all other frame buffer devices that use resource
206 { "offb", offb_init
, NULL
},
208 #ifdef CONFIG_FB_VESA
209 { "vesa", vesafb_init
, vesafb_setup
},
213 * Chipset specific drivers that don't use resource management (yet)
216 #ifdef CONFIG_FB_3DFX
217 { "tdfx", tdfxfb_init
, tdfxfb_setup
},
219 #ifdef CONFIG_FB_SGIVW
220 { "sgivw", sgivwfb_init
, sgivwfb_setup
},
222 #ifdef CONFIG_FB_ACORN
223 { "acorn", acornfb_init
, acornfb_setup
},
225 #ifdef CONFIG_FB_ATARI
226 { "atafb", atafb_init
, atafb_setup
},
229 { "macfb", macfb_init
, macfb_setup
},
232 { "hga", hgafb_init
, hgafb_setup
},
235 { "igafb", igafb_init
, igafb_setup
},
238 { "apollo", dnfb_init
, NULL
},
241 { "q40fb", q40fb_init
, NULL
},
244 { "tga", tgafb_init
, tgafb_setup
},
246 #ifdef CONFIG_FB_HP300
247 { "hpfb", hpfb_init
, hpfb_setup
},
249 #ifdef CONFIG_FB_G364
250 { "g364", g364fb_init
, NULL
},
252 #ifdef CONFIG_FB_SA1100
253 { "sa1100", sa1100fb_init
, sa1100fb_setup
},
255 #ifdef CONFIG_FB_SUN3
256 { "sun3", sun3fb_init
, sun3fb_setup
},
259 { "hitfb", hitfb_init
, hitfb_setup
},
263 * Generic drivers that don't use resource management (yet)
266 #ifdef CONFIG_FB_VGA16
267 { "vga16", vga16fb_init
, vga16fb_setup
},
270 #ifdef CONFIG_GSP_RESOLVER
271 /* Not a real frame buffer device... */
272 { "resolver", NULL
, resolver_video_setup
},
275 #ifdef CONFIG_FB_VIRTUAL
277 * Vfb must be last to avoid that it becomes your primary display if
278 * other display devices are present
280 { "vfb", vfb_init
, vfb_setup
},
284 #define NUM_FB_DRIVERS (sizeof(fb_drivers)/sizeof(*fb_drivers))
286 extern const char *global_mode_option
;
288 static initcall_t pref_init_funcs
[FB_MAX
];
289 static int num_pref_init_funcs __initdata
= 0;
292 struct fb_info
*registered_fb
[FB_MAX
];
293 int num_registered_fb
= 0;
294 extern int fbcon_softback_size
;
296 static int first_fb_vc
= 0;
297 static int last_fb_vc
= MAX_NR_CONSOLES
-1;
298 static int fbcon_is_default
= 1;
301 static int ofonly __initdata
= 0;
304 static int fbmem_read_proc(char *buf
, char **start
, off_t offset
,
305 int len
, int *eof
, void *private)
311 for (fi
= registered_fb
; fi
< ®istered_fb
[FB_MAX
] && len
< 4000; fi
++)
313 clen
+= sprintf(buf
+ clen
, "%d %s\n",
314 GET_FB_IDX((*fi
)->node
),
316 *start
= buf
+ offset
;
321 return clen
< len
? clen
: len
;
325 fb_read(struct file
*file
, char *buf
, size_t count
, loff_t
*ppos
)
327 unsigned long p
= *ppos
;
328 struct inode
*inode
= file
->f_dentry
->d_inode
;
329 int fbidx
= GET_FB_IDX(inode
->i_rdev
);
330 struct fb_info
*info
= registered_fb
[fbidx
];
331 struct fb_ops
*fb
= info
->fbops
;
332 struct fb_fix_screeninfo fix
;
334 if (! fb
|| ! info
->disp
)
337 fb
->fb_get_fix(&fix
,PROC_CONSOLE(info
), info
);
338 if (p
>= fix
.smem_len
)
340 if (count
>= fix
.smem_len
)
341 count
= fix
.smem_len
;
342 if (count
+ p
> fix
.smem_len
)
343 count
= fix
.smem_len
- p
;
347 base_addr
= info
->disp
->screen_base
;
348 count
-= copy_to_user(buf
, base_addr
+p
, count
);
357 fb_write(struct file
*file
, const char *buf
, size_t count
, loff_t
*ppos
)
359 unsigned long p
= *ppos
;
360 struct inode
*inode
= file
->f_dentry
->d_inode
;
361 int fbidx
= GET_FB_IDX(inode
->i_rdev
);
362 struct fb_info
*info
= registered_fb
[fbidx
];
363 struct fb_ops
*fb
= info
->fbops
;
364 struct fb_fix_screeninfo fix
;
367 if (! fb
|| ! info
->disp
)
370 fb
->fb_get_fix(&fix
, PROC_CONSOLE(info
), info
);
371 if (p
> fix
.smem_len
)
373 if (count
>= fix
.smem_len
)
374 count
= fix
.smem_len
;
376 if (count
+ p
> fix
.smem_len
) {
377 count
= fix
.smem_len
- p
;
383 base_addr
= info
->disp
->screen_base
;
384 count
-= copy_from_user(base_addr
+p
, buf
, count
);
394 static void try_to_load(int fb
)
398 sprintf(modname
, "fb%d", fb
);
399 request_module(modname
);
401 #endif /* CONFIG_KMOD */
404 fb_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
,
407 int fbidx
= GET_FB_IDX(inode
->i_rdev
);
408 struct fb_info
*info
= registered_fb
[fbidx
];
409 struct fb_ops
*fb
= info
->fbops
;
411 struct fb_var_screeninfo var
;
412 struct fb_fix_screeninfo fix
;
413 struct fb_con2fbmap con2fb
;
419 case FBIOGET_VSCREENINFO
:
420 if ((i
= fb
->fb_get_var(&var
, PROC_CONSOLE(info
), info
)))
422 return copy_to_user((void *) arg
, &var
,
423 sizeof(var
)) ? -EFAULT
: 0;
424 case FBIOPUT_VSCREENINFO
:
425 if (copy_from_user(&var
, (void *) arg
, sizeof(var
)))
427 i
= var
.activate
& FB_ACTIVATE_ALL
428 ? set_all_vcs(fbidx
, fb
, &var
, info
)
429 : fb
->fb_set_var(&var
, PROC_CONSOLE(info
), info
);
432 if (copy_to_user((void *) arg
, &var
, sizeof(var
)))
435 case FBIOGET_FSCREENINFO
:
436 if ((i
= fb
->fb_get_fix(&fix
, PROC_CONSOLE(info
), info
)))
438 return copy_to_user((void *) arg
, &fix
, sizeof(fix
)) ?
441 if (copy_from_user(&cmap
, (void *) arg
, sizeof(cmap
)))
443 return (fb
->fb_set_cmap(&cmap
, 0, PROC_CONSOLE(info
), info
));
445 if (copy_from_user(&cmap
, (void *) arg
, sizeof(cmap
)))
447 return (fb
->fb_get_cmap(&cmap
, 0, PROC_CONSOLE(info
), info
));
448 case FBIOPAN_DISPLAY
:
449 if (copy_from_user(&var
, (void *) arg
, sizeof(var
)))
451 if (fb
->fb_pan_display
== NULL
)
452 return (var
.xoffset
|| var
.yoffset
) ? -EINVAL
: 0;
453 if ((i
=fb
->fb_pan_display(&var
, PROC_CONSOLE(info
), info
)))
455 if (copy_to_user((void *) arg
, &var
, sizeof(var
)))
458 case FBIOGET_CON2FBMAP
:
459 if (copy_from_user(&con2fb
, (void *)arg
, sizeof(con2fb
)))
461 if (con2fb
.console
< 1 || con2fb
.console
> MAX_NR_CONSOLES
)
463 con2fb
.framebuffer
= con2fb_map
[con2fb
.console
-1];
464 return copy_to_user((void *)arg
, &con2fb
,
465 sizeof(con2fb
)) ? -EFAULT
: 0;
466 case FBIOPUT_CON2FBMAP
:
467 if (copy_from_user(&con2fb
, (void *)arg
, sizeof(con2fb
)))
469 if (con2fb
.console
< 0 || con2fb
.console
> MAX_NR_CONSOLES
)
471 if (con2fb
.framebuffer
< 0 || con2fb
.framebuffer
>= FB_MAX
)
474 if (!registered_fb
[con2fb
.framebuffer
])
475 try_to_load(con2fb
.framebuffer
);
476 #endif /* CONFIG_KMOD */
477 if (!registered_fb
[con2fb
.framebuffer
])
479 if (con2fb
.console
!= 0)
480 set_con2fb_map(con2fb
.console
-1, con2fb
.framebuffer
);
483 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++)
484 set_con2fb_map(i
, con2fb
.framebuffer
);
487 if (info
->blank
== 0)
489 (*info
->blank
)(arg
, info
);
492 if (fb
->fb_ioctl
== NULL
)
494 return fb
->fb_ioctl(inode
, file
, cmd
, arg
, PROC_CONSOLE(info
),
500 fb_mmap(struct file
*file
, struct vm_area_struct
* vma
)
502 int fbidx
= GET_FB_IDX(file
->f_dentry
->d_inode
->i_rdev
);
503 struct fb_info
*info
= registered_fb
[fbidx
];
504 struct fb_ops
*fb
= info
->fbops
;
506 #if !defined(__sparc__) || defined(__sparc_v9__)
507 struct fb_fix_screeninfo fix
;
508 struct fb_var_screeninfo var
;
513 if (vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
))
515 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
521 res
= fb
->fb_mmap(info
, file
, vma
);
526 #if defined(__sparc__) && !defined(__sparc_v9__)
527 /* Should never get here, all fb drivers should have their own
534 fb
->fb_get_fix(&fix
, PROC_CONSOLE(info
), info
);
536 /* frame buffer memory */
537 start
= fix
.smem_start
;
538 len
= PAGE_ALIGN((start
& ~PAGE_MASK
)+fix
.smem_len
);
540 /* memory mapped io */
542 fb
->fb_get_var(&var
, PROC_CONSOLE(info
), info
);
545 start
= fix
.mmio_start
;
546 len
= PAGE_ALIGN((start
& ~PAGE_MASK
)+fix
.mmio_len
);
550 if ((vma
->vm_end
- vma
->vm_start
+ off
) > len
)
553 vma
->vm_pgoff
= off
>> PAGE_SHIFT
;
554 #if defined(__sparc_v9__)
555 vma
->vm_flags
|= (VM_SHM
| VM_LOCKED
);
557 unsigned long align
, j
;
558 for (align
= 0x400000; align
> PAGE_SIZE
; align
>>= 3)
559 if (len
>= align
&& !((start
& ~PAGE_MASK
) & (align
- 1)))
561 if (align
> PAGE_SIZE
&& vma
->vm_start
& (align
- 1)) {
562 /* align as much as possible */
563 struct vm_area_struct
*vmm
;
564 j
= (-vma
->vm_start
) & (align
- 1);
565 vmm
= find_vma(current
->mm
, vma
->vm_start
);
566 if (!vmm
|| vmm
->vm_start
>= vma
->vm_end
+ j
) {
572 if (io_remap_page_range(vma
->vm_start
, off
,
573 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
, 0))
575 vma
->vm_flags
|= VM_IO
;
577 #if defined(__mc68000__)
578 #if defined(CONFIG_SUN3)
579 pgprot_val(vma
->vm_page_prot
) |= SUN3_PAGE_NOCACHE
;
581 if (CPU_IS_020_OR_030
)
582 pgprot_val(vma
->vm_page_prot
) |= _PAGE_NOCACHE030
;
583 if (CPU_IS_040_OR_060
) {
584 pgprot_val(vma
->vm_page_prot
) &= _CACHEMASK040
;
585 /* Use no-cache mode, serialized */
586 pgprot_val(vma
->vm_page_prot
) |= _PAGE_NOCACHE_S
;
589 #elif defined(__powerpc__)
590 pgprot_val(vma
->vm_page_prot
) |= _PAGE_NO_CACHE
|_PAGE_GUARDED
;
591 #elif defined(__alpha__)
592 /* Caching is off in the I/O space quadrant by design. */
593 #elif defined(__i386__)
594 if (boot_cpu_data
.x86
> 3)
595 pgprot_val(vma
->vm_page_prot
) |= _PAGE_PCD
;
596 #elif defined(__mips__)
597 pgprot_val(vma
->vm_page_prot
) &= ~_CACHE_MASK
;
598 pgprot_val(vma
->vm_page_prot
) |= _CACHE_UNCACHED
;
599 #elif defined(__arm__)
600 #if defined(CONFIG_CPU_32) && !defined(CONFIG_ARCH_ACORN)
601 /* On Acorn architectures, we want to keep the framebuffer
604 pgprot_val(vma
->vm_page_prot
) &= ~(PTE_CACHEABLE
| PTE_BUFFERABLE
);
606 #elif defined(__sh__)
607 pgprot_val(vma
->vm_page_prot
) &= ~_PAGE_CACHABLE
;
609 #warning What do we have to do here??
611 if (io_remap_page_range(vma
->vm_start
, off
,
612 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
))
614 #endif /* !__sparc_v9__ */
616 #endif /* !sparc32 */
619 #if 1 /* to go away in 2.5.0 */
620 int GET_FB_IDX(kdev_t rdev
)
622 int fbidx
= MINOR(rdev
);
624 int newfbidx
= fbidx
>> 5;
625 static int warned
= 0;
626 if (!(warned
& (1<<newfbidx
))) {
627 warned
|= 1<<newfbidx
;
628 printk("Warning: Remapping obsolete /dev/fb* minor %d to %d\n",
638 fb_open(struct inode
*inode
, struct file
*file
)
640 int fbidx
= GET_FB_IDX(inode
->i_rdev
);
641 struct fb_info
*info
;
645 if (!(info
= registered_fb
[fbidx
]))
647 #endif /* CONFIG_KMOD */
648 if (!(info
= registered_fb
[fbidx
]))
650 if (info
->fbops
->owner
)
651 __MOD_INC_USE_COUNT(info
->fbops
->owner
);
652 if (info
->fbops
->fb_open
) {
653 res
= info
->fbops
->fb_open(info
,1);
654 if (res
&& info
->fbops
->owner
)
655 __MOD_DEC_USE_COUNT(info
->fbops
->owner
);
661 fb_release(struct inode
*inode
, struct file
*file
)
663 int fbidx
= GET_FB_IDX(inode
->i_rdev
);
664 struct fb_info
*info
;
667 info
= registered_fb
[fbidx
];
668 if (info
->fbops
->fb_release
)
669 info
->fbops
->fb_release(info
,1);
670 if (info
->fbops
->owner
)
671 __MOD_DEC_USE_COUNT(info
->fbops
->owner
);
676 static struct file_operations fb_fops
= {
686 static devfs_handle_t devfs_handle
= NULL
;
689 register_framebuffer(struct fb_info
*fb_info
)
693 static int fb_ever_opened
[FB_MAX
];
694 static int first
= 1;
696 if (num_registered_fb
== FB_MAX
)
699 for (i
= 0 ; i
< FB_MAX
; i
++)
700 if (!registered_fb
[i
])
702 fb_info
->node
= MKDEV(FB_MAJOR
, i
);
703 registered_fb
[i
] = fb_info
;
704 if (!fb_ever_opened
[i
]) {
705 struct module
*owner
= fb_info
->fbops
->owner
;
707 * We assume initial frame buffer devices can be opened this
710 for (j
= 0; j
< MAX_NR_CONSOLES
; j
++)
711 if (con2fb_map
[j
] == i
) {
713 __MOD_INC_USE_COUNT(owner
);
714 if (!fb_info
->fbops
->fb_open
)
716 if (!fb_info
->fbops
->fb_open(fb_info
,0))
719 __MOD_DEC_USE_COUNT(owner
);
721 fb_ever_opened
[i
] = 1;
726 take_over_console(&fb_con
, first_fb_vc
, last_fb_vc
, fbcon_is_default
);
728 sprintf (name_buf
, "%d", i
);
729 fb_info
->devfs_handle
=
730 devfs_register (devfs_handle
, name_buf
, DEVFS_FL_DEFAULT
,
731 FB_MAJOR
, i
, S_IFCHR
| S_IRUGO
| S_IWUGO
,
738 unregister_framebuffer(struct fb_info
*fb_info
)
742 i
= GET_FB_IDX(fb_info
->node
);
743 for (j
= 0; j
< MAX_NR_CONSOLES
; j
++)
744 if (con2fb_map
[j
] == i
)
746 if (!registered_fb
[i
])
748 devfs_unregister (fb_info
->devfs_handle
);
749 fb_info
->devfs_handle
= NULL
;
750 devfs_unregister (fb_info
->devfs_lhandle
);
751 fb_info
->devfs_lhandle
= NULL
;
752 registered_fb
[i
]=NULL
;
762 create_proc_read_entry("fb", 0, 0, fbmem_read_proc
, NULL
);
764 devfs_handle
= devfs_mk_dir (NULL
, "fb", NULL
);
765 if (devfs_register_chrdev(FB_MAJOR
,"fb",&fb_fops
))
766 printk("unable to get major %d for fb devs\n", FB_MAJOR
);
776 * Probe for all builtin frame buffer devices
778 for (i
= 0; i
< num_pref_init_funcs
; i
++)
779 pref_init_funcs
[i
]();
781 for (i
= 0; i
< NUM_FB_DRIVERS
; i
++)
782 if (fb_drivers
[i
].init
)
783 fb_drivers
[i
].init();
787 * Command line options
790 int __init
video_setup(char *options
)
794 if (!options
|| !*options
)
797 if (!strncmp(options
, "scrollback:", 11)) {
800 fbcon_softback_size
= simple_strtoul(options
, &options
, 0);
801 if (*options
== 'k' || *options
== 'K') {
802 fbcon_softback_size
*= 1024;
812 if (!strncmp(options
, "map:", 4)) {
815 for (i
= 0, j
= 0; i
< MAX_NR_CONSOLES
; i
++) {
818 con2fb_map
[i
] = (options
[j
++]-'0') % FB_MAX
;
823 if (!strncmp(options
, "vc:", 3)) {
826 first_fb_vc
= simple_strtoul(options
, &options
, 10) - 1;
829 if (*options
++ == '-')
830 last_fb_vc
= simple_strtoul(options
, &options
, 10) - 1;
831 fbcon_is_default
= 0;
835 if (!strcmp(options
, "ofonly")) {
841 if (num_pref_init_funcs
== FB_MAX
)
844 for (i
= 0; i
< NUM_FB_DRIVERS
; i
++) {
845 j
= strlen(fb_drivers
[i
].name
);
846 if (!strncmp(options
, fb_drivers
[i
].name
, j
) &&
848 if (!strcmp(options
+j
+1, "off"))
849 fb_drivers
[i
].init
= NULL
;
851 if (fb_drivers
[i
].init
) {
852 pref_init_funcs
[num_pref_init_funcs
++] =
854 fb_drivers
[i
].init
= NULL
;
856 if (fb_drivers
[i
].setup
)
857 fb_drivers
[i
].setup(options
+j
+1);
864 * If we get here no fb was specified.
865 * We consider the argument to be a global video mode option.
867 global_mode_option
= options
;
871 __setup("video=", video_setup
);
874 * Visible symbols for modules
877 EXPORT_SYMBOL(register_framebuffer
);
878 EXPORT_SYMBOL(unregister_framebuffer
);
879 EXPORT_SYMBOL(registered_fb
);
880 EXPORT_SYMBOL(num_registered_fb
);
881 #if 1 /* to go away in 2.5.0 */
882 EXPORT_SYMBOL(GET_FB_IDX
);