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