0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/slab.h>
0013 #include <linux/string.h>
0014 #include <linux/fb.h>
0015 #include <linux/vt_kern.h>
0016 #include <linux/console.h>
0017 #include <asm/types.h>
0018 #include "fbcon.h"
0019 #include "fbcon_rotate.h"
0020
0021 static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
0022 {
0023 struct fbcon_ops *ops = info->fbcon_par;
0024 int len, err = 0;
0025 int s_cellsize, d_cellsize, i;
0026 const u8 *src;
0027 u8 *dst;
0028
0029 if (vc->vc_font.data == ops->fontdata &&
0030 ops->p->con_rotate == ops->cur_rotate)
0031 goto finished;
0032
0033 src = ops->fontdata = vc->vc_font.data;
0034 ops->cur_rotate = ops->p->con_rotate;
0035 len = vc->vc_font.charcount;
0036 s_cellsize = ((vc->vc_font.width + 7)/8) *
0037 vc->vc_font.height;
0038 d_cellsize = s_cellsize;
0039
0040 if (ops->rotate == FB_ROTATE_CW ||
0041 ops->rotate == FB_ROTATE_CCW)
0042 d_cellsize = ((vc->vc_font.height + 7)/8) *
0043 vc->vc_font.width;
0044
0045 if (info->fbops->fb_sync)
0046 info->fbops->fb_sync(info);
0047
0048 if (ops->fd_size < d_cellsize * len) {
0049 dst = kmalloc_array(len, d_cellsize, GFP_KERNEL);
0050
0051 if (dst == NULL) {
0052 err = -ENOMEM;
0053 goto finished;
0054 }
0055
0056 ops->fd_size = d_cellsize * len;
0057 kfree(ops->fontbuffer);
0058 ops->fontbuffer = dst;
0059 }
0060
0061 dst = ops->fontbuffer;
0062 memset(dst, 0, ops->fd_size);
0063
0064 switch (ops->rotate) {
0065 case FB_ROTATE_UD:
0066 for (i = len; i--; ) {
0067 rotate_ud(src, dst, vc->vc_font.width,
0068 vc->vc_font.height);
0069
0070 src += s_cellsize;
0071 dst += d_cellsize;
0072 }
0073 break;
0074 case FB_ROTATE_CW:
0075 for (i = len; i--; ) {
0076 rotate_cw(src, dst, vc->vc_font.width,
0077 vc->vc_font.height);
0078 src += s_cellsize;
0079 dst += d_cellsize;
0080 }
0081 break;
0082 case FB_ROTATE_CCW:
0083 for (i = len; i--; ) {
0084 rotate_ccw(src, dst, vc->vc_font.width,
0085 vc->vc_font.height);
0086 src += s_cellsize;
0087 dst += d_cellsize;
0088 }
0089 break;
0090 }
0091
0092 finished:
0093 return err;
0094 }
0095
0096 void fbcon_set_rotate(struct fbcon_ops *ops)
0097 {
0098 ops->rotate_font = fbcon_rotate_font;
0099
0100 switch(ops->rotate) {
0101 case FB_ROTATE_CW:
0102 fbcon_rotate_cw(ops);
0103 break;
0104 case FB_ROTATE_UD:
0105 fbcon_rotate_ud(ops);
0106 break;
0107 case FB_ROTATE_CCW:
0108 fbcon_rotate_ccw(ops);
0109 break;
0110 }
0111 }