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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/drivers/video/fbgen.c -- Generic routines for frame buffer devices
  3.  *
  4.  *  Created 3 Jan 1998 by Geert Uytterhoeven
  5.  *
  6.  * 2001 - Documented with DocBook
  7.  * - Brad Douglas <brad@neruo.com>
  8.  *
  9.  * This file is subject to the terms and conditions of the GNU General Public
  10.  * License.  See the file COPYING in the main directory of this archive
  11.  * for more details.
  12.  */
  13. #include <linux/module.h>
  14. #include <linux/string.h>
  15. #include <linux/tty.h>
  16. #include <linux/fb.h>
  17. #include <linux/slab.h>
  18. #include <asm/uaccess.h>
  19. #include <asm/io.h>
  20. #include <video/fbcon.h>
  21. static int currcon = 0;
  22. /* ---- `Generic' versions of the frame buffer device operations ----------- */
  23. /**
  24.  * fbgen_get_fix - get fixed part of display
  25.  * @fix: fb_fix_screeninfo structure
  26.  * @con: virtual console number
  27.  * @info: frame buffer info structure
  28.  *
  29.  * Get the fixed information part of the display and place it
  30.  * into @fix for virtual console @con on device @info.
  31.  *
  32.  * Returns negative errno on error, or zero on success.
  33.  *
  34.  */
  35. int fbgen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
  36. {
  37.     struct fb_info_gen *info2 = (struct fb_info_gen *)info;
  38.     struct fbgen_hwswitch *fbhw = info2->fbhw;
  39.     char par[info2->parsize];
  40.     if (con == -1)
  41. fbhw->get_par(&par, info2);
  42.     else {
  43. int err;
  44. if ((err = fbhw->decode_var(&fb_display[con].var, &par, info2)))
  45.     return err;
  46.     }
  47.     memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  48.     return fbhw->encode_fix(fix, &par, info2);
  49. }
  50. /**
  51.  * fbgen_get_var - get user defined part of display
  52.  * @var: fb_var_screeninfo structure
  53.  * @con: virtual console number
  54.  * @info: frame buffer info structure
  55.  *
  56.  * Get the user defined part of the display and place it into @var
  57.  * for virtual console @con on device @info.
  58.  *
  59.  * Returns negative errno on error, or zero for success.
  60.  *
  61.  */
  62. int fbgen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
  63. {
  64.     struct fb_info_gen *info2 = (struct fb_info_gen *)info;
  65.     struct fbgen_hwswitch *fbhw = info2->fbhw;
  66.     char par[info2->parsize];
  67.     if (con == -1) {
  68. fbhw->get_par(&par, info2);
  69. fbhw->encode_var(var, &par, info2);
  70.     } else
  71. *var = fb_display[con].var;
  72.     return 0;
  73. }
  74. /**
  75.  * fbgen_set_var - set the user defined part of display
  76.  * @var: fb_var_screeninfo user defined part of the display
  77.  * @con: virtual console number
  78.  * @info: frame buffer info structure
  79.  *
  80.  * Set the user defined part of the display as dictated by @var
  81.  * for virtual console @con on device @info.
  82.  *
  83.  * Returns negative errno on error, or zero for success.
  84.  *
  85.  */
  86. int fbgen_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
  87. {
  88.     struct fb_info_gen *info2 = (struct fb_info_gen *)info;
  89.     int err;
  90.     int oldxres, oldyres, oldbpp, oldxres_virtual, oldyres_virtual, oldyoffset;
  91.     struct fb_bitfield oldred, oldgreen, oldblue;
  92.     if ((err = fbgen_do_set_var(var, con == currcon, info2)))
  93. return err;
  94.     if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
  95. oldxres = fb_display[con].var.xres;
  96. oldyres = fb_display[con].var.yres;
  97. oldxres_virtual = fb_display[con].var.xres_virtual;
  98. oldyres_virtual = fb_display[con].var.yres_virtual;
  99. oldbpp = fb_display[con].var.bits_per_pixel;
  100. oldred = fb_display[con].var.red;
  101. oldgreen = fb_display[con].var.green;
  102. oldblue = fb_display[con].var.blue;
  103. oldyoffset = fb_display[con].var.yoffset;
  104. fb_display[con].var = *var;
  105. if (oldxres != var->xres || oldyres != var->yres ||
  106.     oldxres_virtual != var->xres_virtual ||
  107.     oldyres_virtual != var->yres_virtual ||
  108.     oldbpp != var->bits_per_pixel ||
  109.     (!(memcmp(&oldred, &(var->red), sizeof(struct fb_bitfield)))) || 
  110.     (!(memcmp(&oldgreen, &(var->green), sizeof(struct fb_bitfield)))) ||
  111.     (!(memcmp(&oldblue, &(var->blue), sizeof(struct fb_bitfield)))) ||
  112.     oldyoffset != var->yoffset) {
  113.     fbgen_set_disp(con, info2);
  114.     if (info->changevar)
  115. (*info->changevar)(con);
  116.     if ((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
  117. return err;
  118.     fbgen_install_cmap(con, info2);
  119. }
  120.     }
  121.     var->activate = 0;
  122.     return 0;
  123. }
  124. /**
  125.  * fbgen_get_cmap - get the colormap
  126.  * @cmap: frame buffer colormap structure
  127.  * @kspc: boolean, 0 copy local, 1 put_user() function
  128.  * @con: virtual console number
  129.  * @info: frame buffer info structure
  130.  *
  131.  * Gets the colormap for virtual console @con and places it into
  132.  * @cmap for device @info.
  133.  *
  134.  * Returns negative errno on error, or zero for success.
  135.  *
  136.  */
  137. int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  138.    struct fb_info *info)
  139. {
  140.     struct fb_info_gen *info2 = (struct fb_info_gen *)info;
  141.     struct fbgen_hwswitch *fbhw = info2->fbhw;
  142.     if (con == currcon) /* current console ? */
  143. return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
  144.     else
  145. if (fb_display[con].cmap.len) /* non default colormap ? */
  146.     fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  147. else {
  148.     int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256;
  149.     fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
  150. }
  151.     return 0;
  152. }
  153. /**
  154.  * fbgen_set_cmap - set the colormap
  155.  * @cmap: frame buffer colormap structure
  156.  * @kspc: boolean, 0 copy local, 1 get_user() function
  157.  * @con: virtual console number
  158.  * @info: frame buffer info structure
  159.  *
  160.  * Sets the colormap @cmap for virtual console @con on
  161.  * device @info.
  162.  *
  163.  * Returns negative errno on error, or zero for success.
  164.  *
  165.  */
  166. int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  167.    struct fb_info *info)
  168. {
  169.     struct fb_info_gen *info2 = (struct fb_info_gen *)info;
  170.     struct fbgen_hwswitch *fbhw = info2->fbhw;
  171.     int err;
  172.     if (!fb_display[con].cmap.len) { /* no colormap allocated ? */
  173. int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256;
  174. if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
  175.     return err;
  176.     }
  177.     if (con == currcon) /* current console ? */
  178. return fb_set_cmap(cmap, kspc, fbhw->setcolreg, info);
  179.     else
  180. fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  181.     return 0;
  182. }
  183. /**
  184.  * fbgen_pan_display - pan or wrap the display
  185.  * @var: frame buffer user defined part of display
  186.  * @con: virtual console number
  187.  * @info: frame buffer info structure
  188.  *
  189.  * Pan or wrap virtual console @con for device @info.
  190.  *
  191.  * This call looks only at xoffset, yoffset and the
  192.  * FB_VMODE_YWRAP flag in @var.
  193.  *
  194.  * Returns negative errno on error, or zero for success.
  195.  *
  196.  */
  197. int fbgen_pan_display(struct fb_var_screeninfo *var, int con,
  198.       struct fb_info *info)
  199. {
  200.     struct fb_info_gen *info2 = (struct fb_info_gen *)info;
  201.     struct fbgen_hwswitch *fbhw = info2->fbhw;
  202.     int xoffset = var->xoffset;
  203.     int yoffset = var->yoffset;
  204.     int err;
  205.     if (xoffset < 0 ||
  206. xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
  207. yoffset < 0 ||
  208. yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
  209. return -EINVAL;
  210.     if (con == currcon) {
  211. if (fbhw->pan_display) {
  212.     if ((err = fbhw->pan_display(var, info2)))
  213. return err;
  214. } else
  215.     return -EINVAL;
  216.     }
  217.     fb_display[con].var.xoffset = var->xoffset;
  218.     fb_display[con].var.yoffset = var->yoffset;
  219.     if (var->vmode & FB_VMODE_YWRAP)
  220. fb_display[con].var.vmode |= FB_VMODE_YWRAP;
  221.     else
  222. fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
  223.     return 0;
  224. }
  225. /* ---- Helper functions --------------------------------------------------- */
  226. /**
  227.  * fbgen_do_set_var - change the video mode
  228.  * @var: frame buffer user defined part of display
  229.  * @isactive: boolean, 0 inactive, 1 active
  230.  * @info: generic frame buffer info structure
  231.  *
  232.  * Change the video mode settings for device @info.  If @isactive
  233.  * is non-zero, the changes will be activated immediately.
  234.  *
  235.  * Return negative errno on error, or zero for success.
  236.  *
  237.  */
  238. int fbgen_do_set_var(struct fb_var_screeninfo *var, int isactive,
  239.      struct fb_info_gen *info)
  240. {
  241.     struct fbgen_hwswitch *fbhw = info->fbhw;
  242.     int err, activate;
  243.     char par[info->parsize];
  244.     if ((err = fbhw->decode_var(var, &par, info)))
  245. return err;
  246.     activate = var->activate;
  247.     if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
  248. fbhw->set_par(&par, info);
  249.     fbhw->encode_var(var, &par, info);
  250.     var->activate = activate;
  251.     return 0;
  252. }
  253. /**
  254.  * fbgen_set_disp - set generic display
  255.  * @con: virtual console number
  256.  * @info: generic frame buffer info structure
  257.  *
  258.  * Sets a display on virtual console @con for device @info.
  259.  *
  260.  */
  261. void fbgen_set_disp(int con, struct fb_info_gen *info)
  262. {
  263.     struct fbgen_hwswitch *fbhw = info->fbhw;
  264.     struct fb_fix_screeninfo fix;
  265.     char par[info->parsize];
  266.     struct display *display;
  267.     if (con >= 0)
  268. display = &fb_display[con];
  269.     else
  270. display = info->info.disp; /* used during initialization */
  271.     if (con == -1)
  272. fbhw->get_par(&par, info);
  273.     else
  274. fbhw->decode_var(&fb_display[con].var, &par, info);
  275.     memset(&fix, 0, sizeof(struct fb_fix_screeninfo));
  276.     fbhw->encode_fix(&fix, &par, info);
  277.     display->visual = fix.visual;
  278.     display->type = fix.type;
  279.     display->type_aux = fix.type_aux;
  280.     display->ypanstep = fix.ypanstep;
  281.     display->ywrapstep = fix.ywrapstep;
  282.     display->line_length = fix.line_length;
  283.     if (info->fbhw->blank || fix.visual == FB_VISUAL_PSEUDOCOLOR ||
  284. fix.visual == FB_VISUAL_DIRECTCOLOR)
  285. display->can_soft_blank = 1;
  286.     else
  287. display->can_soft_blank = 0;
  288.     fbhw->set_disp(&par, display, info);
  289. #if 0 /* FIXME: generic inverse is not supported yet */
  290.     display->inverse = (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
  291. #else
  292.     display->inverse = fix.visual == FB_VISUAL_MONO01;
  293. #endif
  294. }
  295. /**
  296.  * fbgen_install_cmap - install the current colormap
  297.  * @con: virtual console number
  298.  * @info: generic frame buffer info structure
  299.  *
  300.  * Installs the current colormap for virtual console @con on
  301.  * device @info.
  302.  *
  303.  */
  304. void fbgen_install_cmap(int con, struct fb_info_gen *info)
  305. {
  306.     struct fbgen_hwswitch *fbhw = info->fbhw;
  307.     if (con != currcon)
  308. return;
  309.     if (fb_display[con].cmap.len)
  310. fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, &info->info);
  311.     else {
  312. int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256;
  313. fb_set_cmap(fb_default_cmap(size), 1, fbhw->setcolreg, &info->info);
  314.     }
  315. }
  316. /**
  317.  * fbgen_update_var - update user defined part of display
  318.  * @con: virtual console number
  319.  * @info: frame buffer info structure
  320.  *
  321.  * Updates the user defined part of the display ('var'
  322.  * structure) on virtual console @con for device @info.
  323.  * This function is called by fbcon.c.
  324.  *
  325.  * Returns negative errno on error, or zero for success.
  326.  *
  327.  */
  328. int fbgen_update_var(int con, struct fb_info *info)
  329. {
  330.     struct fb_info_gen *info2 = (struct fb_info_gen *)info;
  331.     struct fbgen_hwswitch *fbhw = info2->fbhw;
  332.     int err;
  333.     if (fbhw->pan_display) {
  334.         if ((err = fbhw->pan_display(&fb_display[con].var, info2)))
  335.             return err;
  336.     }
  337.     return 0;
  338. }
  339. /**
  340.  * fbgen_switch - switch to a different virtual console.
  341.  * @con: virtual console number
  342.  * @info: frame buffer info structure
  343.  *
  344.  * Switch to virtuall console @con on device @info.
  345.  *
  346.  * Returns zero.
  347.  *
  348.  */
  349. int fbgen_switch(int con, struct fb_info *info)
  350. {
  351.     struct fb_info_gen *info2 = (struct fb_info_gen *)info;
  352.     struct fbgen_hwswitch *fbhw = info2->fbhw;
  353.     /* Do we have to save the colormap ? */
  354.     if (fb_display[currcon].cmap.len)
  355. fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
  356.     &info2->info);
  357.     fbgen_do_set_var(&fb_display[con].var, 1, info2);
  358.     currcon = con;
  359.     /* Install new colormap */
  360.     fbgen_install_cmap(con, info2);
  361.     return 0;
  362. }
  363. /**
  364.  * fbgen_blank - blank the screen
  365.  * @blank: boolean, 0 unblank, 1 blank
  366.  * @info: frame buffer info structure
  367.  *
  368.  * Blank the screen on device @info.
  369.  *
  370.  */
  371. void fbgen_blank(int blank, struct fb_info *info)
  372. {
  373.     struct fb_info_gen *info2 = (struct fb_info_gen *)info;
  374.     struct fbgen_hwswitch *fbhw = info2->fbhw;
  375.     u16 black[16];
  376.     struct fb_cmap cmap;
  377.     if (fbhw->blank && !fbhw->blank(blank, info2))
  378. return;
  379.     if (blank) {
  380. memset(black, 0, 16*sizeof(u16));
  381. cmap.red = black;
  382. cmap.green = black;
  383. cmap.blue = black;
  384. cmap.transp = NULL;
  385. cmap.start = 0;
  386. cmap.len = 16;
  387. fb_set_cmap(&cmap, 1, fbhw->setcolreg, info);
  388.     } else
  389. fbgen_install_cmap(currcon, info2);
  390. }
  391. MODULE_LICENSE("GPL");
  392.     /*
  393.      *  Visible symbols for modules
  394.      */
  395. EXPORT_SYMBOL(fbgen_get_var);
  396. EXPORT_SYMBOL(fbgen_get_cmap);
  397. EXPORT_SYMBOL(fbgen_get_fix);
  398. EXPORT_SYMBOL(fbgen_set_var);
  399. EXPORT_SYMBOL(fbgen_set_cmap);
  400. EXPORT_SYMBOL(fbgen_set_disp);
  401. EXPORT_SYMBOL(fbgen_install_cmap);
  402. EXPORT_SYMBOL(fbgen_pan_display);
  403. EXPORT_SYMBOL(fbgen_update_var);
  404. EXPORT_SYMBOL(fbgen_do_set_var);
  405. EXPORT_SYMBOL(fbgen_switch);
  406. EXPORT_SYMBOL(fbgen_blank);