xref: /openbmc/linux/drivers/video/fbdev/core/tileblit.c (revision 4d75f5c664195b970e1cd2fd25b65b5eff257a0a)
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 
tile_bmove(struct vc_data * vc,struct fb_info * info,int sy,int sx,int dy,int dx,int height,int width)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 
tile_clear(struct vc_data * vc,struct fb_info * info,int sy,int sx,int height,int width,int fg,int bg)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 
tile_putcs(struct vc_data * vc,struct fb_info * info,const unsigned short * s,int count,int yy,int xx,int fg,int bg)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 
tile_clear_margins(struct vc_data * vc,struct fb_info * info,int color,int bottom_only)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 
tile_cursor(struct vc_data * vc,struct fb_info * info,int mode,int fg,int bg)115 static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
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 = (mode == CM_ERASE || use_sw) ? 0 : 1;
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 
tile_update_start(struct fb_info * info)152 static int tile_update_start(struct fb_info *info)
153 {
154 	struct fbcon_ops *ops = info->fbcon_par;
155 	int err;
156 
157 	err = fb_pan_display(info, &ops->var);
158 	ops->var.xoffset = info->var.xoffset;
159 	ops->var.yoffset = info->var.yoffset;
160 	ops->var.vmode = info->var.vmode;
161 	return err;
162 }
163 
fbcon_set_tileops(struct vc_data * vc,struct fb_info * info)164 void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
165 {
166 	struct fb_tilemap map;
167 	struct fbcon_ops *ops = info->fbcon_par;
168 
169 	ops->bmove = tile_bmove;
170 	ops->clear = tile_clear;
171 	ops->putcs = tile_putcs;
172 	ops->clear_margins = tile_clear_margins;
173 	ops->cursor = tile_cursor;
174 	ops->update_start = tile_update_start;
175 
176 	if (ops->p) {
177 		map.width = vc->vc_font.width;
178 		map.height = vc->vc_font.height;
179 		map.depth = 1;
180 		map.length = vc->vc_font.charcount;
181 		map.data = ops->p->fontdata;
182 		info->tileops->fb_settile(info, &map);
183 	}
184 }
185