vesafb.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:18k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * framebuffer driver for VBE 2.0 compliant graphic boards
  3.  *
  4.  * switching to graphics mode happens at boot time (while
  5.  * running in real mode, see arch/i386/boot/video.S).
  6.  *
  7.  * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  8.  *
  9.  */
  10. #include <linux/module.h>
  11. #include <linux/kernel.h>
  12. #include <linux/errno.h>
  13. #include <linux/string.h>
  14. #include <linux/mm.h>
  15. #include <linux/tty.h>
  16. #include <linux/slab.h>
  17. #include <linux/delay.h>
  18. #include <linux/fb.h>
  19. #include <linux/console.h>
  20. #include <linux/selection.h>
  21. #include <linux/ioport.h>
  22. #include <linux/init.h>
  23. #include <asm/io.h>
  24. #include <asm/mtrr.h>
  25. #include <video/fbcon.h>
  26. #include <video/fbcon-cfb8.h>
  27. #include <video/fbcon-cfb16.h>
  28. #include <video/fbcon-cfb24.h>
  29. #include <video/fbcon-cfb32.h>
  30. #include <video/fbcon-mac.h>
  31. #define dac_reg (0x3c8)
  32. #define dac_val (0x3c9)
  33. /* --------------------------------------------------------------------- */
  34. /*
  35.  * card parameters
  36.  */
  37. /* card */
  38. unsigned long video_base; /* physical addr */
  39. int   video_size;
  40. char *video_vbase;        /* mapped */
  41. /* mode */
  42. static int  video_bpp;
  43. static int  video_width;
  44. static int  video_height;
  45. static int  video_height_virtual;
  46. static int  video_type = FB_TYPE_PACKED_PIXELS;
  47. static int  video_visual;
  48. static int  video_linelength;
  49. static int  video_cmap_len;
  50. /* --------------------------------------------------------------------- */
  51. static struct fb_var_screeninfo vesafb_defined = {
  52. 0,0,0,0, /* W,H, W, H (virtual) load xres,xres_virtual*/
  53. 0,0, /* virtual -> visible no offset */
  54. 8, /* depth -> load bits_per_pixel */
  55. 0, /* greyscale ? */
  56. {0,0,0}, /* R */
  57. {0,0,0}, /* G */
  58. {0,0,0}, /* B */
  59. {0,0,0}, /* transparency */
  60. 0, /* standard pixel format */
  61. FB_ACTIVATE_NOW,
  62. -1,-1,
  63. 0,
  64. 0L,0L,0L,0L,0L,
  65. 0L,0L,0, /* No sync info */
  66. FB_VMODE_NONINTERLACED,
  67. {0,0,0,0,0,0}
  68. };
  69. static struct display disp;
  70. static struct fb_info fb_info;
  71. static struct { u_short blue, green, red, pad; } palette[256];
  72. static union {
  73. #ifdef FBCON_HAS_CFB16
  74.     u16 cfb16[16];
  75. #endif
  76. #ifdef FBCON_HAS_CFB24
  77.     u32 cfb24[16];
  78. #endif
  79. #ifdef FBCON_HAS_CFB32
  80.     u32 cfb32[16];
  81. #endif
  82. } fbcon_cmap;
  83. static int             inverse   = 0;
  84. static int             mtrr      = 0;
  85. static int             currcon   = 0;
  86. static int             pmi_setpal = 0; /* pmi for palette changes ??? */
  87. static int             ypan       = 0;  /* 0..nothing, 1..ypan, 2..ywrap */
  88. static unsigned short  *pmi_base  = 0;
  89. static void            (*pmi_start)(void);
  90. static void            (*pmi_pal)(void);
  91. static struct display_switch vesafb_sw;
  92. /* --------------------------------------------------------------------- */
  93. static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
  94.                               struct fb_info *info)
  95. {
  96. #ifdef __i386__
  97. int offset;
  98. if (!ypan)
  99. return -EINVAL;
  100. if (var->xoffset)
  101. return -EINVAL;
  102. if (var->yoffset > var->yres_virtual)
  103. return -EINVAL;
  104. if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual)
  105. return -EINVAL;
  106. offset = (var->yoffset * video_linelength + var->xoffset) / 4;
  107.         __asm__ __volatile__(
  108.                 "call *(%%edi)"
  109.                 : /* no return value */
  110.                 : "a" (0x4f07),         /* EAX */
  111.                   "b" (0),              /* EBX */
  112.                   "c" (offset),         /* ECX */
  113.                   "d" (offset >> 16),   /* EDX */
  114.                   "D" (&pmi_start));    /* EDI */
  115. #endif
  116. return 0;
  117. }
  118. static int vesafb_update_var(int con, struct fb_info *info)
  119. {
  120. if (con == currcon && ypan) {
  121. struct fb_var_screeninfo *var = &fb_display[currcon].var;
  122. return vesafb_pan_display(var,con,info);
  123. }
  124. return 0;
  125. }
  126. static int vesafb_get_fix(struct fb_fix_screeninfo *fix, int con,
  127.  struct fb_info *info)
  128. {
  129. memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  130. strcpy(fix->id,"VESA VGA");
  131. fix->smem_start=video_base;
  132. fix->smem_len=video_size;
  133. fix->type = video_type;
  134. fix->visual = video_visual;
  135. fix->xpanstep  = 0;
  136. fix->ypanstep  = ypan     ? 1 : 0;
  137. fix->ywrapstep = (ypan>1) ? 1 : 0;
  138. fix->line_length=video_linelength;
  139. return 0;
  140. }
  141. static int vesafb_get_var(struct fb_var_screeninfo *var, int con,
  142.  struct fb_info *info)
  143. {
  144. if(con==-1)
  145. memcpy(var, &vesafb_defined, sizeof(struct fb_var_screeninfo));
  146. else
  147. *var=fb_display[con].var;
  148. return 0;
  149. }
  150. static void vesafb_set_disp(int con)
  151. {
  152. struct fb_fix_screeninfo fix;
  153. struct display *display;
  154. struct display_switch *sw;
  155. if (con >= 0)
  156. display = &fb_display[con];
  157. else
  158. display = &disp; /* used during initialization */
  159. vesafb_get_fix(&fix, con, 0);
  160. memset(display, 0, sizeof(struct display));
  161. display->screen_base = video_vbase;
  162. display->visual = fix.visual;
  163. display->type = fix.type;
  164. display->type_aux = fix.type_aux;
  165. display->ypanstep = fix.ypanstep;
  166. display->ywrapstep = fix.ywrapstep;
  167. display->line_length = fix.line_length;
  168. display->next_line = fix.line_length;
  169. display->can_soft_blank = 0;
  170. display->inverse = inverse;
  171. vesafb_get_var(&display->var, -1, &fb_info);
  172. switch (video_bpp) {
  173. #ifdef FBCON_HAS_CFB8
  174. case 8:
  175. sw = &fbcon_cfb8;
  176. break;
  177. #endif
  178. #ifdef FBCON_HAS_CFB16
  179. case 15:
  180. case 16:
  181. sw = &fbcon_cfb16;
  182. display->dispsw_data = fbcon_cmap.cfb16;
  183. break;
  184. #endif
  185. #ifdef FBCON_HAS_CFB24
  186. case 24:
  187. sw = &fbcon_cfb24;
  188. display->dispsw_data = fbcon_cmap.cfb24;
  189. break;
  190. #endif
  191. #ifdef FBCON_HAS_CFB32
  192. case 32:
  193. sw = &fbcon_cfb32;
  194. display->dispsw_data = fbcon_cmap.cfb32;
  195. break;
  196. #endif
  197. default:
  198. #ifdef FBCON_HAS_MAC
  199. sw = &fbcon_mac;
  200. break;
  201. #else
  202. sw = &fbcon_dummy;
  203. return;
  204. #endif
  205. }
  206. memcpy(&vesafb_sw, sw, sizeof(*sw));
  207. display->dispsw = &vesafb_sw;
  208. if (!ypan) {
  209. display->scrollmode = SCROLL_YREDRAW;
  210. vesafb_sw.bmove = fbcon_redraw_bmove;
  211. }
  212. }
  213. static int vesafb_set_var(struct fb_var_screeninfo *var, int con,
  214.   struct fb_info *info)
  215. {
  216. static int first = 1;
  217. if (var->xres           != vesafb_defined.xres           ||
  218.     var->yres           != vesafb_defined.yres           ||
  219.     var->xres_virtual   != vesafb_defined.xres_virtual   ||
  220.     var->yres_virtual   >  video_height_virtual          ||
  221.     var->yres_virtual   <  video_height                  ||
  222.     var->xoffset                                         ||
  223.     var->bits_per_pixel != vesafb_defined.bits_per_pixel ||
  224.     var->nonstd) {
  225. if (first) {
  226. printk(KERN_ERR "Vesafb does not support changing the video moden");
  227. first = 0;
  228. }
  229. return -EINVAL;
  230. }
  231. if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
  232. return 0;
  233. if (ypan) {
  234. if (vesafb_defined.yres_virtual != var->yres_virtual) {
  235. vesafb_defined.yres_virtual = var->yres_virtual;
  236. if (con != -1) {
  237. fb_display[con].var = vesafb_defined;
  238. info->changevar(con);
  239. }
  240. }
  241. if (var->yoffset != vesafb_defined.yoffset)
  242. return vesafb_pan_display(var,con,info);
  243. return 0;
  244. }
  245. if (var->yoffset)
  246. return -EINVAL;
  247. return 0;
  248. }
  249. static int vesa_getcolreg(unsigned regno, unsigned *red, unsigned *green,
  250.   unsigned *blue, unsigned *transp,
  251.   struct fb_info *fb_info)
  252. {
  253. /*
  254.  *  Read a single color register and split it into colors/transparent.
  255.  *  Return != 0 for invalid regno.
  256.  */
  257. if (regno >= video_cmap_len)
  258. return 1;
  259. *red   = palette[regno].red;
  260. *green = palette[regno].green;
  261. *blue  = palette[regno].blue;
  262. *transp = 0;
  263. return 0;
  264. }
  265. #ifdef FBCON_HAS_CFB8
  266. static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
  267. {
  268. #ifdef i386
  269. struct { u_char blue, green, red, pad; } entry;
  270. if (pmi_setpal) {
  271. entry.red   = red   >> 10;
  272. entry.green = green >> 10;
  273. entry.blue  = blue  >> 10;
  274. entry.pad   = 0;
  275.         __asm__ __volatile__(
  276.                 "call *(%%esi)"
  277.                 : /* no return value */
  278.                 : "a" (0x4f09),         /* EAX */
  279.                   "b" (0),              /* EBX */
  280.                   "c" (1),              /* ECX */
  281.                   "d" (regno),          /* EDX */
  282.                   "D" (&entry),         /* EDI */
  283.                   "S" (&pmi_pal));      /* ESI */
  284. } else {
  285. /* without protected mode interface, try VGA registers... */
  286. outb_p(regno,       dac_reg);
  287. outb_p(red   >> 10, dac_val);
  288. outb_p(green >> 10, dac_val);
  289. outb_p(blue  >> 10, dac_val);
  290. }
  291. #endif
  292. }
  293. #endif
  294. static int vesa_setcolreg(unsigned regno, unsigned red, unsigned green,
  295.   unsigned blue, unsigned transp,
  296.   struct fb_info *fb_info)
  297. {
  298. /*
  299.  *  Set a single color register. The values supplied are
  300.  *  already rounded down to the hardware's capabilities
  301.  *  (according to the entries in the `var' structure). Return
  302.  *  != 0 for invalid regno.
  303.  */
  304. if (regno >= video_cmap_len)
  305. return 1;
  306. palette[regno].red   = red;
  307. palette[regno].green = green;
  308. palette[regno].blue  = blue;
  309. switch (video_bpp) {
  310. #ifdef FBCON_HAS_CFB8
  311. case 8:
  312. vesa_setpalette(regno,red,green,blue);
  313. break;
  314. #endif
  315. #ifdef FBCON_HAS_CFB16
  316. case 15:
  317. case 16:
  318. if (vesafb_defined.red.offset == 10) {
  319. /* 1:5:5:5 */
  320. fbcon_cmap.cfb16[regno] =
  321. ((red   & 0xf800) >>  1) |
  322. ((green & 0xf800) >>  6) |
  323. ((blue  & 0xf800) >> 11);
  324. } else {
  325. /* 0:5:6:5 */
  326. fbcon_cmap.cfb16[regno] =
  327. ((red   & 0xf800)      ) |
  328. ((green & 0xfc00) >>  5) |
  329. ((blue  & 0xf800) >> 11);
  330. }
  331. break;
  332. #endif
  333. #ifdef FBCON_HAS_CFB24
  334. case 24:
  335. red   >>= 8;
  336. green >>= 8;
  337. blue  >>= 8;
  338. fbcon_cmap.cfb24[regno] =
  339. (red   << vesafb_defined.red.offset)   |
  340. (green << vesafb_defined.green.offset) |
  341. (blue  << vesafb_defined.blue.offset);
  342. break;
  343. #endif
  344. #ifdef FBCON_HAS_CFB32
  345. case 32:
  346. red   >>= 8;
  347. green >>= 8;
  348. blue  >>= 8;
  349. fbcon_cmap.cfb32[regno] =
  350. (red   << vesafb_defined.red.offset)   |
  351. (green << vesafb_defined.green.offset) |
  352. (blue  << vesafb_defined.blue.offset);
  353. break;
  354. #endif
  355.     }
  356.     return 0;
  357. }
  358. static void do_install_cmap(int con, struct fb_info *info)
  359. {
  360. if (con != currcon)
  361. return;
  362. if (fb_display[con].cmap.len)
  363. fb_set_cmap(&fb_display[con].cmap, 1, vesa_setcolreg, info);
  364. else
  365. fb_set_cmap(fb_default_cmap(video_cmap_len), 1, vesa_setcolreg,
  366.     info);
  367. }
  368. static int vesafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  369.    struct fb_info *info)
  370. {
  371. if (con == currcon) /* current console? */
  372. return fb_get_cmap(cmap, kspc, vesa_getcolreg, info);
  373. else if (fb_display[con].cmap.len) /* non default colormap? */
  374. fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  375. else
  376. fb_copy_cmap(fb_default_cmap(video_cmap_len),
  377.      cmap, kspc ? 0 : 2);
  378. return 0;
  379. }
  380. static int vesafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  381.    struct fb_info *info)
  382. {
  383. int err;
  384. if (!fb_display[con].cmap.len) { /* no colormap allocated? */
  385. err = fb_alloc_cmap(&fb_display[con].cmap,video_cmap_len,0);
  386. if (err)
  387. return err;
  388. }
  389. if (con == currcon) /* current console? */
  390. return fb_set_cmap(cmap, kspc, vesa_setcolreg, info);
  391. else
  392. fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  393. return 0;
  394. }
  395. static struct fb_ops vesafb_ops = {
  396. owner: THIS_MODULE,
  397. fb_get_fix: vesafb_get_fix,
  398. fb_get_var: vesafb_get_var,
  399. fb_set_var: vesafb_set_var,
  400. fb_get_cmap: vesafb_get_cmap,
  401. fb_set_cmap: vesafb_set_cmap,
  402. fb_pan_display: vesafb_pan_display,
  403. };
  404. int __init vesafb_setup(char *options)
  405. {
  406. char *this_opt;
  407. fb_info.fontname[0] = '';
  408. if (!options || !*options)
  409. return 0;
  410. while ((this_opt = strsep(&options, ",")) != NULL) {
  411. if (!*this_opt) continue;
  412. if (! strcmp(this_opt, "inverse"))
  413. inverse=1;
  414. else if (! strcmp(this_opt, "redraw"))
  415. ypan=0;
  416. else if (! strcmp(this_opt, "ypan"))
  417. ypan=1;
  418. else if (! strcmp(this_opt, "ywrap"))
  419. ypan=2;
  420. else if (! strcmp(this_opt, "vgapal"))
  421. pmi_setpal=0;
  422. else if (! strcmp(this_opt, "pmipal"))
  423. pmi_setpal=1;
  424. else if (! strcmp(this_opt, "mtrr"))
  425. mtrr=1;
  426. else if (!strncmp(this_opt, "font:", 5))
  427. strcpy(fb_info.fontname, this_opt+5);
  428. }
  429. return 0;
  430. }
  431. static int vesafb_switch(int con, struct fb_info *info)
  432. {
  433. /* Do we have to save the colormap? */
  434. if (fb_display[currcon].cmap.len)
  435. fb_get_cmap(&fb_display[currcon].cmap, 1, vesa_getcolreg,
  436.     info);
  437. currcon = con;
  438. /* Install new colormap */
  439. do_install_cmap(con, info);
  440. vesafb_update_var(con,info);
  441. return 1;
  442. }
  443. /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
  444. static void vesafb_blank(int blank, struct fb_info *info)
  445. {
  446. /* Not supported */
  447. }
  448. int __init vesafb_init(void)
  449. {
  450. int i,j;
  451. if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
  452. return -ENXIO;
  453. video_base          = screen_info.lfb_base;
  454. video_bpp           = screen_info.lfb_depth;
  455. if (15 == video_bpp)
  456. video_bpp = 16;
  457. video_width         = screen_info.lfb_width;
  458. video_height        = screen_info.lfb_height;
  459. video_linelength    = screen_info.lfb_linelength;
  460. video_size          = screen_info.lfb_size * 65536;
  461. video_visual = (video_bpp == 8) ?
  462. FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
  463. #ifndef __i386__
  464. screen_info.vesapm_seg = 0;
  465. #endif
  466. if (!request_mem_region(video_base, video_size, "vesafb")) {
  467. printk(KERN_WARNING
  468.        "vesafb: abort, cannot reserve video memory at 0x%lxn",
  469. video_base);
  470. /* We cannot make this fatal. Sometimes this comes from magic
  471.    spaces our resource handlers simply don't know about */
  472. }
  473.         video_vbase = ioremap(video_base, video_size);
  474. if (!video_vbase) {
  475. release_mem_region(video_base, video_size);
  476. printk(KERN_ERR
  477.        "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lxn",
  478. video_size, video_base);
  479. return -EIO;
  480. }
  481. printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, size %dkn",
  482.        video_base, video_vbase, video_size/1024);
  483. printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%dn",
  484.        video_width, video_height, video_bpp, video_linelength, screen_info.pages);
  485. if (screen_info.vesapm_seg) {
  486. printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04xn",
  487.        screen_info.vesapm_seg,screen_info.vesapm_off);
  488. }
  489. if (screen_info.vesapm_seg < 0xc000)
  490. ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
  491. if (ypan || pmi_setpal) {
  492. pmi_base  = (unsigned short*)bus_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
  493. pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
  494. pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
  495. printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %pn",pmi_start,pmi_pal);
  496. if (pmi_base[3]) {
  497. printk(KERN_INFO "vesafb: pmi: ports = ");
  498. for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
  499. printk("%x ",pmi_base[i]);
  500. printk("n");
  501. if (pmi_base[i] != 0xffff) {
  502. /*
  503.  * memory areas not supported (yet?)
  504.  *
  505.  * Rules are: we have to set up a descriptor for the requested
  506.  * memory area and pass it in the ES register to the BIOS function.
  507.  */
  508. printk(KERN_INFO "vesafb: can't handle memory requests, pmi disabledn");
  509. ypan = pmi_setpal = 0;
  510. }
  511. }
  512. }
  513. vesafb_defined.xres=video_width;
  514. vesafb_defined.yres=video_height;
  515. vesafb_defined.xres_virtual=video_width;
  516. vesafb_defined.yres_virtual=video_size / video_linelength;
  517. vesafb_defined.bits_per_pixel=video_bpp;
  518. if (ypan && vesafb_defined.yres_virtual > video_height) {
  519. printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%dn",
  520.        (ypan > 1) ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
  521. } else {
  522. printk(KERN_INFO "vesafb: scrolling: redrawn");
  523. vesafb_defined.yres_virtual = video_height;
  524. ypan = 0;
  525. }
  526. video_height_virtual = vesafb_defined.yres_virtual;
  527. /* some dummy values for timing to make fbset happy */
  528. vesafb_defined.pixclock     = 10000000 / video_width * 1000 / video_height;
  529. vesafb_defined.left_margin  = (video_width / 8) & 0xf8;
  530. vesafb_defined.right_margin = 32;
  531. vesafb_defined.upper_margin = 16;
  532. vesafb_defined.lower_margin = 4;
  533. vesafb_defined.hsync_len    = (video_width / 8) & 0xf8;
  534. vesafb_defined.vsync_len    = 4;
  535. if (video_bpp > 8) {
  536. vesafb_defined.red.offset    = screen_info.red_pos;
  537. vesafb_defined.red.length    = screen_info.red_size;
  538. vesafb_defined.green.offset  = screen_info.green_pos;
  539. vesafb_defined.green.length  = screen_info.green_size;
  540. vesafb_defined.blue.offset   = screen_info.blue_pos;
  541. vesafb_defined.blue.length   = screen_info.blue_size;
  542. vesafb_defined.transp.offset = screen_info.rsvd_pos;
  543. vesafb_defined.transp.length = screen_info.rsvd_size;
  544. printk(KERN_INFO "vesafb: directcolor: "
  545.        "size=%d:%d:%d:%d, shift=%d:%d:%d:%dn",
  546.        screen_info.rsvd_size,
  547.        screen_info.red_size,
  548.        screen_info.green_size,
  549.        screen_info.blue_size,
  550.        screen_info.rsvd_pos,
  551.        screen_info.red_pos,
  552.        screen_info.green_pos,
  553.        screen_info.blue_pos);
  554. video_cmap_len = 16;
  555. } else {
  556. vesafb_defined.red.length   = 6;
  557. vesafb_defined.green.length = 6;
  558. vesafb_defined.blue.length  = 6;
  559. for(i = 0; i < 16; i++) {
  560. j = color_table[i];
  561. palette[i].red   = default_red[j];
  562. palette[i].green = default_grn[j];
  563. palette[i].blue  = default_blu[j];
  564. }
  565. video_cmap_len = 256;
  566. }
  567. /* request failure does not faze us, as vgacon probably has this
  568.  * region already (FIXME) */
  569. request_region(0x3c0, 32, "vesafb");
  570. if (mtrr) {
  571. int temp_size = video_size;
  572. /* Find the largest power-of-two */
  573. while (temp_size & (temp_size - 1))
  574.                  temp_size &= (temp_size - 1);
  575.                         
  576.                 /* Try and find a power of two to add */
  577. while (temp_size && mtrr_add(video_base, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
  578. temp_size >>= 1;
  579. }
  580. }
  581. strcpy(fb_info.modename, "VESA VGA");
  582. fb_info.changevar = NULL;
  583. fb_info.node = -1;
  584. fb_info.fbops = &vesafb_ops;
  585. fb_info.disp=&disp;
  586. fb_info.switch_con=&vesafb_switch;
  587. fb_info.updatevar=&vesafb_update_var;
  588. fb_info.blank=&vesafb_blank;
  589. fb_info.flags=FBINFO_FLAG_DEFAULT;
  590. vesafb_set_disp(-1);
  591. if (register_framebuffer(&fb_info)<0)
  592. return -EINVAL;
  593. printk(KERN_INFO "fb%d: %s frame buffer devicen",
  594.        GET_FB_IDX(fb_info.node), fb_info.modename);
  595. return 0;
  596. }
  597. /*
  598.  * Overrides for Emacs so that we follow Linus's tabbing style.
  599.  * ---------------------------------------------------------------------------
  600.  * Local variables:
  601.  * c-basic-offset: 8
  602.  * End:
  603.  */
  604. MODULE_LICENSE("GPL");