16104c370SDaniel Vetter /*
26104c370SDaniel Vetter * linux/drivers/video/console/fbcon_rotate.c -- Software Rotation
36104c370SDaniel Vetter *
46104c370SDaniel Vetter * Copyright (C) 2005 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/slab.h>
136104c370SDaniel Vetter #include <linux/string.h>
146104c370SDaniel Vetter #include <linux/fb.h>
156104c370SDaniel Vetter #include <linux/vt_kern.h>
166104c370SDaniel Vetter #include <linux/console.h>
176104c370SDaniel Vetter #include <asm/types.h>
186104c370SDaniel Vetter #include "fbcon.h"
196104c370SDaniel Vetter #include "fbcon_rotate.h"
206104c370SDaniel Vetter
fbcon_rotate_font(struct fb_info * info,struct vc_data * vc)216104c370SDaniel Vetter static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
226104c370SDaniel Vetter {
236104c370SDaniel Vetter struct fbcon_ops *ops = info->fbcon_par;
246104c370SDaniel Vetter int len, err = 0;
256104c370SDaniel Vetter int s_cellsize, d_cellsize, i;
266104c370SDaniel Vetter const u8 *src;
276104c370SDaniel Vetter u8 *dst;
286104c370SDaniel Vetter
296104c370SDaniel Vetter if (vc->vc_font.data == ops->fontdata &&
306104c370SDaniel Vetter ops->p->con_rotate == ops->cur_rotate)
316104c370SDaniel Vetter goto finished;
326104c370SDaniel Vetter
336104c370SDaniel Vetter src = ops->fontdata = vc->vc_font.data;
346104c370SDaniel Vetter ops->cur_rotate = ops->p->con_rotate;
35*a1ac250aSPeilin Ye len = vc->vc_font.charcount;
366104c370SDaniel Vetter s_cellsize = ((vc->vc_font.width + 7)/8) *
376104c370SDaniel Vetter vc->vc_font.height;
386104c370SDaniel Vetter d_cellsize = s_cellsize;
396104c370SDaniel Vetter
406104c370SDaniel Vetter if (ops->rotate == FB_ROTATE_CW ||
416104c370SDaniel Vetter ops->rotate == FB_ROTATE_CCW)
426104c370SDaniel Vetter d_cellsize = ((vc->vc_font.height + 7)/8) *
436104c370SDaniel Vetter vc->vc_font.width;
446104c370SDaniel Vetter
456104c370SDaniel Vetter if (info->fbops->fb_sync)
466104c370SDaniel Vetter info->fbops->fb_sync(info);
476104c370SDaniel Vetter
486104c370SDaniel Vetter if (ops->fd_size < d_cellsize * len) {
496da2ec56SKees Cook dst = kmalloc_array(len, d_cellsize, GFP_KERNEL);
506104c370SDaniel Vetter
516104c370SDaniel Vetter if (dst == NULL) {
526104c370SDaniel Vetter err = -ENOMEM;
536104c370SDaniel Vetter goto finished;
546104c370SDaniel Vetter }
556104c370SDaniel Vetter
566104c370SDaniel Vetter ops->fd_size = d_cellsize * len;
576104c370SDaniel Vetter kfree(ops->fontbuffer);
586104c370SDaniel Vetter ops->fontbuffer = dst;
596104c370SDaniel Vetter }
606104c370SDaniel Vetter
616104c370SDaniel Vetter dst = ops->fontbuffer;
626104c370SDaniel Vetter memset(dst, 0, ops->fd_size);
636104c370SDaniel Vetter
646104c370SDaniel Vetter switch (ops->rotate) {
656104c370SDaniel Vetter case FB_ROTATE_UD:
666104c370SDaniel Vetter for (i = len; i--; ) {
676104c370SDaniel Vetter rotate_ud(src, dst, vc->vc_font.width,
686104c370SDaniel Vetter vc->vc_font.height);
696104c370SDaniel Vetter
706104c370SDaniel Vetter src += s_cellsize;
716104c370SDaniel Vetter dst += d_cellsize;
726104c370SDaniel Vetter }
736104c370SDaniel Vetter break;
746104c370SDaniel Vetter case FB_ROTATE_CW:
756104c370SDaniel Vetter for (i = len; i--; ) {
766104c370SDaniel Vetter rotate_cw(src, dst, vc->vc_font.width,
776104c370SDaniel Vetter vc->vc_font.height);
786104c370SDaniel Vetter src += s_cellsize;
796104c370SDaniel Vetter dst += d_cellsize;
806104c370SDaniel Vetter }
816104c370SDaniel Vetter break;
826104c370SDaniel Vetter case FB_ROTATE_CCW:
836104c370SDaniel Vetter for (i = len; i--; ) {
846104c370SDaniel Vetter rotate_ccw(src, dst, vc->vc_font.width,
856104c370SDaniel Vetter vc->vc_font.height);
866104c370SDaniel Vetter src += s_cellsize;
876104c370SDaniel Vetter dst += d_cellsize;
886104c370SDaniel Vetter }
896104c370SDaniel Vetter break;
906104c370SDaniel Vetter }
916104c370SDaniel Vetter
926104c370SDaniel Vetter finished:
936104c370SDaniel Vetter return err;
946104c370SDaniel Vetter }
956104c370SDaniel Vetter
fbcon_set_rotate(struct fbcon_ops * ops)966104c370SDaniel Vetter void fbcon_set_rotate(struct fbcon_ops *ops)
976104c370SDaniel Vetter {
986104c370SDaniel Vetter ops->rotate_font = fbcon_rotate_font;
996104c370SDaniel Vetter
1006104c370SDaniel Vetter switch(ops->rotate) {
1016104c370SDaniel Vetter case FB_ROTATE_CW:
1026104c370SDaniel Vetter fbcon_rotate_cw(ops);
1036104c370SDaniel Vetter break;
1046104c370SDaniel Vetter case FB_ROTATE_UD:
1056104c370SDaniel Vetter fbcon_rotate_ud(ops);
1066104c370SDaniel Vetter break;
1076104c370SDaniel Vetter case FB_ROTATE_CCW:
1086104c370SDaniel Vetter fbcon_rotate_ccw(ops);
1096104c370SDaniel Vetter break;
1106104c370SDaniel Vetter }
1116104c370SDaniel Vetter }
112