e100: Convert e100 to use netdev_alloc_skb().
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / video / atafb.c
blob5831893bf7a0d3256cf2e620fcd783102a0a0d2d
1 /*
2 * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
4 * Copyright (C) 1994 Martin Schaller & Roman Hodek
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
10 * History:
11 * - 03 Jan 95: Original version by Martin Schaller: The TT driver and
12 * all the device independent stuff
13 * - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
14 * and wrote the Falcon, ST(E), and External drivers
15 * based on the original TT driver.
16 * - 07 May 95: Martin: Added colormap operations for the external driver
17 * - 21 May 95: Martin: Added support for overscan
18 * Andreas: some bug fixes for this
19 * - Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
20 * Programmable Falcon video modes
21 * (thanks to Christian Cartus for documentation
22 * of VIDEL registers).
23 * - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
24 * on minor 24...31. "user0" may be set on commandline by
25 * "R<x>;<y>;<depth>". (Makes sense only on Falcon)
26 * Video mode switch on Falcon now done at next VBL interrupt
27 * to avoid the annoying right shift of the screen.
28 * - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST
29 * The external-part is legacy, therefore hardware-specific
30 * functions like panning/hardwarescrolling/blanking isn't
31 * supported.
32 * - 29 Sep 97: Juergen: added Romans suggestion for pan_display
33 * (var->xoffset was changed even if no set_screen_base avail.)
34 * - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause
35 * we know how to set the colors
36 * ext_*palette: read from ext_colors (former MV300_colors)
37 * write to ext_colors and RAMDAC
39 * To do:
40 * - For the Falcon it is not possible to set random video modes on
41 * SM124 and SC/TV, only the bootup resolution is supported.
45 #define ATAFB_TT
46 #define ATAFB_STE
47 #define ATAFB_EXT
48 #define ATAFB_FALCON
50 #include <linux/module.h>
51 #include <linux/kernel.h>
52 #include <linux/sched.h>
53 #include <linux/errno.h>
54 #include <linux/string.h>
55 #include <linux/mm.h>
56 #include <linux/slab.h>
57 #include <linux/delay.h>
58 #include <linux/init.h>
59 #include <linux/interrupt.h>
61 #include <asm/setup.h>
62 #include <asm/uaccess.h>
63 #include <asm/pgtable.h>
64 #include <asm/irq.h>
65 #include <asm/io.h>
67 #include <asm/atarihw.h>
68 #include <asm/atariints.h>
69 #include <asm/atari_stram.h>
71 #include <linux/fb.h>
72 #include <asm/atarikb.h>
74 #include <video/fbcon.h>
75 #include <video/fbcon-cfb8.h>
76 #include <video/fbcon-cfb16.h>
77 #include <video/fbcon-iplan2p2.h>
78 #include <video/fbcon-iplan2p4.h>
79 #include <video/fbcon-iplan2p8.h>
80 #include <video/fbcon-mfb.h>
83 #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
84 #define SWITCH_SND6 0x40
85 #define SWITCH_SND7 0x80
86 #define SWITCH_NONE 0x00
89 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
92 static int default_par=0; /* default resolution (0=none) */
94 static unsigned long default_mem_req=0;
96 static int hwscroll=-1;
98 static int use_hwscroll = 1;
100 static int sttt_xres=640,st_yres=400,tt_yres=480;
101 static int sttt_xres_virtual=640,sttt_yres_virtual=400;
102 static int ovsc_offset=0, ovsc_addlen=0;
104 static struct atafb_par {
105 void *screen_base;
106 int yres_virtual;
107 #if defined ATAFB_TT || defined ATAFB_STE
108 union {
109 struct {
110 int mode;
111 int sync;
112 } tt, st;
113 #endif
114 #ifdef ATAFB_FALCON
115 struct falcon_hw {
116 /* Here are fields for storing a video mode, as direct
117 * parameters for the hardware.
119 short sync;
120 short line_width;
121 short line_offset;
122 short st_shift;
123 short f_shift;
124 short vid_control;
125 short vid_mode;
126 short xoffset;
127 short hht, hbb, hbe, hdb, hde, hss;
128 short vft, vbb, vbe, vdb, vde, vss;
129 /* auxiliary information */
130 short mono;
131 short ste_mode;
132 short bpp;
133 } falcon;
134 #endif
135 /* Nothing needed for external mode */
136 } hw;
137 } current_par;
139 /* Don't calculate an own resolution, and thus don't change the one found when
140 * booting (currently used for the Falcon to keep settings for internal video
141 * hardware extensions (e.g. ScreenBlaster) */
142 static int DontCalcRes = 0;
144 #ifdef ATAFB_FALCON
145 #define HHT hw.falcon.hht
146 #define HBB hw.falcon.hbb
147 #define HBE hw.falcon.hbe
148 #define HDB hw.falcon.hdb
149 #define HDE hw.falcon.hde
150 #define HSS hw.falcon.hss
151 #define VFT hw.falcon.vft
152 #define VBB hw.falcon.vbb
153 #define VBE hw.falcon.vbe
154 #define VDB hw.falcon.vdb
155 #define VDE hw.falcon.vde
156 #define VSS hw.falcon.vss
157 #define VCO_CLOCK25 0x04
158 #define VCO_CSYPOS 0x10
159 #define VCO_VSYPOS 0x20
160 #define VCO_HSYPOS 0x40
161 #define VCO_SHORTOFFS 0x100
162 #define VMO_DOUBLE 0x01
163 #define VMO_INTER 0x02
164 #define VMO_PREMASK 0x0c
165 #endif
167 static struct fb_info fb_info;
169 static void *screen_base; /* base address of screen */
170 static void *real_screen_base; /* (only for Overscan) */
172 static int screen_len;
174 static int current_par_valid=0;
176 static int mono_moni=0;
178 static struct display disp;
181 #ifdef ATAFB_EXT
182 /* external video handling */
184 static unsigned external_xres;
185 static unsigned external_xres_virtual;
186 static unsigned external_yres;
187 /* not needed - atafb will never support panning/hardwarescroll with external
188 * static unsigned external_yres_virtual;
191 static unsigned external_depth;
192 static int external_pmode;
193 static void *external_addr = 0;
194 static unsigned long external_len;
195 static unsigned long external_vgaiobase = 0;
196 static unsigned int external_bitspercol = 6;
199 JOE <joe@amber.dinoco.de>:
200 added card type for external driver, is only needed for
201 colormap handling.
204 enum cardtype { IS_VGA, IS_MV300 };
205 static enum cardtype external_card_type = IS_VGA;
208 The MV300 mixes the color registers. So we need an array of munged
209 indices in order to access the correct reg.
211 static int MV300_reg_1bit[2]={0,1};
212 static int MV300_reg_4bit[16]={
213 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
214 static int MV300_reg_8bit[256]={
215 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
216 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
217 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
218 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
219 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
220 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
221 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
222 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
223 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
224 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
225 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
226 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
227 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
228 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
229 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
230 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 };
232 static int *MV300_reg = MV300_reg_8bit;
235 And on the MV300 it's difficult to read out the hardware palette. So we
236 just keep track of the set colors in our own array here, and use that!
239 static struct { unsigned char red,green,blue,pad; } ext_color[256];
240 #endif /* ATAFB_EXT */
243 static int inverse=0;
245 extern int fontheight_8x8;
246 extern int fontwidth_8x8;
247 extern unsigned char fontdata_8x8[];
249 extern int fontheight_8x16;
250 extern int fontwidth_8x16;
251 extern unsigned char fontdata_8x16[];
253 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
254 * TT, or Falcon.
256 * int (*detect)( void )
257 * This function should detect the current video mode settings and
258 * store them in atafb_predefined[0] for later reference by the
259 * user. Return the index+1 of an equivalent predefined mode or 0
260 * if there is no such.
262 * int (*encode_fix)( struct fb_fix_screeninfo *fix,
263 * struct atafb_par *par )
264 * This function should fill in the 'fix' structure based on the
265 * values in the 'par' structure.
267 * int (*decode_var)( struct fb_var_screeninfo *var,
268 * struct atafb_par *par )
269 * Get the video params out of 'var'. If a value doesn't fit, round
270 * it up, if it's too big, return EINVAL.
271 * Round up in the following order: bits_per_pixel, xres, yres,
272 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
273 * horizontal timing, vertical timing.
275 * int (*encode_var)( struct fb_var_screeninfo *var,
276 * struct atafb_par *par );
277 * Fill the 'var' structure based on the values in 'par' and maybe
278 * other values read out of the hardware.
280 * void (*get_par)( struct atafb_par *par )
281 * Fill the hardware's 'par' structure.
283 * void (*set_par)( struct atafb_par *par )
284 * Set the hardware according to 'par'.
286 * int (*getcolreg)( unsigned regno, unsigned *red,
287 * unsigned *green, unsigned *blue,
288 * unsigned *transp, struct fb_info *info )
289 * Read a single color register and split it into
290 * colors/transparent. Return != 0 for invalid regno.
292 * void (*set_screen_base)(void *s_base)
293 * Set the base address of the displayed frame buffer. Only called
294 * if yres_virtual > yres or xres_virtual > xres.
296 * int (*blank)( int blank_mode )
297 * Blank the screen if blank_mode!=0, else unblank. If blank==NULL then
298 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
299 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
300 * doesn't support it. Implements VESA suspend and powerdown modes on
301 * hardware that supports disabling hsync/vsync:
302 * blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown.
305 static struct fb_hwswitch {
306 int (*detect)( void );
307 int (*encode_fix)( struct fb_fix_screeninfo *fix,
308 struct atafb_par *par );
309 int (*decode_var)( struct fb_var_screeninfo *var,
310 struct atafb_par *par );
311 int (*encode_var)( struct fb_var_screeninfo *var,
312 struct atafb_par *par );
313 void (*get_par)( struct atafb_par *par );
314 void (*set_par)( struct atafb_par *par );
315 int (*getcolreg)( unsigned regno, unsigned *red,
316 unsigned *green, unsigned *blue,
317 unsigned *transp, struct fb_info *info );
318 void (*set_screen_base)(void *s_base);
319 int (*blank)( int blank_mode );
320 int (*pan_display)( struct fb_var_screeninfo *var,
321 struct atafb_par *par);
322 } *fbhw;
324 static char *autodetect_names[] = {"autodetect", NULL};
325 static char *stlow_names[] = {"stlow", NULL};
326 static char *stmid_names[] = {"stmid", "default5", NULL};
327 static char *sthigh_names[] = {"sthigh", "default4", NULL};
328 static char *ttlow_names[] = {"ttlow", NULL};
329 static char *ttmid_names[]= {"ttmid", "default1", NULL};
330 static char *tthigh_names[]= {"tthigh", "default2", NULL};
331 static char *vga2_names[] = {"vga2", NULL};
332 static char *vga4_names[] = {"vga4", NULL};
333 static char *vga16_names[] = {"vga16", "default3", NULL};
334 static char *vga256_names[] = {"vga256", NULL};
335 static char *falh2_names[] = {"falh2", NULL};
336 static char *falh16_names[] = {"falh16", NULL};
338 static char **fb_var_names[] = {
339 /* Writing the name arrays directly in this array (via "(char *[]){...}")
340 * crashes gcc 2.5.8 (sigsegv) if the inner array
341 * contains more than two items. I've also seen that all elements
342 * were identical to the last (my cross-gcc) :-(*/
343 autodetect_names,
344 stlow_names,
345 stmid_names,
346 sthigh_names,
347 ttlow_names,
348 ttmid_names,
349 tthigh_names,
350 vga2_names,
351 vga4_names,
352 vga16_names,
353 vga256_names,
354 falh2_names,
355 falh16_names,
356 NULL
357 /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
360 static struct fb_var_screeninfo atafb_predefined[] = {
362 * yres_virtual==0 means use hw-scrolling if possible, else yres
364 { /* autodetect */
365 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
366 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
367 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
368 { /* st low */
369 320, 200, 320, 0, 0, 0, 4, 0,
370 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
371 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
372 { /* st mid */
373 640, 200, 640, 0, 0, 0, 2, 0,
374 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
375 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
376 { /* st high */
377 640, 400, 640, 0, 0, 0, 1, 0,
378 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
379 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
380 { /* tt low */
381 320, 480, 320, 0, 0, 0, 8, 0,
382 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
383 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
384 { /* tt mid */
385 640, 480, 640, 0, 0, 0, 4, 0,
386 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
387 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
388 { /* tt high */
389 1280, 960, 1280, 0, 0, 0, 1, 0,
390 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
391 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
392 { /* vga2 */
393 640, 480, 640, 0, 0, 0, 1, 0,
394 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
395 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
396 { /* vga4 */
397 640, 480, 640, 0, 0, 0, 2, 0,
398 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
399 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
400 { /* vga16 */
401 640, 480, 640, 0, 0, 0, 4, 0,
402 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
403 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
404 { /* vga256 */
405 640, 480, 640, 0, 0, 0, 8, 0,
406 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
407 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
408 { /* falh2 */
409 896, 608, 896, 0, 0, 0, 1, 0,
410 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
411 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
412 { /* falh16 */
413 896, 608, 896, 0, 0, 0, 4, 0,
414 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
415 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
418 static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined);
421 static int
422 get_video_mode(char *vname)
424 char ***name_list;
425 char **name;
426 int i;
427 name_list=fb_var_names;
428 for (i = 0 ; i < num_atafb_predefined ; i++) {
429 name=*(name_list++);
430 if (! name || ! *name)
431 break;
432 while (*name) {
433 if (! strcmp(vname, *name))
434 return i+1;
435 name++;
438 return 0;
443 /* ------------------- TT specific functions ---------------------- */
445 #ifdef ATAFB_TT
447 static int tt_encode_fix( struct fb_fix_screeninfo *fix,
448 struct atafb_par *par )
451 int mode;
453 strcpy(fix->id,"Atari Builtin");
454 fix->smem_start = (unsigned long)real_screen_base;
455 fix->smem_len = screen_len;
456 fix->type=FB_TYPE_INTERLEAVED_PLANES;
457 fix->type_aux=2;
458 fix->visual=FB_VISUAL_PSEUDOCOLOR;
459 mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
460 if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
461 fix->type=FB_TYPE_PACKED_PIXELS;
462 fix->type_aux=0;
463 if (mode == TT_SHIFTER_TTHIGH)
464 fix->visual=FB_VISUAL_MONO01;
466 fix->xpanstep=0;
467 fix->ypanstep=1;
468 fix->ywrapstep=0;
469 fix->line_length = 0;
470 fix->accel = FB_ACCEL_ATARIBLITT;
471 return 0;
475 static int tt_decode_var( struct fb_var_screeninfo *var,
476 struct atafb_par *par )
478 int xres=var->xres;
479 int yres=var->yres;
480 int bpp=var->bits_per_pixel;
481 int linelen;
482 int yres_virtual = var->yres_virtual;
484 if (mono_moni) {
485 if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
486 return -EINVAL;
487 par->hw.tt.mode=TT_SHIFTER_TTHIGH;
488 xres=sttt_xres*2;
489 yres=tt_yres*2;
490 bpp=1;
491 } else {
492 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
493 return -EINVAL;
494 if (bpp > 4) {
495 if (xres > sttt_xres/2 || yres > tt_yres)
496 return -EINVAL;
497 par->hw.tt.mode=TT_SHIFTER_TTLOW;
498 xres=sttt_xres/2;
499 yres=tt_yres;
500 bpp=8;
502 else if (bpp > 2) {
503 if (xres > sttt_xres || yres > tt_yres)
504 return -EINVAL;
505 if (xres > sttt_xres/2 || yres > st_yres/2) {
506 par->hw.tt.mode=TT_SHIFTER_TTMID;
507 xres=sttt_xres;
508 yres=tt_yres;
509 bpp=4;
511 else {
512 par->hw.tt.mode=TT_SHIFTER_STLOW;
513 xres=sttt_xres/2;
514 yres=st_yres/2;
515 bpp=4;
518 else if (bpp > 1) {
519 if (xres > sttt_xres || yres > st_yres/2)
520 return -EINVAL;
521 par->hw.tt.mode=TT_SHIFTER_STMID;
522 xres=sttt_xres;
523 yres=st_yres/2;
524 bpp=2;
526 else if (var->xres > sttt_xres || var->yres > st_yres) {
527 return -EINVAL;
529 else {
530 par->hw.tt.mode=TT_SHIFTER_STHIGH;
531 xres=sttt_xres;
532 yres=st_yres;
533 bpp=1;
536 if (yres_virtual <= 0)
537 yres_virtual = 0;
538 else if (yres_virtual < yres)
539 yres_virtual = yres;
540 if (var->sync & FB_SYNC_EXT)
541 par->hw.tt.sync=0;
542 else
543 par->hw.tt.sync=1;
544 linelen=xres*bpp/8;
545 if (yres_virtual * linelen > screen_len && screen_len)
546 return -EINVAL;
547 if (yres * linelen > screen_len && screen_len)
548 return -EINVAL;
549 if (var->yoffset + yres > yres_virtual && yres_virtual)
550 return -EINVAL;
551 par->yres_virtual = yres_virtual;
552 par->screen_base = screen_base + var->yoffset * linelen;
553 return 0;
556 static int tt_encode_var( struct fb_var_screeninfo *var,
557 struct atafb_par *par )
559 int linelen;
560 memset(var, 0, sizeof(struct fb_var_screeninfo));
561 var->red.offset=0;
562 var->red.length=4;
563 var->red.msb_right=0;
564 var->grayscale=0;
566 var->pixclock=31041;
567 var->left_margin=120; /* these may be incorrect */
568 var->right_margin=100;
569 var->upper_margin=8;
570 var->lower_margin=16;
571 var->hsync_len=140;
572 var->vsync_len=30;
574 var->height=-1;
575 var->width=-1;
577 if (par->hw.tt.sync & 1)
578 var->sync=0;
579 else
580 var->sync=FB_SYNC_EXT;
582 switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
583 case TT_SHIFTER_STLOW:
584 var->xres=sttt_xres/2;
585 var->xres_virtual=sttt_xres_virtual/2;
586 var->yres=st_yres/2;
587 var->bits_per_pixel=4;
588 break;
589 case TT_SHIFTER_STMID:
590 var->xres=sttt_xres;
591 var->xres_virtual=sttt_xres_virtual;
592 var->yres=st_yres/2;
593 var->bits_per_pixel=2;
594 break;
595 case TT_SHIFTER_STHIGH:
596 var->xres=sttt_xres;
597 var->xres_virtual=sttt_xres_virtual;
598 var->yres=st_yres;
599 var->bits_per_pixel=1;
600 break;
601 case TT_SHIFTER_TTLOW:
602 var->xres=sttt_xres/2;
603 var->xres_virtual=sttt_xres_virtual/2;
604 var->yres=tt_yres;
605 var->bits_per_pixel=8;
606 break;
607 case TT_SHIFTER_TTMID:
608 var->xres=sttt_xres;
609 var->xres_virtual=sttt_xres_virtual;
610 var->yres=tt_yres;
611 var->bits_per_pixel=4;
612 break;
613 case TT_SHIFTER_TTHIGH:
614 var->red.length=0;
615 var->xres=sttt_xres*2;
616 var->xres_virtual=sttt_xres_virtual*2;
617 var->yres=tt_yres*2;
618 var->bits_per_pixel=1;
619 break;
621 var->blue=var->green=var->red;
622 var->transp.offset=0;
623 var->transp.length=0;
624 var->transp.msb_right=0;
625 linelen=var->xres_virtual * var->bits_per_pixel / 8;
626 if (! use_hwscroll)
627 var->yres_virtual=var->yres;
628 else if (screen_len) {
629 if (par->yres_virtual)
630 var->yres_virtual = par->yres_virtual;
631 else
632 /* yres_virtual==0 means use maximum */
633 var->yres_virtual = screen_len / linelen;
634 } else {
635 if (hwscroll < 0)
636 var->yres_virtual = 2 * var->yres;
637 else
638 var->yres_virtual=var->yres+hwscroll * 16;
640 var->xoffset=0;
641 if (screen_base)
642 var->yoffset=(par->screen_base - screen_base)/linelen;
643 else
644 var->yoffset=0;
645 var->nonstd=0;
646 var->activate=0;
647 var->vmode=FB_VMODE_NONINTERLACED;
648 return 0;
652 static void tt_get_par( struct atafb_par *par )
654 unsigned long addr;
655 par->hw.tt.mode=shifter_tt.tt_shiftmode;
656 par->hw.tt.sync=shifter.syncmode;
657 addr = ((shifter.bas_hi & 0xff) << 16) |
658 ((shifter.bas_md & 0xff) << 8) |
659 ((shifter.bas_lo & 0xff));
660 par->screen_base = phys_to_virt(addr);
663 static void tt_set_par( struct atafb_par *par )
665 shifter_tt.tt_shiftmode=par->hw.tt.mode;
666 shifter.syncmode=par->hw.tt.sync;
667 /* only set screen_base if really necessary */
668 if (current_par.screen_base != par->screen_base)
669 fbhw->set_screen_base(par->screen_base);
673 static int tt_getcolreg(unsigned regno, unsigned *red,
674 unsigned *green, unsigned *blue,
675 unsigned *transp, struct fb_info *info)
677 int t, col;
679 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
680 regno += 254;
681 if (regno > 255)
682 return 1;
683 t = tt_palette[regno];
684 col = t & 15;
685 col |= col << 4;
686 col |= col << 8;
687 *blue = col;
688 col = (t >> 4) & 15;
689 col |= col << 4;
690 col |= col << 8;
691 *green = col;
692 col = (t >> 8) & 15;
693 col |= col << 4;
694 col |= col << 8;
695 *red = col;
696 *transp = 0;
697 return 0;
701 static int tt_setcolreg(unsigned regno, unsigned red,
702 unsigned green, unsigned blue,
703 unsigned transp, struct fb_info *info)
705 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
706 regno += 254;
707 if (regno > 255)
708 return 1;
709 tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
710 (blue >> 12));
711 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
712 TT_SHIFTER_STHIGH && regno == 254)
713 tt_palette[0] = 0;
714 return 0;
718 static int tt_detect( void )
720 { struct atafb_par par;
722 /* Determine the connected monitor: The DMA sound must be
723 * disabled before reading the MFP GPIP, because the Sound
724 * Done Signal and the Monochrome Detect are XORed together!
726 * Even on a TT, we should look if there is a DMA sound. It was
727 * announced that the Eagle is TT compatible, but only the PCM is
728 * missing...
730 if (ATARIHW_PRESENT(PCM_8BIT)) {
731 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
732 udelay(20); /* wait a while for things to settle down */
734 mono_moni = (mfp.par_dt_reg & 0x80) == 0;
736 tt_get_par(&par);
737 tt_encode_var(&atafb_predefined[0], &par);
739 return 1;
742 #endif /* ATAFB_TT */
744 /* ------------------- Falcon specific functions ---------------------- */
746 #ifdef ATAFB_FALCON
748 static int mon_type; /* Falcon connected monitor */
749 static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
750 #define F_MON_SM 0
751 #define F_MON_SC 1
752 #define F_MON_VGA 2
753 #define F_MON_TV 3
755 static struct pixel_clock {
756 unsigned long f; /* f/[Hz] */
757 unsigned long t; /* t/[ps] (=1/f) */
758 int right, hsync, left; /* standard timing in clock cycles, not pixel */
759 /* hsync initialized in falcon_detect() */
760 int sync_mask; /* or-mask for hw.falcon.sync to set this clock */
761 int control_mask; /* ditto, for hw.falcon.vid_control */
763 f25 = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25},
764 f32 = {32000000, 31250, 18, 0, 42, 0x0, 0},
765 fext = { 0, 0, 18, 0, 42, 0x1, 0};
767 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
768 static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
770 /* Default hsync timing [mon_type] in picoseconds */
771 static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
773 #ifdef FBCON_HAS_CFB16
774 static u16 fbcon_cfb16_cmap[16];
775 #endif
777 static inline int hxx_prescale(struct falcon_hw *hw)
779 return hw->ste_mode ? 16 :
780 vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
783 static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
784 struct atafb_par *par )
786 strcpy(fix->id, "Atari Builtin");
787 fix->smem_start = (unsigned long)real_screen_base;
788 fix->smem_len = screen_len;
789 fix->type = FB_TYPE_INTERLEAVED_PLANES;
790 fix->type_aux = 2;
791 fix->visual = FB_VISUAL_PSEUDOCOLOR;
792 fix->xpanstep = 1;
793 fix->ypanstep = 1;
794 fix->ywrapstep = 0;
795 if (par->hw.falcon.mono) {
796 fix->type = FB_TYPE_PACKED_PIXELS;
797 fix->type_aux = 0;
798 /* no smooth scrolling with longword aligned video mem */
799 fix->xpanstep = 32;
801 else if (par->hw.falcon.f_shift & 0x100) {
802 fix->type = FB_TYPE_PACKED_PIXELS;
803 fix->type_aux = 0;
804 /* Is this ok or should it be DIRECTCOLOR? */
805 fix->visual = FB_VISUAL_TRUECOLOR;
806 fix->xpanstep = 2;
808 fix->line_length = 0;
809 fix->accel = FB_ACCEL_ATARIBLITT;
810 return 0;
814 static int falcon_decode_var( struct fb_var_screeninfo *var,
815 struct atafb_par *par )
817 int bpp = var->bits_per_pixel;
818 int xres = var->xres;
819 int yres = var->yres;
820 int xres_virtual = var->xres_virtual;
821 int yres_virtual = var->yres_virtual;
822 int left_margin, right_margin, hsync_len;
823 int upper_margin, lower_margin, vsync_len;
824 int linelen;
825 int interlace = 0, doubleline = 0;
826 struct pixel_clock *pclock;
827 int plen; /* width of pixel in clock cycles */
828 int xstretch;
829 int prescale;
830 int longoffset = 0;
831 int hfreq, vfreq;
834 Get the video params out of 'var'. If a value doesn't fit, round
835 it up, if it's too big, return EINVAL.
836 Round up in the following order: bits_per_pixel, xres, yres,
837 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
838 horizontal timing, vertical timing.
840 There is a maximum of screen resolution determined by pixelclock
841 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
842 In interlace mode this is " * " *vfmin <= pixelclock.
843 Additional constraints: hfreq.
844 Frequency range for multisync monitors is given via command line.
845 For TV and SM124 both frequencies are fixed.
847 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
848 Y % 16 == 0 to fit 8x16 font
849 Y % 8 == 0 if Y<400
851 Currently interlace and doubleline mode in var are ignored.
852 On SM124 and TV only the standard resolutions can be used.
855 /* Reject uninitialized mode */
856 if (!xres || !yres || !bpp)
857 return -EINVAL;
859 if (mon_type == F_MON_SM && bpp != 1) {
860 return -EINVAL;
862 else if (bpp <= 1) {
863 bpp = 1;
864 par->hw.falcon.f_shift = 0x400;
865 par->hw.falcon.st_shift = 0x200;
867 else if (bpp <= 2) {
868 bpp = 2;
869 par->hw.falcon.f_shift = 0x000;
870 par->hw.falcon.st_shift = 0x100;
872 else if (bpp <= 4) {
873 bpp = 4;
874 par->hw.falcon.f_shift = 0x000;
875 par->hw.falcon.st_shift = 0x000;
877 else if (bpp <= 8) {
878 bpp = 8;
879 par->hw.falcon.f_shift = 0x010;
881 else if (bpp <= 16) {
882 bpp = 16; /* packed pixel mode */
883 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
885 else
886 return -EINVAL;
887 par->hw.falcon.bpp = bpp;
889 if (mon_type == F_MON_SM || DontCalcRes) {
890 /* Skip all calculations. VGA/TV/SC1224 only supported. */
891 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
893 if (bpp > myvar->bits_per_pixel ||
894 var->xres > myvar->xres ||
895 var->yres > myvar->yres)
896 return -EINVAL;
897 fbhw->get_par(par); /* Current par will be new par */
898 goto set_screen_base; /* Don't forget this */
901 /* Only some fixed resolutions < 640x400 */
902 if (xres <= 320)
903 xres = 320;
904 else if (xres <= 640 && bpp != 16)
905 xres = 640;
906 if (yres <= 200)
907 yres = 200;
908 else if (yres <= 240)
909 yres = 240;
910 else if (yres <= 400)
911 yres = 400;
913 /* 2 planes must use STE compatibility mode */
914 par->hw.falcon.ste_mode = bpp==2;
915 par->hw.falcon.mono = bpp==1;
917 /* Total and visible scanline length must be a multiple of one longword,
918 * this and the console fontwidth yields the alignment for xres and
919 * xres_virtual.
920 * TODO: this way "odd" fontheights are not supported
922 * Special case in STE mode: blank and graphic positions don't align,
923 * avoid trash at right margin
925 if (par->hw.falcon.ste_mode)
926 xres = (xres + 63) & ~63;
927 else if (bpp == 1)
928 xres = (xres + 31) & ~31;
929 else
930 xres = (xres + 15) & ~15;
931 if (yres >= 400)
932 yres = (yres + 15) & ~15;
933 else
934 yres = (yres + 7) & ~7;
936 if (xres_virtual < xres)
937 xres_virtual = xres;
938 else if (bpp == 1)
939 xres_virtual = (xres_virtual + 31) & ~31;
940 else
941 xres_virtual = (xres_virtual + 15) & ~15;
943 if (yres_virtual <= 0)
944 yres_virtual = 0;
945 else if (yres_virtual < yres)
946 yres_virtual = yres;
948 /* backward bug-compatibility */
949 if (var->pixclock > 1)
950 var->pixclock -= 1;
952 par->hw.falcon.line_width = bpp * xres / 16;
953 par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
955 /* single or double pixel width */
956 xstretch = (xres < 640) ? 2 : 1;
958 #if 0 /* SM124 supports only 640x400, this is rejected above */
959 if (mon_type == F_MON_SM) {
960 if (xres != 640 && yres != 400)
961 return -EINVAL;
962 plen = 1;
963 pclock = &f32;
964 /* SM124-mode is special */
965 par->hw.falcon.ste_mode = 1;
966 par->hw.falcon.f_shift = 0x000;
967 par->hw.falcon.st_shift = 0x200;
968 left_margin = hsync_len = 128 / plen;
969 right_margin = 0;
970 /* TODO set all margins */
972 else
973 #endif
974 if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
975 plen = 2 * xstretch;
976 if (var->pixclock > f32.t * plen)
977 return -EINVAL;
978 pclock = &f32;
979 if (yres > 240)
980 interlace = 1;
981 if (var->pixclock == 0) {
982 /* set some minimal margins which center the screen */
983 left_margin = 32;
984 right_margin = 18;
985 hsync_len = pclock->hsync / plen;
986 upper_margin = 31;
987 lower_margin = 14;
988 vsync_len = interlace ? 3 : 4;
989 } else {
990 left_margin = var->left_margin;
991 right_margin = var->right_margin;
992 hsync_len = var->hsync_len;
993 upper_margin = var->upper_margin;
994 lower_margin = var->lower_margin;
995 vsync_len = var->vsync_len;
996 if (var->vmode & FB_VMODE_INTERLACED) {
997 upper_margin = (upper_margin + 1) / 2;
998 lower_margin = (lower_margin + 1) / 2;
999 vsync_len = (vsync_len + 1) / 2;
1000 } else if (var->vmode & FB_VMODE_DOUBLE) {
1001 upper_margin *= 2;
1002 lower_margin *= 2;
1003 vsync_len *= 2;
1007 else
1008 { /* F_MON_VGA */
1009 if (bpp == 16)
1010 xstretch = 2; /* Double pixel width only for hicolor */
1011 /* Default values are used for vert./hor. timing if no pixelclock given. */
1012 if (var->pixclock == 0) {
1013 int linesize;
1015 /* Choose master pixelclock depending on hor. timing */
1016 plen = 1 * xstretch;
1017 if ((plen * xres + f25.right+f25.hsync+f25.left) *
1018 fb_info.monspecs.hfmin < f25.f)
1019 pclock = &f25;
1020 else if ((plen * xres + f32.right+f32.hsync+f32.left) *
1021 fb_info.monspecs.hfmin < f32.f)
1022 pclock = &f32;
1023 else if ((plen * xres + fext.right+fext.hsync+fext.left) *
1024 fb_info.monspecs.hfmin < fext.f
1025 && fext.f)
1026 pclock = &fext;
1027 else
1028 return -EINVAL;
1030 left_margin = pclock->left / plen;
1031 right_margin = pclock->right / plen;
1032 hsync_len = pclock->hsync / plen;
1033 linesize = left_margin + xres + right_margin + hsync_len;
1034 upper_margin = 31;
1035 lower_margin = 11;
1036 vsync_len = 3;
1038 else {
1039 /* Choose largest pixelclock <= wanted clock */
1040 int i;
1041 unsigned long pcl = ULONG_MAX;
1042 pclock = 0;
1043 for (i=1; i <= 4; i *= 2) {
1044 if (f25.t*i >= var->pixclock && f25.t*i < pcl) {
1045 pcl = f25.t * i;
1046 pclock = &f25;
1048 if (f32.t*i >= var->pixclock && f32.t*i < pcl) {
1049 pcl = f32.t * i;
1050 pclock = &f32;
1052 if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) {
1053 pcl = fext.t * i;
1054 pclock = &fext;
1057 if (!pclock)
1058 return -EINVAL;
1059 plen = pcl / pclock->t;
1061 left_margin = var->left_margin;
1062 right_margin = var->right_margin;
1063 hsync_len = var->hsync_len;
1064 upper_margin = var->upper_margin;
1065 lower_margin = var->lower_margin;
1066 vsync_len = var->vsync_len;
1067 /* Internal unit is [single lines per (half-)frame] */
1068 if (var->vmode & FB_VMODE_INTERLACED) {
1069 /* # lines in half frame */
1070 /* External unit is [lines per full frame] */
1071 upper_margin = (upper_margin + 1) / 2;
1072 lower_margin = (lower_margin + 1) / 2;
1073 vsync_len = (vsync_len + 1) / 2;
1075 else if (var->vmode & FB_VMODE_DOUBLE) {
1076 /* External unit is [double lines per frame] */
1077 upper_margin *= 2;
1078 lower_margin *= 2;
1079 vsync_len *= 2;
1082 if (pclock == &fext)
1083 longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1085 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1086 /* this is definitely wrong if bus clock != 32MHz */
1087 if (pclock->f / plen / 8 * bpp > 32000000L)
1088 return -EINVAL;
1090 if (vsync_len < 1)
1091 vsync_len = 1;
1093 /* include sync lengths in right/lower margin for all calculations */
1094 right_margin += hsync_len;
1095 lower_margin += vsync_len;
1097 /* ! In all calculations of margins we use # of lines in half frame
1098 * (which is a full frame in non-interlace mode), so we can switch
1099 * between interlace and non-interlace without messing around
1100 * with these.
1102 again:
1103 /* Set base_offset 128 and video bus width */
1104 par->hw.falcon.vid_control = mon_type | f030_bus_width;
1105 if (!longoffset)
1106 par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */
1107 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1108 par->hw.falcon.vid_control |= VCO_HSYPOS;
1109 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1110 par->hw.falcon.vid_control |= VCO_VSYPOS;
1111 /* Pixelclock */
1112 par->hw.falcon.vid_control |= pclock->control_mask;
1113 /* External or internal clock */
1114 par->hw.falcon.sync = pclock->sync_mask | 0x2;
1115 /* Pixellength and prescale */
1116 par->hw.falcon.vid_mode = (2/plen) << 2;
1117 if (doubleline)
1118 par->hw.falcon.vid_mode |= VMO_DOUBLE;
1119 if (interlace)
1120 par->hw.falcon.vid_mode |= VMO_INTER;
1122 /*********************
1123 Horizontal timing: unit = [master clock cycles]
1124 unit of hxx-registers: [master clock cycles * prescale]
1125 Hxx-registers are 9 bit wide
1127 1 line = ((hht + 2) * 2 * prescale) clock cycles
1129 graphic output = hdb & 0x200 ?
1130 ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
1131 ( hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1132 (this must be a multiple of plen*128/bpp, on VGA pixels
1133 to the right may be cut off with a bigger right margin)
1135 start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1136 (hdb - hht - 2) * prescale + hdboff :
1137 hdb * prescale + hdboff
1139 end of graphics relative to start of 1st halfline =
1140 (hde + hht + 2) * prescale + hdeoff
1141 *********************/
1142 /* Calculate VIDEL registers */
1144 int hdb_off, hde_off, base_off;
1145 int gstart, gend1, gend2, align;
1147 prescale = hxx_prescale(&par->hw.falcon);
1148 base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1150 /* Offsets depend on video mode */
1151 /* Offsets are in clock cycles, divide by prescale to
1152 * calculate hd[be]-registers
1154 if (par->hw.falcon.f_shift & 0x100) {
1155 align = 1;
1156 hde_off = 0;
1157 hdb_off = (base_off + 16 * plen) + prescale;
1159 else {
1160 align = 128 / bpp;
1161 hde_off = ((128 / bpp + 2) * plen);
1162 if (par->hw.falcon.ste_mode)
1163 hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1164 else
1165 hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1168 gstart = (prescale/2 + plen * left_margin) / prescale;
1169 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1170 gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
1171 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1172 gend2 = gstart + xres * plen / prescale;
1173 par->HHT = plen * (left_margin + xres + right_margin) /
1174 (2 * prescale) - 2;
1175 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1177 par->HDB = gstart - hdb_off/prescale;
1178 par->HBE = gstart;
1179 if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
1180 par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
1181 par->HBB = gend2 - par->HHT - 2;
1182 #if 0
1183 /* One more Videl constraint: data fetch of two lines must not overlap */
1184 if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1185 /* if this happens increase margins, decrease hfreq. */
1187 #endif
1188 if (hde_off % prescale)
1189 par->HBB++; /* compensate for non matching hde and hbb */
1190 par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1191 if (par->HSS < par->HBB)
1192 par->HSS = par->HBB;
1195 /* check hor. frequency */
1196 hfreq = pclock->f / ((par->HHT+2)*prescale*2);
1197 if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) {
1198 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1199 /* Too high -> enlarge margin */
1200 left_margin += 1;
1201 right_margin += 1;
1202 goto again;
1204 if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1205 return -EINVAL;
1207 /* Vxx-registers */
1208 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1209 * of the first displayed line!
1210 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1211 * non-interlace, odd in interlace mode for synchronisation.
1212 * Vxx-registers are 11 bit wide
1214 par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1215 par->VDB = par->VBE;
1216 par->VDE = yres;
1217 if (!interlace) par->VDE <<= 1;
1218 if (doubleline) par->VDE <<= 1; /* VDE now half lines per (half-)frame */
1219 par->VDE += par->VDB;
1220 par->VBB = par->VDE;
1221 par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1222 par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
1223 /* vbb,vss,vft must be even in interlace mode */
1224 if (interlace) {
1225 par->VBB++;
1226 par->VSS++;
1227 par->VFT++;
1230 /* V-frequency check, hope I didn't create any loop here. */
1231 /* Interlace and doubleline are mutually exclusive. */
1232 vfreq = (hfreq * 2) / (par->VFT + 1);
1233 if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1234 /* Too high -> try again with doubleline */
1235 doubleline = 1;
1236 goto again;
1238 else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1239 /* Too low -> try again with interlace */
1240 interlace = 1;
1241 goto again;
1243 else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1244 /* Doubleline too low -> clear doubleline and enlarge margins */
1245 int lines;
1246 doubleline = 0;
1247 for (lines=0;
1248 (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax;
1249 lines++)
1251 upper_margin += lines;
1252 lower_margin += lines;
1253 goto again;
1255 else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1256 /* Doubleline too high -> enlarge margins */
1257 int lines;
1258 for (lines=0;
1259 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1260 lines+=2)
1262 upper_margin += lines;
1263 lower_margin += lines;
1264 goto again;
1266 else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1267 /* Interlace, too high -> enlarge margins */
1268 int lines;
1269 for (lines=0;
1270 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1271 lines++)
1273 upper_margin += lines;
1274 lower_margin += lines;
1275 goto again;
1277 else if (vfreq < fb_info.monspecs.vfmin ||
1278 vfreq > fb_info.monspecs.vfmax)
1279 return -EINVAL;
1281 set_screen_base:
1282 linelen = xres_virtual * bpp / 8;
1283 if (yres_virtual * linelen > screen_len && screen_len)
1284 return -EINVAL;
1285 if (yres * linelen > screen_len && screen_len)
1286 return -EINVAL;
1287 if (var->yoffset + yres > yres_virtual && yres_virtual)
1288 return -EINVAL;
1289 par->yres_virtual = yres_virtual;
1290 par->screen_base = screen_base + var->yoffset * linelen;
1291 par->hw.falcon.xoffset = 0;
1293 return 0;
1296 static int falcon_encode_var( struct fb_var_screeninfo *var,
1297 struct atafb_par *par )
1299 /* !!! only for VGA !!! */
1300 int linelen;
1301 int prescale, plen;
1302 int hdb_off, hde_off, base_off;
1303 struct falcon_hw *hw = &par->hw.falcon;
1305 memset(var, 0, sizeof(struct fb_var_screeninfo));
1306 /* possible frequencies: 25.175 or 32MHz */
1307 var->pixclock = hw->sync & 0x1 ? fext.t :
1308 hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1310 var->height=-1;
1311 var->width=-1;
1313 var->sync=0;
1314 if (hw->vid_control & VCO_HSYPOS)
1315 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1316 if (hw->vid_control & VCO_VSYPOS)
1317 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1319 var->vmode = FB_VMODE_NONINTERLACED;
1320 if (hw->vid_mode & VMO_INTER)
1321 var->vmode |= FB_VMODE_INTERLACED;
1322 if (hw->vid_mode & VMO_DOUBLE)
1323 var->vmode |= FB_VMODE_DOUBLE;
1325 /* visible y resolution:
1326 * Graphics display starts at line VDB and ends at line
1327 * VDE. If interlace mode off unit of VC-registers is
1328 * half lines, else lines.
1330 var->yres = hw->vde - hw->vdb;
1331 if (!(var->vmode & FB_VMODE_INTERLACED))
1332 var->yres >>= 1;
1333 if (var->vmode & FB_VMODE_DOUBLE)
1334 var->yres >>= 1;
1336 /* to get bpp, we must examine f_shift and st_shift.
1337 * f_shift is valid if any of bits no. 10, 8 or 4
1338 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1339 * if bit 10 set then bit 8 and bit 4 don't care...
1340 * If all these bits are 0 get display depth from st_shift
1341 * (as for ST and STE)
1343 if (hw->f_shift & 0x400) /* 2 colors */
1344 var->bits_per_pixel = 1;
1345 else if (hw->f_shift & 0x100) /* hicolor */
1346 var->bits_per_pixel = 16;
1347 else if (hw->f_shift & 0x010) /* 8 bitplanes */
1348 var->bits_per_pixel = 8;
1349 else if (hw->st_shift == 0)
1350 var->bits_per_pixel = 4;
1351 else if (hw->st_shift == 0x100)
1352 var->bits_per_pixel = 2;
1353 else /* if (hw->st_shift == 0x200) */
1354 var->bits_per_pixel = 1;
1356 var->xres = hw->line_width * 16 / var->bits_per_pixel;
1357 var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1358 if (hw->xoffset)
1359 var->xres_virtual += 16;
1361 if (var->bits_per_pixel == 16) {
1362 var->red.offset=11;
1363 var->red.length=5;
1364 var->red.msb_right=0;
1365 var->green.offset=5;
1366 var->green.length=6;
1367 var->green.msb_right=0;
1368 var->blue.offset=0;
1369 var->blue.length=5;
1370 var->blue.msb_right=0;
1372 else {
1373 var->red.offset=0;
1374 var->red.length = hw->ste_mode ? 4 : 6;
1375 var->red.msb_right=0;
1376 var->grayscale=0;
1377 var->blue=var->green=var->red;
1379 var->transp.offset=0;
1380 var->transp.length=0;
1381 var->transp.msb_right=0;
1383 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1384 if (screen_len) {
1385 if (par->yres_virtual)
1386 var->yres_virtual = par->yres_virtual;
1387 else
1388 /* yres_virtual==0 means use maximum */
1389 var->yres_virtual = screen_len / linelen;
1391 else {
1392 if (hwscroll < 0)
1393 var->yres_virtual = 2 * var->yres;
1394 else
1395 var->yres_virtual=var->yres+hwscroll * 16;
1397 var->xoffset=0; /* TODO change this */
1399 /* hdX-offsets */
1400 prescale = hxx_prescale(hw);
1401 plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1402 base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1403 if (hw->f_shift & 0x100) {
1404 hde_off = 0;
1405 hdb_off = (base_off + 16 * plen) + prescale;
1407 else {
1408 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1409 if (hw->ste_mode)
1410 hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1411 + prescale;
1412 else
1413 hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1414 + prescale;
1417 /* Right margin includes hsync */
1418 var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1419 (hw->hdb & 0x200 ? 2+hw->hht : 0));
1420 if (hw->ste_mode || mon_type!=F_MON_VGA)
1421 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1422 else
1423 /* can't use this in ste_mode, because hbb is +1 off */
1424 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1425 var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1427 /* Lower margin includes vsync */
1428 var->upper_margin = hw->vdb / 2 ; /* round down to full lines */
1429 var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
1430 var->vsync_len = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
1431 if (var->vmode & FB_VMODE_INTERLACED) {
1432 var->upper_margin *= 2;
1433 var->lower_margin *= 2;
1434 var->vsync_len *= 2;
1436 else if (var->vmode & FB_VMODE_DOUBLE) {
1437 var->upper_margin = (var->upper_margin + 1) / 2;
1438 var->lower_margin = (var->lower_margin + 1) / 2;
1439 var->vsync_len = (var->vsync_len + 1) / 2;
1442 var->pixclock *= plen;
1443 var->left_margin /= plen;
1444 var->right_margin /= plen;
1445 var->hsync_len /= plen;
1447 var->right_margin -= var->hsync_len;
1448 var->lower_margin -= var->vsync_len;
1450 if (screen_base)
1451 var->yoffset=(par->screen_base - screen_base)/linelen;
1452 else
1453 var->yoffset=0;
1454 var->nonstd=0; /* what is this for? */
1455 var->activate=0;
1456 return 0;
1460 static int f_change_mode = 0;
1461 static struct falcon_hw f_new_mode;
1462 static int f_pan_display = 0;
1464 static void falcon_get_par( struct atafb_par *par )
1466 unsigned long addr;
1467 struct falcon_hw *hw = &par->hw.falcon;
1469 hw->line_width = shifter_f030.scn_width;
1470 hw->line_offset = shifter_f030.off_next;
1471 hw->st_shift = videl.st_shift & 0x300;
1472 hw->f_shift = videl.f_shift;
1473 hw->vid_control = videl.control;
1474 hw->vid_mode = videl.mode;
1475 hw->sync = shifter.syncmode & 0x1;
1476 hw->xoffset = videl.xoffset & 0xf;
1477 hw->hht = videl.hht;
1478 hw->hbb = videl.hbb;
1479 hw->hbe = videl.hbe;
1480 hw->hdb = videl.hdb;
1481 hw->hde = videl.hde;
1482 hw->hss = videl.hss;
1483 hw->vft = videl.vft;
1484 hw->vbb = videl.vbb;
1485 hw->vbe = videl.vbe;
1486 hw->vdb = videl.vdb;
1487 hw->vde = videl.vde;
1488 hw->vss = videl.vss;
1490 addr = (shifter.bas_hi & 0xff) << 16 |
1491 (shifter.bas_md & 0xff) << 8 |
1492 (shifter.bas_lo & 0xff);
1493 par->screen_base = phys_to_virt(addr);
1495 /* derived parameters */
1496 hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
1497 hw->mono = (hw->f_shift & 0x400) ||
1498 ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
1501 static void falcon_set_par( struct atafb_par *par )
1503 f_change_mode = 0;
1505 /* only set screen_base if really necessary */
1506 if (current_par.screen_base != par->screen_base)
1507 fbhw->set_screen_base(par->screen_base);
1509 /* Don't touch any other registers if we keep the default resolution */
1510 if (DontCalcRes)
1511 return;
1513 /* Tell vbl-handler to change video mode.
1514 * We change modes only on next VBL, to avoid desynchronisation
1515 * (a shift to the right and wrap around by a random number of pixels
1516 * in all monochrome modes).
1517 * This seems to work on my Falcon.
1519 f_new_mode = par->hw.falcon;
1520 f_change_mode = 1;
1524 static irqreturn_t falcon_vbl_switcher( int irq, void *dummy, struct pt_regs *fp )
1526 struct falcon_hw *hw = &f_new_mode;
1528 if (f_change_mode) {
1529 f_change_mode = 0;
1531 if (hw->sync & 0x1) {
1532 /* Enable external pixelclock. This code only for ScreenWonder */
1533 *(volatile unsigned short*)0xffff9202 = 0xffbf;
1535 else {
1536 /* Turn off external clocks. Read sets all output bits to 1. */
1537 *(volatile unsigned short*)0xffff9202;
1539 shifter.syncmode = hw->sync;
1541 videl.hht = hw->hht;
1542 videl.hbb = hw->hbb;
1543 videl.hbe = hw->hbe;
1544 videl.hdb = hw->hdb;
1545 videl.hde = hw->hde;
1546 videl.hss = hw->hss;
1547 videl.vft = hw->vft;
1548 videl.vbb = hw->vbb;
1549 videl.vbe = hw->vbe;
1550 videl.vdb = hw->vdb;
1551 videl.vde = hw->vde;
1552 videl.vss = hw->vss;
1554 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1555 if (hw->ste_mode) {
1556 videl.st_shift = hw->st_shift; /* write enables STE palette */
1558 else {
1559 /* IMPORTANT:
1560 * set st_shift 0, so we can tell the screen-depth if f_shift==0.
1561 * Writing 0 to f_shift enables 4 plane Falcon mode but
1562 * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
1563 * with Falcon palette.
1565 videl.st_shift = 0;
1566 /* now back to Falcon palette mode */
1567 videl.f_shift = hw->f_shift;
1569 /* writing to st_shift changed scn_width and vid_mode */
1570 videl.xoffset = hw->xoffset;
1571 shifter_f030.scn_width = hw->line_width;
1572 shifter_f030.off_next = hw->line_offset;
1573 videl.control = hw->vid_control;
1574 videl.mode = hw->vid_mode;
1576 if (f_pan_display) {
1577 f_pan_display = 0;
1578 videl.xoffset = current_par.hw.falcon.xoffset;
1579 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1581 return IRQ_HANDLED;
1585 static int falcon_pan_display( struct fb_var_screeninfo *var,
1586 struct atafb_par *par )
1588 int xoffset;
1589 int bpp = fb_display[fb_info.currcon].var.bits_per_pixel;
1591 if (bpp == 1)
1592 var->xoffset = up(var->xoffset, 32);
1593 if (bpp != 16)
1594 par->hw.falcon.xoffset = var->xoffset & 15;
1595 else {
1596 par->hw.falcon.xoffset = 0;
1597 var->xoffset = up(var->xoffset, 2);
1599 par->hw.falcon.line_offset = bpp *
1600 (fb_display[fb_info.currcon].var.xres_virtual - fb_display[fb_info.currcon].var.xres) / 16;
1601 if (par->hw.falcon.xoffset)
1602 par->hw.falcon.line_offset -= bpp;
1603 xoffset = var->xoffset - par->hw.falcon.xoffset;
1605 par->screen_base = screen_base +
1606 (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + xoffset) * bpp / 8;
1607 if (fbhw->set_screen_base)
1608 fbhw->set_screen_base (par->screen_base);
1609 else
1610 return -EINVAL; /* shouldn't happen */
1611 f_pan_display = 1;
1612 return 0;
1616 static int falcon_getcolreg( unsigned regno, unsigned *red,
1617 unsigned *green, unsigned *blue,
1618 unsigned *transp, struct fb_info *info )
1619 { unsigned long col;
1621 if (regno > 255)
1622 return 1;
1623 /* This works in STE-mode (with 4bit/color) since f030_col-registers
1624 * hold up to 6bit/color.
1625 * Even with hicolor r/g/b=5/6/5 bit!
1627 col = f030_col[regno];
1628 *red = (col >> 16) & 0xff00;
1629 *green = (col >> 8) & 0xff00;
1630 *blue = (col << 8) & 0xff00;
1631 *transp = 0;
1632 return 0;
1636 static int falcon_setcolreg( unsigned regno, unsigned red,
1637 unsigned green, unsigned blue,
1638 unsigned transp, struct fb_info *info )
1640 if (regno > 255)
1641 return 1;
1642 f030_col[regno] = (((red & 0xfc00) << 16) |
1643 ((green & 0xfc00) << 8) |
1644 ((blue & 0xfc00) >> 8));
1645 if (regno < 16) {
1646 shifter_tt.color_reg[regno] =
1647 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1648 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1649 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1650 #ifdef FBCON_HAS_CFB16
1651 fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
1652 ((green & 0xfc00) >> 5) |
1653 ((blue & 0xf800) >> 11));
1654 #endif
1656 return 0;
1660 static int falcon_blank( int blank_mode )
1662 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1663 * so VIDEL doesn't hog the bus while saving.
1664 * (this may affect usleep()).
1666 int vdb, vss, hbe, hss;
1668 if (mon_type == F_MON_SM) /* this doesn't work on SM124 */
1669 return 1;
1671 vdb = current_par.VDB;
1672 vss = current_par.VSS;
1673 hbe = current_par.HBE;
1674 hss = current_par.HSS;
1676 if (blank_mode >= 1) {
1677 /* disable graphics output (this speeds up the CPU) ... */
1678 vdb = current_par.VFT + 1;
1679 /* ... and blank all lines */
1680 hbe = current_par.HHT + 2;
1682 /* use VESA suspend modes on VGA monitors */
1683 if (mon_type == F_MON_VGA) {
1684 if (blank_mode == 2 || blank_mode == 4)
1685 vss = current_par.VFT + 1;
1686 if (blank_mode == 3 || blank_mode == 4)
1687 hss = current_par.HHT + 2;
1690 videl.vdb = vdb;
1691 videl.vss = vss;
1692 videl.hbe = hbe;
1693 videl.hss = hss;
1695 return 0;
1699 static int falcon_detect( void )
1701 struct atafb_par par;
1702 unsigned char fhw;
1704 /* Determine connected monitor and set monitor parameters */
1705 fhw = *(unsigned char*)0xffff8006;
1706 mon_type = fhw >> 6 & 0x3;
1707 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1708 f030_bus_width = fhw << 6 & 0x80;
1709 switch (mon_type) {
1710 case F_MON_SM:
1711 fb_info.monspecs.vfmin = 70;
1712 fb_info.monspecs.vfmax = 72;
1713 fb_info.monspecs.hfmin = 35713;
1714 fb_info.monspecs.hfmax = 35715;
1715 break;
1716 case F_MON_SC:
1717 case F_MON_TV:
1718 /* PAL...NTSC */
1719 fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
1720 fb_info.monspecs.vfmax = 60;
1721 fb_info.monspecs.hfmin = 15620;
1722 fb_info.monspecs.hfmax = 15755;
1723 break;
1725 /* initialize hsync-len */
1726 f25.hsync = h_syncs[mon_type] / f25.t;
1727 f32.hsync = h_syncs[mon_type] / f32.t;
1728 if (fext.t)
1729 fext.hsync = h_syncs[mon_type] / fext.t;
1731 falcon_get_par(&par);
1732 falcon_encode_var(&atafb_predefined[0], &par);
1734 /* Detected mode is always the "autodetect" slot */
1735 return 1;
1738 #endif /* ATAFB_FALCON */
1740 /* ------------------- ST(E) specific functions ---------------------- */
1742 #ifdef ATAFB_STE
1744 static int stste_encode_fix( struct fb_fix_screeninfo *fix,
1745 struct atafb_par *par )
1748 int mode;
1750 strcpy(fix->id,"Atari Builtin");
1751 fix->smem_start = (unsigned long)real_screen_base;
1752 fix->smem_len = screen_len;
1753 fix->type = FB_TYPE_INTERLEAVED_PLANES;
1754 fix->type_aux = 2;
1755 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1756 mode = par->hw.st.mode & 3;
1757 if (mode == ST_HIGH) {
1758 fix->type = FB_TYPE_PACKED_PIXELS;
1759 fix->type_aux = 0;
1760 fix->visual = FB_VISUAL_MONO10;
1762 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1763 fix->xpanstep = 16;
1764 fix->ypanstep = 1;
1765 } else {
1766 fix->xpanstep = 0;
1767 fix->ypanstep = 0;
1769 fix->ywrapstep = 0;
1770 fix->line_length = 0;
1771 fix->accel = FB_ACCEL_ATARIBLITT;
1772 return 0;
1776 static int stste_decode_var( struct fb_var_screeninfo *var,
1777 struct atafb_par *par )
1779 int xres=var->xres;
1780 int yres=var->yres;
1781 int bpp=var->bits_per_pixel;
1782 int linelen;
1783 int yres_virtual = var->yres_virtual;
1785 if (mono_moni) {
1786 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1787 return -EINVAL;
1788 par->hw.st.mode=ST_HIGH;
1789 xres=sttt_xres;
1790 yres=st_yres;
1791 bpp=1;
1792 } else {
1793 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1794 return -EINVAL;
1795 if (bpp > 2) {
1796 if (xres > sttt_xres/2 || yres > st_yres/2)
1797 return -EINVAL;
1798 par->hw.st.mode=ST_LOW;
1799 xres=sttt_xres/2;
1800 yres=st_yres/2;
1801 bpp=4;
1803 else if (bpp > 1) {
1804 if (xres > sttt_xres || yres > st_yres/2)
1805 return -EINVAL;
1806 par->hw.st.mode=ST_MID;
1807 xres=sttt_xres;
1808 yres=st_yres/2;
1809 bpp=2;
1811 else
1812 return -EINVAL;
1814 if (yres_virtual <= 0)
1815 yres_virtual = 0;
1816 else if (yres_virtual < yres)
1817 yres_virtual = yres;
1818 if (var->sync & FB_SYNC_EXT)
1819 par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
1820 else
1821 par->hw.st.sync=(par->hw.st.sync & ~1);
1822 linelen=xres*bpp/8;
1823 if (yres_virtual * linelen > screen_len && screen_len)
1824 return -EINVAL;
1825 if (yres * linelen > screen_len && screen_len)
1826 return -EINVAL;
1827 if (var->yoffset + yres > yres_virtual && yres_virtual)
1828 return -EINVAL;
1829 par->yres_virtual = yres_virtual;
1830 par->screen_base=screen_base+ var->yoffset*linelen;
1831 return 0;
1834 static int stste_encode_var( struct fb_var_screeninfo *var,
1835 struct atafb_par *par )
1837 int linelen;
1838 memset(var, 0, sizeof(struct fb_var_screeninfo));
1839 var->red.offset=0;
1840 var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1841 var->red.msb_right=0;
1842 var->grayscale=0;
1844 var->pixclock=31041;
1845 var->left_margin=120; /* these are incorrect */
1846 var->right_margin=100;
1847 var->upper_margin=8;
1848 var->lower_margin=16;
1849 var->hsync_len=140;
1850 var->vsync_len=30;
1852 var->height=-1;
1853 var->width=-1;
1855 if (!(par->hw.st.sync & 1))
1856 var->sync=0;
1857 else
1858 var->sync=FB_SYNC_EXT;
1860 switch (par->hw.st.mode & 3) {
1861 case ST_LOW:
1862 var->xres=sttt_xres/2;
1863 var->yres=st_yres/2;
1864 var->bits_per_pixel=4;
1865 break;
1866 case ST_MID:
1867 var->xres=sttt_xres;
1868 var->yres=st_yres/2;
1869 var->bits_per_pixel=2;
1870 break;
1871 case ST_HIGH:
1872 var->xres=sttt_xres;
1873 var->yres=st_yres;
1874 var->bits_per_pixel=1;
1875 break;
1877 var->blue=var->green=var->red;
1878 var->transp.offset=0;
1879 var->transp.length=0;
1880 var->transp.msb_right=0;
1881 var->xres_virtual=sttt_xres_virtual;
1882 linelen=var->xres_virtual * var->bits_per_pixel / 8;
1883 ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
1885 if (! use_hwscroll)
1886 var->yres_virtual=var->yres;
1887 else if (screen_len) {
1888 if (par->yres_virtual)
1889 var->yres_virtual = par->yres_virtual;
1890 else
1891 /* yres_virtual==0 means use maximum */
1892 var->yres_virtual = screen_len / linelen;
1894 else {
1895 if (hwscroll < 0)
1896 var->yres_virtual = 2 * var->yres;
1897 else
1898 var->yres_virtual=var->yres+hwscroll * 16;
1900 var->xoffset=0;
1901 if (screen_base)
1902 var->yoffset=(par->screen_base - screen_base)/linelen;
1903 else
1904 var->yoffset=0;
1905 var->nonstd=0;
1906 var->activate=0;
1907 var->vmode=FB_VMODE_NONINTERLACED;
1908 return 0;
1912 static void stste_get_par( struct atafb_par *par )
1914 unsigned long addr;
1915 par->hw.st.mode=shifter_tt.st_shiftmode;
1916 par->hw.st.sync=shifter.syncmode;
1917 addr = ((shifter.bas_hi & 0xff) << 16) |
1918 ((shifter.bas_md & 0xff) << 8);
1919 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1920 addr |= (shifter.bas_lo & 0xff);
1921 par->screen_base = phys_to_virt(addr);
1924 static void stste_set_par( struct atafb_par *par )
1926 shifter_tt.st_shiftmode=par->hw.st.mode;
1927 shifter.syncmode=par->hw.st.sync;
1928 /* only set screen_base if really necessary */
1929 if (current_par.screen_base != par->screen_base)
1930 fbhw->set_screen_base(par->screen_base);
1934 static int stste_getcolreg(unsigned regno, unsigned *red,
1935 unsigned *green, unsigned *blue,
1936 unsigned *transp, struct fb_info *info)
1938 unsigned col, t;
1940 if (regno > 15)
1941 return 1;
1942 col = shifter_tt.color_reg[regno];
1943 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1944 t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
1945 t |= t << 4;
1946 *red = t | (t << 8);
1947 t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
1948 t |= t << 4;
1949 *green = t | (t << 8);
1950 t = ((col << 1) & 0xe) | ((col >> 3) & 1);
1951 t |= t << 4;
1952 *blue = t | (t << 8);
1954 else {
1955 t = (col >> 7) & 0xe;
1956 t |= t << 4;
1957 *red = t | (t << 8);
1958 t = (col >> 3) & 0xe;
1959 t |= t << 4;
1960 *green = t | (t << 8);
1961 t = (col << 1) & 0xe;
1962 t |= t << 4;
1963 *blue = t | (t << 8);
1965 *transp = 0;
1966 return 0;
1970 static int stste_setcolreg(unsigned regno, unsigned red,
1971 unsigned green, unsigned blue,
1972 unsigned transp, struct fb_info *info)
1974 if (regno > 15)
1975 return 1;
1976 red >>= 12;
1977 blue >>= 12;
1978 green >>= 12;
1979 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1980 shifter_tt.color_reg[regno] =
1981 (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1982 (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1983 ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1984 else
1985 shifter_tt.color_reg[regno] =
1986 ((red & 0xe) << 7) |
1987 ((green & 0xe) << 3) |
1988 ((blue & 0xe) >> 1);
1989 return 0;
1993 static int stste_detect( void )
1995 { struct atafb_par par;
1997 /* Determine the connected monitor: The DMA sound must be
1998 * disabled before reading the MFP GPIP, because the Sound
1999 * Done Signal and the Monochrome Detect are XORed together!
2001 if (ATARIHW_PRESENT(PCM_8BIT)) {
2002 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2003 udelay(20); /* wait a while for things to settle down */
2005 mono_moni = (mfp.par_dt_reg & 0x80) == 0;
2007 stste_get_par(&par);
2008 stste_encode_var(&atafb_predefined[0], &par);
2010 if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2011 use_hwscroll = 0;
2012 return 1;
2015 static void stste_set_screen_base(void *s_base)
2017 unsigned long addr;
2018 addr= virt_to_phys(s_base);
2019 /* Setup Screen Memory */
2020 shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2021 shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2022 if (ATARIHW_PRESENT(EXTD_SHIFTER))
2023 shifter.bas_lo=(unsigned char) (addr & 0x0000ff);
2026 #endif /* ATAFB_STE */
2028 /* Switching the screen size should be done during vsync, otherwise
2029 * the margins may get messed up. This is a well known problem of
2030 * the ST's video system.
2032 * Unfortunately there is hardly any way to find the vsync, as the
2033 * vertical blank interrupt is no longer in time on machines with
2034 * overscan type modifications.
2036 * We can, however, use Timer B to safely detect the black shoulder,
2037 * but then we've got to guess an appropriate delay to find the vsync.
2038 * This might not work on every machine.
2040 * martin_rogge @ ki.maus.de, 8th Aug 1995
2043 #define LINE_DELAY (mono_moni ? 30 : 70)
2044 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2046 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2047 static void st_ovsc_switch(void)
2049 unsigned long flags;
2050 register unsigned char old, new;
2052 if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2053 return;
2054 local_irq_save(flags);
2056 mfp.tim_ct_b = 0x10;
2057 mfp.active_edge |= 8;
2058 mfp.tim_ct_b = 0;
2059 mfp.tim_dt_b = 0xf0;
2060 mfp.tim_ct_b = 8;
2061 while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2063 new = mfp.tim_dt_b;
2064 do {
2065 udelay(LINE_DELAY);
2066 old = new;
2067 new = mfp.tim_dt_b;
2068 } while (old != new);
2069 mfp.tim_ct_b = 0x10;
2070 udelay(SYNC_DELAY);
2072 if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2073 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2074 if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2075 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2076 if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2077 sound_ym.rd_data_reg_sel = 14;
2078 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2079 ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2080 ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2082 local_irq_restore(flags);
2085 /* ------------------- External Video ---------------------- */
2087 #ifdef ATAFB_EXT
2089 static int ext_encode_fix( struct fb_fix_screeninfo *fix,
2090 struct atafb_par *par )
2093 strcpy(fix->id,"Unknown Extern");
2094 fix->smem_start = (unsigned long)external_addr;
2095 fix->smem_len = PAGE_ALIGN(external_len);
2096 if (external_depth == 1) {
2097 fix->type = FB_TYPE_PACKED_PIXELS;
2098 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2099 * for "normal" and "inverted", rsp., in the monochrome case */
2100 fix->visual =
2101 (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2102 external_pmode == FB_TYPE_PACKED_PIXELS) ?
2103 FB_VISUAL_MONO10 :
2104 FB_VISUAL_MONO01;
2106 else {
2107 /* Use STATIC if we don't know how to access color registers */
2108 int visual = external_vgaiobase ?
2109 FB_VISUAL_PSEUDOCOLOR :
2110 FB_VISUAL_STATIC_PSEUDOCOLOR;
2111 switch (external_pmode) {
2112 case -1: /* truecolor */
2113 fix->type=FB_TYPE_PACKED_PIXELS;
2114 fix->visual=FB_VISUAL_TRUECOLOR;
2115 break;
2116 case FB_TYPE_PACKED_PIXELS:
2117 fix->type=FB_TYPE_PACKED_PIXELS;
2118 fix->visual=visual;
2119 break;
2120 case FB_TYPE_PLANES:
2121 fix->type=FB_TYPE_PLANES;
2122 fix->visual=visual;
2123 break;
2124 case FB_TYPE_INTERLEAVED_PLANES:
2125 fix->type=FB_TYPE_INTERLEAVED_PLANES;
2126 fix->type_aux=2;
2127 fix->visual=visual;
2128 break;
2131 fix->xpanstep = 0;
2132 fix->ypanstep = 0;
2133 fix->ywrapstep = 0;
2134 fix->line_length = 0;
2135 return 0;
2139 static int ext_decode_var( struct fb_var_screeninfo *var,
2140 struct atafb_par *par )
2142 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2144 if (var->bits_per_pixel > myvar->bits_per_pixel ||
2145 var->xres > myvar->xres ||
2146 var->xres_virtual > myvar->xres_virtual ||
2147 var->yres > myvar->yres ||
2148 var->xoffset > 0 ||
2149 var->yoffset > 0)
2150 return -EINVAL;
2151 return 0;
2155 static int ext_encode_var( struct fb_var_screeninfo *var,
2156 struct atafb_par *par )
2158 memset(var, 0, sizeof(struct fb_var_screeninfo));
2159 var->red.offset=0;
2160 var->red.length=(external_pmode == -1) ? external_depth/3 :
2161 (external_vgaiobase ? external_bitspercol : 0);
2162 var->red.msb_right=0;
2163 var->grayscale=0;
2165 var->pixclock=31041;
2166 var->left_margin=120; /* these are surely incorrect */
2167 var->right_margin=100;
2168 var->upper_margin=8;
2169 var->lower_margin=16;
2170 var->hsync_len=140;
2171 var->vsync_len=30;
2173 var->height=-1;
2174 var->width=-1;
2176 var->sync=0;
2178 var->xres = external_xres;
2179 var->yres = external_yres;
2180 var->xres_virtual = external_xres_virtual;
2181 var->bits_per_pixel = external_depth;
2183 var->blue=var->green=var->red;
2184 var->transp.offset=0;
2185 var->transp.length=0;
2186 var->transp.msb_right=0;
2187 var->yres_virtual=var->yres;
2188 var->xoffset=0;
2189 var->yoffset=0;
2190 var->nonstd=0;
2191 var->activate=0;
2192 var->vmode=FB_VMODE_NONINTERLACED;
2193 return 0;
2197 static void ext_get_par( struct atafb_par *par )
2199 par->screen_base = external_addr;
2202 static void ext_set_par( struct atafb_par *par )
2206 #define OUTB(port,val) \
2207 *((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
2208 #define INB(port) \
2209 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2210 #define DACDelay \
2211 do { \
2212 unsigned char tmp=INB(0x3da); \
2213 tmp=INB(0x3da); \
2214 } while (0)
2216 static int ext_getcolreg( unsigned regno, unsigned *red,
2217 unsigned *green, unsigned *blue,
2218 unsigned *transp, struct fb_info *info )
2220 if (! external_vgaiobase)
2221 return 1;
2223 *red = ext_color[regno].red;
2224 *green = ext_color[regno].green;
2225 *blue = ext_color[regno].blue;
2226 *transp=0;
2227 return 0;
2230 static int ext_setcolreg( unsigned regno, unsigned red,
2231 unsigned green, unsigned blue,
2232 unsigned transp, struct fb_info *info )
2234 { unsigned char colmask = (1 << external_bitspercol) - 1;
2236 if (! external_vgaiobase)
2237 return 1;
2239 ext_color[regno].red = red;
2240 ext_color[regno].green = green;
2241 ext_color[regno].blue = blue;
2243 switch (external_card_type) {
2244 case IS_VGA:
2245 OUTB(0x3c8, regno);
2246 DACDelay;
2247 OUTB(0x3c9, red & colmask);
2248 DACDelay;
2249 OUTB(0x3c9, green & colmask);
2250 DACDelay;
2251 OUTB(0x3c9, blue & colmask);
2252 DACDelay;
2253 return 0;
2255 case IS_MV300:
2256 OUTB((MV300_reg[regno] << 2)+1, red);
2257 OUTB((MV300_reg[regno] << 2)+1, green);
2258 OUTB((MV300_reg[regno] << 2)+1, blue);
2259 return 0;
2261 default:
2262 return 1;
2267 static int ext_detect( void )
2270 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2271 struct atafb_par dummy_par;
2273 myvar->xres = external_xres;
2274 myvar->xres_virtual = external_xres_virtual;
2275 myvar->yres = external_yres;
2276 myvar->bits_per_pixel = external_depth;
2277 ext_encode_var(myvar, &dummy_par);
2278 return 1;
2281 #endif /* ATAFB_EXT */
2283 /* ------ This is the same for most hardware types -------- */
2285 static void set_screen_base(void *s_base)
2287 unsigned long addr;
2288 addr= virt_to_phys(s_base);
2289 /* Setup Screen Memory */
2290 shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2291 shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2292 shifter.bas_lo=(unsigned char) (addr & 0x0000ff);
2296 static int pan_display( struct fb_var_screeninfo *var,
2297 struct atafb_par *par )
2299 if (!fbhw->set_screen_base ||
2300 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2301 return -EINVAL;
2302 var->xoffset = up(var->xoffset, 16);
2303 par->screen_base = screen_base +
2304 (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + var->xoffset)
2305 * fb_display[fb_info.currcon].var.bits_per_pixel / 8;
2306 fbhw->set_screen_base (par->screen_base);
2307 return 0;
2311 /* ------------ Interfaces to hardware functions ------------ */
2314 #ifdef ATAFB_TT
2315 static struct fb_hwswitch tt_switch = {
2316 tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
2317 tt_get_par, tt_set_par, tt_getcolreg,
2318 set_screen_base, NULL, pan_display
2320 #endif
2322 #ifdef ATAFB_FALCON
2323 static struct fb_hwswitch falcon_switch = {
2324 falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
2325 falcon_get_par, falcon_set_par, falcon_getcolreg,
2326 set_screen_base, falcon_blank, falcon_pan_display
2328 #endif
2330 #ifdef ATAFB_STE
2331 static struct fb_hwswitch st_switch = {
2332 stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
2333 stste_get_par, stste_set_par, stste_getcolreg,
2334 stste_set_screen_base, NULL, pan_display
2336 #endif
2338 #ifdef ATAFB_EXT
2339 static struct fb_hwswitch ext_switch = {
2340 ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
2341 ext_get_par, ext_set_par, ext_getcolreg, NULL, NULL, NULL
2343 #endif
2347 static void atafb_get_par( struct atafb_par *par )
2349 if (current_par_valid) {
2350 *par=current_par;
2352 else
2353 fbhw->get_par(par);
2357 static void atafb_set_par( struct atafb_par *par )
2359 fbhw->set_par(par);
2360 current_par=*par;
2361 current_par_valid=1;
2366 /* =========================================================== */
2367 /* ============== Hardware Independent Functions ============= */
2368 /* =========================================================== */
2371 /* used for hardware scrolling */
2373 static int
2374 fb_update_var(int con, struct fb_info *info)
2376 int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual*
2377 fb_display[con].var.bits_per_pixel>>3;
2379 current_par.screen_base=screen_base + off;
2381 if (fbhw->set_screen_base)
2382 fbhw->set_screen_base(current_par.screen_base);
2383 return 0;
2386 static int
2387 do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2389 int err,activate;
2390 struct atafb_par par;
2391 if ((err=fbhw->decode_var(var, &par)))
2392 return err;
2393 activate=var->activate;
2394 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2395 atafb_set_par(&par);
2396 fbhw->encode_var(var, &par);
2397 var->activate=activate;
2398 return 0;
2401 static int
2402 atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
2404 struct atafb_par par;
2405 if (con == -1)
2406 atafb_get_par(&par);
2407 else {
2408 int err;
2409 if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
2410 return err;
2412 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2413 return fbhw->encode_fix(fix, &par);
2416 static int
2417 atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2419 struct atafb_par par;
2420 if (con == -1) {
2421 atafb_get_par(&par);
2422 fbhw->encode_var(var, &par);
2424 else
2425 *var=fb_display[con].var;
2426 return 0;
2429 static void
2430 atafb_set_disp(int con, struct fb_info *info)
2432 struct fb_fix_screeninfo fix;
2433 struct fb_var_screeninfo var;
2434 struct display *display;
2436 if (con >= 0)
2437 display = &fb_display[con];
2438 else
2439 display = &disp; /* used during initialization */
2441 atafb_get_fix(&fix, con, info);
2442 atafb_get_var(&var, con, info);
2443 if (con == -1)
2444 con=0;
2445 info->screen_base = (void *)fix.smem_start;
2446 display->visual = fix.visual;
2447 display->type = fix.type;
2448 display->type_aux = fix.type_aux;
2449 display->ypanstep = fix.ypanstep;
2450 display->ywrapstep = fix.ywrapstep;
2451 display->line_length = fix.line_length;
2452 if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
2453 fix.visual != FB_VISUAL_DIRECTCOLOR)
2454 display->can_soft_blank = 0;
2455 else
2456 display->can_soft_blank = 1;
2457 display->inverse =
2458 (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
2459 switch (fix.type) {
2460 case FB_TYPE_INTERLEAVED_PLANES:
2461 switch (var.bits_per_pixel) {
2462 #ifdef FBCON_HAS_IPLAN2P2
2463 case 2:
2464 display->dispsw = &fbcon_iplan2p2;
2465 break;
2466 #endif
2467 #ifdef FBCON_HAS_IPLAN2P4
2468 case 4:
2469 display->dispsw = &fbcon_iplan2p4;
2470 break;
2471 #endif
2472 #ifdef FBCON_HAS_IPLAN2P8
2473 case 8:
2474 display->dispsw = &fbcon_iplan2p8;
2475 break;
2476 #endif
2478 break;
2479 case FB_TYPE_PACKED_PIXELS:
2480 switch (var.bits_per_pixel) {
2481 #ifdef FBCON_HAS_MFB
2482 case 1:
2483 display->dispsw = &fbcon_mfb;
2484 break;
2485 #endif
2486 #ifdef FBCON_HAS_CFB8
2487 case 8:
2488 display->dispsw = &fbcon_cfb8;
2489 break;
2490 #endif
2491 #ifdef FBCON_HAS_CFB16
2492 case 16:
2493 display->dispsw = &fbcon_cfb16;
2494 display->dispsw_data = fbcon_cfb16_cmap;
2495 break;
2496 #endif
2498 break;
2502 static int
2503 atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2505 int err,oldxres,oldyres,oldbpp,oldxres_virtual,
2506 oldyres_virtual,oldyoffset;
2507 if ((err=do_fb_set_var(var, con==info->currcon)))
2508 return err;
2509 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2510 oldxres=fb_display[con].var.xres;
2511 oldyres=fb_display[con].var.yres;
2512 oldxres_virtual=fb_display[con].var.xres_virtual;
2513 oldyres_virtual=fb_display[con].var.yres_virtual;
2514 oldbpp=fb_display[con].var.bits_per_pixel;
2515 oldyoffset=fb_display[con].var.yoffset;
2516 fb_display[con].var=*var;
2517 if (oldxres != var->xres || oldyres != var->yres
2518 || oldxres_virtual != var->xres_virtual
2519 || oldyres_virtual != var->yres_virtual
2520 || oldbpp != var->bits_per_pixel
2521 || oldyoffset != var->yoffset) {
2522 atafb_set_disp(con, info);
2523 (*fb_info.changevar)(con);
2524 fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
2525 do_install_cmap(con, info);
2528 var->activate=0;
2529 return 0;
2534 static int
2535 atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
2537 if (con == info->currcon) /* current console ? */
2538 return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
2539 else
2540 if (fb_display[con].cmap.len) /* non default colormap ? */
2541 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
2542 else
2543 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
2544 cmap, kspc ? 0 : 2);
2545 return 0;
2548 static int
2549 atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2551 int xoffset = var->xoffset;
2552 int yoffset = var->yoffset;
2553 int err;
2555 if ( xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
2556 || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
2557 return -EINVAL;
2559 if (con == info->currcon) {
2560 if (fbhw->pan_display) {
2561 if ((err = fbhw->pan_display(var, &current_par)))
2562 return err;
2564 else
2565 return -EINVAL;
2567 fb_display[con].var.xoffset = var->xoffset;
2568 fb_display[con].var.yoffset = var->yoffset;
2569 return 0;
2572 static int
2573 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2575 switch (cmd) {
2576 #ifdef FBCMD_GET_CURRENTPAR
2577 case FBCMD_GET_CURRENTPAR:
2578 if (copy_to_user((void *)arg, (void *)&current_par,
2579 sizeof(struct atafb_par)))
2580 return -EFAULT;
2581 return 0;
2582 #endif
2583 #ifdef FBCMD_SET_CURRENTPAR
2584 case FBCMD_SET_CURRENTPAR:
2585 if (copy_from_user((void *)&current_par, (void *)arg,
2586 sizeof(struct atafb_par)))
2587 return -EFAULT;
2588 atafb_set_par(&current_par);
2589 return 0;
2590 #endif
2592 return -EINVAL;
2595 /* (un)blank/poweroff
2596 * 0 = unblank
2597 * 1 = blank
2598 * 2 = suspend vsync
2599 * 3 = suspend hsync
2600 * 4 = off
2602 static int
2603 atafb_blank(int blank, struct fb_info *info)
2605 unsigned short black[16];
2606 struct fb_cmap cmap;
2607 if (fbhw->blank && !fbhw->blank(blank))
2608 return 1;
2609 if (blank) {
2610 memset(black, 0, 16*sizeof(unsigned short));
2611 cmap.red=black;
2612 cmap.green=black;
2613 cmap.blue=black;
2614 cmap.transp=NULL;
2615 cmap.start=0;
2616 cmap.len=16;
2617 fb_set_cmap(&cmap, 1, info);
2619 else
2620 do_install_cmap(info->currcon, info);
2621 return 0;
2624 static struct fb_ops atafb_ops = {
2625 .owner = THIS_MODULE,
2626 .fb_get_fix = atafb_get_fix,
2627 .fb_get_var = atafb_get_var,
2628 .fb_set_var = atafb_set_var,
2629 .fb_get_cmap = atafb_get_cmap,
2630 .fb_set_cmap = gen_set_cmap,
2631 .fb_pan_display =atafb_pan_display,
2632 .fb_blank = atafb_blank,
2633 .fb_ioctl = atafb_ioctl,
2636 static void
2637 check_default_par( int detected_mode )
2639 char default_name[10];
2640 int i;
2641 struct fb_var_screeninfo var;
2642 unsigned long min_mem;
2644 /* First try the user supplied mode */
2645 if (default_par) {
2646 var=atafb_predefined[default_par-1];
2647 var.activate = FB_ACTIVATE_TEST;
2648 if (do_fb_set_var(&var,1))
2649 default_par=0; /* failed */
2651 /* Next is the autodetected one */
2652 if (! default_par) {
2653 var=atafb_predefined[detected_mode-1]; /* autodetect */
2654 var.activate = FB_ACTIVATE_TEST;
2655 if (!do_fb_set_var(&var,1))
2656 default_par=detected_mode;
2658 /* If that also failed, try some default modes... */
2659 if (! default_par) {
2660 /* try default1, default2... */
2661 for (i=1 ; i < 10 ; i++) {
2662 sprintf(default_name,"default%d",i);
2663 default_par=get_video_mode(default_name);
2664 if (! default_par)
2665 panic("can't set default video mode");
2666 var=atafb_predefined[default_par-1];
2667 var.activate = FB_ACTIVATE_TEST;
2668 if (! do_fb_set_var(&var,1))
2669 break; /* ok */
2672 min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
2673 if (default_mem_req < min_mem)
2674 default_mem_req=min_mem;
2677 static int
2678 atafb_switch(int con, struct fb_info *info)
2680 /* Do we have to save the colormap ? */
2681 if (fb_display[info->currcon].cmap.len)
2682 fb_get_cmap(&fb_display[info->currcon].cmap, 1, fbhw->getcolreg,
2683 info);
2684 do_fb_set_var(&fb_display[con].var,1);
2685 info->currcon=con;
2686 /* Install new colormap */
2687 do_install_cmap(con, info);
2688 return 0;
2691 int __init atafb_init(void)
2693 int pad;
2694 int detected_mode;
2695 unsigned long mem_req;
2697 if (!MACH_IS_ATARI)
2698 return -ENXIO;
2700 do {
2701 #ifdef ATAFB_EXT
2702 if (external_addr) {
2703 fbhw = &ext_switch;
2704 atafb_ops.fb_setcolreg = &ext_setcolreg;
2705 break;
2707 #endif
2708 #ifdef ATAFB_TT
2709 if (ATARIHW_PRESENT(TT_SHIFTER)) {
2710 fbhw = &tt_switch;
2711 atafb_ops.fb_setcolreg = &tt_setcolreg;
2712 break;
2714 #endif
2715 #ifdef ATAFB_FALCON
2716 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
2717 fbhw = &falcon_switch;
2718 atafb_ops.fb_setcolreg = &falcon_setcolreg;
2719 request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
2720 "framebuffer/modeswitch", falcon_vbl_switcher);
2721 break;
2723 #endif
2724 #ifdef ATAFB_STE
2725 if (ATARIHW_PRESENT(STND_SHIFTER) ||
2726 ATARIHW_PRESENT(EXTD_SHIFTER)) {
2727 fbhw = &st_switch;
2728 atafb_ops.fb_setcolreg = &stste_setcolreg;
2729 break;
2731 fbhw = &st_switch;
2732 atafb_ops.fb_setcolreg = &stste_setcolreg;
2733 printk("Cannot determine video hardware; defaulting to ST(e)\n");
2734 #else /* ATAFB_STE */
2735 /* no default driver included */
2736 /* Nobody will ever see this message :-) */
2737 panic("Cannot initialize video hardware");
2738 #endif
2739 } while (0);
2741 /* Multisync monitor capabilities */
2742 /* Atari-TOS defaults if no boot option present */
2743 if (fb_info.monspecs.hfmin == 0) {
2744 fb_info.monspecs.hfmin = 31000;
2745 fb_info.monspecs.hfmax = 32000;
2746 fb_info.monspecs.vfmin = 58;
2747 fb_info.monspecs.vfmax = 62;
2750 detected_mode = fbhw->detect();
2751 check_default_par(detected_mode);
2752 #ifdef ATAFB_EXT
2753 if (!external_addr) {
2754 #endif /* ATAFB_EXT */
2755 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
2756 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
2757 screen_base = atari_stram_alloc(mem_req, "atafb");
2758 if (!screen_base)
2759 panic("Cannot allocate screen memory");
2760 memset(screen_base, 0, mem_req);
2761 pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
2762 screen_base+=pad;
2763 real_screen_base=screen_base+ovsc_offset;
2764 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
2765 st_ovsc_switch();
2766 if (CPU_IS_040_OR_060) {
2767 /* On a '040+, the cache mode of video RAM must be set to
2768 * write-through also for internal video hardware! */
2769 cache_push(virt_to_phys(screen_base), screen_len);
2770 kernel_set_cachemode(screen_base, screen_len,
2771 IOMAP_WRITETHROUGH);
2773 #ifdef ATAFB_EXT
2775 else {
2776 /* Map the video memory (physical address given) to somewhere
2777 * in the kernel address space.
2779 external_addr =
2780 ioremap_writethrough((unsigned long)external_addr,
2781 external_len);
2782 if (external_vgaiobase)
2783 external_vgaiobase =
2784 (unsigned long)ioremap(external_vgaiobase, 0x10000);
2785 screen_base =
2786 real_screen_base = external_addr;
2787 screen_len = external_len & PAGE_MASK;
2788 memset (screen_base, 0, external_len);
2790 #endif /* ATAFB_EXT */
2792 strcpy(fb_info.modename, "Atari Builtin ");
2793 fb_info.changevar = NULL;
2794 fb_info.fbops = &atafb_ops;
2795 fb_info.disp = &disp;
2796 fb_info.currcon = -1;
2797 fb_info.switch_con = &atafb_switch;
2798 fb_info.updatevar = &fb_update_var;
2799 fb_info.flags = FBINFO_FLAG_DEFAULT;
2800 do_fb_set_var(&atafb_predefined[default_par-1], 1);
2801 strcat(fb_info.modename, fb_var_names[default_par-1][0]);
2803 atafb_get_var(&disp.var, -1, &fb_info);
2804 atafb_set_disp(-1, &fb_info);
2805 do_install_cmap(0, &fb_info);
2807 if (register_framebuffer(&fb_info) < 0)
2808 return -EINVAL;
2810 printk("Determined %dx%d, depth %d\n",
2811 disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
2812 if ((disp.var.xres != disp.var.xres_virtual) ||
2813 (disp.var.yres != disp.var.yres_virtual))
2814 printk(" virtual %dx%d\n",
2815 disp.var.xres_virtual, disp.var.yres_virtual);
2816 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2817 fb_info.node, fb_info.modename, screen_len>>10);
2819 /* TODO: This driver cannot be unloaded yet */
2820 return 0;
2824 #ifdef ATAFB_EXT
2825 static void __init atafb_setup_ext(char *spec)
2827 int xres, xres_virtual, yres, depth, planes;
2828 unsigned long addr, len;
2829 char *p;
2831 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2832 * <screen mem addr>
2833 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2834 * [;<xres-virtual>]]]]]
2836 * 09/23/97 Juergen
2837 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2839 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2841 if (!(p = strsep(&spec, ";")) || !*p)
2842 return;
2843 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2844 if (xres <= 0)
2845 return;
2847 if (!(p = strsep(&spec, ";")) || !*p)
2848 return;
2849 yres = simple_strtoul(p, NULL, 10);
2850 if (yres <= 0)
2851 return;
2853 if (!(p = strsep(&spec, ";")) || !*p)
2854 return;
2855 depth = simple_strtoul(p, NULL, 10);
2856 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2857 depth != 16 && depth != 24)
2858 return;
2860 if (!(p = strsep(&spec, ";")) || !*p)
2861 return;
2862 if (*p == 'i')
2863 planes = FB_TYPE_INTERLEAVED_PLANES;
2864 else if (*p == 'p')
2865 planes = FB_TYPE_PACKED_PIXELS;
2866 else if (*p == 'n')
2867 planes = FB_TYPE_PLANES;
2868 else if (*p == 't')
2869 planes = -1; /* true color */
2870 else
2871 return;
2874 if (!(p = strsep(&spec, ";")) || !*p)
2875 return;
2876 addr = simple_strtoul(p, NULL, 0);
2878 if (!(p = strsep(&spec, ";")) || !*p)
2879 len = xres*yres*depth/8;
2880 else
2881 len = simple_strtoul(p, NULL, 0);
2883 if ((p = strsep(&spec, ";")) && *p) {
2884 external_vgaiobase=simple_strtoul(p, NULL, 0);
2887 if ((p = strsep(&spec, ";")) && *p) {
2888 external_bitspercol = simple_strtoul(p, NULL, 0);
2889 if (external_bitspercol > 8)
2890 external_bitspercol = 8;
2891 else if (external_bitspercol < 1)
2892 external_bitspercol = 1;
2895 if ((p = strsep(&spec, ";")) && *p) {
2896 if (!strcmp(p, "vga"))
2897 external_card_type = IS_VGA;
2898 if (!strcmp(p, "mv300"))
2899 external_card_type = IS_MV300;
2902 if ((p = strsep(&spec, ";")) && *p) {
2903 xres_virtual = simple_strtoul(p, NULL, 10);
2904 if (xres_virtual < xres)
2905 xres_virtual = xres;
2906 if (xres_virtual*yres*depth/8 > len)
2907 len=xres_virtual*yres*depth/8;
2910 external_xres = xres;
2911 external_xres_virtual = xres_virtual;
2912 external_yres = yres;
2913 external_depth = depth;
2914 external_pmode = planes;
2915 external_addr = (void *)addr;
2916 external_len = len;
2918 if (external_card_type == IS_MV300)
2919 switch (external_depth) {
2920 case 1:
2921 MV300_reg = MV300_reg_1bit;
2922 break;
2923 case 4:
2924 MV300_reg = MV300_reg_4bit;
2925 break;
2926 case 8:
2927 MV300_reg = MV300_reg_8bit;
2928 break;
2931 #endif /* ATAFB_EXT */
2934 static void __init atafb_setup_int(char *spec)
2936 /* Format to config extended internal video hardware like OverScan:
2937 "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2938 Explanation:
2939 <xres>: x-resolution
2940 <yres>: y-resolution
2941 The following are only needed if you have an overscan which
2942 needs a black border:
2943 <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2944 <yres_max>: max. number of lines your OverScan hardware would allow
2945 <offset>: Offset from physical beginning to visible beginning
2946 of screen in bytes
2948 int xres;
2949 char *p;
2951 if (!(p = strsep(&spec, ";")) || !*p)
2952 return;
2953 xres = simple_strtoul(p, NULL, 10);
2954 if (!(p = strsep(&spec, ";")) || !*p)
2955 return;
2956 sttt_xres=xres;
2957 tt_yres=st_yres=simple_strtoul(p, NULL, 10);
2958 if ((p=strsep(&spec, ";")) && *p) {
2959 sttt_xres_virtual=simple_strtoul(p, NULL, 10);
2961 if ((p=strsep(&spec, ";")) && *p) {
2962 sttt_yres_virtual=simple_strtoul(p, NULL, 0);
2964 if ((p=strsep(&spec, ";")) && *p) {
2965 ovsc_offset=simple_strtoul(p, NULL, 0);
2968 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2969 use_hwscroll=0;
2973 #ifdef ATAFB_FALCON
2974 static void __init atafb_setup_mcap(char *spec)
2976 char *p;
2977 int vmin, vmax, hmin, hmax;
2979 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2980 * <V*> vertical freq. in Hz
2981 * <H*> horizontal freq. in kHz
2983 if (!(p = strsep(&spec, ";")) || !*p)
2984 return;
2985 vmin = simple_strtoul(p, NULL, 10);
2986 if (vmin <= 0)
2987 return;
2988 if (!(p = strsep(&spec, ";")) || !*p)
2989 return;
2990 vmax = simple_strtoul(p, NULL, 10);
2991 if (vmax <= 0 || vmax <= vmin)
2992 return;
2993 if (!(p = strsep(&spec, ";")) || !*p)
2994 return;
2995 hmin = 1000 * simple_strtoul(p, NULL, 10);
2996 if (hmin <= 0)
2997 return;
2998 if (!(p = strsep(&spec, "")) || !*p)
2999 return;
3000 hmax = 1000 * simple_strtoul(p, NULL, 10);
3001 if (hmax <= 0 || hmax <= hmin)
3002 return;
3004 fb_info.monspecs.vfmin = vmin;
3005 fb_info.monspecs.vfmax = vmax;
3006 fb_info.monspecs.hfmin = hmin;
3007 fb_info.monspecs.hfmax = hmax;
3009 #endif /* ATAFB_FALCON */
3012 static void __init atafb_setup_user(char *spec)
3014 /* Format of user defined video mode is: <xres>;<yres>;<depth>
3016 char *p;
3017 int xres, yres, depth, temp;
3019 if (!(p = strsep(&spec, ";")) || !*p)
3020 return;
3021 xres = simple_strtoul(p, NULL, 10);
3022 if (!(p = strsep(&spec, ";")) || !*p)
3023 return;
3024 yres = simple_strtoul(p, NULL, 10);
3025 if (!(p = strsep(&spec, "")) || !*p)
3026 return;
3027 depth = simple_strtoul(p, NULL, 10);
3028 if ((temp=get_video_mode("user0"))) {
3029 default_par=temp;
3030 atafb_predefined[default_par-1].xres = xres;
3031 atafb_predefined[default_par-1].yres = yres;
3032 atafb_predefined[default_par-1].bits_per_pixel = depth;
3036 int __init atafb_setup( char *options )
3038 char *this_opt;
3039 int temp;
3041 fb_info.fontname[0] = '\0';
3043 if (!options || !*options)
3044 return 0;
3046 while ((this_opt = strsep(&options, ",")) != NULL) {
3047 if (!*this_opt) continue;
3048 if ((temp=get_video_mode(this_opt)))
3049 default_par=temp;
3050 else if (! strcmp(this_opt, "inverse"))
3051 inverse=1;
3052 else if (!strncmp(this_opt, "font:", 5))
3053 strcpy(fb_info.fontname, this_opt+5);
3054 else if (! strncmp(this_opt, "hwscroll_",9)) {
3055 hwscroll=simple_strtoul(this_opt+9, NULL, 10);
3056 if (hwscroll < 0)
3057 hwscroll = 0;
3058 if (hwscroll > 200)
3059 hwscroll = 200;
3061 #ifdef ATAFB_EXT
3062 else if (!strcmp(this_opt,"mv300")) {
3063 external_bitspercol = 8;
3064 external_card_type = IS_MV300;
3066 else if (!strncmp(this_opt,"external:",9))
3067 atafb_setup_ext(this_opt+9);
3068 #endif
3069 else if (!strncmp(this_opt,"internal:",9))
3070 atafb_setup_int(this_opt+9);
3071 #ifdef ATAFB_FALCON
3072 else if (!strncmp(this_opt, "eclock:", 7)) {
3073 fext.f = simple_strtoul(this_opt+7, NULL, 10);
3074 /* external pixelclock in kHz --> ps */
3075 fext.t = 1000000000/fext.f;
3076 fext.f *= 1000;
3078 else if (!strncmp(this_opt, "monitorcap:", 11))
3079 atafb_setup_mcap(this_opt+11);
3080 #endif
3081 else if (!strcmp(this_opt, "keep"))
3082 DontCalcRes = 1;
3083 else if (!strncmp(this_opt, "R", 1))
3084 atafb_setup_user(this_opt+1);
3086 return 0;
3089 #ifdef MODULE
3090 MODULE_LICENSE("GPL");
3092 int init_module(void)
3094 return atafb_init();
3096 #endif /* MODULE */