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>
18 #include <video/fbcon.h>
19 #include <video/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_1 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
39 #define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4) /* Diagnostic Memory Request. Write Word */
40 #define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
41 #define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
42 #define AP_CONTROL_2 isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
43 #define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
44 #define AP_LUT_RED isaIO2mem(AP_IOBASE+9) /* Red Lookup Table register. Write */
45 #define AP_LUT_GREEN isaIO2mem(AP_IOBASE+0xb) /* Green Lookup Table register. Write */
46 #define AP_LUT_BLUE isaIO2mem(AP_IOBASE+0xd) /* Blue Lookup Table register. Write */
47 #define AP_AD_CHANNEL isaIO2mem(AP_IOBASE+0xf) /* A/D Result/Channel register. Read/Write */
50 #define FRAME_BUFFER_START 0x0A0000
51 #define FRAME_BUFFER_LEN 0x20000
54 #define VECTOR_MODE 0x40 /* 010x.xxxx */
55 #define DBLT_MODE 0x80 /* 100x.xxxx */
56 #define NORMAL_MODE 0xE0 /* 111x.xxxx */
57 #define SHIFT_BITS 0x1F /* xxx1.1111 */
58 /* other bits are Shift value */
61 #define AD_BLT 0x80 /* 1xxx.xxxx */
63 #define ROP_EN 0x10 /* xxx1.xxxx */
64 #define DST_EQ_SRC 0x00 /* xxx0.xxxx */
65 #define nRESET_SYNC 0x08 /* xxxx.1xxx */
66 #define SYNC_ENAB 0x02 /* xxxx.xx1x */
68 #define BLANK_DISP 0x00 /* xxxx.xxx0 */
69 #define ENAB_DISP 0x01 /* xxxx.xxx1 */
71 #define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
76 * Following 3 defines are common to 1, 4 and 8 plane.
79 #define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
80 #define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
81 #define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
82 one plane of image mem */
85 # define RESET_CREG 0x80 /* 1000.0000 */
87 /* ROP REG - all one nibble */
88 /* ********* NOTE : this is used r0,r1,r2,r3 *********** */
89 #define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
91 #define SRC_AND_DEST 0x1
92 #define SRC_AND_nDEST 0x2
94 #define nSRC_AND_DEST 0x4
96 #define SRC_XOR_DEST 0x6
97 #define SRC_OR_DEST 0x7
98 #define SRC_NOR_DEST 0x8
99 #define SRC_XNOR_DEST 0x9
101 #define SRC_OR_nDEST 0xB
103 #define nSRC_OR_DEST 0xD
104 #define SRC_NAND_DEST 0xE
107 #define SWAP(A) ((A>>8) | ((A&0xff) <<8))
110 void dn_video_setup(char *options
, int *ints
);
112 /* frame buffer operations */
114 static int dn_fb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
115 struct fb_info
*info
);
116 static int dn_fb_get_var(struct fb_var_screeninfo
*var
, int con
,
117 struct fb_info
*info
);
118 static int dn_fb_set_var(struct fb_var_screeninfo
*var
, int isactive
,
119 struct fb_info
*info
);
120 static int dn_fb_get_cmap(struct fb_cmap
*cmap
,int kspc
,int con
,
121 struct fb_info
*info
);
122 static int dn_fb_set_cmap(struct fb_cmap
*cmap
,int kspc
,int con
,
123 struct fb_info
*info
);
124 static int dn_fb_pan_display(struct fb_var_screeninfo
*var
, int con
,
125 struct fb_info
*info
);
126 static int dn_fb_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
,
127 unsigned long arg
, int con
, struct fb_info
*info
);
129 static int dnfbcon_switch(int con
,struct fb_info
*info
);
130 static int dnfbcon_updatevar(int con
,struct fb_info
*info
);
131 static void dnfbcon_blank(int blank
,struct fb_info
*info
);
133 static void dn_fb_set_disp(int con
,struct fb_info
*info
);
135 static struct display disp
[MAX_NR_CONSOLES
];
136 static struct fb_info fb_info
;
137 static struct fb_ops dn_fb_ops
= {
139 fb_get_fix
: dn_fb_get_fix
,
140 fb_get_var
: dn_fb_get_var
,
141 fb_set_var
: dn_fb_set_var
,
142 fb_get_cmap
: dn_fb_get_cmap
,
143 fb_set_cmap
: dn_fb_set_cmap
,
144 fb_pan_display
: dn_fb_pan_display
,
145 fb_ioctl
: dn_fb_ioctl
,
148 static int currcon
=0;
150 #define NUM_TOTAL_MODES 1
151 struct fb_var_screeninfo dn_fb_predefined
[] = {
157 static char dn_fb_name
[]="Apollo ";
162 static struct display_switch dispsw_apollofb
;
164 static int dn_fb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
165 struct fb_info
*info
) {
167 strcpy(fix
->id
,"Apollo Color4");
168 fix
->smem_start
=(FRAME_BUFFER_START
+IO_BASE
);
169 fix
->smem_len
=FRAME_BUFFER_LEN
;
170 fix
->type
=FB_TYPE_PACKED_PIXELS
;
172 fix
->visual
=FB_VISUAL_MONO10
;
176 fix
->line_length
=128;
182 static int dn_fb_get_var(struct fb_var_screeninfo
*var
, int con
,
183 struct fb_info
*info
) {
187 var
->xres_virtual
=1024;
188 var
->yres_virtual
=1024;
191 var
->bits_per_pixel
=1;
203 var
->vmode
=FB_VMODE_NONINTERLACED
;
209 static int dn_fb_set_var(struct fb_var_screeninfo
*var
, int con
,
210 struct fb_info
*info
) {
212 printk("fb_set_var\n");
217 if(var
->xres_virtual
!=1024)
219 if(var
->yres_virtual
!=1024)
225 if(var
->bits_per_pixel
!=1)
227 if(var
->grayscale
!=0)
235 if(var
->left_margin
!=0)
237 if(var
->right_margin
!=0)
239 if(var
->hsync_len
!=0)
241 if(var
->vsync_len
!=0)
245 if(var
->vmode
!=FB_VMODE_NONINTERLACED
)
252 static int dn_fb_get_cmap(struct fb_cmap
*cmap
,int kspc
,int con
,
253 struct fb_info
*info
) {
255 printk("get cmap not supported\n");
260 static int dn_fb_set_cmap(struct fb_cmap
*cmap
,int kspc
,int con
,
261 struct fb_info
*info
) {
263 printk("set cmap not supported\n");
269 static int dn_fb_pan_display(struct fb_var_screeninfo
*var
, int con
,
270 struct fb_info
*info
) {
272 printk("panning not supported\n");
278 static int dn_fb_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
,
279 unsigned long arg
, int con
, struct fb_info
*info
) {
281 printk("no IOCTLs as of yet.\n");
287 static void dn_fb_set_disp(int con
, struct fb_info
*info
) {
289 struct fb_fix_screeninfo fix
;
290 struct display
*display
;
293 dn_fb_get_fix(&fix
,con
, info
);
296 display
=&fb_display
[con
];
303 display
->screen_base
= (u_char
*)fix
.smem_start
;
304 printk("screenbase: %lx\n",fix
.smem_start
);
305 display
->visual
= fix
.visual
;
306 display
->type
= fix
.type
;
307 display
->type_aux
= fix
.type_aux
;
308 display
->ypanstep
= fix
.ypanstep
;
309 display
->ywrapstep
= fix
.ywrapstep
;
310 display
->can_soft_blank
= 1;
311 display
->inverse
= 0;
312 display
->line_length
= fix
.line_length
;
313 display
->scrollmode
= SCROLL_YREDRAW
;
315 display
->dispsw
= &fbcon_mfb
;
317 display
->dispsw
=&fbcon_dummy
;
322 unsigned long dnfb_init(unsigned long mem_start
) {
326 printk("dn_fb_init\n");
328 fb_info
.changevar
=NULL
;
329 strcpy(&fb_info
.modename
[0],dn_fb_name
);
330 fb_info
.fontname
[0]=0;
332 fb_info
.switch_con
=&dnfbcon_switch
;
333 fb_info
.updatevar
=&dnfbcon_updatevar
;
334 fb_info
.blank
=&dnfbcon_blank
;
336 fb_info
.fbops
= &dn_fb_ops
;
337 fb_info
.flags
= FBINFO_FLAG_DEFAULT
;
339 dn_fb_get_var(&disp
[0].var
,0, &fb_info
);
340 dn_fb_set_disp(-1, &fb_info
);
342 printk("dn_fb_init: register\n");
343 err
=register_framebuffer(&fb_info
);
345 panic("unable to register apollo frame buffer\n");
348 /* now we have registered we can safely setup the hardware */
350 outb(RESET_CREG
, AP_CONTROL_3A
);
351 outb(NORMAL_MODE
, AP_CONTROL_0
);
352 outb((AD_BLT
| DST_EQ_SRC
| NORM_CREG1
), AP_CONTROL_1
);
353 outb(S_DATA_PLN
, AP_CONTROL_2
);
354 outw(SWAP(0x3), AP_ROP_1
);
356 printk("apollo frame buffer alive and kicking !\n");
364 static int dnfbcon_switch(int con
, struct fb_info
*info
) {
372 static int dnfbcon_updatevar(int con
, struct fb_info
*info
) {
378 static void dnfbcon_blank(int blank
, struct fb_info
*info
) {
381 outb(0x0, AP_CONTROL_3A
);
384 outb(0x1, AP_CONTROL_3A
);
391 void dn_video_setup(char *options
, int *ints
) {
397 void dn_bitblt(struct display
*p
,int x_src
,int y_src
, int x_dest
, int y_dest
,
398 int x_count
, int y_count
) {
400 int incr
,y_delta
,pre_read
=0,x_end
,x_word_count
;
402 uint start_mask
,end_mask
,dest
;
405 incr
=(y_dest
<=y_src
) ? 1 : -1 ;
407 src
=(ushort
*)(p
->screen_base
+ y_src
*p
->next_line
+(x_src
>> 4));
408 dest
=y_dest
*(p
->next_line
>> 1)+(x_dest
>> 4);
411 y_delta
=(p
->next_line
*8)-x_src
-x_count
;
412 x_end
=x_dest
+x_count
-1;
413 x_word_count
=(x_end
>>4) - (x_dest
>> 4) + 1;
414 start_mask
=0xffff0000 >> (x_dest
& 0xf);
415 end_mask
=0x7ffff >> (x_end
& 0xf);
416 outb((((x_dest
& 0xf) - (x_src
&0xf)) % 16)|(0x4 << 5),AP_CONTROL_0
);
417 if((x_dest
& 0xf) < (x_src
& 0xf))
421 y_delta
=-((p
->next_line
*8)-x_src
-x_count
);
422 x_end
=x_dest
-x_count
+1;
423 x_word_count
=(x_dest
>>4) - (x_end
>> 4) + 1;
424 start_mask
=0x7ffff >> (x_dest
& 0xf);
425 end_mask
=0xffff0000 >> (x_end
& 0xf);
426 outb(((-((x_src
& 0xf) - (x_dest
&0xf))) % 16)|(0x4 << 5),AP_CONTROL_0
);
427 if((x_dest
& 0xf) > (x_src
& 0xf))
431 for(i
=0;i
<y_count
;i
++) {
439 outb(start_mask
,AP_WRITE_ENABLE
);
443 outb(0,AP_WRITE_ENABLE
);
445 for(j
=1;j
<(x_word_count
-1);j
++) {
451 outb(start_mask
,AP_WRITE_ENABLE
);
457 outb(start_mask
| end_mask
, AP_WRITE_ENABLE
);
465 outb(NORMAL_MODE
,AP_CONTROL_0
);
468 static void bmove_apollofb(struct display
*p
, int sy
, int sx
, int dy
, int dx
,
469 int height
, int width
)
472 int fontheight
,fontwidth
;
474 fontheight
=fontheight(p
);
475 fontwidth
=fontwidth(p
);
478 dn_bitblt(p
,sx
,sy
*fontheight
,dx
,dy
*fontheight
,width
*fontwidth
,
484 if (sx
== 0 && dx
== 0 && width
== p
->next_line
) {
485 src
= p
->screen_base
+sy
*fontheight
*width
;
486 dest
= p
->screen_base
+dy
*fontheight
*width
;
487 mymemmove(dest
, src
, height
*fontheight
*width
);
488 } else if (dy
<= sy
) {
489 src
= p
->screen_base
+sy
*fontheight
*p
->next_line
+sx
;
490 dest
= p
->screen_base
+dy
*fontheight
*p
->next_line
+dx
;
491 for (rows
= height
*fontheight
; rows
--;) {
492 mymemmove(dest
, src
, width
);
494 dest
+= p
->next_line
;
497 src
= p
->screen_base
+((sy
+height
)*fontheight
-1)*p
->next_line
+sx
;
498 dest
= p
->screen_base
+((dy
+height
)*fontheight
-1)*p
->next_line
+dx
;
499 for (rows
= height
*fontheight
; rows
--;) {
500 mymemmove(dest
, src
, width
);
502 dest
-= p
->next_line
;
508 static void clear_apollofb(struct vc_data
*conp
, struct display
*p
, int sy
, int sx
,
509 int height
, int width
)
511 fbcon_mfb_clear(conp
,p
,sy
,sx
,height
,width
);
514 static void putc_apollofb(struct vc_data
*conp
, struct display
*p
, int c
, int yy
,
517 fbcon_mfb_putc(conp
,p
,c
,yy
,xx
);
520 static void putcs_apollofb(struct vc_data
*conp
, struct display
*p
, const unsigned short *s
,
521 int count
, int yy
, int xx
)
523 fbcon_mfb_putcs(conp
,p
,s
,count
,yy
,xx
);
526 static void rev_char_apollofb(struct display
*p
, int xx
, int yy
)
528 fbcon_mfb_revc(p
,xx
,yy
);
531 static struct display_switch dispsw_apollofb
= {
532 setup
: fbcon_mfb_setup
,
533 bmove
: bmove_apollofb
,
534 clear
: clear_apollofb
,
536 putcs
: putcs_apollofb
,
537 revc
: rev_char_apollofb
,
538 fontwidthmask
: FONTWIDTH(8)