2 * Linux/drivers/video/retz3fb.c -- RetinaZ3 frame buffer device
4 * Copyright (C) 1997 Jes Sorensen
6 * This file is based on the CyberVision64 frame buffer device and
7 * the generic Cirrus Logic driver.
9 * cyberfb.c: Copyright (C) 1996 Martin Apel,
11 * clgen.c: Copyright (C) 1996 Frank Neumann
14 * - 22 Jan 97: Initial work
15 * - 14 Feb 97: Screen initialization works somewhat, still only
16 * 8-bit packed pixel is supported.
18 * This file is subject to the terms and conditions of the GNU General Public
19 * License. See the file COPYING in the main directory of this archive
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/errno.h>
26 #include <linux/string.h>
28 #include <linux/tty.h>
29 #include <linux/slab.h>
30 #include <linux/delay.h>
32 #include <linux/zorro.h>
33 #include <linux/init.h>
35 #include <asm/uaccess.h>
36 #include <asm/system.h>
38 #include <asm/pgtable.h>
41 #include <video/fbcon.h>
42 #include <video/fbcon-cfb8.h>
43 #include <video/fbcon-cfb16.h>
47 /* #define DEBUG if(1) */
51 * Reserve space for one pattern line.
53 * For the time being we only support 4MB boards!
56 #define PAT_MEM_SIZE 16*3
57 #define PAT_MEM_OFF (4*1024*1024 - PAT_MEM_SIZE)
68 struct fb_bitfield red;
69 struct fb_bitfield green;
70 struct fb_bitfield blue;
71 struct fb_bitfield transp;
74 int left_margin; /* time from sync to picture */
75 int right_margin; /* time from picture to sync */
76 int upper_margin; /* time from sync to picture */
78 int hsync_len; /* length of horizontal sync */
79 int vsync_len; /* length of vertical sync */
86 long h_total; /* Horizontal Total */
87 long h_sstart; /* Horizontal Sync Start */
88 long h_sstop; /* Horizontal Sync Stop */
89 long h_bstart; /* Horizontal Blank Start */
90 long h_bstop; /* Horizontal Blank Stop */
91 long h_dispend; /* Horizontal Display End */
92 long v_total; /* Vertical Total */
93 long v_sstart; /* Vertical Sync Start */
94 long v_sstop; /* Vertical Sync Stop */
95 long v_bstart; /* Vertical Blank Start */
96 long v_bstop; /* Vertical Blank Stop */
97 long v_dispend; /* Horizontal Display End */
100 struct retz3_fb_info {
103 unsigned char *fbmem;
104 unsigned long fbsize;
105 volatile unsigned char *regs;
106 unsigned long physfbmem;
107 unsigned long physregs;
109 int current_par_valid; /* set to 0 by memset */
112 struct retz3fb_par current_par;
113 unsigned char color_table [256][3];
117 static char fontname[40] __initdata = { 0 };
119 #define retz3info(info) ((struct retz3_fb_info *)(info))
120 #define fbinfo(info) ((struct fb_info *)(info))
127 static char retz3fb_name[16] = "RetinaZ3";
131 * A small info on how to convert XFree86 timing values into fb
132 * timings - by Frank Neumann:
134 An XFree86 mode line consists of the following fields:
135 "800x600" 50 800 856 976 1040 600 637 643 666
136 < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
138 The fields in the fb_var_screeninfo structure are:
139 unsigned long pixclock; * pixel clock in ps (pico seconds) *
140 unsigned long left_margin; * time from sync to picture *
141 unsigned long right_margin; * time from picture to sync *
142 unsigned long upper_margin; * time from sync to picture *
143 unsigned long lower_margin;
144 unsigned long hsync_len; * length of horizontal sync *
145 unsigned long vsync_len; * length of vertical sync *
149 fb: In Picoseconds (ps)
151 pixclock = 1000000 / DCF
153 2) horizontal timings:
154 left_margin = HFL - SH2
155 right_margin = SH1 - HR
156 hsync_len = SH2 - SH1
159 upper_margin = VFL - SV2
160 lower_margin = SV1 - VR
161 vsync_len = SV2 - SV1
163 Good examples for VESA timings can be found in the XFree86 source tree,
164 under "programs/Xserver/hw/xfree86/doc/modeDB.txt".
168 * Predefined Video Modes
173 struct fb_var_screeninfo var;
174 } retz3fb_predefined[] __initdata = {
176 * NB: it is very important to adjust the pixel-clock to the color-depth.
180 "640x480", { /* 640x480, 8 bpp */
181 640, 480, 640, 480, 0, 0, 8, 0,
182 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
183 0, 0, -1, -1, FB_ACCEL_NONE, 39722, 48, 16, 33, 10, 96, 2,
184 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
188 ModeLine "800x600" 36 800 824 896 1024 600 601 603 625
189 < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
192 "800x600", { /* 800x600, 8 bpp */
193 800, 600, 800, 600, 0, 0, 8, 0,
194 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
195 0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 120, 2,
196 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
200 "800x600-60", { /* 800x600, 8 bpp */
201 800, 600, 800, 600, 0, 0, 8, 0,
202 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
203 0, 0, -1, -1, FB_ACCELF_TEXT, 25000, 88, 40, 23, 1, 128, 4,
204 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
208 "800x600-70", { /* 800x600, 8 bpp */
209 800, 600, 800, 600, 0, 0, 8, 0,
210 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
211 0, 0, -1, -1, FB_ACCELF_TEXT, 22272, 40, 24, 15, 9, 144, 12,
212 FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED
216 ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
217 < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
220 "1024x768i", { /* 1024x768, 8 bpp, interlaced */
221 1024, 768, 1024, 768, 0, 0, 8, 0,
222 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
223 0, 0, -1, -1, FB_ACCELF_TEXT, 22222, 40, 40, 32, 9, 160, 8,
224 FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED
229 1024, 768, 1024, 768, 0, 0, 8, 0,
230 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
231 0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
232 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
236 "640x480-16", { /* 640x480, 16 bpp */
237 640, 480, 640, 480, 0, 0, 16, 0,
238 {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
239 0, 0, -1, -1, 0, 38461/2, 28, 32, 12, 10, 96, 2,
240 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
244 "640x480-24", { /* 640x480, 24 bpp */
245 640, 480, 640, 480, 0, 0, 24, 0,
246 {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0},
247 0, 0, -1, -1, 0, 38461/3, 28, 32, 12, 10, 96, 2,
248 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
254 #define NUM_TOTAL_MODES ARRAY_SIZE(retz3fb_predefined)
256 static struct fb_var_screeninfo retz3fb_default;
258 static int z3fb_inverse = 0;
259 static int z3fb_mode __initdata = 0;
263 * Interface used by the world
266 int retz3fb_setup(char *options);
268 static int retz3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
269 struct fb_info *info);
270 static int retz3fb_get_var(struct fb_var_screeninfo *var, int con,
271 struct fb_info *info);
272 static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
273 struct fb_info *info);
274 static int retz3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
275 struct fb_info *info);
276 static int retz3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
277 struct fb_info *info);
281 * Interface to the low level console driver
284 int retz3fb_init(void);
285 static int z3fb_switch(int con, struct fb_info *info);
286 static int z3fb_updatevar(int con, struct fb_info *info);
287 static void z3fb_blank(int blank, struct fb_info *info);
291 * Text console acceleration
294 #ifdef FBCON_HAS_CFB8
295 static struct display_switch fbcon_retz3_8;
300 * Accelerated Functions used by the low level console driver
303 static void retz3_bitblt(struct display *p,
304 unsigned short curx, unsigned short cury, unsigned
305 short destx, unsigned short desty, unsigned short
306 width, unsigned short height, unsigned short cmd,
307 unsigned short mask);
310 * Hardware Specific Routines
313 static int retz3_encode_fix(struct fb_info *info,
314 struct fb_fix_screeninfo *fix,
315 struct retz3fb_par *par);
316 static int retz3_decode_var(struct fb_var_screeninfo *var,
317 struct retz3fb_par *par);
318 static int retz3_encode_var(struct fb_var_screeninfo *var,
319 struct retz3fb_par *par);
320 static int retz3_getcolreg(unsigned int regno, unsigned int *red,
321 unsigned int *green, unsigned int *blue,
322 unsigned int *transp, struct fb_info *info);
323 static int retz3_setcolreg(unsigned int regno, unsigned int red,
324 unsigned int green, unsigned int blue,
325 unsigned int transp, struct fb_info *info);
331 static void retz3fb_get_par(struct fb_info *info, struct retz3fb_par *par);
332 static void retz3fb_set_par(struct fb_info *info, struct retz3fb_par *par);
333 static int do_fb_set_var(struct fb_info *info,
334 struct fb_var_screeninfo *var, int isactive);
335 static void do_install_cmap(int con, struct fb_info *info);
336 static void retz3fb_set_disp(int con, struct fb_info *info);
337 static int get_video_mode(const char *name);
340 /* -------------------- Hardware specific routines ------------------------- */
342 static unsigned short find_fq(unsigned int freq)
346 long prev = 0x7fffffff;
349 unsigned short res = 0;
351 if (freq <= 31250000)
353 else if (freq <= 62500000)
355 else if (freq <= 125000000)
357 else if (freq <= 250000000)
364 f = freq >> (10 - n2);
366 m = (f * n1) / (14318180/1024);
371 tmp = (((m * 14318180) >> n2) / n1) - freq;
377 res = (((n2 << 5) | (n1-2)) << 8) | (m-2);
380 } while ( (++n1) <= 21);
386 static int retz3_set_video(struct fb_info *info,
387 struct fb_var_screeninfo *var,
388 struct retz3fb_par *par)
390 volatile unsigned char *regs = retz3info(info)->regs;
393 int xres, hfront, hsync, hback;
394 int yres, vfront, vsync, vback;
396 unsigned short best_freq;
397 struct display_data data;
399 short clocksel = 0; /* Apparantly this is always zero */
401 int bpp = var->bits_per_pixel;
409 if ((bpp != 8) && (bpp != 16) && (bpp != 24))
415 xres = var->xres * bpp / 4;
416 hfront = var->right_margin * bpp / 4;
417 hsync = var->hsync_len * bpp / 4;
418 hback = var->left_margin * bpp / 4;
420 if (var->vmode & FB_VMODE_DOUBLE)
422 yres = var->yres * 2;
423 vfront = var->lower_margin * 2;
424 vsync = var->vsync_len * 2;
425 vback = var->upper_margin * 2;
427 else if (var->vmode & FB_VMODE_INTERLACED)
429 yres = (var->yres + 1) / 2;
430 vfront = (var->lower_margin + 1) / 2;
431 vsync = (var->vsync_len + 1) / 2;
432 vback = (var->upper_margin + 1) / 2;
436 yres = var->yres; /* -1 ? */
437 vfront = var->lower_margin;
438 vsync = var->vsync_len;
439 vback = var->upper_margin;
442 data.h_total = (hback / 8) + (xres / 8)
443 + (hfront / 8) + (hsync / 8) - 1 /* + 1 */;
444 data.h_dispend = ((xres + bpp - 1)/ 8) - 1;
445 data.h_bstart = xres / 8 - 1 /* + 1 */;
447 data.h_bstop = data.h_total+1 + 2 + 1;
448 data.h_sstart = (xres / 8) + (hfront / 8) + 1;
449 data.h_sstop = (xres / 8) + (hfront / 8) + (hsync / 8) + 1;
451 data.v_total = yres + vfront + vsync + vback - 1;
453 data.v_dispend = yres - 1;
454 data.v_bstart = yres - 1;
456 data.v_bstop = data.v_total;
457 data.v_sstart = yres + vfront - 1 - 2;
458 data.v_sstop = yres + vfront + vsync - 1;
462 printk("HBS: %i\n", data.h_bstart);
463 printk("HSS: %i\n", data.h_sstart);
464 printk("HSE: %i\n", data.h_sstop);
465 printk("HBE: %i\n", data.h_bstop);
466 printk("HT: %i\n", data.h_total);
468 printk("hsync: %i\n", hsync);
469 printk("hfront: %i\n", hfront);
470 printk("hback: %i\n", hback);
472 printk("VBS: %i\n", data.v_bstart);
473 printk("VSS: %i\n", data.v_sstart);
474 printk("VSE: %i\n", data.v_sstop);
475 printk("VBE: %i\n", data.v_bstop);
476 printk("VT: %i\n", data.v_total);
478 printk("vsync: %i\n", vsync);
479 printk("vfront: %i\n", vfront);
480 printk("vback: %i\n", vback);
483 if (data.v_total >= 1024)
484 printk(KERN_ERR "MAYDAY: v_total >= 1024; bailing out!\n");
486 reg_w(regs, GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
487 reg_w(regs, GREG_FEATURE_CONTROL_W, 0x00);
489 seq_w(regs, SEQ_RESET, 0x00);
490 seq_w(regs, SEQ_RESET, 0x03); /* reset sequencer logic */
493 * CLOCKING_MODE bits:
494 * 2: This one is only set for certain text-modes, wonder if
495 * it may be for EGA-lines? (it was referred to as CLKDIV2)
496 * (The CL drivers sets it to 0x21 with the comment:
497 * FullBandwidth (video off) and 8/9 dot clock)
499 seq_w(regs, SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */);
501 seq_w(regs, SEQ_MAP_MASK, 0x0f); /* enable writing to plane 0-3 */
502 seq_w(regs, SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */
503 seq_w(regs, SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/
504 seq_w(regs, SEQ_RESET, 0x01);
505 seq_w(regs, SEQ_RESET, 0x03);
507 seq_w(regs, SEQ_EXTENDED_ENABLE, 0x05);
509 seq_w(regs, SEQ_CURSOR_CONTROL, 0x00); /* disable cursor */
510 seq_w(regs, SEQ_PRIM_HOST_OFF_HI, 0x00);
511 seq_w(regs, SEQ_PRIM_HOST_OFF_HI, 0x00);
512 seq_w(regs, SEQ_LINEAR_0, 0x4a);
513 seq_w(regs, SEQ_LINEAR_1, 0x00);
515 seq_w(regs, SEQ_SEC_HOST_OFF_HI, 0x00);
516 seq_w(regs, SEQ_SEC_HOST_OFF_LO, 0x00);
517 seq_w(regs, SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
520 * The lower 4 bits (0-3) are used to set the font-width for
521 * text-mode - DON'T try to set this for gfx-mode.
523 seq_w(regs, SEQ_EXT_CLOCK_MODE, 0x10);
524 seq_w(regs, SEQ_EXT_VIDEO_ADDR, 0x03);
527 * Extended Pixel Control:
528 * bit 0: text-mode=0, gfx-mode=1 (Graphics Byte ?)
529 * bit 1: (Packed/Nibble Pixel Format ?)
530 * bit 4-5: depth, 0=1-8bpp, 1=9-16bpp, 2=17-24bpp
532 seq_w(regs, SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4));
534 seq_w(regs, SEQ_BUS_WIDTH_FEEDB, 0x04);
535 seq_w(regs, SEQ_COLOR_EXP_WFG, 0x01);
536 seq_w(regs, SEQ_COLOR_EXP_WBG, 0x00);
537 seq_w(regs, SEQ_EXT_RW_CONTROL, 0x00);
538 seq_w(regs, SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8)));
539 seq_w(regs, SEQ_COLOR_KEY_CNTL, 0x40);
540 seq_w(regs, SEQ_COLOR_KEY_MATCH0, 0x00);
541 seq_w(regs, SEQ_COLOR_KEY_MATCH1, 0x00);
542 seq_w(regs, SEQ_COLOR_KEY_MATCH2, 0x00);
543 seq_w(regs, SEQ_CRC_CONTROL, 0x00);
544 seq_w(regs, SEQ_PERF_SELECT, 0x10);
545 seq_w(regs, SEQ_ACM_APERTURE_1, 0x00);
546 seq_w(regs, SEQ_ACM_APERTURE_2, 0x30);
547 seq_w(regs, SEQ_ACM_APERTURE_3, 0x00);
548 seq_w(regs, SEQ_MEMORY_MAP_CNTL, 0x03);
551 /* unlock register CRT0..CRT7 */
552 crt_w(regs, CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20);
554 /* Zuerst zu schreibende Werte nur per printk ausgeben */
555 DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total);
556 crt_w(regs, CRT_HOR_TOTAL, data.h_total & 0xff);
558 DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend);
559 crt_w(regs, CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff);
561 DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart);
562 crt_w(regs, CRT_START_HOR_BLANK, data.h_bstart & 0xff);
564 DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32);
565 crt_w(regs, CRT_END_HOR_BLANK, 0x80 | (data.h_bstop & 0x1f));
567 DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart);
568 crt_w(regs, CRT_START_HOR_RETR, data.h_sstart & 0xff);
570 tmp = (data.h_sstop & 0x1f);
571 if (data.h_bstop & 0x20)
573 DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp);
574 crt_w(regs, CRT_END_HOR_RETR, tmp);
576 DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff);
577 crt_w(regs, CRT_VER_TOTAL, (data.v_total & 0xff));
579 tmp = 0x10; /* LineCompare bit #9 */
580 if (data.v_total & 256)
582 if (data.v_dispend & 256)
584 if (data.v_sstart & 256)
586 if (data.v_bstart & 256)
588 if (data.v_total & 512)
590 if (data.v_dispend & 512)
592 if (data.v_sstart & 512)
594 DEBUG printk("CRT_OVERFLOW: %d\n", tmp);
595 crt_w(regs, CRT_OVERFLOW, tmp);
597 crt_w(regs, CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */
599 tmp = 0x40; /* LineCompare bit #8 */
600 if (data.v_bstart & 512)
602 if (var->vmode & FB_VMODE_DOUBLE)
604 DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp);
605 crt_w(regs, CRT_MAX_SCAN_LINE, tmp);
607 crt_w(regs, CRT_CURSOR_START, 0x00);
608 crt_w(regs, CRT_CURSOR_END, 8 & 0x1f); /* font height */
610 crt_w(regs, CRT_START_ADDR_HIGH, 0x00);
611 crt_w(regs, CRT_START_ADDR_LOW, 0x00);
613 crt_w(regs, CRT_CURSOR_LOC_HIGH, 0x00);
614 crt_w(regs, CRT_CURSOR_LOC_LOW, 0x00);
616 DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff);
617 crt_w(regs, CRT_START_VER_RETR, (data.v_sstart & 0xff));
620 /* 5 refresh cycles per scanline */
621 DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16);
622 crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));
624 DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16);
625 crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));
627 DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff);
628 crt_w(regs, CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff));
630 DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff);
631 crt_w(regs, CRT_START_VER_BLANK, (data.v_bstart & 0xff));
633 DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff);
634 crt_w(regs, CRT_END_VER_BLANK, (data.v_bstop & 0xff));
636 DEBUG printk("CRT_MODE_CONTROL: 0xe3\n");
637 crt_w(regs, CRT_MODE_CONTROL, 0xe3);
639 DEBUG printk("CRT_LINE_COMPARE: 0xff\n");
640 crt_w(regs, CRT_LINE_COMPARE, 0xff);
642 tmp = (var->xres_virtual / 8) * (bpp / 8);
643 crt_w(regs, CRT_OFFSET, tmp);
645 crt_w(regs, CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */
647 tmp = 0x20; /* Enable extended end bits */
648 if (data.h_total & 0x100)
650 if ((data.h_dispend) & 0x100)
652 if (data.h_bstart & 0x100)
654 if (data.h_sstart & 0x100)
656 if (var->vmode & FB_VMODE_INTERLACED)
658 DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp);
659 crt_w(regs, CRT_EXT_HOR_TIMING1, tmp);
662 if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100)
664 crt_w(regs, CRT_EXT_START_ADDR, tmp);
667 if (data.h_total & 0x200)
669 if ((data.h_dispend) & 0x200)
671 if (data.h_bstart & 0x200)
673 if (data.h_sstart & 0x200)
675 tmp |= ((data.h_bstop & 0xc0) >> 2);
676 tmp |= ((data.h_sstop & 0x60) << 1);
677 crt_w(regs, CRT_EXT_HOR_TIMING2, tmp);
678 DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp);
680 tmp = 0x10; /* Line compare bit 10 */
681 if (data.v_total & 0x400)
683 if ((data.v_dispend) & 0x400)
685 if (data.v_bstart & 0x400)
687 if (data.v_sstart & 0x400)
689 tmp |= ((data.v_bstop & 0x300) >> 3);
690 if (data.v_sstop & 0x10)
692 crt_w(regs, CRT_EXT_VER_TIMING, tmp);
693 DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp);
695 crt_w(regs, CRT_MONITOR_POWER, 0x00);
698 * Convert from ps to Hz.
700 freq = 2000000000 / var->pixclock;
703 best_freq = find_fq(freq);
704 pll_w(regs, 0x02, best_freq);
705 best_freq = find_fq(61000000);
706 pll_w(regs, 0x0a, best_freq);
707 pll_w(regs, 0x0e, 0x22);
709 gfx_w(regs, GFX_SET_RESET, 0x00);
710 gfx_w(regs, GFX_ENABLE_SET_RESET, 0x00);
711 gfx_w(regs, GFX_COLOR_COMPARE, 0x00);
712 gfx_w(regs, GFX_DATA_ROTATE, 0x00);
713 gfx_w(regs, GFX_READ_MAP_SELECT, 0x00);
714 gfx_w(regs, GFX_GRAPHICS_MODE, 0x00);
715 gfx_w(regs, GFX_MISC, 0x05);
716 gfx_w(regs, GFX_COLOR_XCARE, 0x0f);
717 gfx_w(regs, GFX_BITMASK, 0xff);
719 reg_r(regs, ACT_ADDRESS_RESET);
720 attr_w(regs, ACT_PALETTE0 , 0x00);
721 attr_w(regs, ACT_PALETTE1 , 0x01);
722 attr_w(regs, ACT_PALETTE2 , 0x02);
723 attr_w(regs, ACT_PALETTE3 , 0x03);
724 attr_w(regs, ACT_PALETTE4 , 0x04);
725 attr_w(regs, ACT_PALETTE5 , 0x05);
726 attr_w(regs, ACT_PALETTE6 , 0x06);
727 attr_w(regs, ACT_PALETTE7 , 0x07);
728 attr_w(regs, ACT_PALETTE8 , 0x08);
729 attr_w(regs, ACT_PALETTE9 , 0x09);
730 attr_w(regs, ACT_PALETTE10, 0x0a);
731 attr_w(regs, ACT_PALETTE11, 0x0b);
732 attr_w(regs, ACT_PALETTE12, 0x0c);
733 attr_w(regs, ACT_PALETTE13, 0x0d);
734 attr_w(regs, ACT_PALETTE14, 0x0e);
735 attr_w(regs, ACT_PALETTE15, 0x0f);
736 reg_r(regs, ACT_ADDRESS_RESET);
738 attr_w(regs, ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */
740 attr_w(regs, ACT_OVERSCAN_COLOR, 0x00);
741 attr_w(regs, ACT_COLOR_PLANE_ENA, 0x0f);
742 attr_w(regs, ACT_HOR_PEL_PANNING, 0x00);
743 attr_w(regs, ACT_COLOR_SELECT, 0x00);
745 reg_r(regs, ACT_ADDRESS_RESET);
746 reg_w(regs, ACT_DATA, 0x20);
748 reg_w(regs, VDAC_MASK, 0xff);
751 * Extended palette addressing ???
755 reg_w(regs, 0x83c6, 0x00);
758 reg_w(regs, 0x83c6, 0x60);
761 reg_w(regs, 0x83c6, 0xe0);
764 printk(KERN_INFO "Illegal color-depth: %i\n", bpp);
767 reg_w(regs, VDAC_ADDRESS, 0x00);
769 seq_w(regs, SEQ_MAP_MASK, 0x0f );
776 * This function should fill in the `fix' structure based on the
777 * values in the `par' structure.
780 static int retz3_encode_fix(struct fb_info *info,
781 struct fb_fix_screeninfo *fix,
782 struct retz3fb_par *par)
784 struct retz3_fb_info *zinfo = retz3info(info);
786 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
787 strcpy(fix->id, retz3fb_name);
788 fix->smem_start = zinfo->physfbmem;
789 fix->smem_len = zinfo->fbsize;
790 fix->mmio_start = zinfo->physregs;
791 fix->mmio_len = 0x00c00000;
793 fix->type = FB_TYPE_PACKED_PIXELS;
796 fix->visual = FB_VISUAL_PSEUDOCOLOR;
798 fix->visual = FB_VISUAL_TRUECOLOR;
803 fix->line_length = 0;
805 fix->accel = FB_ACCEL_NCR_77C32BLT;
812 * Get the video params out of `var'. If a value doesn't fit, round
813 * it up, if it's too big, return -EINVAL.
816 static int retz3_decode_var(struct fb_var_screeninfo *var,
817 struct retz3fb_par *par)
819 par->xres = var->xres;
820 par->yres = var->yres;
821 par->xres_vir = var->xres_virtual;
822 par->yres_vir = var->yres_virtual;
823 par->bpp = var->bits_per_pixel;
824 par->pixclock = var->pixclock;
825 par->vmode = var->vmode;
828 par->green = var->green;
829 par->blue = var->blue;
830 par->transp = var->transp;
832 par->left_margin = var->left_margin;
833 par->right_margin = var->right_margin;
834 par->upper_margin = var->upper_margin;
835 par->lower_margin = var->lower_margin;
836 par->hsync_len = var->hsync_len;
837 par->vsync_len = var->vsync_len;
839 if (var->accel_flags & FB_ACCELF_TEXT)
840 par->accel = FB_ACCELF_TEXT;
849 * Fill the `var' structure based on the values in `par' and maybe
850 * other values read out of the hardware.
853 static int retz3_encode_var(struct fb_var_screeninfo *var,
854 struct retz3fb_par *par)
856 memset(var, 0, sizeof(struct fb_var_screeninfo));
857 var->xres = par->xres;
858 var->yres = par->yres;
859 var->xres_virtual = par->xres_vir;
860 var->yres_virtual = par->yres_vir;
864 var->bits_per_pixel = par->bpp;
868 var->green = par->green;
869 var->blue = par->blue;
870 var->transp = par->transp;
878 var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0;
880 var->pixclock = par->pixclock;
882 var->sync = 0; /* ??? */
883 var->left_margin = par->left_margin;
884 var->right_margin = par->right_margin;
885 var->upper_margin = par->upper_margin;
886 var->lower_margin = par->lower_margin;
887 var->hsync_len = par->hsync_len;
888 var->vsync_len = par->vsync_len;
890 var->vmode = par->vmode;
896 * Set a single color register. Return != 0 for invalid regno.
899 static int retz3_setcolreg(unsigned int regno, unsigned int red,
900 unsigned int green, unsigned int blue,
901 unsigned int transp, struct fb_info *info)
903 struct retz3_fb_info *zinfo = retz3info(info);
904 volatile unsigned char *regs = zinfo->regs;
906 /* We'll get to this */
915 zinfo->color_table[regno][0] = red;
916 zinfo->color_table[regno][1] = green;
917 zinfo->color_table[regno][2] = blue;
919 reg_w(regs, VDAC_ADDRESS_W, regno);
920 reg_w(regs, VDAC_DATA, red);
921 reg_w(regs, VDAC_DATA, green);
922 reg_w(regs, VDAC_DATA, blue);
929 * Read a single color register and split it into
930 * colors/transparent. Return != 0 for invalid regno.
933 static int retz3_getcolreg(unsigned int regno, unsigned int *red,
934 unsigned int *green, unsigned int *blue,
935 unsigned int *transp, struct fb_info *info)
937 struct retz3_fb_info *zinfo = retz3info(info);
942 t = zinfo->color_table[regno][0];
943 *red = (t<<10) | (t<<4) | (t>>2);
944 t = zinfo->color_table[regno][1];
945 *green = (t<<10) | (t<<4) | (t>>2);
946 t = zinfo->color_table[regno][2];
947 *blue = (t<<10) | (t<<4) | (t>>2);
953 static inline void retz3_busy(struct display *p)
955 struct retz3_fb_info *zinfo = retz3info(p->fb_info);
956 volatile unsigned char *acm = zinfo->base + ACM_OFFSET;
957 unsigned char blt_status;
959 if (zinfo->blitbusy) {
961 blt_status = *((acm) + (ACM_START_STATUS + 2));
962 }while ((blt_status & 1) == 0);
968 static void retz3_bitblt (struct display *p,
969 unsigned short srcx, unsigned short srcy,
970 unsigned short destx, unsigned short desty,
971 unsigned short width, unsigned short height,
972 unsigned short cmd, unsigned short mask)
974 struct fb_var_screeninfo *var = &p->var;
975 struct retz3_fb_info *zinfo = retz3info(p->fb_info);
976 volatile unsigned long *acm = (unsigned long *)(zinfo->base + ACM_OFFSET);
977 unsigned long *pattern = (unsigned long *)(zinfo->fbmem + PAT_MEM_OFF);
981 unsigned long pat, src, dst;
983 int i, xres_virtual = var->xres_virtual;
984 short bpp = (var->bits_per_pixel & 0xff);
989 tmp = mask | (mask << 16);
999 *(acm + ACM_RASTEROP_ROTATION/4) = tmp;
1003 pat = 8 * PAT_MEM_OFF;
1004 dst = bpp * (destx + desty * xres_virtual);
1007 * Source is not set for clear.
1009 if ((cmd != Z3BLTclear) && (cmd != Z3BLTset)) {
1010 src = bpp * (srcx + srcy * xres_virtual);
1014 src += bpp * (width - 1);
1015 dst += bpp * (width - 1);
1020 src += bpp * (height - 1) * xres_virtual;
1021 dst += bpp * (height - 1) * xres_virtual;
1025 *(acm + ACM_SOURCE/4) = cpu_to_le32(src);
1028 *(acm + ACM_PATTERN/4) = cpu_to_le32(pat);
1030 *(acm + ACM_DESTINATION/4) = cpu_to_le32(dst);
1033 *(acm + ACM_CONTROL/4) = tmp;
1035 tmp = width | (height << 16);
1037 *(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp);
1039 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
1040 *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
1041 zinfo->blitbusy = 1;
1046 * Move cursor to x, y
1048 static void retz3_MoveCursor (unsigned short x, unsigned short y)
1050 /* Guess we gotta deal with the cursor at some point */
1056 * Fill the hardware's `par' structure.
1059 static void retz3fb_get_par(struct fb_info *info, struct retz3fb_par *par)
1061 struct retz3_fb_info *zinfo = retz3info(info);
1063 if (zinfo->current_par_valid)
1064 *par = zinfo->current_par;
1066 retz3_decode_var(&retz3fb_default, par);
1070 static void retz3fb_set_par(struct fb_info *info, struct retz3fb_par *par)
1072 struct retz3_fb_info *zinfo = retz3info(info);
1074 zinfo->current_par = *par;
1075 zinfo->current_par_valid = 1;
1079 static int do_fb_set_var(struct fb_info *info,
1080 struct fb_var_screeninfo *var, int isactive)
1083 struct retz3fb_par par;
1084 struct retz3_fb_info *zinfo = retz3info(info);
1086 if ((err = retz3_decode_var(var, &par)))
1088 activate = var->activate;
1090 /* XXX ... what to do about isactive ? */
1092 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
1093 retz3fb_set_par(info, &par);
1094 retz3_encode_var(var, &par);
1095 var->activate = activate;
1097 retz3_set_video(info, var, &zinfo->current_par);
1103 static void do_install_cmap(int con, struct fb_info *info)
1105 struct retz3_fb_info *zinfo = retz3info(info);
1107 if (con != zinfo->currcon)
1109 if (fb_display[con].cmap.len)
1110 fb_set_cmap(&fb_display[con].cmap, 1, retz3_setcolreg, info);
1112 fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
1113 1, retz3_setcolreg, info);
1117 * Get the Fixed Part of the Display
1120 static int retz3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
1121 struct fb_info *info)
1123 struct retz3fb_par par;
1127 retz3fb_get_par(info, &par);
1129 error = retz3_decode_var(&fb_display[con].var, &par);
1130 return(error ? error : retz3_encode_fix(info, fix, &par));
1135 * Get the User Defined Part of the Display
1138 static int retz3fb_get_var(struct fb_var_screeninfo *var, int con,
1139 struct fb_info *info)
1141 struct retz3fb_par par;
1145 retz3fb_get_par(info, &par);
1146 error = retz3_encode_var(var, &par);
1148 *var = fb_display[con].var;
1153 static void retz3fb_set_disp(int con, struct fb_info *info)
1155 struct fb_fix_screeninfo fix;
1156 struct display *display;
1157 struct retz3_fb_info *zinfo = retz3info(info);
1160 display = &fb_display[con];
1162 display = &zinfo->disp; /* used during initialization */
1164 retz3fb_get_fix(&fix, con, info);
1169 display->screen_base = zinfo->fbmem;
1170 display->visual = fix.visual;
1171 display->type = fix.type;
1172 display->type_aux = fix.type_aux;
1173 display->ypanstep = fix.ypanstep;
1174 display->ywrapstep = fix.ywrapstep;
1175 display->can_soft_blank = 1;
1176 display->inverse = z3fb_inverse;
1179 * This seems to be about 20% faster.
1181 display->scrollmode = SCROLL_YREDRAW;
1183 switch (display->var.bits_per_pixel) {
1184 #ifdef FBCON_HAS_CFB8
1186 if (display->var.accel_flags & FB_ACCELF_TEXT) {
1187 display->dispsw = &fbcon_retz3_8;
1188 retz3_set_video(info, &display->var, &zinfo->current_par);
1190 display->dispsw = &fbcon_cfb8;
1193 #ifdef FBCON_HAS_CFB16
1195 display->dispsw = &fbcon_cfb16;
1199 display->dispsw = &fbcon_dummy;
1206 * Set the User Defined Part of the Display
1209 static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
1210 struct fb_info *info)
1212 int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
1213 struct display *display;
1214 struct retz3_fb_info *zinfo = retz3info(info);
1217 display = &fb_display[con];
1219 display = &zinfo->disp; /* used during initialization */
1221 if ((err = do_fb_set_var(info, var, con == zinfo->currcon)))
1223 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
1224 oldxres = display->var.xres;
1225 oldyres = display->var.yres;
1226 oldvxres = display->var.xres_virtual;
1227 oldvyres = display->var.yres_virtual;
1228 oldbpp = display->var.bits_per_pixel;
1229 oldaccel = display->var.accel_flags;
1230 display->var = *var;
1232 if (oldxres != var->xres || oldyres != var->yres ||
1233 oldvxres != var->xres_virtual ||
1234 oldvyres != var->yres_virtual ||
1235 oldbpp != var->bits_per_pixel ||
1236 oldaccel != var->accel_flags) {
1238 struct fb_fix_screeninfo fix;
1239 retz3fb_get_fix(&fix, con, info);
1241 display->screen_base = zinfo->fbmem;
1242 display->visual = fix.visual;
1243 display->type = fix.type;
1244 display->type_aux = fix.type_aux;
1245 display->ypanstep = fix.ypanstep;
1246 display->ywrapstep = fix.ywrapstep;
1247 display->line_length = fix.line_length;
1248 display->can_soft_blank = 1;
1249 display->inverse = z3fb_inverse;
1250 switch (display->var.bits_per_pixel) {
1251 #ifdef FBCON_HAS_CFB8
1253 if (var->accel_flags & FB_ACCELF_TEXT) {
1254 display->dispsw = &fbcon_retz3_8;
1256 display->dispsw = &fbcon_cfb8;
1259 #ifdef FBCON_HAS_CFB16
1261 display->dispsw = &fbcon_cfb16;
1265 display->dispsw = &fbcon_dummy;
1269 * We still need to find a way to tell the X
1270 * server that the video mem has been fiddled with
1271 * so it redraws the entire screen when switching
1272 * between X and a text console.
1274 retz3_set_video(info, var, &zinfo->current_par);
1276 if (info->changevar)
1277 (*info->changevar)(con);
1280 if (oldbpp != var->bits_per_pixel) {
1281 if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
1283 do_install_cmap(con, info);
1294 static int retz3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
1295 struct fb_info *info)
1297 struct retz3_fb_info *zinfo = retz3info(info);
1299 if (con == zinfo->currcon) /* current console? */
1300 return(fb_get_cmap(cmap, kspc, retz3_getcolreg, info));
1301 else if (fb_display[con].cmap.len) /* non default colormap? */
1302 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
1304 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
1305 cmap, kspc ? 0 : 2);
1314 static int retz3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
1315 struct fb_info *info)
1318 struct retz3_fb_info *zinfo = retz3info(info);
1320 if (!fb_display[con].cmap.len) { /* no colormap allocated? */
1321 if ((err = fb_alloc_cmap(&fb_display[con].cmap,
1322 1<<fb_display[con].var.bits_per_pixel,
1326 if (con == zinfo->currcon) /* current console? */
1327 return(fb_set_cmap(cmap, kspc, retz3_setcolreg, info));
1329 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
1334 static struct fb_ops retz3fb_ops = {
1336 fb_get_fix: retz3fb_get_fix,
1337 fb_get_var: retz3fb_get_var,
1338 fb_set_var: retz3fb_set_var,
1339 fb_get_cmap: retz3fb_get_cmap,
1340 fb_set_cmap: retz3fb_set_cmap,
1344 int __init retz3fb_setup(char *options)
1348 if (!options || !*options)
1351 while ((this_opt = strsep(&options, ",")) != NULL) {
1354 if (!strcmp(this_opt, "inverse")) {
1357 } else if (!strncmp(this_opt, "font:", 5)) {
1358 strncpy(fontname, this_opt+5, 39);
1359 fontname[39] = '\0';
1361 z3fb_mode = get_video_mode(this_opt);
1371 int __init retz3fb_init(void)
1373 unsigned long board_addr, board_size;
1374 struct zorro_dev *z = NULL;
1375 volatile unsigned char *regs;
1376 struct retz3fb_par par;
1377 struct retz3_fb_info *zinfo;
1378 struct fb_info *fb_info;
1382 while ((z = zorro_find_device(ZORRO_PROD_MACROSYSTEMS_RETINA_Z3, z))) {
1383 board_addr = z->resource.start;
1384 board_size = z->resource.end-z->resource.start+1;
1385 if (!request_mem_region(board_addr, 0x0c00000,
1388 if (!request_mem_region(board_addr+VIDEO_MEM_OFFSET,
1390 release_mem_region(board_addr, 0x00c00000);
1393 if (!(zinfo = kmalloc(sizeof(struct retz3_fb_info),
1396 memset(zinfo, 0, sizeof(struct retz3_fb_info));
1398 zinfo->base = ioremap(board_addr, board_size);
1399 zinfo->regs = zinfo->base;
1400 zinfo->fbmem = zinfo->base + VIDEO_MEM_OFFSET;
1401 /* Get memory size - for now we asume its a 4MB board */
1402 zinfo->fbsize = 0x00400000; /* 4 MB */
1403 zinfo->physregs = board_addr;
1404 zinfo->physfbmem = board_addr + VIDEO_MEM_OFFSET;
1406 fb_info = fbinfo(zinfo);
1408 for (i = 0; i < 256; i++){
1409 for (i = 0; i < 256; i++){
1410 zinfo->color_table[i][0] = i;
1411 zinfo->color_table[i][1] = i;
1412 zinfo->color_table[i][2] = i;
1417 /* Disable hardware cursor */
1418 seq_w(regs, SEQ_CURSOR_Y_INDEX, 0x00);
1420 retz3_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, fb_info);
1421 retz3_setcolreg (254, 0, 0, 0, 0, fb_info);
1423 strcpy(fb_info->modename, retz3fb_name);
1424 fb_info->changevar = NULL;
1426 fb_info->fbops = &retz3fb_ops;
1427 fb_info->disp = &zinfo->disp;
1428 fb_info->switch_con = &z3fb_switch;
1429 fb_info->updatevar = &z3fb_updatevar;
1430 fb_info->blank = &z3fb_blank;
1431 fb_info->flags = FBINFO_FLAG_DEFAULT;
1432 strncpy(fb_info->fontname, fontname, 40);
1434 if (z3fb_mode == -1)
1435 retz3fb_default = retz3fb_predefined[0].var;
1437 retz3_decode_var(&retz3fb_default, &par);
1438 retz3_encode_var(&retz3fb_default, &par);
1440 do_fb_set_var(fb_info, &retz3fb_default, 0);
1441 retz3fb_get_var(&zinfo->disp.var, -1, fb_info);
1443 retz3fb_set_disp(-1, fb_info);
1445 do_install_cmap(0, fb_info);
1447 if (register_framebuffer(fb_info) < 0)
1450 printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of "
1451 "video memory\n", GET_FB_IDX(fb_info->node),
1452 fb_info->modename, zinfo->fbsize>>10);
1454 /* FIXME: This driver cannot be unloaded yet */
1463 static int z3fb_switch(int con, struct fb_info *info)
1465 struct retz3_fb_info *zinfo = retz3info(info);
1467 /* Do we have to save the colormap? */
1468 if (fb_display[zinfo->currcon].cmap.len)
1469 fb_get_cmap(&fb_display[zinfo->currcon].cmap, 1,
1470 retz3_getcolreg, info);
1472 do_fb_set_var(info, &fb_display[con].var, 1);
1473 zinfo->currcon = con;
1474 /* Install new colormap */
1475 do_install_cmap(con, info);
1481 * Update the `var' structure (called by fbcon.c)
1483 * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1484 * Since it's called by a kernel driver, no range checking is done.
1487 static int z3fb_updatevar(int con, struct fb_info *info)
1494 * Blank the display.
1497 static void z3fb_blank(int blank, struct fb_info *info)
1499 struct retz3_fb_info *zinfo = retz3info(info);
1500 volatile unsigned char *regs = retz3info(info)->regs;
1504 for (i = 0; i < 256; i++){
1505 reg_w(regs, VDAC_ADDRESS_W, i);
1506 reg_w(regs, VDAC_DATA, 0);
1507 reg_w(regs, VDAC_DATA, 0);
1508 reg_w(regs, VDAC_DATA, 0);
1511 for (i = 0; i < 256; i++){
1512 reg_w(regs, VDAC_ADDRESS_W, i);
1513 reg_w(regs, VDAC_DATA, zinfo->color_table[i][0]);
1514 reg_w(regs, VDAC_DATA, zinfo->color_table[i][1]);
1515 reg_w(regs, VDAC_DATA, zinfo->color_table[i][2]);
1524 static int __init get_video_mode(const char *name)
1528 for (i = 0; i < NUM_TOTAL_MODES; i++)
1529 if (!strcmp(name, retz3fb_predefined[i].name)){
1530 retz3fb_default = retz3fb_predefined[i].var;
1538 MODULE_LICENSE("GPL");
1540 int init_module(void)
1542 return retz3fb_init();
1545 void cleanup_module(void)
1548 * Not reached because the usecount will never
1549 * be decremented to zero
1551 * FIXME: clean up ... *
1558 * Text console acceleration
1561 #ifdef FBCON_HAS_CFB8
1562 static void retz3_8_bmove(struct display *p, int sy, int sx,
1563 int dy, int dx, int height, int width)
1565 int fontwidth = fontwidth(p);
1573 (unsigned short)(sy*fontheight(p)),
1575 (unsigned short)(dy*fontheight(p)),
1576 (unsigned short)width,
1577 (unsigned short)(height*fontheight(p)),
1582 static void retz3_8_clear(struct vc_data *conp, struct display *p,
1583 int sy, int sx, int height, int width)
1586 int fontwidth = fontwidth(p);
1591 col = attr_bgcol_ec(p, conp);
1597 (unsigned short)(sy*fontheight(p)),
1599 (unsigned short)(sy*fontheight(p)),
1600 (unsigned short)width,
1601 (unsigned short)(height*fontheight(p)),
1607 static void retz3_putc(struct vc_data *conp, struct display *p, int c,
1611 fbcon_cfb8_putc(conp, p, c, yy, xx);
1615 static void retz3_putcs(struct vc_data *conp, struct display *p,
1616 const unsigned short *s, int count,
1620 fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
1624 static void retz3_revc(struct display *p, int xx, int yy)
1627 fbcon_cfb8_revc(p, xx, yy);
1631 static void retz3_clear_margins(struct vc_data* conp, struct display* p,
1635 fbcon_cfb8_clear_margins(conp, p, bottom_only);
1639 static struct display_switch fbcon_retz3_8 = {
1640 setup: fbcon_cfb8_setup,
1641 bmove: retz3_8_bmove,
1642 clear: retz3_8_clear,
1646 clear_margins: retz3_clear_margins,
1647 fontwidthmask: FONTWIDTH(8)