16104c370SDaniel Vetter /*
26104c370SDaniel Vetter  *  linux/drivers/video/console/tileblit.c -- Tile Blitting Operation
36104c370SDaniel Vetter  *
46104c370SDaniel Vetter  *      Copyright (C) 2004 Antonino Daplas <adaplas @pol.net>
56104c370SDaniel Vetter  *
66104c370SDaniel Vetter  *  This file is subject to the terms and conditions of the GNU General Public
76104c370SDaniel Vetter  *  License.  See the file COPYING in the main directory of this archive for
86104c370SDaniel Vetter  *  more details.
96104c370SDaniel Vetter  */
106104c370SDaniel Vetter 
116104c370SDaniel Vetter #include <linux/module.h>
126104c370SDaniel Vetter #include <linux/string.h>
136104c370SDaniel Vetter #include <linux/fb.h>
146104c370SDaniel Vetter #include <linux/vt_kern.h>
156104c370SDaniel Vetter #include <linux/console.h>
166104c370SDaniel Vetter #include <asm/types.h>
176104c370SDaniel Vetter #include "fbcon.h"
186104c370SDaniel Vetter 
tile_bmove(struct vc_data * vc,struct fb_info * info,int sy,int sx,int dy,int dx,int height,int width)196104c370SDaniel Vetter static void tile_bmove(struct vc_data *vc, struct fb_info *info, int sy,
206104c370SDaniel Vetter 		       int sx, int dy, int dx, int height, int width)
216104c370SDaniel Vetter {
226104c370SDaniel Vetter 	struct fb_tilearea area;
236104c370SDaniel Vetter 
246104c370SDaniel Vetter 	area.sx = sx;
256104c370SDaniel Vetter 	area.sy = sy;
266104c370SDaniel Vetter 	area.dx = dx;
276104c370SDaniel Vetter 	area.dy = dy;
286104c370SDaniel Vetter 	area.height = height;
296104c370SDaniel Vetter 	area.width = width;
306104c370SDaniel Vetter 
316104c370SDaniel Vetter 	info->tileops->fb_tilecopy(info, &area);
326104c370SDaniel Vetter }
336104c370SDaniel Vetter 
tile_clear(struct vc_data * vc,struct fb_info * info,int sy,int sx,int height,int width)346104c370SDaniel Vetter static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy,
356104c370SDaniel Vetter 		       int sx, int height, int width)
366104c370SDaniel Vetter {
376104c370SDaniel Vetter 	struct fb_tilerect rect;
386104c370SDaniel Vetter 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
396104c370SDaniel Vetter 	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
406104c370SDaniel Vetter 
416104c370SDaniel Vetter 	rect.index = vc->vc_video_erase_char &
426104c370SDaniel Vetter 		((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
436104c370SDaniel Vetter 	rect.fg = attr_fgcol_ec(fgshift, vc, info);
446104c370SDaniel Vetter 	rect.bg = attr_bgcol_ec(bgshift, vc, info);
456104c370SDaniel Vetter 	rect.sx = sx;
466104c370SDaniel Vetter 	rect.sy = sy;
476104c370SDaniel Vetter 	rect.width = width;
486104c370SDaniel Vetter 	rect.height = height;
496104c370SDaniel Vetter 	rect.rop = ROP_COPY;
506104c370SDaniel Vetter 
516104c370SDaniel Vetter 	info->tileops->fb_tilefill(info, &rect);
526104c370SDaniel Vetter }
536104c370SDaniel Vetter 
tile_putcs(struct vc_data * vc,struct fb_info * info,const unsigned short * s,int count,int yy,int xx,int fg,int bg)546104c370SDaniel Vetter static void tile_putcs(struct vc_data *vc, struct fb_info *info,
556104c370SDaniel Vetter 		       const unsigned short *s, int count, int yy, int xx,
566104c370SDaniel Vetter 		       int fg, int bg)
576104c370SDaniel Vetter {
586104c370SDaniel Vetter 	struct fb_tileblit blit;
596104c370SDaniel Vetter 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
606104c370SDaniel Vetter 	int size = sizeof(u32) * count, i;
616104c370SDaniel Vetter 
626104c370SDaniel Vetter 	blit.sx = xx;
636104c370SDaniel Vetter 	blit.sy = yy;
646104c370SDaniel Vetter 	blit.width = count;
656104c370SDaniel Vetter 	blit.height = 1;
666104c370SDaniel Vetter 	blit.fg = fg;
676104c370SDaniel Vetter 	blit.bg = bg;
686104c370SDaniel Vetter 	blit.length = count;
696104c370SDaniel Vetter 	blit.indices = (u32 *) fb_get_buffer_offset(info, &info->pixmap, size);
706104c370SDaniel Vetter 	for (i = 0; i < count; i++)
716104c370SDaniel Vetter 		blit.indices[i] = (u32)(scr_readw(s++) & charmask);
726104c370SDaniel Vetter 
736104c370SDaniel Vetter 	info->tileops->fb_tileblit(info, &blit);
746104c370SDaniel Vetter }
756104c370SDaniel Vetter 
tile_clear_margins(struct vc_data * vc,struct fb_info * info,int color,int bottom_only)766104c370SDaniel Vetter static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
7774c1c8b3SDavid Lechner 			       int color, int bottom_only)
786104c370SDaniel Vetter {
796104c370SDaniel Vetter 	return;
806104c370SDaniel Vetter }
816104c370SDaniel Vetter 
tile_cursor(struct vc_data * vc,struct fb_info * info,int mode,int fg,int bg)826104c370SDaniel Vetter static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
8306a0df4dSLinus Torvalds 			int fg, int bg)
846104c370SDaniel Vetter {
856104c370SDaniel Vetter 	struct fb_tilecursor cursor;
86c0e4b3adSJiri Slaby 	int use_sw = vc->vc_cursor_type & CUR_SW;
876104c370SDaniel Vetter 
8828bc24fcSJiri Slaby 	cursor.sx = vc->state.x;
8928bc24fcSJiri Slaby 	cursor.sy = vc->state.y;
906104c370SDaniel Vetter 	cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1;
916104c370SDaniel Vetter 	cursor.fg = fg;
926104c370SDaniel Vetter 	cursor.bg = bg;
936104c370SDaniel Vetter 
946104c370SDaniel Vetter 	switch (vc->vc_cursor_type & 0x0f) {
956104c370SDaniel Vetter 	case CUR_NONE:
966104c370SDaniel Vetter 		cursor.shape = FB_TILE_CURSOR_NONE;
976104c370SDaniel Vetter 		break;
986104c370SDaniel Vetter 	case CUR_UNDERLINE:
996104c370SDaniel Vetter 		cursor.shape = FB_TILE_CURSOR_UNDERLINE;
1006104c370SDaniel Vetter 		break;
1016104c370SDaniel Vetter 	case CUR_LOWER_THIRD:
1026104c370SDaniel Vetter 		cursor.shape = FB_TILE_CURSOR_LOWER_THIRD;
1036104c370SDaniel Vetter 		break;
1046104c370SDaniel Vetter 	case CUR_LOWER_HALF:
1056104c370SDaniel Vetter 		cursor.shape = FB_TILE_CURSOR_LOWER_HALF;
1066104c370SDaniel Vetter 		break;
1076104c370SDaniel Vetter 	case CUR_TWO_THIRDS:
1086104c370SDaniel Vetter 		cursor.shape = FB_TILE_CURSOR_TWO_THIRDS;
1096104c370SDaniel Vetter 		break;
1106104c370SDaniel Vetter 	case CUR_BLOCK:
1116104c370SDaniel Vetter 	default:
1126104c370SDaniel Vetter 		cursor.shape = FB_TILE_CURSOR_BLOCK;
1136104c370SDaniel Vetter 		break;
1146104c370SDaniel Vetter 	}
1156104c370SDaniel Vetter 
1166104c370SDaniel Vetter 	info->tileops->fb_tilecursor(info, &cursor);
1176104c370SDaniel Vetter }
1186104c370SDaniel Vetter 
tile_update_start(struct fb_info * info)1196104c370SDaniel Vetter static int tile_update_start(struct fb_info *info)
1206104c370SDaniel Vetter {
1216104c370SDaniel Vetter 	struct fbcon_ops *ops = info->fbcon_par;
1226104c370SDaniel Vetter 	int err;
1236104c370SDaniel Vetter 
1246104c370SDaniel Vetter 	err = fb_pan_display(info, &ops->var);
1256104c370SDaniel Vetter 	ops->var.xoffset = info->var.xoffset;
1266104c370SDaniel Vetter 	ops->var.yoffset = info->var.yoffset;
1276104c370SDaniel Vetter 	ops->var.vmode = info->var.vmode;
1286104c370SDaniel Vetter 	return err;
1296104c370SDaniel Vetter }
1306104c370SDaniel Vetter 
fbcon_set_tileops(struct vc_data * vc,struct fb_info * info)1316104c370SDaniel Vetter void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
1326104c370SDaniel Vetter {
1336104c370SDaniel Vetter 	struct fb_tilemap map;
1346104c370SDaniel Vetter 	struct fbcon_ops *ops = info->fbcon_par;
1356104c370SDaniel Vetter 
1366104c370SDaniel Vetter 	ops->bmove = tile_bmove;
1376104c370SDaniel Vetter 	ops->clear = tile_clear;
1386104c370SDaniel Vetter 	ops->putcs = tile_putcs;
1396104c370SDaniel Vetter 	ops->clear_margins = tile_clear_margins;
1406104c370SDaniel Vetter 	ops->cursor = tile_cursor;
1416104c370SDaniel Vetter 	ops->update_start = tile_update_start;
1426104c370SDaniel Vetter 
1436104c370SDaniel Vetter 	if (ops->p) {
1446104c370SDaniel Vetter 		map.width = vc->vc_font.width;
1456104c370SDaniel Vetter 		map.height = vc->vc_font.height;
1466104c370SDaniel Vetter 		map.depth = 1;
147*a1ac250aSPeilin Ye 		map.length = vc->vc_font.charcount;
1486104c370SDaniel Vetter 		map.data = ops->p->fontdata;
1496104c370SDaniel Vetter 		info->tileops->fb_settile(info, &map);
1506104c370SDaniel Vetter 	}
1516104c370SDaniel Vetter }
152