1ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas/*
2ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas *  linux/drivers/video/console/fbcon_ccw.c -- Software Rotation - 270 degrees
3ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas *
4ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas *      Copyright (C) 2005 Antonino Daplas <adaplas @pol.net>
5ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas *
6ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas *  This file is subject to the terms and conditions of the GNU General Public
7ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas *  License.  See the file COPYING in the main directory of this archive for
8ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas *  more details.
9ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas */
10ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
11ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas#include <linux/module.h>
125a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
13ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas#include <linux/string.h>
14ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas#include <linux/fb.h>
15ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas#include <linux/vt_kern.h>
16ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas#include <linux/console.h>
17ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas#include <asm/types.h>
18ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas#include "fbcon.h"
19ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas#include "fbcon_rotate.h"
20ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
21ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas/*
22ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas * Rotation 270 degrees
23ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas */
24ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
2526c5be3c750df6f8a9193d478905627ec75f7f41Denys Vlasenkostatic void ccw_update_attr(u8 *dst, u8 *src, int attribute,
26ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas				  struct vc_data *vc)
27ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas{
28ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
29ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	int width = (vc->vc_font.height + 7) >> 3;
30ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	int mod = vc->vc_font.height % 8;
31ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u8 c, msk = ~(0xff << offset), msk1 = 0;
32ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
33ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (mod)
34ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		msk <<= (8 - mod);
35ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
36ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (offset > mod)
371a9c3f78a32ddc4ec50f5da2cf2db5db6f442986Benjamin Herrenschmidt		msk1 |= 0x01;
38ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
39ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	for (i = 0; i < vc->vc_font.width; i++) {
40ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		for (j = 0; j < width; j++) {
41ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			c = *src;
42ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
43ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			if (attribute & FBCON_ATTRIBUTE_UNDERLINE) {
44ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas				if (j == width - 1)
45ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas					c |= msk;
46ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
47ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas				if (msk1 && j == width - 2)
48ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas					c |= msk1;
49ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			}
50ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
51ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			if (attribute & FBCON_ATTRIBUTE_BOLD && i)
52ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas				*(dst - width) |= c;
53ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
54ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			if (attribute & FBCON_ATTRIBUTE_REVERSE)
55ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas				c = ~c;
56ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			src++;
57ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			*dst++ = c;
58ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		}
59ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
60ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas}
61ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
62ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
63ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplasstatic void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
64ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		     int sx, int dy, int dx, int height, int width)
65ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas{
66ab767201881fec073157986c314485ab26caa4a0Antonino A. Daplas	struct fbcon_ops *ops = info->fbcon_par;
67ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	struct fb_copyarea area;
68ab767201881fec073157986c314485ab26caa4a0Antonino A. Daplas	u32 vyres = GETVYRES(ops->p->scrollmode, info);
69ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
70ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	area.sx = sy * vc->vc_font.height;
71ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	area.sy = vyres - ((sx + width) * vc->vc_font.width);
72ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	area.dx = dy * vc->vc_font.height;
73ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	area.dy = vyres - ((dx + width) * vc->vc_font.width);
74ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	area.width = height * vc->vc_font.height;
75ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	area.height  = width * vc->vc_font.width;
76ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
77ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	info->fbops->fb_copyarea(info, &area);
78ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas}
79ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
80ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplasstatic void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
81ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		     int sx, int height, int width)
82ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas{
83ab767201881fec073157986c314485ab26caa4a0Antonino A. Daplas	struct fbcon_ops *ops = info->fbcon_par;
84ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	struct fb_fillrect region;
85ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
86ab767201881fec073157986c314485ab26caa4a0Antonino A. Daplas	u32 vyres = GETVYRES(ops->p->scrollmode, info);
87ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
8891c4313206e4409871e2ddd13c29508afe1c8834Thomas Pfaff	region.color = attr_bgcol_ec(bgshift,vc,info);
89ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	region.dx = sy * vc->vc_font.height;
90ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	region.dy = vyres - ((sx + width) * vc->vc_font.width);
91ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	region.height = width * vc->vc_font.width;
92ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	region.width = height * vc->vc_font.height;
93ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	region.rop = ROP_COPY;
94ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
95ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	info->fbops->fb_fillrect(info, &region);
96ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas}
97ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
98ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplasstatic inline void ccw_putcs_aligned(struct vc_data *vc, struct fb_info *info,
99ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas				    const u16 *s, u32 attr, u32 cnt,
100ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas				    u32 d_pitch, u32 s_pitch, u32 cellsize,
101ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas				    struct fb_image *image, u8 *buf, u8 *dst)
102ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas{
103ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	struct fbcon_ops *ops = info->fbcon_par;
104ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
105ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u32 idx = (vc->vc_font.height + 7) >> 3;
106ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u8 *src;
107ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
108ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	while (cnt--) {
109ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;
110ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
111ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		if (attr) {
112ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			ccw_update_attr(buf, src, attr, vc);
113ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			src = buf;
114ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		}
115ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
116ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		if (likely(idx == 1))
117ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			__fb_pad_aligned_buffer(dst, d_pitch, src, idx,
118ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas						vc->vc_font.width);
119ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		else
120ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			fb_pad_aligned_buffer(dst, d_pitch, src, idx,
121ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas					      vc->vc_font.width);
122ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
123ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		dst += d_pitch * vc->vc_font.width;
124ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
125ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
126ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	info->fbops->fb_imageblit(info, image);
127ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas}
128ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
129ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplasstatic void ccw_putcs(struct vc_data *vc, struct fb_info *info,
130ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		      const unsigned short *s, int count, int yy, int xx,
131ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		      int fg, int bg)
132ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas{
133ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	struct fb_image image;
134ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	struct fbcon_ops *ops = info->fbcon_par;
135ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u32 width = (vc->vc_font.height + 7)/8;
136ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u32 cellsize = width * vc->vc_font.width;
137ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u32 maxcnt = info->pixmap.size/cellsize;
138ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u32 scan_align = info->pixmap.scan_align - 1;
139ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u32 buf_align = info->pixmap.buf_align - 1;
140ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u32 cnt, pitch, size;
141ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u32 attribute = get_attribute(info, scr_readw(s));
142ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u8 *dst, *buf = NULL;
143ab767201881fec073157986c314485ab26caa4a0Antonino A. Daplas	u32 vyres = GETVYRES(ops->p->scrollmode, info);
144ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
145ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (!ops->fontbuffer)
146ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		return;
147ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
148ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	image.fg_color = fg;
149ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	image.bg_color = bg;
150ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	image.dx = yy * vc->vc_font.height;
151ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	image.dy = vyres - ((xx + count) * vc->vc_font.width);
152ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	image.width = vc->vc_font.height;
153ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	image.depth = 1;
154ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
155ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (attribute) {
156ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		buf = kmalloc(cellsize, GFP_KERNEL);
157ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		if (!buf)
158ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			return;
159ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
160ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
161ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	s += count - 1;
162ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
163ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	while (count) {
164ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		if (count > maxcnt)
165ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			cnt = maxcnt;
166ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		else
167ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			cnt = count;
168ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
169ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		image.height = vc->vc_font.width * cnt;
170ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		pitch = ((image.width + 7) >> 3) + scan_align;
171ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		pitch &= ~scan_align;
172ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		size = pitch * image.height + buf_align;
173ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		size &= ~buf_align;
174ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		dst = fb_get_buffer_offset(info, &info->pixmap, size);
175ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		image.data = dst;
176ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ccw_putcs_aligned(vc, info, s, attribute, cnt, pitch,
177ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas				 width, cellsize, &image, buf, dst);
178ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		image.dy += image.height;
179ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		count -= cnt;
180ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		s -= cnt;
181ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
182ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
183ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	/* buf is always NULL except when in monochrome mode, so in this case
184ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	   it's a gain to check buf against NULL even though kfree() handles
185ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	   NULL pointers just fine */
186ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (unlikely(buf))
187ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		kfree(buf);
188ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
189ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas}
190ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
191ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplasstatic void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
192ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			     int bottom_only)
193ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas{
194ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	unsigned int cw = vc->vc_font.width;
195ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	unsigned int ch = vc->vc_font.height;
196ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	unsigned int rw = info->var.yres - (vc->vc_cols*cw);
197ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	unsigned int bh = info->var.xres - (vc->vc_rows*ch);
198ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	unsigned int bs = vc->vc_rows*ch;
199ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	struct fb_fillrect region;
200ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
201ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
20291c4313206e4409871e2ddd13c29508afe1c8834Thomas Pfaff	region.color = attr_bgcol_ec(bgshift,vc,info);
203ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	region.rop = ROP_COPY;
204ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
205ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (rw && !bottom_only) {
206ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		region.dx = 0;
207ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		region.dy = info->var.yoffset;
208ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		region.height = rw;
209ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		region.width = info->var.xres_virtual;
210ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		info->fbops->fb_fillrect(info, &region);
211ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
212ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
213ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (bh) {
214ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		region.dx = info->var.xoffset + bs;
215ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		region.dy = 0;
216ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas                region.height = info->var.yres_virtual;
217ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas                region.width = bh;
218ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		info->fbops->fb_fillrect(info, &region);
219ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
220ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas}
221ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
222b73deed32d08740bdbf5f4aab43d988e4d135d95Antonino A. Daplasstatic void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
223b73deed32d08740bdbf5f4aab43d988e4d135d95Antonino A. Daplas		       int softback_lines, int fg, int bg)
224ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas{
225ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	struct fb_cursor cursor;
226b73deed32d08740bdbf5f4aab43d988e4d135d95Antonino A. Daplas	struct fbcon_ops *ops = info->fbcon_par;
227ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
228ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	int w = (vc->vc_font.height + 7) >> 3, c;
229b73deed32d08740bdbf5f4aab43d988e4d135d95Antonino A. Daplas	int y = real_y(ops->p, vc->vc_y);
230ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	int attribute, use_sw = (vc->vc_cursor_type & 0x10);
231ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	int err = 1, dx, dy;
232ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	char *src;
233b73deed32d08740bdbf5f4aab43d988e4d135d95Antonino A. Daplas	u32 vyres = GETVYRES(ops->p->scrollmode, info);
234ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
235ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (!ops->fontbuffer)
236ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		return;
237ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
238ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.set = 0;
239ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
240ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (softback_lines) {
241ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		if (y + softback_lines >= vc->vc_rows) {
242ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			mode = CM_ERASE;
243ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			ops->cursor_flash = 0;
244ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			return;
245ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		} else
246ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			y += softback_lines;
247ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
248ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
249ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas 	c = scr_readw((u16 *) vc->vc_pos);
250ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	attribute = get_attribute(info, c);
251ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
252ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
253ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (ops->cursor_state.image.data != src ||
254ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_reset) {
255ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_state.image.data = src;
256ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    cursor.set |= FB_CUR_SETIMAGE;
257ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
258ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
259ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (attribute) {
260ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		u8 *dst;
261ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
262ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		dst = kmalloc(w * vc->vc_font.width, GFP_ATOMIC);
263ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		if (!dst)
264ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			return;
265ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		kfree(ops->cursor_data);
266ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_data = dst;
267ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ccw_update_attr(dst, src, attribute, vc);
268ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		src = dst;
269ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
270ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
271ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (ops->cursor_state.image.fg_color != fg ||
272ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_state.image.bg_color != bg ||
273ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_reset) {
274ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.image.fg_color = fg;
275ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.image.bg_color = bg;
276ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		cursor.set |= FB_CUR_SETCMAP;
277ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
278ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
279ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (ops->cursor_state.image.height != vc->vc_font.width ||
280ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_state.image.width != vc->vc_font.height ||
281ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_reset) {
282ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.image.height = vc->vc_font.width;
283ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.image.width = vc->vc_font.height;
284ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		cursor.set |= FB_CUR_SETSIZE;
285ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
286ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
287ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	dx = y * vc->vc_font.height;
288ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	dy = vyres - ((vc->vc_x + 1) * vc->vc_font.width);
289ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
290ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (ops->cursor_state.image.dx != dx ||
291ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_state.image.dy != dy ||
292ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_reset) {
293ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.image.dx = dx;
294ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.image.dy = dy;
295ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		cursor.set |= FB_CUR_SETPOS;
296ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
297ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
298ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
299ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_reset) {
300ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.hot.x = cursor.hot.y = 0;
301ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		cursor.set |= FB_CUR_SETHOT;
302ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
303ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
304ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (cursor.set & FB_CUR_SETSIZE ||
305b73deed32d08740bdbf5f4aab43d988e4d135d95Antonino A. Daplas	    vc->vc_cursor_type != ops->p->cursor_shape ||
306ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_state.mask == NULL ||
307ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	    ops->cursor_reset) {
308ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC);
309ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		int cur_height, size, i = 0;
310ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		int width = (vc->vc_font.width + 7)/8;
311ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
312ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		if (!mask)
313ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			return;
314ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
315ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		tmp = kmalloc(width * vc->vc_font.height, GFP_ATOMIC);
316ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
317ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		if (!tmp) {
318ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			kfree(mask);
319ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			return;
320ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		}
321ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
322ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		kfree(ops->cursor_state.mask);
323ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.mask = mask;
324ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
325b73deed32d08740bdbf5f4aab43d988e4d135d95Antonino A. Daplas		ops->p->cursor_shape = vc->vc_cursor_type;
326ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		cursor.set |= FB_CUR_SETSHAPE;
327ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
328b73deed32d08740bdbf5f4aab43d988e4d135d95Antonino A. Daplas		switch (ops->p->cursor_shape & CUR_HWMASK) {
329ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		case CUR_NONE:
330ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			cur_height = 0;
331ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			break;
332ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		case CUR_UNDERLINE:
333ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			cur_height = (vc->vc_font.height < 10) ? 1 : 2;
334ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			break;
335ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		case CUR_LOWER_THIRD:
336ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			cur_height = vc->vc_font.height/3;
337ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			break;
338ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		case CUR_LOWER_HALF:
339ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			cur_height = vc->vc_font.height >> 1;
340ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			break;
341ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		case CUR_TWO_THIRDS:
342ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			cur_height = (vc->vc_font.height << 1)/3;
343ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			break;
344ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		case CUR_BLOCK:
345ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		default:
346ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			cur_height = vc->vc_font.height;
347ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			break;
348ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		}
349ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
350ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		size = (vc->vc_font.height - cur_height) * width;
351ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		while (size--)
352ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			tmp[i++] = 0;
353ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		size = cur_height * width;
354ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		while (size--)
355ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas			tmp[i++] = 0xff;
356ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		memset(mask, 0, w * vc->vc_font.width);
357ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		rotate_ccw(tmp, mask, vc->vc_font.width, vc->vc_font.height);
358ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		kfree(tmp);
359ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
360ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
361ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	switch (mode) {
362ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	case CM_ERASE:
363ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.enable = 0;
364ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		break;
365ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	case CM_DRAW:
366ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	case CM_MOVE:
367ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	default:
368ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		ops->cursor_state.enable = (use_sw) ? 0 : 1;
369ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		break;
370ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	}
371ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
372ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.image.data = src;
373ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.image.fg_color = ops->cursor_state.image.fg_color;
374ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.image.bg_color = ops->cursor_state.image.bg_color;
375ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.image.dx = ops->cursor_state.image.dx;
376ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.image.dy = ops->cursor_state.image.dy;
377ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.image.height = ops->cursor_state.image.height;
378ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.image.width = ops->cursor_state.image.width;
379ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.hot.x = ops->cursor_state.hot.x;
380ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.hot.y = ops->cursor_state.hot.y;
381ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.mask = ops->cursor_state.mask;
382ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.enable = ops->cursor_state.enable;
383ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.image.depth = 1;
384ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	cursor.rop = ROP_XOR;
385ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
386ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (info->fbops->fb_cursor)
387ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		err = info->fbops->fb_cursor(info, &cursor);
388ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
389ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	if (err)
390ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas		soft_cursor(info, &cursor);
391ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
392ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->cursor_reset = 0;
393ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas}
394ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
39548afdf6eb750b6836932e4d492b90448bc68dfc0Adrian Bunkstatic int ccw_update_start(struct fb_info *info)
396ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas{
397ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	struct fbcon_ops *ops = info->fbcon_par;
398ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	u32 yoffset;
399ab767201881fec073157986c314485ab26caa4a0Antonino A. Daplas	u32 vyres = GETVYRES(ops->p->scrollmode, info);
400ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	int err;
401ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
402ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	yoffset = (vyres - info->var.yres) - ops->var.xoffset;
403ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->var.xoffset = ops->var.yoffset;
404ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->var.yoffset = yoffset;
405ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	err = fb_pan_display(info, &ops->var);
406ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->var.xoffset = info->var.xoffset;
407ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->var.yoffset = info->var.yoffset;
408ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->var.vmode = info->var.vmode;
409ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	return err;
410ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas}
411ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
412ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplasvoid fbcon_rotate_ccw(struct fbcon_ops *ops)
413ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas{
414ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->bmove = ccw_bmove;
415ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->clear = ccw_clear;
416ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->putcs = ccw_putcs;
417ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->clear_margins = ccw_clear_margins;
418ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->cursor = ccw_cursor;
419ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas	ops->update_start = ccw_update_start;
420ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas}
421ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. DaplasEXPORT_SYMBOL(fbcon_rotate_ccw);
422ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. Daplas
423ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. DaplasMODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
424ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. DaplasMODULE_DESCRIPTION("Console Rotation (270 degrees) Support");
425ed8c0e99f27451a9b980adf0de318d60e6de811fAntonino A. DaplasMODULE_LICENSE("GPL");
426