2 * linux/drivers/video/fbcon-sti.c -- Low level frame buffer
3 * operations for generic HP video boards using STI (standard
4 * text interface) firmware
6 * Based on linux/drivers/video/fbcon-artist.c
7 * Created 5 Apr 1997 by Geert Uytterhoeven
8 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive for
14 #include <linux/module.h>
15 #include <linux/tty.h>
16 #include <linux/console.h>
17 #include <linux/string.h>
19 #include <linux/delay.h>
20 #include <asm/gsc.h> /* for gsc_read/write */
21 #include <asm/types.h>
23 #include <video/fbcon.h>
24 #include <video/fbcon-mfb.h>
26 #include "sti/sticore.h"
28 /* Translate an address as it would be found in a 2048x2048x1 bit frame
29 * buffer into a logical address Artist actually expects. Addresses fed
30 * into Artist look like this:
32 * FFFF FFFF LLLL LLLL LLLC CCCC CCCC CC00
34 * our "RAM" addresses look like this:
36 * FFFF FFFF 0000 0LLL LLLL LLLL CCCC CCCC [CCC]
44 return (unsigned long) addr;
46 u32 a = (unsigned long) addr;
50 r = a & 0xff000000; /* fixed part */
51 r += ((a & 0x000000ff) << 5);
52 r += ((a & 0x00ffff00) << 3);
54 r = a & 0xff000000; /* fixed part */
55 r += ((a & 0x000000ff) << 5);
56 r += ((a & 0x0007ff00) << 5);
63 /* All those functions need better names. */
66 memcpy_fromhp_tohp(void *dest, void *src, int count)
68 unsigned long d = ram2log(dest);
69 unsigned long s = ram2log(src);
72 count &= ~3; /* XXX */
76 gsc_writel(~gsc_readl(s), d);
84 memset_tohp(void *dest, u32 word, int count)
86 unsigned long d = ram2log(dest);
101 unsigned long s = ram2log(src);
103 return ~gsc_readb(s);
107 writeb_hp(u8 b, void *dst)
109 unsigned long d = ram2log(dst);
111 if((d&0xf0000000) != 0xf0000000) {
112 printk("writeb_hp %02x %p (%08lx) (%p)\n",
113 b, dst, d, __builtin_return_address(0));
121 fbcon_sti_setup(struct display *p)
124 p->next_line = p->line_length;
126 p->next_line = p->var.xres_virtual>>3;
131 fbcon_sti_bmove(struct display *p, int sy, int sx,
133 int height, int width)
135 #if 0 /* Unfortunately, still broken */
136 sti_bmove(default_sti /* FIXME */, sy, sx, dy, dx, height, width);
141 if (sx == 0 && dx == 0 && width == p->next_line) {
142 src = p->screen_base+sy*fontheight(p)*width;
143 dest = p->screen_base+dy*fontheight(p)*width;
144 memcpy_fromhp_tohp(dest, src, height*fontheight(p)*width);
145 } else if (dy <= sy) {
146 src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
147 dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
148 for (rows = height*fontheight(p); rows--;) {
149 memcpy_fromhp_tohp(dest, src, width);
151 dest += p->next_line;
154 src = p->screen_base+((sy+height)*fontheight(p)-1)*p->next_line+sx;
155 dest = p->screen_base+((dy+height)*fontheight(p)-1)*p->next_line+dx;
156 for (rows = height*fontheight(p); rows--;) {
157 memcpy_fromhp_tohp(dest, src, width);
159 dest -= p->next_line;
166 fbcon_sti_clear(struct vc_data *conp,
167 struct display *p, int sy, int sx,
168 int height, int width)
172 int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
174 dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
176 if (sx == 0 && width == p->next_line) {
178 memset_tohp(dest, ~0, height*fontheight(p)*width);
180 memset_tohp(dest, 0, height*fontheight(p)*width);
182 for (rows = height*fontheight(p); rows--; dest += p->next_line)
184 memset_tohp(dest, 0xffffffff, width);
186 memset_tohp(dest, 0x00000000, width);
189 static void fbcon_sti_putc(struct vc_data *conp,
190 struct display *p, int c,
194 u_int rows, bold, revs, underl;
197 dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
198 cdat = p->fontdata+(c&p->charmask)*fontheight(p);
199 bold = attr_bold(p,c);
200 revs = attr_reverse(p,c);
201 underl = attr_underline(p,c);
203 for (rows = fontheight(p); rows--; dest += p->next_line) {
215 static void fbcon_sti_putcs(struct vc_data *conp,
217 const unsigned short *s,
218 int count, int yy, int xx)
220 u8 *dest, *dest0, *cdat;
221 u_int rows, bold, revs, underl;
225 if(((unsigned)xx > 200) || ((unsigned) yy > 200)) {
226 printk("refusing to putcs %p %p %p %d %d %d (%p)\n",
227 conp, p, s, count, yy, xx, __builtin_return_address(0));
232 dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
233 if(((u32)dest0&0xf0000000)!=0xf0000000) {
234 printk("refusing to putcs %p %p %p %d %d %d (%p) %p = %p + %d * %d * %ld + %d\n",
235 conp, p, s, count, yy, xx, __builtin_return_address(0),
236 dest0, p->screen_base, yy, fontheight(p), p->next_line,
242 bold = attr_bold(p, c);
243 revs = attr_reverse(p, c);
244 underl = attr_underline(p, c);
247 c = scr_readw(s++) & p->charmask;
249 cdat = p->fontdata+c*fontheight(p);
250 for (rows = fontheight(p); rows--; dest += p->next_line) {
252 if (0 && underl && !rows)
263 static void fbcon_sti_revc(struct display *p,
270 dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
271 for (rows = fontheight(p); rows--; dest += p->next_line) {
273 writeb_hp (~d, dest);
278 fbcon_sti_clear_margins(struct vc_data *conp,
284 int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
287 /* XXX Need to handle right margin? */
289 height = p->var.yres - conp->vc_rows * fontheight(p);
292 bottom = conp->vc_rows + p->yscroll;
293 if (bottom >= p->vrows)
295 dest = p->screen_base + bottom * fontheight(p) * p->next_line;
297 memset_tohp(dest, 0xffffffff, height * p->next_line);
299 memset_tohp(dest, 0x00000000, height * p->next_line);
304 * `switch' for the low level operations
307 struct display_switch fbcon_sti = {
308 setup: fbcon_sti_setup,
309 bmove: fbcon_sti_bmove,
310 clear: fbcon_sti_clear,
311 putc: fbcon_sti_putc,
312 putcs: fbcon_sti_putcs,
313 revc: fbcon_sti_revc,
314 clear_margins: fbcon_sti_clear_margins,
315 fontwidthmask: FONTWIDTH(8)
318 MODULE_LICENSE("GPL");