| 1 | |
| 2 | * linux/drivers/video/console/tileblit.c -- Tile Blitting Operation
|
| 3 | *
|
| 4 | * Copyright (C) 2004 Antonino Daplas <adaplas @pol.net>
|
| 5 | *
|
| 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 for
|
| 8 | * more details.
|
| 9 |
|
| 10 |
|
| 11 | #include <linux/module.h>
|
| 12 | #include <linux/string.h>
|
| 13 | #include <linux/fb.h>
|
| 14 | #include <linux/vt_kern.h>
|
| 15 | #include <linux/console.h>
|
| 16 | #include <asm/types.h>
|
| 17 | #include "fbcon.h"
|
| 18 |
|
| 19 | static void tile_bmove(struct vc_data *vc, struct fb_info *info, int sy,
|
| 20 | int sx, int dy, int dx, int height, int width)
|
| 21 | {
|
| 22 | struct fb_tilearea area;
|
| 23 |
|
| 24 | area.sx = sx;
|
| 25 | area.sy = sy;
|
| 26 | area.dx = dx;
|
| 27 | area.dy = dy;
|
| 28 | area.height = height;
|
| 29 | area.width = width;
|
| 30 |
|
| 31 | info->tileops->fb_tilecopy(info, &area);
|
| 32 | }
|
| 33 |
|
| 34 | static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy,
|
| 35 | int sx, int height, int width, int fg, int bg)
|
| 36 | {
|
| 37 | struct fb_tilerect rect;
|
| 38 |
|
| 39 | rect.index = vc->vc_video_erase_char &
|
| 40 | ((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
|
| 41 | rect.fg = fg;
|
| 42 | rect.bg = bg;
|
| 43 | rect.sx = sx;
|
| 44 | rect.sy = sy;
|
| 45 | rect.width = width;
|
| 46 | rect.height = height;
|
| 47 | rect.rop = ROP_COPY;
|
| 48 |
|
| 49 | info->tileops->fb_tilefill(info, &rect);
|
| 50 | }
|
| 51 |
|
| 52 | static void tile_putcs(struct vc_data *vc, struct fb_info *info,
|
| 53 | const unsigned short *s, int count, int yy, int xx,
|
| 54 | int fg, int bg)
|
| 55 | {
|
| 56 | struct fb_tileblit blit;
|
| 57 | unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
|
| 58 | int size = sizeof(u32) * count, i;
|
| 59 |
|
| 60 | blit.sx = xx;
|
| 61 | blit.sy = yy;
|
| 62 | blit.width = count;
|
| 63 | blit.height = 1;
|
| 64 | blit.fg = fg;
|
| 65 | blit.bg = bg;
|
| 66 | blit.length = count;
|
| 67 | blit.indices = (u32 *) fb_get_buffer_offset(info, &info->pixmap, size);
|
| 68 | for (i = 0; i < count; i++)
|
| 69 | blit.indices[i] = (u32)(scr_readw(s++) & charmask);
|
| 70 |
|
| 71 | info->tileops->fb_tileblit(info, &blit);
|
| 72 | }
|
| 73 |
|
| 74 | static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
|
| 75 | int color, int bottom_only)
|
| 76 | {
|
| 77 | unsigned int cw = vc->vc_font.width;
|
| 78 | unsigned int ch = vc->vc_font.height;
|
| 79 | unsigned int rw = info->var.xres - (vc->vc_cols*cw);
|
| 80 | unsigned int bh = info->var.yres - (vc->vc_rows*ch);
|
| 81 | unsigned int rs = info->var.xres - rw;
|
| 82 | unsigned int bs = info->var.yres - bh;
|
| 83 | unsigned int vwt = info->var.xres_virtual / cw;
|
| 84 | unsigned int vht = info->var.yres_virtual / ch;
|
| 85 | struct fb_tilerect rect;
|
| 86 |
|
| 87 | rect.index = vc->vc_video_erase_char &
|
| 88 | ((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
|
| 89 | rect.fg = color;
|
| 90 | rect.bg = color;
|
| 91 |
|
| 92 | if ((int) rw > 0 && !bottom_only) {
|
| 93 | rect.sx = (info->var.xoffset + rs + cw - 1) / cw;
|
| 94 | rect.sy = 0;
|
| 95 | rect.width = (rw + cw - 1) / cw;
|
| 96 | rect.height = vht;
|
| 97 | if (rect.width + rect.sx > vwt)
|
| 98 | rect.width = vwt - rect.sx;
|
| 99 | if (rect.sx < vwt)
|
| 100 | info->tileops->fb_tilefill(info, &rect);
|
| 101 | }
|
| 102 |
|
| 103 | if ((int) bh > 0) {
|
| 104 | rect.sx = info->var.xoffset / cw;
|
| 105 | rect.sy = (info->var.yoffset + bs) / ch;
|
| 106 | rect.width = rs / cw;
|
| 107 | rect.height = (bh + ch - 1) / ch;
|
| 108 | if (rect.height + rect.sy > vht)
|
| 109 | rect.height = vht - rect.sy;
|
| 110 | if (rect.sy < vht)
|
| 111 | info->tileops->fb_tilefill(info, &rect);
|
| 112 | }
|
| 113 | }
|
| 114 |
|
| 115 | static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
|
| 116 | int fg, int bg)
|
| 117 | {
|
| 118 | struct fb_tilecursor cursor;
|
| 119 | int use_sw = vc->vc_cursor_type & CUR_SW;
|
| 120 |
|
| 121 | cursor.sx = vc->state.x;
|
| 122 | cursor.sy = vc->state.y;
|
| 123 | cursor.mode = enable && !use_sw;
|
| 124 | cursor.fg = fg;
|
| 125 | cursor.bg = bg;
|
| 126 |
|
| 127 | switch (vc->vc_cursor_type & 0x0f) {
|
| 128 | case CUR_NONE:
|
| 129 | cursor.shape = FB_TILE_CURSOR_NONE;
|
| 130 | break;
|
| 131 | case CUR_UNDERLINE:
|
| 132 | cursor.shape = FB_TILE_CURSOR_UNDERLINE;
|
| 133 | break;
|
| 134 | case CUR_LOWER_THIRD:
|
| 135 | cursor.shape = FB_TILE_CURSOR_LOWER_THIRD;
|
| 136 | break;
|
| 137 | case CUR_LOWER_HALF:
|
| 138 | cursor.shape = FB_TILE_CURSOR_LOWER_HALF;
|
| 139 | break;
|
| 140 | case CUR_TWO_THIRDS:
|
| 141 | cursor.shape = FB_TILE_CURSOR_TWO_THIRDS;
|
| 142 | break;
|
| 143 | case CUR_BLOCK:
|
| 144 | default:
|
| 145 | cursor.shape = FB_TILE_CURSOR_BLOCK;
|
| 146 | break;
|
| 147 | }
|
| 148 |
|
| 149 | info->tileops->fb_tilecursor(info, &cursor);
|
| 150 | }
|
| 151 |
|
| 152 | static int tile_update_start(struct fb_info *info)
|
| 153 | {
|
| 154 | struct fbcon_par *par = info->fbcon_par;
|
| 155 | int err;
|
| 156 |
|
| 157 | err = fb_pan_display(info, &par->var);
|
| 158 | par->var.xoffset = info->var.xoffset;
|
| 159 | par->var.yoffset = info->var.yoffset;
|
| 160 | par->var.vmode = info->var.vmode;
|
| 161 | return err;
|
| 162 | }
|
| 163 |
|
| 164 | static const struct fbcon_bitops tile_fbcon_bitops = {
|
| 165 | .bmove = tile_bmove,
|
| 166 | .clear = tile_clear,
|
| 167 | .putcs = tile_putcs,
|
| 168 | .clear_margins = tile_clear_margins,
|
| 169 | .cursor = tile_cursor,
|
| 170 | .update_start = tile_update_start,
|
| 171 | };
|
| 172 |
|
| 173 | void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
|
| 174 | {
|
| 175 | struct fb_tilemap map;
|
| 176 | struct fbcon_par *par = info->fbcon_par;
|
| 177 |
|
| 178 | par->bitops = &tile_fbcon_bitops;
|
| 179 |
|
| 180 | if (par->p) {
|
| 181 | map.width = vc->vc_font.width;
|
| 182 | map.height = vc->vc_font.height;
|
| 183 | map.depth = 1;
|
| 184 | map.length = vc->vc_font.charcount;
|
| 185 | map.data = par->p->fontdata;
|
| 186 | info->tileops->fb_settile(info, &map);
|
| 187 | }
|
| 188 | }
|