Import 2.4.0-test5pre5
[davej-history.git] / drivers / video / dn_cfb4.c
blob18ec1b79bed30d844b396dd34f8cbe14eeb99178
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 <video/fbcon.h>
19 #include <video/fbcon-mfb.h>
20 #include "dn_accel.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_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
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 */
60 /* CREG 1 */
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 */
73 /* CREG 2B */
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 */
84 /* CREG 3A/CREG 3B */
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)) )
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
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 = {
138 owner: THIS_MODULE,
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[] = {
153 { 0, },
157 static char dn_fb_name[]="Apollo ";
159 /* accel stuff */
160 #define USE_DN_ACCEL
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;
171 fix->type_aux=0;
172 fix->visual=FB_VISUAL_MONO10;
173 fix->xpanstep=0;
174 fix->ypanstep=0;
175 fix->ywrapstep=0;
176 fix->line_length=128;
178 return 0;
182 static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
183 struct fb_info *info) {
185 var->xres=1024;
186 var->yres=800;
187 var->xres_virtual=1024;
188 var->yres_virtual=1024;
189 var->xoffset=0;
190 var->yoffset=0;
191 var->bits_per_pixel=1;
192 var->grayscale=0;
193 var->nonstd=0;
194 var->activate=0;
195 var->height=-1;
196 var->width=-1;
197 var->pixclock=0;
198 var->left_margin=0;
199 var->right_margin=0;
200 var->hsync_len=0;
201 var->vsync_len=0;
202 var->sync=0;
203 var->vmode=FB_VMODE_NONINTERLACED;
205 return 0;
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");
213 if(var->xres!=1024)
214 return -EINVAL;
215 if(var->yres!=800)
216 return -EINVAL;
217 if(var->xres_virtual!=1024)
218 return -EINVAL;
219 if(var->yres_virtual!=1024)
220 return -EINVAL;
221 if(var->xoffset!=0)
222 return -EINVAL;
223 if(var->yoffset!=0)
224 return -EINVAL;
225 if(var->bits_per_pixel!=1)
226 return -EINVAL;
227 if(var->grayscale!=0)
228 return -EINVAL;
229 if(var->nonstd!=0)
230 return -EINVAL;
231 if(var->activate!=0)
232 return -EINVAL;
233 if(var->pixclock!=0)
234 return -EINVAL;
235 if(var->left_margin!=0)
236 return -EINVAL;
237 if(var->right_margin!=0)
238 return -EINVAL;
239 if(var->hsync_len!=0)
240 return -EINVAL;
241 if(var->vsync_len!=0)
242 return -EINVAL;
243 if(var->sync!=0)
244 return -EINVAL;
245 if(var->vmode!=FB_VMODE_NONINTERLACED)
246 return -EINVAL;
248 return 0;
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");
257 return -EINVAL;
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");
265 return -EINVAL;
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");
274 return -EINVAL;
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");
283 return -EINVAL;
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);
295 if (con>=0)
296 display=&fb_display[con];
297 else
298 display=&disp[0];
300 if(con==-1)
301 con=0;
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;
314 #ifdef FBCON_HAS_MFB
315 display->dispsw = &fbcon_mfb;
316 #else
317 display->dispsw=&fbcon_dummy;
318 #endif
322 unsigned long dnfb_init(unsigned long mem_start) {
324 int err;
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;
331 fb_info.disp=disp;
332 fb_info.switch_con=&dnfbcon_switch;
333 fb_info.updatevar=&dnfbcon_updatevar;
334 fb_info.blank=&dnfbcon_blank;
335 fb_info.node = -1;
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);
344 if(err < 0) {
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");
359 return mem_start;
364 static int dnfbcon_switch(int con, struct fb_info *info) {
366 currcon=con;
368 return 0;
372 static int dnfbcon_updatevar(int con, struct fb_info *info) {
374 return 0;
378 static void dnfbcon_blank(int blank, struct fb_info *info) {
380 if(blank) {
381 outb(0x0, AP_CONTROL_3A);
383 else {
384 outb(0x1, AP_CONTROL_3A);
387 return ;
391 void dn_video_setup(char *options, int *ints) {
393 return;
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;
401 ushort *src,dummy;
402 uint start_mask,end_mask,dest;
403 short i,j;
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);
410 if(incr>0) {
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))
418 pre_read=1;
420 else {
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))
428 pre_read=1;
431 for(i=0;i<y_count;i++) {
433 if(pre_read) {
434 dummy=*src;
435 src+=incr;
438 if(x_word_count) {
439 outb(start_mask,AP_WRITE_ENABLE);
440 *src=dest;
441 src+=incr;
442 dest+=incr;
443 outb(0,AP_WRITE_ENABLE);
445 for(j=1;j<(x_word_count-1);j++) {
446 *src=dest;
447 src+=incr;
448 dest+=incr;
451 outb(start_mask,AP_WRITE_ENABLE);
452 *src=dest;
453 dest+=incr;
454 src+=incr;
456 else {
457 outb(start_mask | end_mask, AP_WRITE_ENABLE);
458 *src=dest;
459 dest+=incr;
460 src+=incr;
462 src+=(y_delta/16);
463 dest+=(y_delta/16);
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);
477 #ifdef USE_DN_ACCEL
478 dn_bitblt(p,sx,sy*fontheight,dx,dy*fontheight,width*fontwidth,
479 height*fontheight);
480 #else
481 u_char *src, *dest;
482 u_int rows;
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);
493 src += p->next_line;
494 dest += p->next_line;
496 } else {
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);
501 src -= p->next_line;
502 dest -= p->next_line;
505 #endif
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,
515 int xx)
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,
535 putc: putc_apollofb,
536 putcs: putcs_apollofb,
537 revc: rev_char_apollofb,
538 fontwidthmask: FONTWIDTH(8)