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