Merge with Linu 2.4.0-test6-pre6.
[linux-2.6/linux-mips.git] / drivers / video / dn_cfb8.c
bloba654717b3d2f96740d4d46e6a1ea8c40dabd719b
1 #include <linux/kernel.h>
2 #include <linux/errno.h>
3 #include <linux/string.h>
4 #include <linux/mm.h>
5 #include <linux/tty.h>
6 #include <linux/malloc.h>
7 #include <linux/delay.h>
8 #include <linux/interrupt.h>
9 #include <asm/setup.h>
10 #include <asm/segment.h>
11 #include <asm/system.h>
12 #include <asm/irq.h>
13 #include <asm/amigahw.h>
14 #include <asm/amigaints.h>
15 #include <asm/apollohw.h>
16 #include <linux/fb.h>
17 #include <linux/module.h>
18 #include "dn_accel.h"
19 #include "fbcon.h"
20 #include "fbcon-mfb.h"
22 /* apollo video HW definitions */
25 * Control Registers. IOBASE + $x
27 * Note: these are the Memory/IO BASE definitions for a mono card set to the
28 * alternate address
30 * Control 3A and 3B serve identical functions except that 3A
31 * deals with control 1 and 3b deals with Color LUT reg.
34 #define AP_IOBASE 0x3d0 /* Base address of 1 plane board. */
35 #define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */
36 #define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */
37 #define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */
38 #define AP_ROP_0 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
39 #define AP_ROP_1 isaIO2mem(AP_IOBASE+4) /* Raster Operation reg. Write Word */
40 #define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+6) /* Diagnostic Memory Request. Write Word */
41 #define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
42 #define AP_LUT_DATA isaIO2mem(AP_IOBASE+9) /* Control Register 0. Read/Write */
43 #define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
44 #define AP_LUT_CONTROL isaIO2mem(AP_IOBASE+0xb) /* Control Register 1. Read/Write */
45 #define AP_CONTROL_2A isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
46 #define AP_CONTROL_2B isaIO2mem(AP_IOBASE+0xd) /* Control Register 2. Read/Write */
47 #define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
48 #define AP_CONTROL_3B isaIO2mem(AP_IOBASE+0xf) /* Control Register 3a. Read/Write */
51 #define FRAME_BUFFER_START 0x0A0000
52 #define FRAME_BUFFER_LEN 0x20000
54 /* CREG 0 */
55 #define VECTOR_MODE 0x40 /* 010x.xxxx */
56 #define DBLT_MODE 0x80 /* 100x.xxxx */
57 #define NORMAL_MODE 0xE0 /* 111x.xxxx */
58 #define SHIFT_BITS 0x1F /* xxx1.1111 */
59 /* other bits are Shift value */
61 /* CREG 1 */
62 #define AD_BLT 0x80 /* 1xxx.xxxx */
64 #define ROP_EN 0x10 /* xxx1.xxxx */
65 #define DST_EQ_SRC 0x00 /* xxx0.xxxx */
66 #define nRESET_SYNC 0x08 /* xxxx.1xxx */
67 #define SYNC_ENAB 0x02 /* xxxx.xx1x */
69 #define BLANK_DISP 0x00 /* xxxx.xxx0 */
70 #define ENAB_DISP 0x01 /* xxxx.xxx1 */
72 #define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
74 /* CREG 2B */
77 * Following 3 defines are common to 1, 4 and 8 plane.
80 #define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
81 #define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
82 #define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
83 one plane of image mem */
85 /* CREG 3A/CREG 3B */
86 # define RESET_CREG 0x80 /* 1000.0000 */
88 /* ROP REG - all one nibble */
89 /* ********* NOTE : this is used r0,r1,r2,r3 *********** */
90 #define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
91 #define DEST_ZERO 0x0
92 #define SRC_AND_DEST 0x1
93 #define SRC_AND_nDEST 0x2
94 #define SRC 0x3
95 #define nSRC_AND_DEST 0x4
96 #define DEST 0x5
97 #define SRC_XOR_DEST 0x6
98 #define SRC_OR_DEST 0x7
99 #define SRC_NOR_DEST 0x8
100 #define SRC_XNOR_DEST 0x9
101 #define nDEST 0xA
102 #define SRC_OR_nDEST 0xB
103 #define nSRC 0xC
104 #define nSRC_OR_DEST 0xD
105 #define SRC_NAND_DEST 0xE
106 #define DEST_ONE 0xF
108 #define SWAP(A) ((A>>8) | ((A&0xff) <<8))
111 /* frame buffer operations */
113 static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
114 struct fb_info *info);
115 static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
116 struct fb_info *info);
117 static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
118 struct fb_info *info);
119 static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
120 struct fb_info *info);
121 static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
122 struct fb_info *info);
124 static int dnfbcon_switch(int con,struct fb_info *info);
125 static int dnfbcon_updatevar(int con,struct fb_info *info);
126 static void dnfbcon_blank(int blank,struct fb_info *info);
128 static void dn_fb_set_disp(int con,struct fb_info *info);
130 static struct display disp[MAX_NR_CONSOLES];
131 static struct fb_info fb_info;
132 static struct fb_ops dn_fb_ops = {
133 owner: THIS_MODULE,
134 fb_get_fix: dn_fb_get_fix,
135 fb_get_var: dn_fb_get_var,
136 fb_set_var: dn_fb_set_var,
137 fb_get_cmap: dn_fb_get_cmap,
138 fb_set_cmap: dn_fb_set_cmap,
141 static int currcon=0;
143 #define NUM_TOTAL_MODES 1
144 struct fb_var_screeninfo dn_fb_predefined[] = {
146 { 0, },
150 static char dn_fb_name[]="Apollo ";
152 /* accel stuff */
153 #define USE_DN_ACCEL
155 static struct display_switch dispsw_apollofb;
157 static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
158 struct fb_info *info) {
160 strcpy(fix->id,"Apollo Color8");
161 fix->smem_start=(char*)(FRAME_BUFFER_START+IO_BASE);
162 fix->smem_len=FRAME_BUFFER_LEN;
163 fix->type=FB_TYPE_PACKED_PIXELS;
164 fix->type_aux=0;
165 fix->visual=FB_VISUAL_MONO10;
166 fix->xpanstep=0;
167 fix->ypanstep=0;
168 fix->ywrapstep=0;
169 fix->line_length=128;
171 return 0;
175 static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
176 struct fb_info *info) {
178 var->xres=1024;
179 var->yres=800;
180 var->xres_virtual=1024;
181 var->yres_virtual=1024;
182 var->xoffset=0;
183 var->yoffset=0;
184 var->bits_per_pixel=1;
185 var->grayscale=0;
186 var->nonstd=0;
187 var->activate=0;
188 var->height=-1;
189 var->width=-1;
190 var->pixclock=0;
191 var->left_margin=0;
192 var->right_margin=0;
193 var->hsync_len=0;
194 var->vsync_len=0;
195 var->sync=0;
196 var->vmode=FB_VMODE_NONINTERLACED;
198 return 0;
202 static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
203 struct fb_info *info) {
205 printk("fb_set_var\n");
206 if(var->xres!=1024)
207 return -EINVAL;
208 if(var->yres!=800)
209 return -EINVAL;
210 if(var->xres_virtual!=1024)
211 return -EINVAL;
212 if(var->yres_virtual!=1024)
213 return -EINVAL;
214 if(var->xoffset!=0)
215 return -EINVAL;
216 if(var->yoffset!=0)
217 return -EINVAL;
218 if(var->bits_per_pixel!=1)
219 return -EINVAL;
220 if(var->grayscale!=0)
221 return -EINVAL;
222 if(var->nonstd!=0)
223 return -EINVAL;
224 if(var->activate!=0)
225 return -EINVAL;
226 if(var->pixclock!=0)
227 return -EINVAL;
228 if(var->left_margin!=0)
229 return -EINVAL;
230 if(var->right_margin!=0)
231 return -EINVAL;
232 if(var->hsync_len!=0)
233 return -EINVAL;
234 if(var->vsync_len!=0)
235 return -EINVAL;
236 if(var->sync!=0)
237 return -EINVAL;
238 if(var->vmode!=FB_VMODE_NONINTERLACED)
239 return -EINVAL;
241 return 0;
245 static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
246 struct fb_info *info) {
248 printk("get cmap not supported\n");
250 return -EINVAL;
253 static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
254 struct fb_info *info) {
256 printk("set cmap not supported\n");
258 return -EINVAL;
262 static void dn_fb_set_disp(int con, struct fb_info *info) {
264 struct fb_fix_screeninfo fix;
266 dn_fb_get_fix(&fix,con, info);
267 if(con==-1)
268 con=0;
270 disp[con].screen_base = (u_char *)fix.smem_start;
271 printk("screenbase: %p\n",fix.smem_start);
272 disp[con].visual = fix.visual;
273 disp[con].type = fix.type;
274 disp[con].type_aux = fix.type_aux;
275 disp[con].ypanstep = fix.ypanstep;
276 disp[con].ywrapstep = fix.ywrapstep;
277 disp[con].can_soft_blank = 1;
278 disp[con].inverse = 0;
279 disp[con].line_length = fix.line_length;
280 disp[con].dispsw = &dispsw_apollofb;
283 unsigned long dn_fb_init(unsigned long mem_start) {
285 int err;
287 printk("dn_fb_init\n");
289 fb_info.changevar=NULL;
290 strcpy(&fb_info.modename[0],dn_fb_name);
291 fb_info.fontname[0]=0;
292 fb_info.disp=disp;
293 fb_info.switch_con=&dnfbcon_switch;
294 fb_info.updatevar=&dnfbcon_updatevar;
295 fb_info.blank=&dnfbcon_blank;
296 fb_info.node = -1;
297 fb_info.fbops = &dn_fb_ops;
299 printk("dn_fb_init: register\n");
300 err=register_framebuffer(&fb_info);
301 if(err < 0) {
302 panic("unable to register apollo frame buffer\n");
305 /* now we have registered we can safely setup the hardware */
307 outb(RESET_CREG, AP_CONTROL_3A);
308 outb(RESET_CREG, AP_CONTROL_3B);
309 outw(0x0, AP_WRITE_ENABLE);
310 outb(NORMAL_MODE, AP_CONTROL_0);
311 outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
312 outb(0, AP_CONTROL_2A);
313 outb(S_DATA_PLN, AP_CONTROL_2B);
314 outw(SWAP(0x3), AP_ROP_1);
316 printk("apollo frame buffer alive and kicking !\n");
318 dn_fb_get_var(&disp[0].var,0, &fb_info);
320 dn_fb_set_disp(-1, &fb_info);
322 return mem_start;
327 static int dnfbcon_switch(int con, struct fb_info *info) {
329 currcon=con;
331 return 0;
335 static int dnfbcon_updatevar(int con, struct fb_info *info) {
337 return 0;
341 static void dnfbcon_blank(int blank, struct fb_info *info) {
343 if(blank) {
344 outb(0x0, AP_CONTROL_3A);
346 else {
347 outb(0x1, AP_CONTROL_3A);
350 return ;
354 void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
355 int x_count, int y_count) {
357 int incr,y_delta,pre_read=0,x_end,x_word_count;
358 ushort *src,dummy;
359 uint start_mask,end_mask,dest;
360 short i,j;
362 incr=(y_dest<=y_src) ? 1 : -1 ;
364 src=(ushort *)(p->screen_base+ y_src*p->next_line+(x_src >> 4));
365 dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
367 if(incr>0) {
368 y_delta=(p->next_line*8)-x_src-x_count;
369 x_end=x_dest+x_count-1;
370 x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
371 start_mask=0xffff0000 >> (x_dest & 0xf);
372 end_mask=0x7ffff >> (x_end & 0xf);
373 outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0);
374 if((x_dest & 0xf) < (x_src & 0xf))
375 pre_read=1;
377 else {
378 y_delta=-((p->next_line*8)-x_src-x_count);
379 x_end=x_dest-x_count+1;
380 x_word_count=(x_dest>>4) - (x_end >> 4) + 1;
381 start_mask=0x7ffff >> (x_dest & 0xf);
382 end_mask=0xffff0000 >> (x_end & 0xf);
383 outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0);
384 if((x_dest & 0xf) > (x_src & 0xf))
385 pre_read=1;
388 for(i=0;i<y_count;i++) {
390 if(pre_read) {
391 dummy=*src;
392 src+=incr;
395 if(x_word_count) {
396 outb(start_mask,AP_WRITE_ENABLE);
397 *src=dest;
398 src+=incr;
399 dest+=incr;
400 outb(0,AP_WRITE_ENABLE);
402 for(j=1;j<(x_word_count-1);j++) {
403 *src=dest;
404 src+=incr;
405 dest+=incr;
408 outb(start_mask,AP_WRITE_ENABLE);
409 *src=dest;
410 dest+=incr;
411 src+=incr;
413 else {
414 outb(start_mask | end_mask, AP_WRITE_ENABLE);
415 *src=dest;
416 dest+=incr;
417 src+=incr;
419 src+=(y_delta/16);
420 dest+=(y_delta/16);
422 outb(NORMAL_MODE,AP_CONTROL_0);
425 static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
426 int height, int width)
429 #ifdef USE_DN_ACCEL
430 dn_bitblt(p,sx,sy*p->fontheight,dx,dy*p->fontheight,width*p->fontwidth,
431 height*p->fontheight);
432 #else
433 u_char *src, *dest;
434 u_int rows;
436 if (sx == 0 && dx == 0 && width == p->next_line) {
437 src = p->screen_base+sy*p->fontheight*width;
438 dest = p->screen_base+dy*p->fontheight*width;
439 mymemmove(dest, src, height*p->fontheight*width);
440 } else if (dy <= sy) {
441 src = p->screen_base+sy*p->fontheight*p->next_line+sx;
442 dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
443 for (rows = height*p->fontheight; rows--;) {
444 mymemmove(dest, src, width);
445 src += p->next_line;
446 dest += p->next_line;
448 } else {
449 src = p->screen_base+((sy+height)*p->fontheight-1)*p->next_line+sx;
450 dest = p->screen_base+((dy+height)*p->fontheight-1)*p->next_line+dx;
451 for (rows = height*p->fontheight; rows--;) {
452 mymemmove(dest, src, width);
453 src -= p->next_line;
454 dest -= p->next_line;
457 #endif
460 static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
461 int height, int width)
463 u_char *dest;
464 u_int rows;
466 dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
468 if (sx == 0 && width == p->next_line)
469 if (attr_reverse(p,conp))
470 mymemset(dest, height*p->fontheight*width);
471 else
472 mymemclear(dest, height*p->fontheight*width);
473 else
474 for (rows = height*p->fontheight; rows--; dest += p->next_line)
475 if (attr_reverse(p,conp))
476 mymemset(dest, width);
477 else
478 mymemclear_small(dest, width);
481 static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
482 int xx)
484 u_char *dest, *cdat;
485 u_int rows, bold, revs, underl;
486 u_char d;
488 c &= 0xff;
490 dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
491 cdat = p->fontdata+c*p->fontheight;
492 bold = attr_bold(p,conp);
493 revs = attr_reverse(p,conp);
494 underl = attr_underline(p,conp);
496 for (rows = p->fontheight; rows--; dest += p->next_line) {
497 d = *cdat++;
498 if (underl && !rows)
499 d = 0xff;
500 else if (bold)
501 d |= d>>1;
502 if (revs)
503 d = ~d;
504 *dest = d;
508 static void putcs_apollofb(struct vc_data *conp, struct display *p, const char *s,
509 int count, int yy, int xx)
511 u_char *dest, *dest0, *cdat;
512 u_int rows, bold, revs, underl;
513 u_char c, d;
515 dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
516 bold = attr_bold(p,conp);
517 revs = attr_reverse(p,conp);
518 underl = attr_underline(p,conp);
520 while (count--) {
521 c = *s++;
522 dest = dest0++;
523 cdat = p->fontdata+c*p->fontheight;
524 for (rows = p->fontheight; rows--; dest += p->next_line) {
525 d = *cdat++;
526 if (underl && !rows)
527 d = 0xff;
528 else if (bold)
529 d |= d>>1;
530 if (revs)
531 d = ~d;
532 *dest = d;
537 static void rev_char_apollofb(struct display *p, int xx, int yy)
539 u_char *dest;
540 u_int rows;
542 dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
543 for (rows = p->fontheight; rows--; dest += p->next_line)
544 *dest = ~*dest;
547 static struct display_switch dispsw_apollofb = {
548 setup: fbcon_mfb_setup,
549 bmove: bmove_apollofb,
550 clear: clear_apollofb,
551 putc: putc_apollofb,
552 putcs: putcs_apollofb,
553 revc: rev_char_apollofb,
554 fontwidthmask: FONTWIDTH(8)