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 <video/fbcon.h>
19 #include <video/fbcon-mfb.h>
20 #include "dn_accel.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_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 */
48
49
50 #define FRAME_BUFFER_START 0x0A0000
51 #define FRAME_BUFFER_LEN 0x20000
52
53 /* CREG 0 */
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 */
59
60 /* CREG 1 */
61 #define AD_BLT 0x80 /* 1xxx.xxxx */
62
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 */
67
68 #define BLANK_DISP 0x00 /* xxxx.xxx0 */
69 #define ENAB_DISP 0x01 /* xxxx.xxx1 */
70
71 #define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
72
73 /* CREG 2B */
74
75 /*
76 * Following 3 defines are common to 1, 4 and 8 plane.
77 */
78
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 */
83
84 /* CREG 3A/CREG 3B */
85 # define RESET_CREG 0x80 /* 1000.0000 */
86
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)) )
90 #define DEST_ZERO 0x0
91 #define SRC_AND_DEST 0x1
92 #define SRC_AND_nDEST 0x2
93 #define SRC 0x3
94 #define nSRC_AND_DEST 0x4
95 #define DEST 0x5
96 #define SRC_XOR_DEST 0x6
97 #define SRC_OR_DEST 0x7
98 #define SRC_NOR_DEST 0x8
99 #define SRC_XNOR_DEST 0x9
100 #define nDEST 0xA
101 #define SRC_OR_nDEST 0xB
102 #define nSRC 0xC
103 #define nSRC_OR_DEST 0xD
104 #define SRC_NAND_DEST 0xE
105 #define DEST_ONE 0xF
106
107 #define SWAP(A) ((A>>8) | ((A&0xff) <<8))
108
109
110 /* frame buffer operations */
111
112 static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
113 struct fb_info *info);
114 static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
115 struct fb_info *info);
116 static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
117 struct fb_info *info);
118 static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
119 struct fb_info *info);
120 static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
121 struct fb_info *info);
122
123 static int dnfbcon_switch(int con,struct fb_info *info);
124 static int dnfbcon_updatevar(int con,struct fb_info *info);
125 static void dnfbcon_blank(int blank,struct fb_info *info);
126
127 static void dn_fb_set_disp(int con,struct fb_info *info);
128
129 static struct display disp[MAX_NR_CONSOLES];
130 static struct fb_info fb_info;
131 static struct fb_ops dn_fb_ops = {
132 owner: THIS_MODULE,
133 fb_get_fix: dn_fb_get_fix,
134 fb_get_var: dn_fb_get_var,
135 fb_set_var: dn_fb_set_var,
136 fb_get_cmap: dn_fb_get_cmap,
137 fb_set_cmap: dn_fb_set_cmap,
138 };
139
140 static int currcon=0;
141
142 #define NUM_TOTAL_MODES 1
143 struct fb_var_screeninfo dn_fb_predefined[] = {
144
145 { 0, },
146
147 };
148
149 static char dn_fb_name[]="Apollo ";
150
151 /* accel stuff */
152 #define USE_DN_ACCEL
153
154 static struct display_switch dispsw_apollofb;
155
dn_fb_get_fix(struct fb_fix_screeninfo * fix,int con,struct fb_info * info)156 static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
157 struct fb_info *info) {
158
159 strcpy(fix->id,"Apollo Color4");
160 fix->smem_start=(FRAME_BUFFER_START+IO_BASE);
161 fix->smem_len=FRAME_BUFFER_LEN;
162 fix->type=FB_TYPE_PACKED_PIXELS;
163 fix->type_aux=0;
164 fix->visual=FB_VISUAL_MONO10;
165 fix->xpanstep=0;
166 fix->ypanstep=0;
167 fix->ywrapstep=0;
168 fix->line_length=128;
169
170 return 0;
171
172 }
173
dn_fb_get_var(struct fb_var_screeninfo * var,int con,struct fb_info * info)174 static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
175 struct fb_info *info) {
176
177 var->xres=1024;
178 var->yres=800;
179 var->xres_virtual=1024;
180 var->yres_virtual=1024;
181 var->xoffset=0;
182 var->yoffset=0;
183 var->bits_per_pixel=1;
184 var->grayscale=0;
185 var->nonstd=0;
186 var->activate=0;
187 var->height=-1;
188 var->width=-1;
189 var->pixclock=0;
190 var->left_margin=0;
191 var->right_margin=0;
192 var->hsync_len=0;
193 var->vsync_len=0;
194 var->sync=0;
195 var->vmode=FB_VMODE_NONINTERLACED;
196
197 return 0;
198
199 }
200
dn_fb_set_var(struct fb_var_screeninfo * var,int con,struct fb_info * info)201 static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
202 struct fb_info *info) {
203
204 printk("fb_set_var\n");
205 if(var->xres!=1024)
206 return -EINVAL;
207 if(var->yres!=800)
208 return -EINVAL;
209 if(var->xres_virtual!=1024)
210 return -EINVAL;
211 if(var->yres_virtual!=1024)
212 return -EINVAL;
213 if(var->xoffset!=0)
214 return -EINVAL;
215 if(var->yoffset!=0)
216 return -EINVAL;
217 if(var->bits_per_pixel!=1)
218 return -EINVAL;
219 if(var->grayscale!=0)
220 return -EINVAL;
221 if(var->nonstd!=0)
222 return -EINVAL;
223 if(var->activate!=0)
224 return -EINVAL;
225 if(var->pixclock!=0)
226 return -EINVAL;
227 if(var->left_margin!=0)
228 return -EINVAL;
229 if(var->right_margin!=0)
230 return -EINVAL;
231 if(var->hsync_len!=0)
232 return -EINVAL;
233 if(var->vsync_len!=0)
234 return -EINVAL;
235 if(var->sync!=0)
236 return -EINVAL;
237 if(var->vmode!=FB_VMODE_NONINTERLACED)
238 return -EINVAL;
239
240 return 0;
241
242 }
243
dn_fb_get_cmap(struct fb_cmap * cmap,int kspc,int con,struct fb_info * info)244 static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
245 struct fb_info *info) {
246
247 printk("get cmap not supported\n");
248
249 return -EINVAL;
250 }
251
dn_fb_set_cmap(struct fb_cmap * cmap,int kspc,int con,struct fb_info * info)252 static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
253 struct fb_info *info) {
254
255 printk("set cmap not supported\n");
256
257 return -EINVAL;
258
259 }
260
dn_fb_set_disp(int con,struct fb_info * info)261 static void dn_fb_set_disp(int con, struct fb_info *info) {
262
263 struct fb_fix_screeninfo fix;
264 struct display *display;
265
266
267 dn_fb_get_fix(&fix,con, info);
268
269 if (con>=0)
270 display=&fb_display[con];
271 else
272 display=&disp[0];
273
274 if(con==-1)
275 con=0;
276
277 display->screen_base = (u_char *)fix.smem_start;
278 printk("screenbase: %lx\n",fix.smem_start);
279 display->visual = fix.visual;
280 display->type = fix.type;
281 display->type_aux = fix.type_aux;
282 display->ypanstep = fix.ypanstep;
283 display->ywrapstep = fix.ywrapstep;
284 display->can_soft_blank = 1;
285 display->inverse = 0;
286 display->line_length = fix.line_length;
287 display->scrollmode = SCROLL_YREDRAW;
288 #ifdef FBCON_HAS_MFB
289 display->dispsw = &fbcon_mfb;
290 #else
291 display->dispsw=&fbcon_dummy;
292 #endif
293
294 }
295
dnfb_init(unsigned long mem_start)296 unsigned long dnfb_init(unsigned long mem_start) {
297
298 int err;
299
300 printk("dn_fb_init\n");
301
302 fb_info.changevar=NULL;
303 strcpy(&fb_info.modename[0],dn_fb_name);
304 fb_info.fontname[0]=0;
305 fb_info.disp=disp;
306 fb_info.switch_con=&dnfbcon_switch;
307 fb_info.updatevar=&dnfbcon_updatevar;
308 fb_info.blank=&dnfbcon_blank;
309 fb_info.node = -1;
310 fb_info.fbops = &dn_fb_ops;
311 fb_info.flags = FBINFO_FLAG_DEFAULT;
312
313 dn_fb_get_var(&disp[0].var,0, &fb_info);
314 dn_fb_set_disp(-1, &fb_info);
315
316 printk("dn_fb_init: register\n");
317 err=register_framebuffer(&fb_info);
318 if(err < 0) {
319 panic("unable to register apollo frame buffer\n");
320 }
321
322 /* now we have registered we can safely setup the hardware */
323
324 outb(RESET_CREG, AP_CONTROL_3A);
325 outb(NORMAL_MODE, AP_CONTROL_0);
326 outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
327 outb(S_DATA_PLN, AP_CONTROL_2);
328 outw(SWAP(0x3), AP_ROP_1);
329
330 printk("apollo frame buffer alive and kicking !\n");
331
332
333 return mem_start;
334
335 }
336
337
dnfbcon_switch(int con,struct fb_info * info)338 static int dnfbcon_switch(int con, struct fb_info *info) {
339
340 currcon=con;
341
342 return 0;
343
344 }
345
dnfbcon_updatevar(int con,struct fb_info * info)346 static int dnfbcon_updatevar(int con, struct fb_info *info) {
347
348 return 0;
349
350 }
351
dnfbcon_blank(int blank,struct fb_info * info)352 static void dnfbcon_blank(int blank, struct fb_info *info) {
353
354 if(blank) {
355 outb(0x0, AP_CONTROL_3A);
356 }
357 else {
358 outb(0x1, AP_CONTROL_3A);
359 }
360
361 return ;
362
363 }
364
dn_bitblt(struct display * p,int x_src,int y_src,int x_dest,int y_dest,int x_count,int y_count)365 void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
366 int x_count, int y_count) {
367
368 int incr,y_delta,pre_read=0,x_end,x_word_count;
369 ushort *src,dummy;
370 uint start_mask,end_mask,dest;
371 short i,j;
372
373 incr=(y_dest<=y_src) ? 1 : -1 ;
374
375 src=(ushort *)(p->screen_base+ y_src*p->next_line+(x_src >> 4));
376 dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
377
378 if(incr>0) {
379 y_delta=(p->next_line*8)-x_src-x_count;
380 x_end=x_dest+x_count-1;
381 x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
382 start_mask=0xffff0000 >> (x_dest & 0xf);
383 end_mask=0x7ffff >> (x_end & 0xf);
384 outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0);
385 if((x_dest & 0xf) < (x_src & 0xf))
386 pre_read=1;
387 }
388 else {
389 y_delta=-((p->next_line*8)-x_src-x_count);
390 x_end=x_dest-x_count+1;
391 x_word_count=(x_dest>>4) - (x_end >> 4) + 1;
392 start_mask=0x7ffff >> (x_dest & 0xf);
393 end_mask=0xffff0000 >> (x_end & 0xf);
394 outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0);
395 if((x_dest & 0xf) > (x_src & 0xf))
396 pre_read=1;
397 }
398
399 for(i=0;i<y_count;i++) {
400
401 if(pre_read) {
402 dummy=*src;
403 src+=incr;
404 }
405
406 if(x_word_count) {
407 outb(start_mask,AP_WRITE_ENABLE);
408 *src=dest;
409 src+=incr;
410 dest+=incr;
411 outb(0,AP_WRITE_ENABLE);
412
413 for(j=1;j<(x_word_count-1);j++) {
414 *src=dest;
415 src+=incr;
416 dest+=incr;
417 }
418
419 outb(start_mask,AP_WRITE_ENABLE);
420 *src=dest;
421 dest+=incr;
422 src+=incr;
423 }
424 else {
425 outb(start_mask | end_mask, AP_WRITE_ENABLE);
426 *src=dest;
427 dest+=incr;
428 src+=incr;
429 }
430 src+=(y_delta/16);
431 dest+=(y_delta/16);
432 }
433 outb(NORMAL_MODE,AP_CONTROL_0);
434 }
435
bmove_apollofb(struct display * p,int sy,int sx,int dy,int dx,int height,int width)436 static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
437 int height, int width)
438 {
439
440 int fontheight,fontwidth;
441
442 fontheight=fontheight(p);
443 fontwidth=fontwidth(p);
444
445 #ifdef USE_DN_ACCEL
446 dn_bitblt(p,sx,sy*fontheight,dx,dy*fontheight,width*fontwidth,
447 height*fontheight);
448 #else
449 u_char *src, *dest;
450 u_int rows;
451
452 if (sx == 0 && dx == 0 && width == p->next_line) {
453 src = p->screen_base+sy*fontheight*width;
454 dest = p->screen_base+dy*fontheight*width;
455 mymemmove(dest, src, height*fontheight*width);
456 } else if (dy <= sy) {
457 src = p->screen_base+sy*fontheight*p->next_line+sx;
458 dest = p->screen_base+dy*fontheight*p->next_line+dx;
459 for (rows = height*fontheight; rows--;) {
460 mymemmove(dest, src, width);
461 src += p->next_line;
462 dest += p->next_line;
463 }
464 } else {
465 src = p->screen_base+((sy+height)*fontheight-1)*p->next_line+sx;
466 dest = p->screen_base+((dy+height)*fontheight-1)*p->next_line+dx;
467 for (rows = height*fontheight; rows--;) {
468 mymemmove(dest, src, width);
469 src -= p->next_line;
470 dest -= p->next_line;
471 }
472 }
473 #endif
474 }
475
clear_apollofb(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)476 static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
477 int height, int width)
478 {
479 fbcon_mfb_clear(conp,p,sy,sx,height,width);
480 }
481
putc_apollofb(struct vc_data * conp,struct display * p,int c,int yy,int xx)482 static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
483 int xx)
484 {
485 fbcon_mfb_putc(conp,p,c,yy,xx);
486 }
487
putcs_apollofb(struct vc_data * conp,struct display * p,const unsigned short * s,int count,int yy,int xx)488 static void putcs_apollofb(struct vc_data *conp, struct display *p, const unsigned short *s,
489 int count, int yy, int xx)
490 {
491 fbcon_mfb_putcs(conp,p,s,count,yy,xx);
492 }
493
rev_char_apollofb(struct display * p,int xx,int yy)494 static void rev_char_apollofb(struct display *p, int xx, int yy)
495 {
496 fbcon_mfb_revc(p,xx,yy);
497 }
498
499 static struct display_switch dispsw_apollofb = {
500 setup: fbcon_mfb_setup,
501 bmove: bmove_apollofb,
502 clear: clear_apollofb,
503 putc: putc_apollofb,
504 putcs: putcs_apollofb,
505 revc: rev_char_apollofb,
506 fontwidthmask: FONTWIDTH(8)
507 };
508
509 MODULE_LICENSE("GPL");
510