clean
[linux-2.4.21-pre4.git] / drivers / video / dn_cfb8.c
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/slab.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"
21
22 /* apollo video HW definitions */
23
24 /*
25  * Control Registers.   IOBASE + $x
26  *
27  * Note: these are the Memory/IO BASE definitions for a mono card set to the
28  * alternate address
29  *
30  * Control 3A and 3B serve identical functions except that 3A
31  * deals with control 1 and 3b deals with Color LUT reg.
32  */
33
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 */
49
50
51 #define FRAME_BUFFER_START 0x0A0000
52 #define FRAME_BUFFER_LEN 0x20000
53
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 */
60
61 /* CREG 1 */
62 #define AD_BLT      0x80 /* 1xxx.xxxx */
63
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 */
68
69 #define BLANK_DISP      0x00 /* xxxx.xxx0 */
70 #define ENAB_DISP       0x01 /* xxxx.xxx1 */
71
72 #define NORM_CREG1      (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
73
74 /* CREG 2B */
75
76 /*
77  * Following 3 defines are common to 1, 4 and 8 plane.
78  */
79
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 */
84
85 /* CREG 3A/CREG 3B */
86 #       define RESET_CREG 0x80 /* 1000.0000 */
87
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
107
108 #define SWAP(A) ((A>>8) | ((A&0xff) <<8))
109
110
111 /* frame buffer operations */
112
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);
123
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);
127
128 static void dn_fb_set_disp(int con,struct fb_info *info);
129
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,
139 };
140
141 static int currcon=0;
142
143 #define NUM_TOTAL_MODES 1
144 struct fb_var_screeninfo dn_fb_predefined[] = {
145
146         { 0, },
147
148 };
149
150 static char dn_fb_name[]="Apollo ";
151
152 /* accel stuff */
153 #define USE_DN_ACCEL
154
155 static struct display_switch dispsw_apollofb;
156
157 static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
158                          struct fb_info *info) {
159
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;
170
171         return 0;
172
173 }
174         
175 static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
176                          struct fb_info *info) {
177                 
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;
197
198         return 0;
199
200 }
201
202 static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
203                          struct fb_info *info) {
204
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;
240
241         return 0;
242
243 }
244
245 static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
246                           struct fb_info *info) {
247
248         printk("get cmap not supported\n");
249
250         return -EINVAL;
251 }
252
253 static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
254                           struct fb_info *info) {
255
256         printk("set cmap not supported\n");
257
258         return -EINVAL;
259
260 }
261
262 static void dn_fb_set_disp(int con, struct fb_info *info) {
263
264   struct fb_fix_screeninfo fix;
265
266   dn_fb_get_fix(&fix,con, info);
267   if(con==-1) 
268     con=0;
269
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;
281 }
282   
283 unsigned long dn_fb_init(unsigned long mem_start) {
284
285         int err;
286        
287 printk("dn_fb_init\n");
288
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;
298         
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");
303         }
304  
305         /* now we have registered we can safely setup the hardware */
306
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);
315
316         printk("apollo frame buffer alive and kicking !\n");
317
318         dn_fb_get_var(&disp[0].var,0, &fb_info);
319
320         dn_fb_set_disp(-1, &fb_info);
321
322         return mem_start;
323
324 }       
325
326         
327 static int dnfbcon_switch(int con,  struct fb_info *info) { 
328
329         currcon=con;
330         
331         return 0;
332
333 }
334
335 static int dnfbcon_updatevar(int con,  struct fb_info *info) {
336
337         return 0;
338
339 }
340
341 static void dnfbcon_blank(int blank,  struct fb_info *info) {
342
343         if(blank)  {
344                 outb(0x0,  AP_CONTROL_3A);
345         }
346         else {
347                 outb(0x1,  AP_CONTROL_3A);
348         }
349
350         return ;
351
352 }
353
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) {
356
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;
361
362         incr=(y_dest<=y_src) ? 1 : -1 ;
363
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);
366         
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;
376         }
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;
386         }
387
388         for(i=0;i<y_count;i++) {
389                         
390                 if(pre_read) {
391                         dummy=*src;
392                         src+=incr;
393                 }
394
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);
401
402                         for(j=1;j<(x_word_count-1);j++) {
403                                 *src=dest;
404                                 src+=incr;      
405                                 dest+=incr;
406                         }
407
408                         outb(start_mask,AP_WRITE_ENABLE);
409                         *src=dest;
410                         dest+=incr;
411                         src+=incr;
412                 }
413                 else {
414                         outb(start_mask | end_mask, AP_WRITE_ENABLE);
415                         *src=dest;
416                         dest+=incr;
417                         src+=incr;
418                 }
419                 src+=(y_delta/16);
420                 dest+=(y_delta/16);
421         }
422         outb(NORMAL_MODE,AP_CONTROL_0);
423 }
424
425 static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
426                       int height, int width)
427 {
428
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;
435
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;
447         }
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;
455         }
456     }
457 #endif
458 }
459
460 static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
461                       int height, int width)
462 {
463     u_char *dest;
464     u_int rows;
465
466     dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
467
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);
479 }
480
481 static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
482                      int xx)
483 {
484     u_char *dest, *cdat;
485     u_int rows, bold, revs, underl;
486     u_char d;
487
488     c &= 0xff;
489
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);
495
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;
505     }
506 }
507
508 static void putcs_apollofb(struct vc_data *conp, struct display *p, const char *s,
509                       int count, int yy, int xx)
510 {
511     u_char *dest, *dest0, *cdat;
512     u_int rows, bold, revs, underl;
513     u_char c, d;
514
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);
519
520     while (count--) {
521         c = scr_readw(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;
533         }
534     }
535 }
536
537 static void rev_char_apollofb(struct display *p, int xx, int yy)
538 {
539     u_char *dest;
540     u_int rows;
541
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;
545 }
546
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)
555 };
556
557 MODULE_LICENSE("GPL");