1 #include <linux/kernel.h>
2 #include <linux/errno.h>
3 #include <linux/string.h>
6 #include <linux/malloc.h>
7 #include <linux/delay.h>
8 #include <linux/interrupt.h>
10 #include <asm/segment.h>
11 #include <asm/system.h>
13 #include <asm/amigahw.h>
14 #include <asm/amigaints.h>
15 #include <asm/apollohw.h>
17 #include <linux/module.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
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
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 */
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 */
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 */
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)) )
92 #define SRC_AND_DEST 0x1
93 #define SRC_AND_nDEST 0x2
95 #define nSRC_AND_DEST 0x4
97 #define SRC_XOR_DEST 0x6
98 #define SRC_OR_DEST 0x7
99 #define SRC_NOR_DEST 0x8
100 #define SRC_XNOR_DEST 0x9
102 #define SRC_OR_nDEST 0xB
104 #define nSRC_OR_DEST 0xD
105 #define SRC_NAND_DEST 0xE
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
= {
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
[] = {
150 static char dn_fb_name
[]="Apollo ";
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
;
165 fix
->visual
=FB_VISUAL_MONO10
;
169 fix
->line_length
=128;
175 static int dn_fb_get_var(struct fb_var_screeninfo
*var
, int con
,
176 struct fb_info
*info
) {
180 var
->xres_virtual
=1024;
181 var
->yres_virtual
=1024;
184 var
->bits_per_pixel
=1;
196 var
->vmode
=FB_VMODE_NONINTERLACED
;
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");
210 if(var
->xres_virtual
!=1024)
212 if(var
->yres_virtual
!=1024)
218 if(var
->bits_per_pixel
!=1)
220 if(var
->grayscale
!=0)
228 if(var
->left_margin
!=0)
230 if(var
->right_margin
!=0)
232 if(var
->hsync_len
!=0)
234 if(var
->vsync_len
!=0)
238 if(var
->vmode
!=FB_VMODE_NONINTERLACED
)
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");
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");
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
);
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
) {
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;
293 fb_info
.switch_con
=&dnfbcon_switch
;
294 fb_info
.updatevar
=&dnfbcon_updatevar
;
295 fb_info
.blank
=&dnfbcon_blank
;
297 fb_info
.fbops
= &dn_fb_ops
;
299 printk("dn_fb_init: register\n");
300 err
=register_framebuffer(&fb_info
);
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
);
327 static int dnfbcon_switch(int con
, struct fb_info
*info
) {
335 static int dnfbcon_updatevar(int con
, struct fb_info
*info
) {
341 static void dnfbcon_blank(int blank
, struct fb_info
*info
) {
344 outb(0x0, AP_CONTROL_3A
);
347 outb(0x1, AP_CONTROL_3A
);
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
;
359 uint start_mask
,end_mask
,dest
;
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);
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))
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))
388 for(i
=0;i
<y_count
;i
++) {
396 outb(start_mask
,AP_WRITE_ENABLE
);
400 outb(0,AP_WRITE_ENABLE
);
402 for(j
=1;j
<(x_word_count
-1);j
++) {
408 outb(start_mask
,AP_WRITE_ENABLE
);
414 outb(start_mask
| end_mask
, AP_WRITE_ENABLE
);
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
)
430 dn_bitblt(p
,sx
,sy
*p
->fontheight
,dx
,dy
*p
->fontheight
,width
*p
->fontwidth
,
431 height
*p
->fontheight
);
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
);
446 dest
+= p
->next_line
;
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
);
454 dest
-= p
->next_line
;
460 static void clear_apollofb(struct vc_data
*conp
, struct display
*p
, int sy
, int sx
,
461 int height
, int width
)
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
);
472 mymemclear(dest
, height
*p
->fontheight
*width
);
474 for (rows
= height
*p
->fontheight
; rows
--; dest
+= p
->next_line
)
475 if (attr_reverse(p
,conp
))
476 mymemset(dest
, width
);
478 mymemclear_small(dest
, width
);
481 static void putc_apollofb(struct vc_data
*conp
, struct display
*p
, int c
, int yy
,
485 u_int rows
, bold
, revs
, underl
;
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
) {
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
;
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
);
523 cdat
= p
->fontdata
+c
*p
->fontheight
;
524 for (rows
= p
->fontheight
; rows
--; dest
+= p
->next_line
) {
537 static void rev_char_apollofb(struct display
*p
, int xx
, int yy
)
542 dest
= p
->screen_base
+yy
*p
->fontheight
*p
->next_line
+xx
;
543 for (rows
= p
->fontheight
; rows
--; dest
+= p
->next_line
)
547 static struct display_switch dispsw_apollofb
= {
548 setup
: fbcon_mfb_setup
,
549 bmove
: bmove_apollofb
,
550 clear
: clear_apollofb
,
552 putcs
: putcs_apollofb
,
553 revc
: rev_char_apollofb
,
554 fontwidthmask
: FONTWIDTH(8)