25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/errno.h>
28 #include <linux/string.h>
36 #include <asm/bootinfo.h>
38 #include <asm/dec/tc.h>
40 #include <video/fbcon.h>
41 #include <video/fbcon-cfb8.h>
47 #define DRIVER_VERSION "0.02"
49 #define DRIVER_DESCRIPTION "PMAG-AA Framebuffer Driver"
58 #define PMAG_AA_BT455_OFFSET 0x100000
63 #define PMAG_AA_BT431_OFFSET 0x180000
69 #define PMAG_AA_ONBOARD_FBMEM_OFFSET 0x200000
80 #define CURSOR_TIMER_FREQ (HZ / 50)
81 #define CURSOR_BLINK_RATE (20)
82 #define CURSOR_DRAW_DELAY (2)
100 static struct aafb_par {
103 static int currcon = -1;
110 bt431_position_cursor(info->
bt431, c->
x, c->
y);
111 bt431_enable_cursor(info->
bt431);
113 bt431_erase_cursor(info->
bt431);
116 static void aafbcon_cursor(
struct display *disp,
int mode,
int x,
int y)
121 x *= fontwidth(disp);
122 y *= fontheight(disp);
129 aafb_set_cursor(info, 0);
130 c->
x = x - disp->var.xoffset;
131 c->
y = y - disp->var.yoffset;
140 aafb_set_cursor(info, c->
on);
154 if (width > 64 || height > 64 || width < 0 || height < 0)
160 bt431_set_font(info->
bt431, fgc, width, height);
165 static void aafb_cursor_timer_handler(
unsigned long data)
175 aafb_set_cursor(info, c->
on);
197 c->
timer.function = aafb_cursor_timer_handler;
208 static struct display_switch aafb_switch8 = {
209 .setup = fbcon_cfb8_setup,
210 .bmove = fbcon_cfb8_bmove,
211 .clear = fbcon_cfb8_clear,
212 .putc = fbcon_cfb8_putc,
213 .putcs = fbcon_cfb8_putcs,
214 .revc = fbcon_cfb8_revc,
215 .cursor = aafbcon_cursor,
216 .set_font = aafbcon_set_font,
217 .clear_margins = fbcon_cfb8_clear_margins,
218 .fontwidthmask = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
221 static void aafb_get_par(
struct aafb_par *par)
245 static void aafb_set_disp(
struct display *disp,
int con,
250 disp->fb_info = &info->
info;
251 aafb_set_var(&disp->var, con, &info->
info);
252 if (disp->conp && disp->conp->vc_sw && disp->conp->vc_sw->con_cursor)
253 disp->conp->vc_sw->con_cursor(disp->conp,
CM_ERASE);
254 disp->dispsw = &aafb_switch8;
255 disp->dispsw_data = 0;
257 aafb_get_fix(&fix, con, &info->
info);
259 disp->visual = fix.
visual;
260 disp->type = fix.
type;
265 disp->next_line = 2048;
266 disp->can_soft_blank = 1;
270 aafbcon_set_font(disp, fontwidth(disp), fontheight(disp));
273 static int aafb_get_cmap(
struct fb_cmap *cmap,
int kspc,
int con,
276 static u16 color[2] = {0x0000, 0x000f};
283 static int aafb_set_cmap(
struct fb_cmap *cmap,
int kspc,
int con,
290 &&
memcmp(cmap->
red, color,
sizeof(color)) == 0
292 &&
memcmp(cmap->
blue, color,
sizeof(color)) == 0
305 static int aafb_switch(
int con,
struct fb_info *info)
308 struct display *old = (currcon < 0) ? &ip->
disp : (fb_display + currcon);
309 struct display *
new = (con < 0) ? &ip->
disp : (fb_display + con);
311 if (old->conp && old->conp->vc_sw && old->conp->vc_sw->con_cursor)
312 old->conp->vc_sw->con_cursor(old->conp,
CM_ERASE);
316 aafb_set_disp(
new, con, ip);
322 struct aafb_par *par)
334 var->
red.msb_right = 0;
335 var->
green.offset = 0;
336 var->
green.length = 1;
337 var->
green.msb_right = 0;
338 var->
blue.offset = 0;
339 var->
blue.length = 0;
340 var->
blue.msb_right = 0;
343 var->
transp.msb_right = 0;
359 aafb_encode_var(var, &par);
372 aafb_encode_var(var, &par);
378 static int aafb_update_var(
int con,
struct fb_info *info)
381 struct display *disp = (con < 0) ? &ip->
disp : (fb_display + con);
391 static void aafb_blank(
int blank,
struct fb_info *info)
394 u8 val = blank ? 0x00 : 0x0f;
396 bt455_write_cmap_entry(ip->
bt455, 1, val, val, val);
400 static struct fb_ops aafb_ops = {
402 .fb_get_fix = aafb_get_fix,
403 .fb_get_var = aafb_get_var,
404 .fb_set_var = aafb_set_var,
405 .fb_get_cmap = aafb_get_cmap,
406 .fb_set_cmap = aafb_set_cmap,
407 .fb_ioctl = aafb_ioctl
412 unsigned long base_addr =
CKSEG1ADDR(get_tc_base_addr(slot));
433 ip->
info.fbops = &aafb_ops;
436 ip->
info.switch_con = &aafb_switch;
437 ip->
info.updatevar = &aafb_update_var;
438 ip->
info.blank = &aafb_blank;
440 aafb_set_disp(&ip->
disp, currcon, ip);
445 bt455_erase_cursor(ip->
bt455);
448 bt455_write_cmap_entry(ip->
bt455, 0, 0x00, 0x00, 0x00);
449 bt455_write_cmap_entry(ip->
bt455, 1, 0x0f, 0x0f, 0x0f);
452 bt431_init_cursor(ip->
bt431);
453 aafb_cursor_init(ip);
462 GET_FB_IDX(ip->
info.node), ip->
info.modename, slot);
467 static int __exit exit_one(
int slot)
485 while ((sid = search_tc_card(
"PMAG-AA")) >= 0) {
491 return found ? 0 : -
ENXIO;
494 static void __exit pmagaafb_exit(
void)
498 while ((sid = search_tc_card(
"PMAG-AA")) >= 0) {
500 release_tc_card(sid);