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/uaccess.h>
11 #include <asm/setup.h>
12 #include <asm/segment.h>
13 #include <asm/system.h>
14 /*#include <asm/irq.h>*/
15 #include <asm/q40_master.h>
17 #include <linux/module.h>
18 #include <asm/pgtable.h>
20 #include <video/fbcon.h>
21 #include <video/fbcon-cfb16.h>
23 #define FBIOSETSCROLLMODE 0x4611
25 #define Q40_PHYS_SCREEN_ADDR 0xFE800000
26 static unsigned long q40_screen_addr
;
28 static u16 fbcon_cmap_cfb16
[16];
30 /* frame buffer operations */
32 static int q40fb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
33 struct fb_info
*info
);
34 static int q40fb_get_var(struct fb_var_screeninfo
*var
, int con
,
35 struct fb_info
*info
);
36 static int q40fb_set_var(struct fb_var_screeninfo
*var
, int con
,
37 struct fb_info
*info
);
38 static int q40fb_get_cmap(struct fb_cmap
*cmap
,int kspc
,int con
,
39 struct fb_info
*info
);
40 static int q40fb_set_cmap(struct fb_cmap
*cmap
,int kspc
,int con
,
41 struct fb_info
*info
);
42 static int q40fb_pan_display(struct fb_var_screeninfo
*var
, int con
,
43 struct fb_info
*info
);
44 static int q40fb_ioctl(struct inode
*inode
, struct file
*file
,
45 unsigned int cmd
, unsigned long arg
, int con
,
46 struct fb_info
*info
);
48 static int q40con_switch(int con
, struct fb_info
*info
);
49 static int q40con_updatevar(int con
, struct fb_info
*info
);
50 static void q40con_blank(int blank
, struct fb_info
*info
);
52 static void q40fb_set_disp(int con
, struct fb_info
*info
);
54 static struct display disp
[MAX_NR_CONSOLES
];
55 static struct fb_info fb_info
;
56 static struct fb_ops q40fb_ops
= {
58 fb_get_fix
: q40fb_get_fix
,
59 fb_get_var
: q40fb_get_var
,
60 fb_set_var
: q40fb_set_var
,
61 fb_get_cmap
: q40fb_get_cmap
,
62 fb_set_cmap
: q40fb_set_cmap
,
63 fb_pan_display
: q40fb_pan_display
,
64 fb_ioctl
: q40fb_ioctl
,
69 static char q40fb_name
[]="Q40";
71 static int q40fb_get_fix(struct fb_fix_screeninfo
*fix
, int con
,
74 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
76 strcpy(fix
->id
,"Q40");
77 fix
->smem_start
=q40_screen_addr
;
78 fix
->smem_len
=1024*1024;
79 fix
->type
=FB_TYPE_PACKED_PIXELS
;
81 fix
->visual
=FB_VISUAL_TRUECOLOR
; /* good approximation so far ..*/;
85 fix
->line_length
=1024*2;
87 /* no mmio,accel ...*/
93 static int q40fb_get_var(struct fb_var_screeninfo
*var
, int con
,
96 memset(var
, 0, sizeof(struct fb_var_screeninfo
));
100 var
->xres_virtual
=1024;
101 var
->yres_virtual
=512;
104 var
->bits_per_pixel
=16;
107 var
->activate
=FB_ACTIVATE_NOW
;
108 var
->height
=230; /* approx for my 17" monitor, more important */
109 var
->width
=300; /* than the absolute values is the unusual aspect ratio*/
111 var
->red
.offset
=6; /*6*/
113 var
->green
.offset
=11; /*11*/
117 var
->transp
.length
=0;
125 var
->vmode
=FB_VMODE_NONINTERLACED
;
131 static int q40fb_set_var(struct fb_var_screeninfo
*var
, int con
,
132 struct fb_info
*info
)
138 if(var
->xres_virtual
!=1024)
140 if(var
->yres_virtual
!=512)
146 if(var
->bits_per_pixel
!=16)
148 if(var
->grayscale
!=0)
152 if(var
->activate
!=FB_ACTIVATE_NOW
)
156 if(var
->left_margin
!=0)
158 if(var
->right_margin
!=0)
160 if(var
->hsync_len
!=0)
162 if(var
->vsync_len
!=0)
166 if(var
->vmode
!=FB_VMODE_NONINTERLACED
)
173 static int q40_getcolreg(unsigned regno
, unsigned *red
, unsigned *green
,
174 unsigned *blue
, unsigned *transp
,
175 struct fb_info
*info
)
178 * Read a single color register and split it into colors/transparent.
179 * The return values must have a 16 bit magnitude.
180 * Return != 0 for invalid regno.
182 if (regno
>=16) return 1;
185 *green
= ((fbcon_cmap_cfb16
[regno
]>>11) & 31)<<11;
186 *red
= ((fbcon_cmap_cfb16
[regno
]>>6) & 31)<<11;
187 *blue
= ((fbcon_cmap_cfb16
[regno
]) & 63)<<10;
192 static int q40_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
193 unsigned blue
, unsigned transp
,
194 const struct fb_info
*info
)
197 * Set a single color register. The values supplied have a 16 bit
199 * Return != 0 for invalid regno.
207 fbcon_cmap_cfb16
[regno
] = ((red
& 31) <<6) |
208 ((green
& 31) << 11) |
214 static int q40fb_get_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
215 struct fb_info
*info
)
218 if (con
== currcon
) /* current console? */
219 return fb_get_cmap(cmap
, kspc
, q40_getcolreg
, info
);
220 else if (fb_display
[con
].cmap
.len
) /* non default colormap? */
221 fb_copy_cmap(&fb_display
[con
].cmap
, cmap
, kspc
? 0 : 2);
223 fb_copy_cmap(fb_default_cmap(1<<fb_display
[con
].var
.bits_per_pixel
),
227 printk(KERN_ERR
"get cmap not supported\n");
233 static int q40fb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
234 struct fb_info
*info
)
239 if (!fb_display
[con
].cmap
.len
) { /* no colormap allocated? */
240 if ((err
= fb_alloc_cmap(&fb_display
[con
].cmap
,
241 1<<fb_display
[con
].var
.bits_per_pixel
,
245 if (con
== currcon
) /* current console? */
246 return fb_set_cmap(cmap
, kspc
, q40_setcolreg
, info
);
248 fb_copy_cmap(cmap
, &fb_display
[con
].cmap
, kspc
? 0 : 1);
251 printk(KERN_ERR
"set cmap not supported\n");
257 static int q40fb_pan_display(struct fb_var_screeninfo
*var
, int con
,
258 struct fb_info
*info
)
260 printk(KERN_ERR
"panning not supported\n");
266 static int q40fb_ioctl(struct inode
*inode
, struct file
*file
,
267 unsigned int cmd
, unsigned long arg
, int con
,
268 struct fb_info
*info
)
272 struct display
*display
;
275 display
= &fb_display
[con
];
279 if (cmd
== FBIOSETSCROLLMODE
)
281 i
= verify_area(VERIFY_READ
, (void *)arg
, sizeof(unsigned long));
284 copy_from_user(&i
, (void *)arg
, sizeof(unsigned long));
285 display
->scrollmode
= i
;
287 q40_updatescrollmode(display
);
294 static void q40fb_set_disp(int con
, struct fb_info
*info
)
296 struct fb_fix_screeninfo fix
;
297 struct display
*display
;
299 q40fb_get_fix(&fix
, con
, info
);
302 display
= &fb_display
[con
];
308 display
->screen_base
= fix
.smem_start
;
309 display
->visual
= fix
.visual
;
310 display
->type
= fix
.type
;
311 display
->type_aux
= fix
.type_aux
;
312 display
->ypanstep
= fix
.ypanstep
;
313 display
->ywrapstep
= fix
.ywrapstep
;
314 display
->can_soft_blank
= 0;
315 display
->inverse
= 0;
316 display
->line_length
= fix
.line_length
;
318 display
->scrollmode
= SCROLL_YREDRAW
;
320 #ifdef FBCON_HAS_CFB16
321 display
->dispsw
= &fbcon_cfb16
;
322 disp
->dispsw_data
= fbcon_cmap_cfb16
;
324 display
->dispsw
= &fbcon_dummy
;
334 q40_screen_addr
= kernel_map(Q40_PHYS_SCREEN_ADDR
, 1024*1024,
335 KERNELMAP_NO_COPYBACK
, NULL
);
337 q40_screen_addr
= Q40_PHYS_SCREEN_ADDR
; /* mapped in q40/config.c */
340 fb_info
.changevar
=NULL
;
341 strcpy(&fb_info
.modename
[0],q40fb_name
);
342 fb_info
.fontname
[0]=0;
344 fb_info
.switch_con
=&q40con_switch
;
345 fb_info
.updatevar
=&q40con_updatevar
;
346 fb_info
.blank
=&q40con_blank
;
348 fb_info
.fbops
= &q40fb_ops
;
349 fb_info
.flags
= FBINFO_FLAG_DEFAULT
; /* not as module for now */
351 master_outb(3,DISPLAY_CONTROL_REG
);
353 q40fb_get_var(&disp
[0].var
, 0, &fb_info
);
354 q40fb_set_disp(-1, &fb_info
);
356 if (register_framebuffer(&fb_info
) < 0) {
357 printk(KERN_ERR
"unable to register Q40 frame buffer\n");
361 printk(KERN_INFO
"fb%d: Q40 frame buffer alive and kicking !\n",
362 GET_FB_IDX(fb_info
.node
));
367 static int q40con_switch(int con
, struct fb_info
*info
)
375 static int q40con_updatevar(int con
, struct fb_info
*info
)
380 static void q40con_blank(int blank
, struct fb_info
*info
)