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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/video/cfb16.c -- Low level frame buffer operations for 16 bpp
  3.  *    truecolor packed pixels
  4.  *
  5.  * Created 5 Apr 1997 by Geert Uytterhoeven
  6.  *
  7.  *  This file is subject to the terms and conditions of the GNU General Public
  8.  *  License.  See the file COPYING in the main directory of this archive for
  9.  *  more details.
  10.  */
  11. #include <linux/module.h>
  12. #include <linux/tty.h>
  13. #include <linux/console.h>
  14. #include <linux/string.h>
  15. #include <linux/fb.h>
  16. #include <asm/io.h>
  17. #include <video/fbcon.h>
  18. #include <video/fbcon-cfb16.h>
  19.     /*
  20.      *  16 bpp packed pixels
  21.      */
  22. static u32 tab_cfb16[] = {
  23. #if defined(__BIG_ENDIAN)
  24.     0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
  25. #elif defined(__LITTLE_ENDIAN)
  26.     0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
  27. #else
  28. #error FIXME: No endianness??
  29. #endif
  30. };
  31. void fbcon_cfb16_setup(struct display *p)
  32. {
  33.     p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1;
  34.     p->next_plane = 0;
  35. }
  36. void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, int dx,
  37.        int height, int width)
  38. {
  39.     int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
  40.     u8 *src, *dst;
  41.     if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes) {
  42. fb_memmove(p->screen_base + dy * linesize,
  43.   p->screen_base + sy * linesize,
  44.   height * linesize);
  45. return;
  46.     }
  47.     if (fontwidthlog(p)) {
  48. sx <<= fontwidthlog(p)+1;
  49. dx <<= fontwidthlog(p)+1;
  50. width <<= fontwidthlog(p)+1;
  51.     } else {
  52. sx *= fontwidth(p)*2;
  53. dx *= fontwidth(p)*2;
  54. width *= fontwidth(p)*2;
  55.     }
  56.     if (dy < sy || (dy == sy && dx < sx)) {
  57. src = p->screen_base + sy * linesize + sx;
  58. dst = p->screen_base + dy * linesize + dx;
  59. for (rows = height * fontheight(p); rows--;) {
  60.     fb_memmove(dst, src, width);
  61.     src += bytes;
  62.     dst += bytes;
  63. }
  64.     } else {
  65. src = p->screen_base + (sy+height) * linesize + sx - bytes;
  66. dst = p->screen_base + (dy+height) * linesize + dx - bytes;
  67. for (rows = height * fontheight(p); rows--;) {
  68.     fb_memmove(dst, src, width);
  69.     src -= bytes;
  70.     dst -= bytes;
  71. }
  72.     }
  73. }
  74. static inline void rectfill(u8 *dest, int width, int height, u32 data,
  75.     int linesize)
  76. {
  77.     int i;
  78.     data |= data<<16;
  79.     while (height-- > 0) {
  80. u32 *p = (u32 *)dest;
  81. for (i = 0; i < width/4; i++) {
  82.     fb_writel(data, p++);
  83.     fb_writel(data, p++);
  84. }
  85. if (width & 2)
  86.     fb_writel(data, p++);
  87. if (width & 1)
  88.     fb_writew(data, (u16*)p);
  89. dest += linesize;
  90.     }
  91. }
  92. void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, int sx,
  93.        int height, int width)
  94. {
  95.     u8 *dest;
  96.     int bytes = p->next_line, lines = height * fontheight(p);
  97.     u32 bgx;
  98.     dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2;
  99.     bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
  100.     width *= fontwidth(p)/4;
  101.     if (width * 8 == bytes)
  102. rectfill(dest, lines * width * 4, 1, bgx, bytes);
  103.     else
  104. rectfill(dest, width * 4, lines, bgx, bytes);
  105. }
  106. void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy,
  107.       int xx)
  108. {
  109.     u8 *dest, *cdat, bits;
  110.     int bytes = p->next_line, rows;
  111.     u32 eorx, fgx, bgx;
  112.     dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
  113.     fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
  114.     bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
  115.     fgx |= (fgx << 16);
  116.     bgx |= (bgx << 16);
  117.     eorx = fgx ^ bgx;
  118.     switch (fontwidth(p)) {
  119.     case 4:
  120.     case 8:
  121. cdat = p->fontdata + (c & p->charmask) * fontheight(p);
  122. for (rows = fontheight(p); rows--; dest += bytes) {
  123.     bits = *cdat++;
  124.     fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest);
  125.     fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4);
  126.     if (fontwidth(p) == 8) {
  127. fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8);
  128. fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12);
  129.     }
  130. }
  131. break;
  132.     case 12:
  133.     case 16:
  134. cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
  135. for (rows = fontheight(p); rows--; dest += bytes) {
  136.     bits = *cdat++;
  137.     fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest);
  138.     fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4);
  139.     fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8);
  140.     fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12);
  141.     bits = *cdat++;
  142.     fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest+16);
  143.     fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+20);
  144.     if (fontwidth(p) == 16) {
  145. fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+24);
  146. fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+28);
  147.     }
  148. }
  149. break;
  150.     }
  151. }
  152. void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
  153.        const unsigned short *s, int count, int yy, int xx)
  154. {
  155.     u8 *cdat, *dest, *dest0;
  156.     u16 c;
  157.     int rows, bytes = p->next_line;
  158.     u32 eorx, fgx, bgx;
  159.     dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
  160.     c = scr_readw(s);
  161.     fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
  162.     bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
  163.     fgx |= (fgx << 16);
  164.     bgx |= (bgx << 16);
  165.     eorx = fgx ^ bgx;
  166.     switch (fontwidth(p)) {
  167.     case 4:
  168.     case 8:
  169. while (count--) {
  170.     c = scr_readw(s++) & p->charmask;
  171.     cdat = p->fontdata + c * fontheight(p);
  172.     for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
  173. u8 bits = *cdat++;
  174.         fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest);
  175.         fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4);
  176. if (fontwidth(p) == 8) {
  177.     fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8);
  178.     fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12);
  179. }
  180.     }
  181.     dest0 += fontwidth(p)*2;;
  182. }
  183. break;
  184.     case 12:
  185.     case 16:
  186. while (count--) {
  187.     c = scr_readw(s++) & p->charmask;
  188.     cdat = p->fontdata + (c * fontheight(p) << 1);
  189.     for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
  190. u8 bits = *cdat++;
  191.         fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest);
  192.         fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4);
  193.         fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8);
  194.         fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12);
  195. bits = *cdat++;
  196.         fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest+16);
  197.         fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+20);
  198. if (fontwidth(p) == 16) {
  199.     fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+24);
  200.     fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+28);
  201. }
  202.     }
  203.     dest0 += fontwidth(p)*2;
  204. }
  205. break;
  206.     }
  207. }
  208. void fbcon_cfb16_revc(struct display *p, int xx, int yy)
  209. {
  210.     u8 *dest;
  211.     int bytes = p->next_line, rows;
  212.     dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2;
  213.     for (rows = fontheight(p); rows--; dest += bytes) {
  214. switch (fontwidth(p)) {
  215. case 16:
  216.     fb_writel(fb_readl(dest+24) ^ 0xffffffff, dest+24);
  217.     fb_writel(fb_readl(dest+28) ^ 0xffffffff, dest+28);
  218.     /* FALL THROUGH */
  219. case 12:
  220.     fb_writel(fb_readl(dest+16) ^ 0xffffffff, dest+16);
  221.     fb_writel(fb_readl(dest+20) ^ 0xffffffff, dest+20);
  222.     /* FALL THROUGH */
  223. case 8:
  224.     fb_writel(fb_readl(dest+8) ^ 0xffffffff, dest+8);
  225.     fb_writel(fb_readl(dest+12) ^ 0xffffffff, dest+12);
  226.     /* FALL THROUGH */
  227. case 4:
  228.     fb_writel(fb_readl(dest+0) ^ 0xffffffff, dest+0);
  229.     fb_writel(fb_readl(dest+4) ^ 0xffffffff, dest+4);
  230. }
  231.     }
  232. }
  233. void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p,
  234.        int bottom_only)
  235. {
  236.     int bytes = p->next_line;
  237.     u32 bgx;
  238.     unsigned int right_start = conp->vc_cols*fontwidth(p);
  239.     unsigned int bottom_start = conp->vc_rows*fontheight(p);
  240.     unsigned int right_width, bottom_width;
  241.     bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
  242.     if (!bottom_only && (right_width = p->var.xres-right_start))
  243. rectfill(p->screen_base+right_start*2, right_width,
  244.  p->var.yres_virtual, bgx, bytes);
  245.     if ((bottom_width = p->var.yres-bottom_start))
  246. rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
  247.  right_start, bottom_width, bgx, bytes);
  248. }
  249.     /*
  250.      *  `switch' for the low level operations
  251.      */
  252. struct display_switch fbcon_cfb16 = {
  253.     setup: fbcon_cfb16_setup,
  254.     bmove: fbcon_cfb16_bmove,
  255.     clear: fbcon_cfb16_clear,
  256.     putc: fbcon_cfb16_putc,
  257.     putcs: fbcon_cfb16_putcs,
  258.     revc: fbcon_cfb16_revc,
  259.     clear_margins: fbcon_cfb16_clear_margins,
  260.     fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
  261. };
  262. #ifdef MODULE
  263. MODULE_LICENSE("GPL");
  264. int init_module(void)
  265. {
  266.     return 0;
  267. }
  268. void cleanup_module(void)
  269. {}
  270. #endif /* MODULE */
  271.     /*
  272.      *  Visible symbols for modules
  273.      */
  274. EXPORT_SYMBOL(fbcon_cfb16);
  275. EXPORT_SYMBOL(fbcon_cfb16_setup);
  276. EXPORT_SYMBOL(fbcon_cfb16_bmove);
  277. EXPORT_SYMBOL(fbcon_cfb16_clear);
  278. EXPORT_SYMBOL(fbcon_cfb16_putc);
  279. EXPORT_SYMBOL(fbcon_cfb16_putcs);
  280. EXPORT_SYMBOL(fbcon_cfb16_revc);
  281. EXPORT_SYMBOL(fbcon_cfb16_clear_margins);