File: /usr/src/linux/drivers/video/dn_cfb4.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 <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     
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             
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     
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     
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     
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     
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       
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     	
338     static int dnfbcon_switch(int con,  struct fb_info *info) { 
339     
340     	currcon=con;
341     	
342     	return 0;
343     
344     }
345     
346     static int dnfbcon_updatevar(int con,  struct fb_info *info) {
347     
348     	return 0;
349     
350     }
351     
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     
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     
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     
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     
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     
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     
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