1 /* 2 * linux/drivers/video/console/fbcon_rotate.c -- Software Rotation 3 * 4 * Copyright (C) 2005 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/slab.h> 13 #include <linux/string.h> 14 #include <linux/fb.h> 15 #include <linux/vt_kern.h> 16 #include <linux/console.h> 17 #include <asm/types.h> 18 #include "fbcon.h" 19 #include "fbcon_rotate.h" 20 21 static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc) 22 { 23 struct fbcon_ops *ops = info->fbcon_par; 24 int len, err = 0; 25 int s_cellsize, d_cellsize, i; 26 const u8 *src; 27 u8 *dst; 28 29 if (vc->vc_font.data == ops->fontdata && 30 ops->p->con_rotate == ops->cur_rotate) 31 goto finished; 32 33 src = ops->fontdata = vc->vc_font.data; 34 ops->cur_rotate = ops->p->con_rotate; 35 len = vc->vc_font.charcount; 36 s_cellsize = ((vc->vc_font.width + 7)/8) * 37 vc->vc_font.height; 38 d_cellsize = s_cellsize; 39 40 if (ops->rotate == FB_ROTATE_CW || 41 ops->rotate == FB_ROTATE_CCW) 42 d_cellsize = ((vc->vc_font.height + 7)/8) * 43 vc->vc_font.width; 44 45 if (info->fbops->fb_sync) 46 info->fbops->fb_sync(info); 47 48 if (ops->fd_size < d_cellsize * len) { 49 dst = kmalloc_array(len, d_cellsize, GFP_KERNEL); 50 51 if (dst == NULL) { 52 err = -ENOMEM; 53 goto finished; 54 } 55 56 ops->fd_size = d_cellsize * len; 57 kfree(ops->fontbuffer); 58 ops->fontbuffer = dst; 59 } 60 61 dst = ops->fontbuffer; 62 memset(dst, 0, ops->fd_size); 63 64 switch (ops->rotate) { 65 case FB_ROTATE_UD: 66 for (i = len; i--; ) { 67 rotate_ud(src, dst, vc->vc_font.width, 68 vc->vc_font.height); 69 70 src += s_cellsize; 71 dst += d_cellsize; 72 } 73 break; 74 case FB_ROTATE_CW: 75 for (i = len; i--; ) { 76 rotate_cw(src, dst, vc->vc_font.width, 77 vc->vc_font.height); 78 src += s_cellsize; 79 dst += d_cellsize; 80 } 81 break; 82 case FB_ROTATE_CCW: 83 for (i = len; i--; ) { 84 rotate_ccw(src, dst, vc->vc_font.width, 85 vc->vc_font.height); 86 src += s_cellsize; 87 dst += d_cellsize; 88 } 89 break; 90 } 91 92 finished: 93 return err; 94 } 95 96 void fbcon_set_rotate(struct fbcon_ops *ops) 97 { 98 ops->rotate_font = fbcon_rotate_font; 99 100 switch(ops->rotate) { 101 case FB_ROTATE_CW: 102 fbcon_rotate_cw(ops); 103 break; 104 case FB_ROTATE_UD: 105 fbcon_rotate_ud(ops); 106 break; 107 case FB_ROTATE_CCW: 108 fbcon_rotate_ccw(ops); 109 break; 110 } 111 } 112