ACPI: prevent ACPI quirk warning mass spamming in logs
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / video / atafb.c
blobbffe2b946344b37881f0fed387965562b357724d
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/errno.h>
53 #include <linux/string.h>
54 #include <linux/mm.h>
55 #include <linux/slab.h>
56 #include <linux/delay.h>
57 #include <linux/init.h>
58 #include <linux/interrupt.h>
60 #include <asm/setup.h>
61 #include <asm/uaccess.h>
62 #include <asm/pgtable.h>
63 #include <asm/irq.h>
64 #include <asm/io.h>
66 #include <asm/atarihw.h>
67 #include <asm/atariints.h>
68 #include <asm/atari_stram.h>
70 #include <linux/fb.h>
71 #include <asm/atarikb.h>
73 #include <video/fbcon.h>
74 #include <video/fbcon-cfb8.h>
75 #include <video/fbcon-cfb16.h>
76 #include <video/fbcon-iplan2p2.h>
77 #include <video/fbcon-iplan2p4.h>
78 #include <video/fbcon-iplan2p8.h>
79 #include <video/fbcon-mfb.h>
82 #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
83 #define SWITCH_SND6 0x40
84 #define SWITCH_SND7 0x80
85 #define SWITCH_NONE 0x00
88 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
91 static int default_par=0; /* default resolution (0=none) */
93 static unsigned long default_mem_req=0;
95 static int hwscroll=-1;
97 static int use_hwscroll = 1;
99 static int sttt_xres=640,st_yres=400,tt_yres=480;
100 static int sttt_xres_virtual=640,sttt_yres_virtual=400;
101 static int ovsc_offset=0, ovsc_addlen=0;
103 static struct atafb_par {
104 void *screen_base;
105 int yres_virtual;
106 #if defined ATAFB_TT || defined ATAFB_STE
107 union {
108 struct {
109 int mode;
110 int sync;
111 } tt, st;
112 #endif
113 #ifdef ATAFB_FALCON
114 struct falcon_hw {
115 /* Here are fields for storing a video mode, as direct
116 * parameters for the hardware.
118 short sync;
119 short line_width;
120 short line_offset;
121 short st_shift;
122 short f_shift;
123 short vid_control;
124 short vid_mode;
125 short xoffset;
126 short hht, hbb, hbe, hdb, hde, hss;
127 short vft, vbb, vbe, vdb, vde, vss;
128 /* auxiliary information */
129 short mono;
130 short ste_mode;
131 short bpp;
132 } falcon;
133 #endif
134 /* Nothing needed for external mode */
135 } hw;
136 } current_par;
138 /* Don't calculate an own resolution, and thus don't change the one found when
139 * booting (currently used for the Falcon to keep settings for internal video
140 * hardware extensions (e.g. ScreenBlaster) */
141 static int DontCalcRes = 0;
143 #ifdef ATAFB_FALCON
144 #define HHT hw.falcon.hht
145 #define HBB hw.falcon.hbb
146 #define HBE hw.falcon.hbe
147 #define HDB hw.falcon.hdb
148 #define HDE hw.falcon.hde
149 #define HSS hw.falcon.hss
150 #define VFT hw.falcon.vft
151 #define VBB hw.falcon.vbb
152 #define VBE hw.falcon.vbe
153 #define VDB hw.falcon.vdb
154 #define VDE hw.falcon.vde
155 #define VSS hw.falcon.vss
156 #define VCO_CLOCK25 0x04
157 #define VCO_CSYPOS 0x10
158 #define VCO_VSYPOS 0x20
159 #define VCO_HSYPOS 0x40
160 #define VCO_SHORTOFFS 0x100
161 #define VMO_DOUBLE 0x01
162 #define VMO_INTER 0x02
163 #define VMO_PREMASK 0x0c
164 #endif
166 static struct fb_info fb_info;
168 static void *screen_base; /* base address of screen */
169 static void *real_screen_base; /* (only for Overscan) */
171 static int screen_len;
173 static int current_par_valid=0;
175 static int mono_moni=0;
177 static struct display disp;
180 #ifdef ATAFB_EXT
181 /* external video handling */
183 static unsigned external_xres;
184 static unsigned external_xres_virtual;
185 static unsigned external_yres;
186 /* not needed - atafb will never support panning/hardwarescroll with external
187 * static unsigned external_yres_virtual;
190 static unsigned external_depth;
191 static int external_pmode;
192 static void *external_addr = 0;
193 static unsigned long external_len;
194 static unsigned long external_vgaiobase = 0;
195 static unsigned int external_bitspercol = 6;
198 JOE <joe@amber.dinoco.de>:
199 added card type for external driver, is only needed for
200 colormap handling.
203 enum cardtype { IS_VGA, IS_MV300 };
204 static enum cardtype external_card_type = IS_VGA;
207 The MV300 mixes the color registers. So we need an array of munged
208 indices in order to access the correct reg.
210 static int MV300_reg_1bit[2]={0,1};
211 static int MV300_reg_4bit[16]={
212 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
213 static int MV300_reg_8bit[256]={
214 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
215 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
216 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
217 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
218 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
219 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
220 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
221 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
222 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
223 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
224 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
225 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
226 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
227 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
228 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
229 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 };
231 static int *MV300_reg = MV300_reg_8bit;
234 And on the MV300 it's difficult to read out the hardware palette. So we
235 just keep track of the set colors in our own array here, and use that!
238 static struct { unsigned char red,green,blue,pad; } ext_color[256];
239 #endif /* ATAFB_EXT */
242 static int inverse=0;
244 extern int fontheight_8x8;
245 extern int fontwidth_8x8;
246 extern unsigned char fontdata_8x8[];
248 extern int fontheight_8x16;
249 extern int fontwidth_8x16;
250 extern unsigned char fontdata_8x16[];
252 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
253 * TT, or Falcon.
255 * int (*detect)( void )
256 * This function should detect the current video mode settings and
257 * store them in atafb_predefined[0] for later reference by the
258 * user. Return the index+1 of an equivalent predefined mode or 0
259 * if there is no such.
261 * int (*encode_fix)( struct fb_fix_screeninfo *fix,
262 * struct atafb_par *par )
263 * This function should fill in the 'fix' structure based on the
264 * values in the 'par' structure.
266 * int (*decode_var)( struct fb_var_screeninfo *var,
267 * struct atafb_par *par )
268 * Get the video params out of 'var'. If a value doesn't fit, round
269 * it up, if it's too big, return EINVAL.
270 * Round up in the following order: bits_per_pixel, xres, yres,
271 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
272 * horizontal timing, vertical timing.
274 * int (*encode_var)( struct fb_var_screeninfo *var,
275 * struct atafb_par *par );
276 * Fill the 'var' structure based on the values in 'par' and maybe
277 * other values read out of the hardware.
279 * void (*get_par)( struct atafb_par *par )
280 * Fill the hardware's 'par' structure.
282 * void (*set_par)( struct atafb_par *par )
283 * Set the hardware according to 'par'.
285 * int (*getcolreg)( unsigned regno, unsigned *red,
286 * unsigned *green, unsigned *blue,
287 * unsigned *transp, struct fb_info *info )
288 * Read a single color register and split it into
289 * colors/transparent. Return != 0 for invalid regno.
291 * void (*set_screen_base)(void *s_base)
292 * Set the base address of the displayed frame buffer. Only called
293 * if yres_virtual > yres or xres_virtual > xres.
295 * int (*blank)( int blank_mode )
296 * Blank the screen if blank_mode!=0, else unblank. If blank==NULL then
297 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
298 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
299 * doesn't support it. Implements VESA suspend and powerdown modes on
300 * hardware that supports disabling hsync/vsync:
301 * blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown.
304 static struct fb_hwswitch {
305 int (*detect)( void );
306 int (*encode_fix)( struct fb_fix_screeninfo *fix,
307 struct atafb_par *par );
308 int (*decode_var)( struct fb_var_screeninfo *var,
309 struct atafb_par *par );
310 int (*encode_var)( struct fb_var_screeninfo *var,
311 struct atafb_par *par );
312 void (*get_par)( struct atafb_par *par );
313 void (*set_par)( struct atafb_par *par );
314 int (*getcolreg)( unsigned regno, unsigned *red,
315 unsigned *green, unsigned *blue,
316 unsigned *transp, struct fb_info *info );
317 void (*set_screen_base)(void *s_base);
318 int (*blank)( int blank_mode );
319 int (*pan_display)( struct fb_var_screeninfo *var,
320 struct atafb_par *par);
321 } *fbhw;
323 static char *autodetect_names[] = {"autodetect", NULL};
324 static char *stlow_names[] = {"stlow", NULL};
325 static char *stmid_names[] = {"stmid", "default5", NULL};
326 static char *sthigh_names[] = {"sthigh", "default4", NULL};
327 static char *ttlow_names[] = {"ttlow", NULL};
328 static char *ttmid_names[]= {"ttmid", "default1", NULL};
329 static char *tthigh_names[]= {"tthigh", "default2", NULL};
330 static char *vga2_names[] = {"vga2", NULL};
331 static char *vga4_names[] = {"vga4", NULL};
332 static char *vga16_names[] = {"vga16", "default3", NULL};
333 static char *vga256_names[] = {"vga256", NULL};
334 static char *falh2_names[] = {"falh2", NULL};
335 static char *falh16_names[] = {"falh16", NULL};
337 static char **fb_var_names[] = {
338 /* Writing the name arrays directly in this array (via "(char *[]){...}")
339 * crashes gcc 2.5.8 (sigsegv) if the inner array
340 * contains more than two items. I've also seen that all elements
341 * were identical to the last (my cross-gcc) :-(*/
342 autodetect_names,
343 stlow_names,
344 stmid_names,
345 sthigh_names,
346 ttlow_names,
347 ttmid_names,
348 tthigh_names,
349 vga2_names,
350 vga4_names,
351 vga16_names,
352 vga256_names,
353 falh2_names,
354 falh16_names,
355 NULL
356 /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
359 static struct fb_var_screeninfo atafb_predefined[] = {
361 * yres_virtual==0 means use hw-scrolling if possible, else yres
363 { /* autodetect */
364 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
365 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
366 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
367 { /* st low */
368 320, 200, 320, 0, 0, 0, 4, 0,
369 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
370 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
371 { /* st mid */
372 640, 200, 640, 0, 0, 0, 2, 0,
373 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
374 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
375 { /* st high */
376 640, 400, 640, 0, 0, 0, 1, 0,
377 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
378 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
379 { /* tt low */
380 320, 480, 320, 0, 0, 0, 8, 0,
381 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
382 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
383 { /* tt mid */
384 640, 480, 640, 0, 0, 0, 4, 0,
385 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
386 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
387 { /* tt high */
388 1280, 960, 1280, 0, 0, 0, 1, 0,
389 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
390 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
391 { /* vga2 */
392 640, 480, 640, 0, 0, 0, 1, 0,
393 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
394 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
395 { /* vga4 */
396 640, 480, 640, 0, 0, 0, 2, 0,
397 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
398 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
399 { /* vga16 */
400 640, 480, 640, 0, 0, 0, 4, 0,
401 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
402 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
403 { /* vga256 */
404 640, 480, 640, 0, 0, 0, 8, 0,
405 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
406 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
407 { /* falh2 */
408 896, 608, 896, 0, 0, 0, 1, 0,
409 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
410 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
411 { /* falh16 */
412 896, 608, 896, 0, 0, 0, 4, 0,
413 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
414 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
417 static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined);
420 static int
421 get_video_mode(char *vname)
423 char ***name_list;
424 char **name;
425 int i;
426 name_list=fb_var_names;
427 for (i = 0 ; i < num_atafb_predefined ; i++) {
428 name=*(name_list++);
429 if (! name || ! *name)
430 break;
431 while (*name) {
432 if (! strcmp(vname, *name))
433 return i+1;
434 name++;
437 return 0;
442 /* ------------------- TT specific functions ---------------------- */
444 #ifdef ATAFB_TT
446 static int tt_encode_fix( struct fb_fix_screeninfo *fix,
447 struct atafb_par *par )
450 int mode;
452 strcpy(fix->id,"Atari Builtin");
453 fix->smem_start = (unsigned long)real_screen_base;
454 fix->smem_len = screen_len;
455 fix->type=FB_TYPE_INTERLEAVED_PLANES;
456 fix->type_aux=2;
457 fix->visual=FB_VISUAL_PSEUDOCOLOR;
458 mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
459 if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
460 fix->type=FB_TYPE_PACKED_PIXELS;
461 fix->type_aux=0;
462 if (mode == TT_SHIFTER_TTHIGH)
463 fix->visual=FB_VISUAL_MONO01;
465 fix->xpanstep=0;
466 fix->ypanstep=1;
467 fix->ywrapstep=0;
468 fix->line_length = 0;
469 fix->accel = FB_ACCEL_ATARIBLITT;
470 return 0;
474 static int tt_decode_var( struct fb_var_screeninfo *var,
475 struct atafb_par *par )
477 int xres=var->xres;
478 int yres=var->yres;
479 int bpp=var->bits_per_pixel;
480 int linelen;
481 int yres_virtual = var->yres_virtual;
483 if (mono_moni) {
484 if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
485 return -EINVAL;
486 par->hw.tt.mode=TT_SHIFTER_TTHIGH;
487 xres=sttt_xres*2;
488 yres=tt_yres*2;
489 bpp=1;
490 } else {
491 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
492 return -EINVAL;
493 if (bpp > 4) {
494 if (xres > sttt_xres/2 || yres > tt_yres)
495 return -EINVAL;
496 par->hw.tt.mode=TT_SHIFTER_TTLOW;
497 xres=sttt_xres/2;
498 yres=tt_yres;
499 bpp=8;
501 else if (bpp > 2) {
502 if (xres > sttt_xres || yres > tt_yres)
503 return -EINVAL;
504 if (xres > sttt_xres/2 || yres > st_yres/2) {
505 par->hw.tt.mode=TT_SHIFTER_TTMID;
506 xres=sttt_xres;
507 yres=tt_yres;
508 bpp=4;
510 else {
511 par->hw.tt.mode=TT_SHIFTER_STLOW;
512 xres=sttt_xres/2;
513 yres=st_yres/2;
514 bpp=4;
517 else if (bpp > 1) {
518 if (xres > sttt_xres || yres > st_yres/2)
519 return -EINVAL;
520 par->hw.tt.mode=TT_SHIFTER_STMID;
521 xres=sttt_xres;
522 yres=st_yres/2;
523 bpp=2;
525 else if (var->xres > sttt_xres || var->yres > st_yres) {
526 return -EINVAL;
528 else {
529 par->hw.tt.mode=TT_SHIFTER_STHIGH;
530 xres=sttt_xres;
531 yres=st_yres;
532 bpp=1;
535 if (yres_virtual <= 0)
536 yres_virtual = 0;
537 else if (yres_virtual < yres)
538 yres_virtual = yres;
539 if (var->sync & FB_SYNC_EXT)
540 par->hw.tt.sync=0;
541 else
542 par->hw.tt.sync=1;
543 linelen=xres*bpp/8;
544 if (yres_virtual * linelen > screen_len && screen_len)
545 return -EINVAL;
546 if (yres * linelen > screen_len && screen_len)
547 return -EINVAL;
548 if (var->yoffset + yres > yres_virtual && yres_virtual)
549 return -EINVAL;
550 par->yres_virtual = yres_virtual;
551 par->screen_base = screen_base + var->yoffset * linelen;
552 return 0;
555 static int tt_encode_var( struct fb_var_screeninfo *var,
556 struct atafb_par *par )
558 int linelen;
559 memset(var, 0, sizeof(struct fb_var_screeninfo));
560 var->red.offset=0;
561 var->red.length=4;
562 var->red.msb_right=0;
563 var->grayscale=0;
565 var->pixclock=31041;
566 var->left_margin=120; /* these may be incorrect */
567 var->right_margin=100;
568 var->upper_margin=8;
569 var->lower_margin=16;
570 var->hsync_len=140;
571 var->vsync_len=30;
573 var->height=-1;
574 var->width=-1;
576 if (par->hw.tt.sync & 1)
577 var->sync=0;
578 else
579 var->sync=FB_SYNC_EXT;
581 switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
582 case TT_SHIFTER_STLOW:
583 var->xres=sttt_xres/2;
584 var->xres_virtual=sttt_xres_virtual/2;
585 var->yres=st_yres/2;
586 var->bits_per_pixel=4;
587 break;
588 case TT_SHIFTER_STMID:
589 var->xres=sttt_xres;
590 var->xres_virtual=sttt_xres_virtual;
591 var->yres=st_yres/2;
592 var->bits_per_pixel=2;
593 break;
594 case TT_SHIFTER_STHIGH:
595 var->xres=sttt_xres;
596 var->xres_virtual=sttt_xres_virtual;
597 var->yres=st_yres;
598 var->bits_per_pixel=1;
599 break;
600 case TT_SHIFTER_TTLOW:
601 var->xres=sttt_xres/2;
602 var->xres_virtual=sttt_xres_virtual/2;
603 var->yres=tt_yres;
604 var->bits_per_pixel=8;
605 break;
606 case TT_SHIFTER_TTMID:
607 var->xres=sttt_xres;
608 var->xres_virtual=sttt_xres_virtual;
609 var->yres=tt_yres;
610 var->bits_per_pixel=4;
611 break;
612 case TT_SHIFTER_TTHIGH:
613 var->red.length=0;
614 var->xres=sttt_xres*2;
615 var->xres_virtual=sttt_xres_virtual*2;
616 var->yres=tt_yres*2;
617 var->bits_per_pixel=1;
618 break;
620 var->blue=var->green=var->red;
621 var->transp.offset=0;
622 var->transp.length=0;
623 var->transp.msb_right=0;
624 linelen=var->xres_virtual * var->bits_per_pixel / 8;
625 if (! use_hwscroll)
626 var->yres_virtual=var->yres;
627 else if (screen_len) {
628 if (par->yres_virtual)
629 var->yres_virtual = par->yres_virtual;
630 else
631 /* yres_virtual==0 means use maximum */
632 var->yres_virtual = screen_len / linelen;
633 } else {
634 if (hwscroll < 0)
635 var->yres_virtual = 2 * var->yres;
636 else
637 var->yres_virtual=var->yres+hwscroll * 16;
639 var->xoffset=0;
640 if (screen_base)
641 var->yoffset=(par->screen_base - screen_base)/linelen;
642 else
643 var->yoffset=0;
644 var->nonstd=0;
645 var->activate=0;
646 var->vmode=FB_VMODE_NONINTERLACED;
647 return 0;
651 static void tt_get_par( struct atafb_par *par )
653 unsigned long addr;
654 par->hw.tt.mode=shifter_tt.tt_shiftmode;
655 par->hw.tt.sync=shifter.syncmode;
656 addr = ((shifter.bas_hi & 0xff) << 16) |
657 ((shifter.bas_md & 0xff) << 8) |
658 ((shifter.bas_lo & 0xff));
659 par->screen_base = phys_to_virt(addr);
662 static void tt_set_par( struct atafb_par *par )
664 shifter_tt.tt_shiftmode=par->hw.tt.mode;
665 shifter.syncmode=par->hw.tt.sync;
666 /* only set screen_base if really necessary */
667 if (current_par.screen_base != par->screen_base)
668 fbhw->set_screen_base(par->screen_base);
672 static int tt_getcolreg(unsigned regno, unsigned *red,
673 unsigned *green, unsigned *blue,
674 unsigned *transp, struct fb_info *info)
676 int t, col;
678 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
679 regno += 254;
680 if (regno > 255)
681 return 1;
682 t = tt_palette[regno];
683 col = t & 15;
684 col |= col << 4;
685 col |= col << 8;
686 *blue = col;
687 col = (t >> 4) & 15;
688 col |= col << 4;
689 col |= col << 8;
690 *green = col;
691 col = (t >> 8) & 15;
692 col |= col << 4;
693 col |= col << 8;
694 *red = col;
695 *transp = 0;
696 return 0;
700 static int tt_setcolreg(unsigned regno, unsigned red,
701 unsigned green, unsigned blue,
702 unsigned transp, struct fb_info *info)
704 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
705 regno += 254;
706 if (regno > 255)
707 return 1;
708 tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
709 (blue >> 12));
710 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
711 TT_SHIFTER_STHIGH && regno == 254)
712 tt_palette[0] = 0;
713 return 0;
717 static int tt_detect( void )
719 { struct atafb_par par;
721 /* Determine the connected monitor: The DMA sound must be
722 * disabled before reading the MFP GPIP, because the Sound
723 * Done Signal and the Monochrome Detect are XORed together!
725 * Even on a TT, we should look if there is a DMA sound. It was
726 * announced that the Eagle is TT compatible, but only the PCM is
727 * missing...
729 if (ATARIHW_PRESENT(PCM_8BIT)) {
730 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
731 udelay(20); /* wait a while for things to settle down */
733 mono_moni = (mfp.par_dt_reg & 0x80) == 0;
735 tt_get_par(&par);
736 tt_encode_var(&atafb_predefined[0], &par);
738 return 1;
741 #endif /* ATAFB_TT */
743 /* ------------------- Falcon specific functions ---------------------- */
745 #ifdef ATAFB_FALCON
747 static int mon_type; /* Falcon connected monitor */
748 static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
749 #define F_MON_SM 0
750 #define F_MON_SC 1
751 #define F_MON_VGA 2
752 #define F_MON_TV 3
754 static struct pixel_clock {
755 unsigned long f; /* f/[Hz] */
756 unsigned long t; /* t/[ps] (=1/f) */
757 int right, hsync, left; /* standard timing in clock cycles, not pixel */
758 /* hsync initialized in falcon_detect() */
759 int sync_mask; /* or-mask for hw.falcon.sync to set this clock */
760 int control_mask; /* ditto, for hw.falcon.vid_control */
762 f25 = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25},
763 f32 = {32000000, 31250, 18, 0, 42, 0x0, 0},
764 fext = { 0, 0, 18, 0, 42, 0x1, 0};
766 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
767 static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
769 /* Default hsync timing [mon_type] in picoseconds */
770 static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
772 #ifdef FBCON_HAS_CFB16
773 static u16 fbcon_cfb16_cmap[16];
774 #endif
776 static inline int hxx_prescale(struct falcon_hw *hw)
778 return hw->ste_mode ? 16 :
779 vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
782 static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
783 struct atafb_par *par )
785 strcpy(fix->id, "Atari Builtin");
786 fix->smem_start = (unsigned long)real_screen_base;
787 fix->smem_len = screen_len;
788 fix->type = FB_TYPE_INTERLEAVED_PLANES;
789 fix->type_aux = 2;
790 fix->visual = FB_VISUAL_PSEUDOCOLOR;
791 fix->xpanstep = 1;
792 fix->ypanstep = 1;
793 fix->ywrapstep = 0;
794 if (par->hw.falcon.mono) {
795 fix->type = FB_TYPE_PACKED_PIXELS;
796 fix->type_aux = 0;
797 /* no smooth scrolling with longword aligned video mem */
798 fix->xpanstep = 32;
800 else if (par->hw.falcon.f_shift & 0x100) {
801 fix->type = FB_TYPE_PACKED_PIXELS;
802 fix->type_aux = 0;
803 /* Is this ok or should it be DIRECTCOLOR? */
804 fix->visual = FB_VISUAL_TRUECOLOR;
805 fix->xpanstep = 2;
807 fix->line_length = 0;
808 fix->accel = FB_ACCEL_ATARIBLITT;
809 return 0;
813 static int falcon_decode_var( struct fb_var_screeninfo *var,
814 struct atafb_par *par )
816 int bpp = var->bits_per_pixel;
817 int xres = var->xres;
818 int yres = var->yres;
819 int xres_virtual = var->xres_virtual;
820 int yres_virtual = var->yres_virtual;
821 int left_margin, right_margin, hsync_len;
822 int upper_margin, lower_margin, vsync_len;
823 int linelen;
824 int interlace = 0, doubleline = 0;
825 struct pixel_clock *pclock;
826 int plen; /* width of pixel in clock cycles */
827 int xstretch;
828 int prescale;
829 int longoffset = 0;
830 int hfreq, vfreq;
833 Get the video params out of 'var'. If a value doesn't fit, round
834 it up, if it's too big, return EINVAL.
835 Round up in the following order: bits_per_pixel, xres, yres,
836 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
837 horizontal timing, vertical timing.
839 There is a maximum of screen resolution determined by pixelclock
840 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
841 In interlace mode this is " * " *vfmin <= pixelclock.
842 Additional constraints: hfreq.
843 Frequency range for multisync monitors is given via command line.
844 For TV and SM124 both frequencies are fixed.
846 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
847 Y % 16 == 0 to fit 8x16 font
848 Y % 8 == 0 if Y<400
850 Currently interlace and doubleline mode in var are ignored.
851 On SM124 and TV only the standard resolutions can be used.
854 /* Reject uninitialized mode */
855 if (!xres || !yres || !bpp)
856 return -EINVAL;
858 if (mon_type == F_MON_SM && bpp != 1) {
859 return -EINVAL;
861 else if (bpp <= 1) {
862 bpp = 1;
863 par->hw.falcon.f_shift = 0x400;
864 par->hw.falcon.st_shift = 0x200;
866 else if (bpp <= 2) {
867 bpp = 2;
868 par->hw.falcon.f_shift = 0x000;
869 par->hw.falcon.st_shift = 0x100;
871 else if (bpp <= 4) {
872 bpp = 4;
873 par->hw.falcon.f_shift = 0x000;
874 par->hw.falcon.st_shift = 0x000;
876 else if (bpp <= 8) {
877 bpp = 8;
878 par->hw.falcon.f_shift = 0x010;
880 else if (bpp <= 16) {
881 bpp = 16; /* packed pixel mode */
882 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
884 else
885 return -EINVAL;
886 par->hw.falcon.bpp = bpp;
888 if (mon_type == F_MON_SM || DontCalcRes) {
889 /* Skip all calculations. VGA/TV/SC1224 only supported. */
890 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
892 if (bpp > myvar->bits_per_pixel ||
893 var->xres > myvar->xres ||
894 var->yres > myvar->yres)
895 return -EINVAL;
896 fbhw->get_par(par); /* Current par will be new par */
897 goto set_screen_base; /* Don't forget this */
900 /* Only some fixed resolutions < 640x400 */
901 if (xres <= 320)
902 xres = 320;
903 else if (xres <= 640 && bpp != 16)
904 xres = 640;
905 if (yres <= 200)
906 yres = 200;
907 else if (yres <= 240)
908 yres = 240;
909 else if (yres <= 400)
910 yres = 400;
912 /* 2 planes must use STE compatibility mode */
913 par->hw.falcon.ste_mode = bpp==2;
914 par->hw.falcon.mono = bpp==1;
916 /* Total and visible scanline length must be a multiple of one longword,
917 * this and the console fontwidth yields the alignment for xres and
918 * xres_virtual.
919 * TODO: this way "odd" fontheights are not supported
921 * Special case in STE mode: blank and graphic positions don't align,
922 * avoid trash at right margin
924 if (par->hw.falcon.ste_mode)
925 xres = (xres + 63) & ~63;
926 else if (bpp == 1)
927 xres = (xres + 31) & ~31;
928 else
929 xres = (xres + 15) & ~15;
930 if (yres >= 400)
931 yres = (yres + 15) & ~15;
932 else
933 yres = (yres + 7) & ~7;
935 if (xres_virtual < xres)
936 xres_virtual = xres;
937 else if (bpp == 1)
938 xres_virtual = (xres_virtual + 31) & ~31;
939 else
940 xres_virtual = (xres_virtual + 15) & ~15;
942 if (yres_virtual <= 0)
943 yres_virtual = 0;
944 else if (yres_virtual < yres)
945 yres_virtual = yres;
947 /* backward bug-compatibility */
948 if (var->pixclock > 1)
949 var->pixclock -= 1;
951 par->hw.falcon.line_width = bpp * xres / 16;
952 par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
954 /* single or double pixel width */
955 xstretch = (xres < 640) ? 2 : 1;
957 #if 0 /* SM124 supports only 640x400, this is rejected above */
958 if (mon_type == F_MON_SM) {
959 if (xres != 640 && yres != 400)
960 return -EINVAL;
961 plen = 1;
962 pclock = &f32;
963 /* SM124-mode is special */
964 par->hw.falcon.ste_mode = 1;
965 par->hw.falcon.f_shift = 0x000;
966 par->hw.falcon.st_shift = 0x200;
967 left_margin = hsync_len = 128 / plen;
968 right_margin = 0;
969 /* TODO set all margins */
971 else
972 #endif
973 if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
974 plen = 2 * xstretch;
975 if (var->pixclock > f32.t * plen)
976 return -EINVAL;
977 pclock = &f32;
978 if (yres > 240)
979 interlace = 1;
980 if (var->pixclock == 0) {
981 /* set some minimal margins which center the screen */
982 left_margin = 32;
983 right_margin = 18;
984 hsync_len = pclock->hsync / plen;
985 upper_margin = 31;
986 lower_margin = 14;
987 vsync_len = interlace ? 3 : 4;
988 } else {
989 left_margin = var->left_margin;
990 right_margin = var->right_margin;
991 hsync_len = var->hsync_len;
992 upper_margin = var->upper_margin;
993 lower_margin = var->lower_margin;
994 vsync_len = var->vsync_len;
995 if (var->vmode & FB_VMODE_INTERLACED) {
996 upper_margin = (upper_margin + 1) / 2;
997 lower_margin = (lower_margin + 1) / 2;
998 vsync_len = (vsync_len + 1) / 2;
999 } else if (var->vmode & FB_VMODE_DOUBLE) {
1000 upper_margin *= 2;
1001 lower_margin *= 2;
1002 vsync_len *= 2;
1006 else
1007 { /* F_MON_VGA */
1008 if (bpp == 16)
1009 xstretch = 2; /* Double pixel width only for hicolor */
1010 /* Default values are used for vert./hor. timing if no pixelclock given. */
1011 if (var->pixclock == 0) {
1012 int linesize;
1014 /* Choose master pixelclock depending on hor. timing */
1015 plen = 1 * xstretch;
1016 if ((plen * xres + f25.right+f25.hsync+f25.left) *
1017 fb_info.monspecs.hfmin < f25.f)
1018 pclock = &f25;
1019 else if ((plen * xres + f32.right+f32.hsync+f32.left) *
1020 fb_info.monspecs.hfmin < f32.f)
1021 pclock = &f32;
1022 else if ((plen * xres + fext.right+fext.hsync+fext.left) *
1023 fb_info.monspecs.hfmin < fext.f
1024 && fext.f)
1025 pclock = &fext;
1026 else
1027 return -EINVAL;
1029 left_margin = pclock->left / plen;
1030 right_margin = pclock->right / plen;
1031 hsync_len = pclock->hsync / plen;
1032 linesize = left_margin + xres + right_margin + hsync_len;
1033 upper_margin = 31;
1034 lower_margin = 11;
1035 vsync_len = 3;
1037 else {
1038 /* Choose largest pixelclock <= wanted clock */
1039 int i;
1040 unsigned long pcl = ULONG_MAX;
1041 pclock = 0;
1042 for (i=1; i <= 4; i *= 2) {
1043 if (f25.t*i >= var->pixclock && f25.t*i < pcl) {
1044 pcl = f25.t * i;
1045 pclock = &f25;
1047 if (f32.t*i >= var->pixclock && f32.t*i < pcl) {
1048 pcl = f32.t * i;
1049 pclock = &f32;
1051 if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) {
1052 pcl = fext.t * i;
1053 pclock = &fext;
1056 if (!pclock)
1057 return -EINVAL;
1058 plen = pcl / pclock->t;
1060 left_margin = var->left_margin;
1061 right_margin = var->right_margin;
1062 hsync_len = var->hsync_len;
1063 upper_margin = var->upper_margin;
1064 lower_margin = var->lower_margin;
1065 vsync_len = var->vsync_len;
1066 /* Internal unit is [single lines per (half-)frame] */
1067 if (var->vmode & FB_VMODE_INTERLACED) {
1068 /* # lines in half frame */
1069 /* External unit is [lines per full frame] */
1070 upper_margin = (upper_margin + 1) / 2;
1071 lower_margin = (lower_margin + 1) / 2;
1072 vsync_len = (vsync_len + 1) / 2;
1074 else if (var->vmode & FB_VMODE_DOUBLE) {
1075 /* External unit is [double lines per frame] */
1076 upper_margin *= 2;
1077 lower_margin *= 2;
1078 vsync_len *= 2;
1081 if (pclock == &fext)
1082 longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1084 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1085 /* this is definitely wrong if bus clock != 32MHz */
1086 if (pclock->f / plen / 8 * bpp > 32000000L)
1087 return -EINVAL;
1089 if (vsync_len < 1)
1090 vsync_len = 1;
1092 /* include sync lengths in right/lower margin for all calculations */
1093 right_margin += hsync_len;
1094 lower_margin += vsync_len;
1096 /* ! In all calculations of margins we use # of lines in half frame
1097 * (which is a full frame in non-interlace mode), so we can switch
1098 * between interlace and non-interlace without messing around
1099 * with these.
1101 again:
1102 /* Set base_offset 128 and video bus width */
1103 par->hw.falcon.vid_control = mon_type | f030_bus_width;
1104 if (!longoffset)
1105 par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */
1106 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1107 par->hw.falcon.vid_control |= VCO_HSYPOS;
1108 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1109 par->hw.falcon.vid_control |= VCO_VSYPOS;
1110 /* Pixelclock */
1111 par->hw.falcon.vid_control |= pclock->control_mask;
1112 /* External or internal clock */
1113 par->hw.falcon.sync = pclock->sync_mask | 0x2;
1114 /* Pixellength and prescale */
1115 par->hw.falcon.vid_mode = (2/plen) << 2;
1116 if (doubleline)
1117 par->hw.falcon.vid_mode |= VMO_DOUBLE;
1118 if (interlace)
1119 par->hw.falcon.vid_mode |= VMO_INTER;
1121 /*********************
1122 Horizontal timing: unit = [master clock cycles]
1123 unit of hxx-registers: [master clock cycles * prescale]
1124 Hxx-registers are 9 bit wide
1126 1 line = ((hht + 2) * 2 * prescale) clock cycles
1128 graphic output = hdb & 0x200 ?
1129 ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
1130 ( hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1131 (this must be a multiple of plen*128/bpp, on VGA pixels
1132 to the right may be cut off with a bigger right margin)
1134 start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1135 (hdb - hht - 2) * prescale + hdboff :
1136 hdb * prescale + hdboff
1138 end of graphics relative to start of 1st halfline =
1139 (hde + hht + 2) * prescale + hdeoff
1140 *********************/
1141 /* Calculate VIDEL registers */
1143 int hdb_off, hde_off, base_off;
1144 int gstart, gend1, gend2, align;
1146 prescale = hxx_prescale(&par->hw.falcon);
1147 base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1149 /* Offsets depend on video mode */
1150 /* Offsets are in clock cycles, divide by prescale to
1151 * calculate hd[be]-registers
1153 if (par->hw.falcon.f_shift & 0x100) {
1154 align = 1;
1155 hde_off = 0;
1156 hdb_off = (base_off + 16 * plen) + prescale;
1158 else {
1159 align = 128 / bpp;
1160 hde_off = ((128 / bpp + 2) * plen);
1161 if (par->hw.falcon.ste_mode)
1162 hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1163 else
1164 hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1167 gstart = (prescale/2 + plen * left_margin) / prescale;
1168 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1169 gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
1170 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1171 gend2 = gstart + xres * plen / prescale;
1172 par->HHT = plen * (left_margin + xres + right_margin) /
1173 (2 * prescale) - 2;
1174 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1176 par->HDB = gstart - hdb_off/prescale;
1177 par->HBE = gstart;
1178 if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
1179 par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
1180 par->HBB = gend2 - par->HHT - 2;
1181 #if 0
1182 /* One more Videl constraint: data fetch of two lines must not overlap */
1183 if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) {
1184 /* if this happens increase margins, decrease hfreq. */
1186 #endif
1187 if (hde_off % prescale)
1188 par->HBB++; /* compensate for non matching hde and hbb */
1189 par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1190 if (par->HSS < par->HBB)
1191 par->HSS = par->HBB;
1194 /* check hor. frequency */
1195 hfreq = pclock->f / ((par->HHT+2)*prescale*2);
1196 if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) {
1197 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1198 /* Too high -> enlarge margin */
1199 left_margin += 1;
1200 right_margin += 1;
1201 goto again;
1203 if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1204 return -EINVAL;
1206 /* Vxx-registers */
1207 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1208 * of the first displayed line!
1209 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1210 * non-interlace, odd in interlace mode for synchronisation.
1211 * Vxx-registers are 11 bit wide
1213 par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1214 par->VDB = par->VBE;
1215 par->VDE = yres;
1216 if (!interlace) par->VDE <<= 1;
1217 if (doubleline) par->VDE <<= 1; /* VDE now half lines per (half-)frame */
1218 par->VDE += par->VDB;
1219 par->VBB = par->VDE;
1220 par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1221 par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
1222 /* vbb,vss,vft must be even in interlace mode */
1223 if (interlace) {
1224 par->VBB++;
1225 par->VSS++;
1226 par->VFT++;
1229 /* V-frequency check, hope I didn't create any loop here. */
1230 /* Interlace and doubleline are mutually exclusive. */
1231 vfreq = (hfreq * 2) / (par->VFT + 1);
1232 if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1233 /* Too high -> try again with doubleline */
1234 doubleline = 1;
1235 goto again;
1237 else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1238 /* Too low -> try again with interlace */
1239 interlace = 1;
1240 goto again;
1242 else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1243 /* Doubleline too low -> clear doubleline and enlarge margins */
1244 int lines;
1245 doubleline = 0;
1246 for (lines=0;
1247 (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax;
1248 lines++)
1250 upper_margin += lines;
1251 lower_margin += lines;
1252 goto again;
1254 else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1255 /* Doubleline too high -> enlarge margins */
1256 int lines;
1257 for (lines=0;
1258 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1259 lines+=2)
1261 upper_margin += lines;
1262 lower_margin += lines;
1263 goto again;
1265 else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1266 /* Interlace, too high -> enlarge margins */
1267 int lines;
1268 for (lines=0;
1269 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1270 lines++)
1272 upper_margin += lines;
1273 lower_margin += lines;
1274 goto again;
1276 else if (vfreq < fb_info.monspecs.vfmin ||
1277 vfreq > fb_info.monspecs.vfmax)
1278 return -EINVAL;
1280 set_screen_base:
1281 linelen = xres_virtual * bpp / 8;
1282 if (yres_virtual * linelen > screen_len && screen_len)
1283 return -EINVAL;
1284 if (yres * linelen > screen_len && screen_len)
1285 return -EINVAL;
1286 if (var->yoffset + yres > yres_virtual && yres_virtual)
1287 return -EINVAL;
1288 par->yres_virtual = yres_virtual;
1289 par->screen_base = screen_base + var->yoffset * linelen;
1290 par->hw.falcon.xoffset = 0;
1292 return 0;
1295 static int falcon_encode_var( struct fb_var_screeninfo *var,
1296 struct atafb_par *par )
1298 /* !!! only for VGA !!! */
1299 int linelen;
1300 int prescale, plen;
1301 int hdb_off, hde_off, base_off;
1302 struct falcon_hw *hw = &par->hw.falcon;
1304 memset(var, 0, sizeof(struct fb_var_screeninfo));
1305 /* possible frequencies: 25.175 or 32MHz */
1306 var->pixclock = hw->sync & 0x1 ? fext.t :
1307 hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1309 var->height=-1;
1310 var->width=-1;
1312 var->sync=0;
1313 if (hw->vid_control & VCO_HSYPOS)
1314 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1315 if (hw->vid_control & VCO_VSYPOS)
1316 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1318 var->vmode = FB_VMODE_NONINTERLACED;
1319 if (hw->vid_mode & VMO_INTER)
1320 var->vmode |= FB_VMODE_INTERLACED;
1321 if (hw->vid_mode & VMO_DOUBLE)
1322 var->vmode |= FB_VMODE_DOUBLE;
1324 /* visible y resolution:
1325 * Graphics display starts at line VDB and ends at line
1326 * VDE. If interlace mode off unit of VC-registers is
1327 * half lines, else lines.
1329 var->yres = hw->vde - hw->vdb;
1330 if (!(var->vmode & FB_VMODE_INTERLACED))
1331 var->yres >>= 1;
1332 if (var->vmode & FB_VMODE_DOUBLE)
1333 var->yres >>= 1;
1335 /* to get bpp, we must examine f_shift and st_shift.
1336 * f_shift is valid if any of bits no. 10, 8 or 4
1337 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1338 * if bit 10 set then bit 8 and bit 4 don't care...
1339 * If all these bits are 0 get display depth from st_shift
1340 * (as for ST and STE)
1342 if (hw->f_shift & 0x400) /* 2 colors */
1343 var->bits_per_pixel = 1;
1344 else if (hw->f_shift & 0x100) /* hicolor */
1345 var->bits_per_pixel = 16;
1346 else if (hw->f_shift & 0x010) /* 8 bitplanes */
1347 var->bits_per_pixel = 8;
1348 else if (hw->st_shift == 0)
1349 var->bits_per_pixel = 4;
1350 else if (hw->st_shift == 0x100)
1351 var->bits_per_pixel = 2;
1352 else /* if (hw->st_shift == 0x200) */
1353 var->bits_per_pixel = 1;
1355 var->xres = hw->line_width * 16 / var->bits_per_pixel;
1356 var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1357 if (hw->xoffset)
1358 var->xres_virtual += 16;
1360 if (var->bits_per_pixel == 16) {
1361 var->red.offset=11;
1362 var->red.length=5;
1363 var->red.msb_right=0;
1364 var->green.offset=5;
1365 var->green.length=6;
1366 var->green.msb_right=0;
1367 var->blue.offset=0;
1368 var->blue.length=5;
1369 var->blue.msb_right=0;
1371 else {
1372 var->red.offset=0;
1373 var->red.length = hw->ste_mode ? 4 : 6;
1374 var->red.msb_right=0;
1375 var->grayscale=0;
1376 var->blue=var->green=var->red;
1378 var->transp.offset=0;
1379 var->transp.length=0;
1380 var->transp.msb_right=0;
1382 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1383 if (screen_len) {
1384 if (par->yres_virtual)
1385 var->yres_virtual = par->yres_virtual;
1386 else
1387 /* yres_virtual==0 means use maximum */
1388 var->yres_virtual = screen_len / linelen;
1390 else {
1391 if (hwscroll < 0)
1392 var->yres_virtual = 2 * var->yres;
1393 else
1394 var->yres_virtual=var->yres+hwscroll * 16;
1396 var->xoffset=0; /* TODO change this */
1398 /* hdX-offsets */
1399 prescale = hxx_prescale(hw);
1400 plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1401 base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1402 if (hw->f_shift & 0x100) {
1403 hde_off = 0;
1404 hdb_off = (base_off + 16 * plen) + prescale;
1406 else {
1407 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1408 if (hw->ste_mode)
1409 hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1410 + prescale;
1411 else
1412 hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1413 + prescale;
1416 /* Right margin includes hsync */
1417 var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1418 (hw->hdb & 0x200 ? 2+hw->hht : 0));
1419 if (hw->ste_mode || mon_type!=F_MON_VGA)
1420 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1421 else
1422 /* can't use this in ste_mode, because hbb is +1 off */
1423 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1424 var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1426 /* Lower margin includes vsync */
1427 var->upper_margin = hw->vdb / 2 ; /* round down to full lines */
1428 var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
1429 var->vsync_len = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
1430 if (var->vmode & FB_VMODE_INTERLACED) {
1431 var->upper_margin *= 2;
1432 var->lower_margin *= 2;
1433 var->vsync_len *= 2;
1435 else if (var->vmode & FB_VMODE_DOUBLE) {
1436 var->upper_margin = (var->upper_margin + 1) / 2;
1437 var->lower_margin = (var->lower_margin + 1) / 2;
1438 var->vsync_len = (var->vsync_len + 1) / 2;
1441 var->pixclock *= plen;
1442 var->left_margin /= plen;
1443 var->right_margin /= plen;
1444 var->hsync_len /= plen;
1446 var->right_margin -= var->hsync_len;
1447 var->lower_margin -= var->vsync_len;
1449 if (screen_base)
1450 var->yoffset=(par->screen_base - screen_base)/linelen;
1451 else
1452 var->yoffset=0;
1453 var->nonstd=0; /* what is this for? */
1454 var->activate=0;
1455 return 0;
1459 static int f_change_mode = 0;
1460 static struct falcon_hw f_new_mode;
1461 static int f_pan_display = 0;
1463 static void falcon_get_par( struct atafb_par *par )
1465 unsigned long addr;
1466 struct falcon_hw *hw = &par->hw.falcon;
1468 hw->line_width = shifter_f030.scn_width;
1469 hw->line_offset = shifter_f030.off_next;
1470 hw->st_shift = videl.st_shift & 0x300;
1471 hw->f_shift = videl.f_shift;
1472 hw->vid_control = videl.control;
1473 hw->vid_mode = videl.mode;
1474 hw->sync = shifter.syncmode & 0x1;
1475 hw->xoffset = videl.xoffset & 0xf;
1476 hw->hht = videl.hht;
1477 hw->hbb = videl.hbb;
1478 hw->hbe = videl.hbe;
1479 hw->hdb = videl.hdb;
1480 hw->hde = videl.hde;
1481 hw->hss = videl.hss;
1482 hw->vft = videl.vft;
1483 hw->vbb = videl.vbb;
1484 hw->vbe = videl.vbe;
1485 hw->vdb = videl.vdb;
1486 hw->vde = videl.vde;
1487 hw->vss = videl.vss;
1489 addr = (shifter.bas_hi & 0xff) << 16 |
1490 (shifter.bas_md & 0xff) << 8 |
1491 (shifter.bas_lo & 0xff);
1492 par->screen_base = phys_to_virt(addr);
1494 /* derived parameters */
1495 hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
1496 hw->mono = (hw->f_shift & 0x400) ||
1497 ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
1500 static void falcon_set_par( struct atafb_par *par )
1502 f_change_mode = 0;
1504 /* only set screen_base if really necessary */
1505 if (current_par.screen_base != par->screen_base)
1506 fbhw->set_screen_base(par->screen_base);
1508 /* Don't touch any other registers if we keep the default resolution */
1509 if (DontCalcRes)
1510 return;
1512 /* Tell vbl-handler to change video mode.
1513 * We change modes only on next VBL, to avoid desynchronisation
1514 * (a shift to the right and wrap around by a random number of pixels
1515 * in all monochrome modes).
1516 * This seems to work on my Falcon.
1518 f_new_mode = par->hw.falcon;
1519 f_change_mode = 1;
1523 static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
1525 struct falcon_hw *hw = &f_new_mode;
1527 if (f_change_mode) {
1528 f_change_mode = 0;
1530 if (hw->sync & 0x1) {
1531 /* Enable external pixelclock. This code only for ScreenWonder */
1532 *(volatile unsigned short*)0xffff9202 = 0xffbf;
1534 else {
1535 /* Turn off external clocks. Read sets all output bits to 1. */
1536 *(volatile unsigned short*)0xffff9202;
1538 shifter.syncmode = hw->sync;
1540 videl.hht = hw->hht;
1541 videl.hbb = hw->hbb;
1542 videl.hbe = hw->hbe;
1543 videl.hdb = hw->hdb;
1544 videl.hde = hw->hde;
1545 videl.hss = hw->hss;
1546 videl.vft = hw->vft;
1547 videl.vbb = hw->vbb;
1548 videl.vbe = hw->vbe;
1549 videl.vdb = hw->vdb;
1550 videl.vde = hw->vde;
1551 videl.vss = hw->vss;
1553 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1554 if (hw->ste_mode) {
1555 videl.st_shift = hw->st_shift; /* write enables STE palette */
1557 else {
1558 /* IMPORTANT:
1559 * set st_shift 0, so we can tell the screen-depth if f_shift==0.
1560 * Writing 0 to f_shift enables 4 plane Falcon mode but
1561 * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
1562 * with Falcon palette.
1564 videl.st_shift = 0;
1565 /* now back to Falcon palette mode */
1566 videl.f_shift = hw->f_shift;
1568 /* writing to st_shift changed scn_width and vid_mode */
1569 videl.xoffset = hw->xoffset;
1570 shifter_f030.scn_width = hw->line_width;
1571 shifter_f030.off_next = hw->line_offset;
1572 videl.control = hw->vid_control;
1573 videl.mode = hw->vid_mode;
1575 if (f_pan_display) {
1576 f_pan_display = 0;
1577 videl.xoffset = current_par.hw.falcon.xoffset;
1578 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1580 return IRQ_HANDLED;
1584 static int falcon_pan_display( struct fb_var_screeninfo *var,
1585 struct atafb_par *par )
1587 int xoffset;
1588 int bpp = fb_display[fb_info.currcon].var.bits_per_pixel;
1590 if (bpp == 1)
1591 var->xoffset = up(var->xoffset, 32);
1592 if (bpp != 16)
1593 par->hw.falcon.xoffset = var->xoffset & 15;
1594 else {
1595 par->hw.falcon.xoffset = 0;
1596 var->xoffset = up(var->xoffset, 2);
1598 par->hw.falcon.line_offset = bpp *
1599 (fb_display[fb_info.currcon].var.xres_virtual - fb_display[fb_info.currcon].var.xres) / 16;
1600 if (par->hw.falcon.xoffset)
1601 par->hw.falcon.line_offset -= bpp;
1602 xoffset = var->xoffset - par->hw.falcon.xoffset;
1604 par->screen_base = screen_base +
1605 (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + xoffset) * bpp / 8;
1606 if (fbhw->set_screen_base)
1607 fbhw->set_screen_base (par->screen_base);
1608 else
1609 return -EINVAL; /* shouldn't happen */
1610 f_pan_display = 1;
1611 return 0;
1615 static int falcon_getcolreg( unsigned regno, unsigned *red,
1616 unsigned *green, unsigned *blue,
1617 unsigned *transp, struct fb_info *info )
1618 { unsigned long col;
1620 if (regno > 255)
1621 return 1;
1622 /* This works in STE-mode (with 4bit/color) since f030_col-registers
1623 * hold up to 6bit/color.
1624 * Even with hicolor r/g/b=5/6/5 bit!
1626 col = f030_col[regno];
1627 *red = (col >> 16) & 0xff00;
1628 *green = (col >> 8) & 0xff00;
1629 *blue = (col << 8) & 0xff00;
1630 *transp = 0;
1631 return 0;
1635 static int falcon_setcolreg( unsigned regno, unsigned red,
1636 unsigned green, unsigned blue,
1637 unsigned transp, struct fb_info *info )
1639 if (regno > 255)
1640 return 1;
1641 f030_col[regno] = (((red & 0xfc00) << 16) |
1642 ((green & 0xfc00) << 8) |
1643 ((blue & 0xfc00) >> 8));
1644 if (regno < 16) {
1645 shifter_tt.color_reg[regno] =
1646 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1647 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1648 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1649 #ifdef FBCON_HAS_CFB16
1650 fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
1651 ((green & 0xfc00) >> 5) |
1652 ((blue & 0xf800) >> 11));
1653 #endif
1655 return 0;
1659 static int falcon_blank( int blank_mode )
1661 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1662 * so VIDEL doesn't hog the bus while saving.
1663 * (this may affect usleep()).
1665 int vdb, vss, hbe, hss;
1667 if (mon_type == F_MON_SM) /* this doesn't work on SM124 */
1668 return 1;
1670 vdb = current_par.VDB;
1671 vss = current_par.VSS;
1672 hbe = current_par.HBE;
1673 hss = current_par.HSS;
1675 if (blank_mode >= 1) {
1676 /* disable graphics output (this speeds up the CPU) ... */
1677 vdb = current_par.VFT + 1;
1678 /* ... and blank all lines */
1679 hbe = current_par.HHT + 2;
1681 /* use VESA suspend modes on VGA monitors */
1682 if (mon_type == F_MON_VGA) {
1683 if (blank_mode == 2 || blank_mode == 4)
1684 vss = current_par.VFT + 1;
1685 if (blank_mode == 3 || blank_mode == 4)
1686 hss = current_par.HHT + 2;
1689 videl.vdb = vdb;
1690 videl.vss = vss;
1691 videl.hbe = hbe;
1692 videl.hss = hss;
1694 return 0;
1698 static int falcon_detect( void )
1700 struct atafb_par par;
1701 unsigned char fhw;
1703 /* Determine connected monitor and set monitor parameters */
1704 fhw = *(unsigned char*)0xffff8006;
1705 mon_type = fhw >> 6 & 0x3;
1706 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1707 f030_bus_width = fhw << 6 & 0x80;
1708 switch (mon_type) {
1709 case F_MON_SM:
1710 fb_info.monspecs.vfmin = 70;
1711 fb_info.monspecs.vfmax = 72;
1712 fb_info.monspecs.hfmin = 35713;
1713 fb_info.monspecs.hfmax = 35715;
1714 break;
1715 case F_MON_SC:
1716 case F_MON_TV:
1717 /* PAL...NTSC */
1718 fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
1719 fb_info.monspecs.vfmax = 60;
1720 fb_info.monspecs.hfmin = 15620;
1721 fb_info.monspecs.hfmax = 15755;
1722 break;
1724 /* initialize hsync-len */
1725 f25.hsync = h_syncs[mon_type] / f25.t;
1726 f32.hsync = h_syncs[mon_type] / f32.t;
1727 if (fext.t)
1728 fext.hsync = h_syncs[mon_type] / fext.t;
1730 falcon_get_par(&par);
1731 falcon_encode_var(&atafb_predefined[0], &par);
1733 /* Detected mode is always the "autodetect" slot */
1734 return 1;
1737 #endif /* ATAFB_FALCON */
1739 /* ------------------- ST(E) specific functions ---------------------- */
1741 #ifdef ATAFB_STE
1743 static int stste_encode_fix( struct fb_fix_screeninfo *fix,
1744 struct atafb_par *par )
1747 int mode;
1749 strcpy(fix->id,"Atari Builtin");
1750 fix->smem_start = (unsigned long)real_screen_base;
1751 fix->smem_len = screen_len;
1752 fix->type = FB_TYPE_INTERLEAVED_PLANES;
1753 fix->type_aux = 2;
1754 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1755 mode = par->hw.st.mode & 3;
1756 if (mode == ST_HIGH) {
1757 fix->type = FB_TYPE_PACKED_PIXELS;
1758 fix->type_aux = 0;
1759 fix->visual = FB_VISUAL_MONO10;
1761 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1762 fix->xpanstep = 16;
1763 fix->ypanstep = 1;
1764 } else {
1765 fix->xpanstep = 0;
1766 fix->ypanstep = 0;
1768 fix->ywrapstep = 0;
1769 fix->line_length = 0;
1770 fix->accel = FB_ACCEL_ATARIBLITT;
1771 return 0;
1775 static int stste_decode_var( struct fb_var_screeninfo *var,
1776 struct atafb_par *par )
1778 int xres=var->xres;
1779 int yres=var->yres;
1780 int bpp=var->bits_per_pixel;
1781 int linelen;
1782 int yres_virtual = var->yres_virtual;
1784 if (mono_moni) {
1785 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1786 return -EINVAL;
1787 par->hw.st.mode=ST_HIGH;
1788 xres=sttt_xres;
1789 yres=st_yres;
1790 bpp=1;
1791 } else {
1792 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1793 return -EINVAL;
1794 if (bpp > 2) {
1795 if (xres > sttt_xres/2 || yres > st_yres/2)
1796 return -EINVAL;
1797 par->hw.st.mode=ST_LOW;
1798 xres=sttt_xres/2;
1799 yres=st_yres/2;
1800 bpp=4;
1802 else if (bpp > 1) {
1803 if (xres > sttt_xres || yres > st_yres/2)
1804 return -EINVAL;
1805 par->hw.st.mode=ST_MID;
1806 xres=sttt_xres;
1807 yres=st_yres/2;
1808 bpp=2;
1810 else
1811 return -EINVAL;
1813 if (yres_virtual <= 0)
1814 yres_virtual = 0;
1815 else if (yres_virtual < yres)
1816 yres_virtual = yres;
1817 if (var->sync & FB_SYNC_EXT)
1818 par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
1819 else
1820 par->hw.st.sync=(par->hw.st.sync & ~1);
1821 linelen=xres*bpp/8;
1822 if (yres_virtual * linelen > screen_len && screen_len)
1823 return -EINVAL;
1824 if (yres * linelen > screen_len && screen_len)
1825 return -EINVAL;
1826 if (var->yoffset + yres > yres_virtual && yres_virtual)
1827 return -EINVAL;
1828 par->yres_virtual = yres_virtual;
1829 par->screen_base=screen_base+ var->yoffset*linelen;
1830 return 0;
1833 static int stste_encode_var( struct fb_var_screeninfo *var,
1834 struct atafb_par *par )
1836 int linelen;
1837 memset(var, 0, sizeof(struct fb_var_screeninfo));
1838 var->red.offset=0;
1839 var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1840 var->red.msb_right=0;
1841 var->grayscale=0;
1843 var->pixclock=31041;
1844 var->left_margin=120; /* these are incorrect */
1845 var->right_margin=100;
1846 var->upper_margin=8;
1847 var->lower_margin=16;
1848 var->hsync_len=140;
1849 var->vsync_len=30;
1851 var->height=-1;
1852 var->width=-1;
1854 if (!(par->hw.st.sync & 1))
1855 var->sync=0;
1856 else
1857 var->sync=FB_SYNC_EXT;
1859 switch (par->hw.st.mode & 3) {
1860 case ST_LOW:
1861 var->xres=sttt_xres/2;
1862 var->yres=st_yres/2;
1863 var->bits_per_pixel=4;
1864 break;
1865 case ST_MID:
1866 var->xres=sttt_xres;
1867 var->yres=st_yres/2;
1868 var->bits_per_pixel=2;
1869 break;
1870 case ST_HIGH:
1871 var->xres=sttt_xres;
1872 var->yres=st_yres;
1873 var->bits_per_pixel=1;
1874 break;
1876 var->blue=var->green=var->red;
1877 var->transp.offset=0;
1878 var->transp.length=0;
1879 var->transp.msb_right=0;
1880 var->xres_virtual=sttt_xres_virtual;
1881 linelen=var->xres_virtual * var->bits_per_pixel / 8;
1882 ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
1884 if (! use_hwscroll)
1885 var->yres_virtual=var->yres;
1886 else if (screen_len) {
1887 if (par->yres_virtual)
1888 var->yres_virtual = par->yres_virtual;
1889 else
1890 /* yres_virtual==0 means use maximum */
1891 var->yres_virtual = screen_len / linelen;
1893 else {
1894 if (hwscroll < 0)
1895 var->yres_virtual = 2 * var->yres;
1896 else
1897 var->yres_virtual=var->yres+hwscroll * 16;
1899 var->xoffset=0;
1900 if (screen_base)
1901 var->yoffset=(par->screen_base - screen_base)/linelen;
1902 else
1903 var->yoffset=0;
1904 var->nonstd=0;
1905 var->activate=0;
1906 var->vmode=FB_VMODE_NONINTERLACED;
1907 return 0;
1911 static void stste_get_par( struct atafb_par *par )
1913 unsigned long addr;
1914 par->hw.st.mode=shifter_tt.st_shiftmode;
1915 par->hw.st.sync=shifter.syncmode;
1916 addr = ((shifter.bas_hi & 0xff) << 16) |
1917 ((shifter.bas_md & 0xff) << 8);
1918 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1919 addr |= (shifter.bas_lo & 0xff);
1920 par->screen_base = phys_to_virt(addr);
1923 static void stste_set_par( struct atafb_par *par )
1925 shifter_tt.st_shiftmode=par->hw.st.mode;
1926 shifter.syncmode=par->hw.st.sync;
1927 /* only set screen_base if really necessary */
1928 if (current_par.screen_base != par->screen_base)
1929 fbhw->set_screen_base(par->screen_base);
1933 static int stste_getcolreg(unsigned regno, unsigned *red,
1934 unsigned *green, unsigned *blue,
1935 unsigned *transp, struct fb_info *info)
1937 unsigned col, t;
1939 if (regno > 15)
1940 return 1;
1941 col = shifter_tt.color_reg[regno];
1942 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1943 t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
1944 t |= t << 4;
1945 *red = t | (t << 8);
1946 t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
1947 t |= t << 4;
1948 *green = t | (t << 8);
1949 t = ((col << 1) & 0xe) | ((col >> 3) & 1);
1950 t |= t << 4;
1951 *blue = t | (t << 8);
1953 else {
1954 t = (col >> 7) & 0xe;
1955 t |= t << 4;
1956 *red = t | (t << 8);
1957 t = (col >> 3) & 0xe;
1958 t |= t << 4;
1959 *green = t | (t << 8);
1960 t = (col << 1) & 0xe;
1961 t |= t << 4;
1962 *blue = t | (t << 8);
1964 *transp = 0;
1965 return 0;
1969 static int stste_setcolreg(unsigned regno, unsigned red,
1970 unsigned green, unsigned blue,
1971 unsigned transp, struct fb_info *info)
1973 if (regno > 15)
1974 return 1;
1975 red >>= 12;
1976 blue >>= 12;
1977 green >>= 12;
1978 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1979 shifter_tt.color_reg[regno] =
1980 (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1981 (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1982 ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1983 else
1984 shifter_tt.color_reg[regno] =
1985 ((red & 0xe) << 7) |
1986 ((green & 0xe) << 3) |
1987 ((blue & 0xe) >> 1);
1988 return 0;
1992 static int stste_detect( void )
1994 { struct atafb_par par;
1996 /* Determine the connected monitor: The DMA sound must be
1997 * disabled before reading the MFP GPIP, because the Sound
1998 * Done Signal and the Monochrome Detect are XORed together!
2000 if (ATARIHW_PRESENT(PCM_8BIT)) {
2001 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2002 udelay(20); /* wait a while for things to settle down */
2004 mono_moni = (mfp.par_dt_reg & 0x80) == 0;
2006 stste_get_par(&par);
2007 stste_encode_var(&atafb_predefined[0], &par);
2009 if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2010 use_hwscroll = 0;
2011 return 1;
2014 static void stste_set_screen_base(void *s_base)
2016 unsigned long addr;
2017 addr= virt_to_phys(s_base);
2018 /* Setup Screen Memory */
2019 shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2020 shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2021 if (ATARIHW_PRESENT(EXTD_SHIFTER))
2022 shifter.bas_lo=(unsigned char) (addr & 0x0000ff);
2025 #endif /* ATAFB_STE */
2027 /* Switching the screen size should be done during vsync, otherwise
2028 * the margins may get messed up. This is a well known problem of
2029 * the ST's video system.
2031 * Unfortunately there is hardly any way to find the vsync, as the
2032 * vertical blank interrupt is no longer in time on machines with
2033 * overscan type modifications.
2035 * We can, however, use Timer B to safely detect the black shoulder,
2036 * but then we've got to guess an appropriate delay to find the vsync.
2037 * This might not work on every machine.
2039 * martin_rogge @ ki.maus.de, 8th Aug 1995
2042 #define LINE_DELAY (mono_moni ? 30 : 70)
2043 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2045 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2046 static void st_ovsc_switch(void)
2048 unsigned long flags;
2049 register unsigned char old, new;
2051 if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2052 return;
2053 local_irq_save(flags);
2055 mfp.tim_ct_b = 0x10;
2056 mfp.active_edge |= 8;
2057 mfp.tim_ct_b = 0;
2058 mfp.tim_dt_b = 0xf0;
2059 mfp.tim_ct_b = 8;
2060 while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2062 new = mfp.tim_dt_b;
2063 do {
2064 udelay(LINE_DELAY);
2065 old = new;
2066 new = mfp.tim_dt_b;
2067 } while (old != new);
2068 mfp.tim_ct_b = 0x10;
2069 udelay(SYNC_DELAY);
2071 if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2072 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2073 if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2074 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2075 if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2076 sound_ym.rd_data_reg_sel = 14;
2077 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2078 ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2079 ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2081 local_irq_restore(flags);
2084 /* ------------------- External Video ---------------------- */
2086 #ifdef ATAFB_EXT
2088 static int ext_encode_fix( struct fb_fix_screeninfo *fix,
2089 struct atafb_par *par )
2092 strcpy(fix->id,"Unknown Extern");
2093 fix->smem_start = (unsigned long)external_addr;
2094 fix->smem_len = PAGE_ALIGN(external_len);
2095 if (external_depth == 1) {
2096 fix->type = FB_TYPE_PACKED_PIXELS;
2097 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2098 * for "normal" and "inverted", rsp., in the monochrome case */
2099 fix->visual =
2100 (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2101 external_pmode == FB_TYPE_PACKED_PIXELS) ?
2102 FB_VISUAL_MONO10 :
2103 FB_VISUAL_MONO01;
2105 else {
2106 /* Use STATIC if we don't know how to access color registers */
2107 int visual = external_vgaiobase ?
2108 FB_VISUAL_PSEUDOCOLOR :
2109 FB_VISUAL_STATIC_PSEUDOCOLOR;
2110 switch (external_pmode) {
2111 case -1: /* truecolor */
2112 fix->type=FB_TYPE_PACKED_PIXELS;
2113 fix->visual=FB_VISUAL_TRUECOLOR;
2114 break;
2115 case FB_TYPE_PACKED_PIXELS:
2116 fix->type=FB_TYPE_PACKED_PIXELS;
2117 fix->visual=visual;
2118 break;
2119 case FB_TYPE_PLANES:
2120 fix->type=FB_TYPE_PLANES;
2121 fix->visual=visual;
2122 break;
2123 case FB_TYPE_INTERLEAVED_PLANES:
2124 fix->type=FB_TYPE_INTERLEAVED_PLANES;
2125 fix->type_aux=2;
2126 fix->visual=visual;
2127 break;
2130 fix->xpanstep = 0;
2131 fix->ypanstep = 0;
2132 fix->ywrapstep = 0;
2133 fix->line_length = 0;
2134 return 0;
2138 static int ext_decode_var( struct fb_var_screeninfo *var,
2139 struct atafb_par *par )
2141 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2143 if (var->bits_per_pixel > myvar->bits_per_pixel ||
2144 var->xres > myvar->xres ||
2145 var->xres_virtual > myvar->xres_virtual ||
2146 var->yres > myvar->yres ||
2147 var->xoffset > 0 ||
2148 var->yoffset > 0)
2149 return -EINVAL;
2150 return 0;
2154 static int ext_encode_var( struct fb_var_screeninfo *var,
2155 struct atafb_par *par )
2157 memset(var, 0, sizeof(struct fb_var_screeninfo));
2158 var->red.offset=0;
2159 var->red.length=(external_pmode == -1) ? external_depth/3 :
2160 (external_vgaiobase ? external_bitspercol : 0);
2161 var->red.msb_right=0;
2162 var->grayscale=0;
2164 var->pixclock=31041;
2165 var->left_margin=120; /* these are surely incorrect */
2166 var->right_margin=100;
2167 var->upper_margin=8;
2168 var->lower_margin=16;
2169 var->hsync_len=140;
2170 var->vsync_len=30;
2172 var->height=-1;
2173 var->width=-1;
2175 var->sync=0;
2177 var->xres = external_xres;
2178 var->yres = external_yres;
2179 var->xres_virtual = external_xres_virtual;
2180 var->bits_per_pixel = external_depth;
2182 var->blue=var->green=var->red;
2183 var->transp.offset=0;
2184 var->transp.length=0;
2185 var->transp.msb_right=0;
2186 var->yres_virtual=var->yres;
2187 var->xoffset=0;
2188 var->yoffset=0;
2189 var->nonstd=0;
2190 var->activate=0;
2191 var->vmode=FB_VMODE_NONINTERLACED;
2192 return 0;
2196 static void ext_get_par( struct atafb_par *par )
2198 par->screen_base = external_addr;
2201 static void ext_set_par( struct atafb_par *par )
2205 #define OUTB(port,val) \
2206 *((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
2207 #define INB(port) \
2208 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2209 #define DACDelay \
2210 do { \
2211 unsigned char tmp=INB(0x3da); \
2212 tmp=INB(0x3da); \
2213 } while (0)
2215 static int ext_getcolreg( unsigned regno, unsigned *red,
2216 unsigned *green, unsigned *blue,
2217 unsigned *transp, struct fb_info *info )
2219 if (! external_vgaiobase)
2220 return 1;
2222 *red = ext_color[regno].red;
2223 *green = ext_color[regno].green;
2224 *blue = ext_color[regno].blue;
2225 *transp=0;
2226 return 0;
2229 static int ext_setcolreg( unsigned regno, unsigned red,
2230 unsigned green, unsigned blue,
2231 unsigned transp, struct fb_info *info )
2233 { unsigned char colmask = (1 << external_bitspercol) - 1;
2235 if (! external_vgaiobase)
2236 return 1;
2238 ext_color[regno].red = red;
2239 ext_color[regno].green = green;
2240 ext_color[regno].blue = blue;
2242 switch (external_card_type) {
2243 case IS_VGA:
2244 OUTB(0x3c8, regno);
2245 DACDelay;
2246 OUTB(0x3c9, red & colmask);
2247 DACDelay;
2248 OUTB(0x3c9, green & colmask);
2249 DACDelay;
2250 OUTB(0x3c9, blue & colmask);
2251 DACDelay;
2252 return 0;
2254 case IS_MV300:
2255 OUTB((MV300_reg[regno] << 2)+1, red);
2256 OUTB((MV300_reg[regno] << 2)+1, green);
2257 OUTB((MV300_reg[regno] << 2)+1, blue);
2258 return 0;
2260 default:
2261 return 1;
2266 static int ext_detect( void )
2269 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2270 struct atafb_par dummy_par;
2272 myvar->xres = external_xres;
2273 myvar->xres_virtual = external_xres_virtual;
2274 myvar->yres = external_yres;
2275 myvar->bits_per_pixel = external_depth;
2276 ext_encode_var(myvar, &dummy_par);
2277 return 1;
2280 #endif /* ATAFB_EXT */
2282 /* ------ This is the same for most hardware types -------- */
2284 static void set_screen_base(void *s_base)
2286 unsigned long addr;
2287 addr= virt_to_phys(s_base);
2288 /* Setup Screen Memory */
2289 shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2290 shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2291 shifter.bas_lo=(unsigned char) (addr & 0x0000ff);
2295 static int pan_display( struct fb_var_screeninfo *var,
2296 struct atafb_par *par )
2298 if (!fbhw->set_screen_base ||
2299 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2300 return -EINVAL;
2301 var->xoffset = up(var->xoffset, 16);
2302 par->screen_base = screen_base +
2303 (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + var->xoffset)
2304 * fb_display[fb_info.currcon].var.bits_per_pixel / 8;
2305 fbhw->set_screen_base (par->screen_base);
2306 return 0;
2310 /* ------------ Interfaces to hardware functions ------------ */
2313 #ifdef ATAFB_TT
2314 static struct fb_hwswitch tt_switch = {
2315 tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
2316 tt_get_par, tt_set_par, tt_getcolreg,
2317 set_screen_base, NULL, pan_display
2319 #endif
2321 #ifdef ATAFB_FALCON
2322 static struct fb_hwswitch falcon_switch = {
2323 falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
2324 falcon_get_par, falcon_set_par, falcon_getcolreg,
2325 set_screen_base, falcon_blank, falcon_pan_display
2327 #endif
2329 #ifdef ATAFB_STE
2330 static struct fb_hwswitch st_switch = {
2331 stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
2332 stste_get_par, stste_set_par, stste_getcolreg,
2333 stste_set_screen_base, NULL, pan_display
2335 #endif
2337 #ifdef ATAFB_EXT
2338 static struct fb_hwswitch ext_switch = {
2339 ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
2340 ext_get_par, ext_set_par, ext_getcolreg, NULL, NULL, NULL
2342 #endif
2346 static void atafb_get_par( struct atafb_par *par )
2348 if (current_par_valid) {
2349 *par=current_par;
2351 else
2352 fbhw->get_par(par);
2356 static void atafb_set_par( struct atafb_par *par )
2358 fbhw->set_par(par);
2359 current_par=*par;
2360 current_par_valid=1;
2365 /* =========================================================== */
2366 /* ============== Hardware Independent Functions ============= */
2367 /* =========================================================== */
2370 /* used for hardware scrolling */
2372 static int
2373 fb_update_var(int con, struct fb_info *info)
2375 int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual*
2376 fb_display[con].var.bits_per_pixel>>3;
2378 current_par.screen_base=screen_base + off;
2380 if (fbhw->set_screen_base)
2381 fbhw->set_screen_base(current_par.screen_base);
2382 return 0;
2385 static int
2386 do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2388 int err,activate;
2389 struct atafb_par par;
2390 if ((err=fbhw->decode_var(var, &par)))
2391 return err;
2392 activate=var->activate;
2393 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2394 atafb_set_par(&par);
2395 fbhw->encode_var(var, &par);
2396 var->activate=activate;
2397 return 0;
2400 static int
2401 atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
2403 struct atafb_par par;
2404 if (con == -1)
2405 atafb_get_par(&par);
2406 else {
2407 int err;
2408 if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
2409 return err;
2411 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2412 return fbhw->encode_fix(fix, &par);
2415 static int
2416 atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2418 struct atafb_par par;
2419 if (con == -1) {
2420 atafb_get_par(&par);
2421 fbhw->encode_var(var, &par);
2423 else
2424 *var=fb_display[con].var;
2425 return 0;
2428 static void
2429 atafb_set_disp(int con, struct fb_info *info)
2431 struct fb_fix_screeninfo fix;
2432 struct fb_var_screeninfo var;
2433 struct display *display;
2435 if (con >= 0)
2436 display = &fb_display[con];
2437 else
2438 display = &disp; /* used during initialization */
2440 atafb_get_fix(&fix, con, info);
2441 atafb_get_var(&var, con, info);
2442 if (con == -1)
2443 con=0;
2444 info->screen_base = (void *)fix.smem_start;
2445 display->visual = fix.visual;
2446 display->type = fix.type;
2447 display->type_aux = fix.type_aux;
2448 display->ypanstep = fix.ypanstep;
2449 display->ywrapstep = fix.ywrapstep;
2450 display->line_length = fix.line_length;
2451 if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
2452 fix.visual != FB_VISUAL_DIRECTCOLOR)
2453 display->can_soft_blank = 0;
2454 else
2455 display->can_soft_blank = 1;
2456 display->inverse =
2457 (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
2458 switch (fix.type) {
2459 case FB_TYPE_INTERLEAVED_PLANES:
2460 switch (var.bits_per_pixel) {
2461 #ifdef FBCON_HAS_IPLAN2P2
2462 case 2:
2463 display->dispsw = &fbcon_iplan2p2;
2464 break;
2465 #endif
2466 #ifdef FBCON_HAS_IPLAN2P4
2467 case 4:
2468 display->dispsw = &fbcon_iplan2p4;
2469 break;
2470 #endif
2471 #ifdef FBCON_HAS_IPLAN2P8
2472 case 8:
2473 display->dispsw = &fbcon_iplan2p8;
2474 break;
2475 #endif
2477 break;
2478 case FB_TYPE_PACKED_PIXELS:
2479 switch (var.bits_per_pixel) {
2480 #ifdef FBCON_HAS_MFB
2481 case 1:
2482 display->dispsw = &fbcon_mfb;
2483 break;
2484 #endif
2485 #ifdef FBCON_HAS_CFB8
2486 case 8:
2487 display->dispsw = &fbcon_cfb8;
2488 break;
2489 #endif
2490 #ifdef FBCON_HAS_CFB16
2491 case 16:
2492 display->dispsw = &fbcon_cfb16;
2493 display->dispsw_data = fbcon_cfb16_cmap;
2494 break;
2495 #endif
2497 break;
2501 static int
2502 atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2504 int err,oldxres,oldyres,oldbpp,oldxres_virtual,
2505 oldyres_virtual,oldyoffset;
2506 if ((err=do_fb_set_var(var, con==info->currcon)))
2507 return err;
2508 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2509 oldxres=fb_display[con].var.xres;
2510 oldyres=fb_display[con].var.yres;
2511 oldxres_virtual=fb_display[con].var.xres_virtual;
2512 oldyres_virtual=fb_display[con].var.yres_virtual;
2513 oldbpp=fb_display[con].var.bits_per_pixel;
2514 oldyoffset=fb_display[con].var.yoffset;
2515 fb_display[con].var=*var;
2516 if (oldxres != var->xres || oldyres != var->yres
2517 || oldxres_virtual != var->xres_virtual
2518 || oldyres_virtual != var->yres_virtual
2519 || oldbpp != var->bits_per_pixel
2520 || oldyoffset != var->yoffset) {
2521 atafb_set_disp(con, info);
2522 (*fb_info.changevar)(con);
2523 fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
2524 do_install_cmap(con, info);
2527 var->activate=0;
2528 return 0;
2533 static int
2534 atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
2536 if (con == info->currcon) /* current console ? */
2537 return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
2538 else
2539 if (fb_display[con].cmap.len) /* non default colormap ? */
2540 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
2541 else
2542 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
2543 cmap, kspc ? 0 : 2);
2544 return 0;
2547 static int
2548 atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2550 int xoffset = var->xoffset;
2551 int yoffset = var->yoffset;
2552 int err;
2554 if ( xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
2555 || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
2556 return -EINVAL;
2558 if (con == info->currcon) {
2559 if (fbhw->pan_display) {
2560 if ((err = fbhw->pan_display(var, &current_par)))
2561 return err;
2563 else
2564 return -EINVAL;
2566 fb_display[con].var.xoffset = var->xoffset;
2567 fb_display[con].var.yoffset = var->yoffset;
2568 return 0;
2571 static int
2572 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2574 switch (cmd) {
2575 #ifdef FBCMD_GET_CURRENTPAR
2576 case FBCMD_GET_CURRENTPAR:
2577 if (copy_to_user((void *)arg, (void *)&current_par,
2578 sizeof(struct atafb_par)))
2579 return -EFAULT;
2580 return 0;
2581 #endif
2582 #ifdef FBCMD_SET_CURRENTPAR
2583 case FBCMD_SET_CURRENTPAR:
2584 if (copy_from_user((void *)&current_par, (void *)arg,
2585 sizeof(struct atafb_par)))
2586 return -EFAULT;
2587 atafb_set_par(&current_par);
2588 return 0;
2589 #endif
2591 return -EINVAL;
2594 /* (un)blank/poweroff
2595 * 0 = unblank
2596 * 1 = blank
2597 * 2 = suspend vsync
2598 * 3 = suspend hsync
2599 * 4 = off
2601 static int
2602 atafb_blank(int blank, struct fb_info *info)
2604 unsigned short black[16];
2605 struct fb_cmap cmap;
2606 if (fbhw->blank && !fbhw->blank(blank))
2607 return 1;
2608 if (blank) {
2609 memset(black, 0, 16*sizeof(unsigned short));
2610 cmap.red=black;
2611 cmap.green=black;
2612 cmap.blue=black;
2613 cmap.transp=NULL;
2614 cmap.start=0;
2615 cmap.len=16;
2616 fb_set_cmap(&cmap, 1, info);
2618 else
2619 do_install_cmap(info->currcon, info);
2620 return 0;
2623 static struct fb_ops atafb_ops = {
2624 .owner = THIS_MODULE,
2625 .fb_get_fix = atafb_get_fix,
2626 .fb_get_var = atafb_get_var,
2627 .fb_set_var = atafb_set_var,
2628 .fb_get_cmap = atafb_get_cmap,
2629 .fb_set_cmap = gen_set_cmap,
2630 .fb_pan_display =atafb_pan_display,
2631 .fb_blank = atafb_blank,
2632 .fb_ioctl = atafb_ioctl,
2635 static void
2636 check_default_par( int detected_mode )
2638 char default_name[10];
2639 int i;
2640 struct fb_var_screeninfo var;
2641 unsigned long min_mem;
2643 /* First try the user supplied mode */
2644 if (default_par) {
2645 var=atafb_predefined[default_par-1];
2646 var.activate = FB_ACTIVATE_TEST;
2647 if (do_fb_set_var(&var,1))
2648 default_par=0; /* failed */
2650 /* Next is the autodetected one */
2651 if (! default_par) {
2652 var=atafb_predefined[detected_mode-1]; /* autodetect */
2653 var.activate = FB_ACTIVATE_TEST;
2654 if (!do_fb_set_var(&var,1))
2655 default_par=detected_mode;
2657 /* If that also failed, try some default modes... */
2658 if (! default_par) {
2659 /* try default1, default2... */
2660 for (i=1 ; i < 10 ; i++) {
2661 sprintf(default_name,"default%d",i);
2662 default_par=get_video_mode(default_name);
2663 if (! default_par)
2664 panic("can't set default video mode");
2665 var=atafb_predefined[default_par-1];
2666 var.activate = FB_ACTIVATE_TEST;
2667 if (! do_fb_set_var(&var,1))
2668 break; /* ok */
2671 min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
2672 if (default_mem_req < min_mem)
2673 default_mem_req=min_mem;
2676 static int
2677 atafb_switch(int con, struct fb_info *info)
2679 /* Do we have to save the colormap ? */
2680 if (fb_display[info->currcon].cmap.len)
2681 fb_get_cmap(&fb_display[info->currcon].cmap, 1, fbhw->getcolreg,
2682 info);
2683 do_fb_set_var(&fb_display[con].var,1);
2684 info->currcon=con;
2685 /* Install new colormap */
2686 do_install_cmap(con, info);
2687 return 0;
2690 int __init atafb_init(void)
2692 int pad;
2693 int detected_mode;
2694 unsigned long mem_req;
2696 if (!MACH_IS_ATARI)
2697 return -ENXIO;
2699 do {
2700 #ifdef ATAFB_EXT
2701 if (external_addr) {
2702 fbhw = &ext_switch;
2703 atafb_ops.fb_setcolreg = &ext_setcolreg;
2704 break;
2706 #endif
2707 #ifdef ATAFB_TT
2708 if (ATARIHW_PRESENT(TT_SHIFTER)) {
2709 fbhw = &tt_switch;
2710 atafb_ops.fb_setcolreg = &tt_setcolreg;
2711 break;
2713 #endif
2714 #ifdef ATAFB_FALCON
2715 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
2716 fbhw = &falcon_switch;
2717 atafb_ops.fb_setcolreg = &falcon_setcolreg;
2718 request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
2719 "framebuffer/modeswitch", falcon_vbl_switcher);
2720 break;
2722 #endif
2723 #ifdef ATAFB_STE
2724 if (ATARIHW_PRESENT(STND_SHIFTER) ||
2725 ATARIHW_PRESENT(EXTD_SHIFTER)) {
2726 fbhw = &st_switch;
2727 atafb_ops.fb_setcolreg = &stste_setcolreg;
2728 break;
2730 fbhw = &st_switch;
2731 atafb_ops.fb_setcolreg = &stste_setcolreg;
2732 printk("Cannot determine video hardware; defaulting to ST(e)\n");
2733 #else /* ATAFB_STE */
2734 /* no default driver included */
2735 /* Nobody will ever see this message :-) */
2736 panic("Cannot initialize video hardware");
2737 #endif
2738 } while (0);
2740 /* Multisync monitor capabilities */
2741 /* Atari-TOS defaults if no boot option present */
2742 if (fb_info.monspecs.hfmin == 0) {
2743 fb_info.monspecs.hfmin = 31000;
2744 fb_info.monspecs.hfmax = 32000;
2745 fb_info.monspecs.vfmin = 58;
2746 fb_info.monspecs.vfmax = 62;
2749 detected_mode = fbhw->detect();
2750 check_default_par(detected_mode);
2751 #ifdef ATAFB_EXT
2752 if (!external_addr) {
2753 #endif /* ATAFB_EXT */
2754 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
2755 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
2756 screen_base = atari_stram_alloc(mem_req, "atafb");
2757 if (!screen_base)
2758 panic("Cannot allocate screen memory");
2759 memset(screen_base, 0, mem_req);
2760 pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
2761 screen_base+=pad;
2762 real_screen_base=screen_base+ovsc_offset;
2763 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
2764 st_ovsc_switch();
2765 if (CPU_IS_040_OR_060) {
2766 /* On a '040+, the cache mode of video RAM must be set to
2767 * write-through also for internal video hardware! */
2768 cache_push(virt_to_phys(screen_base), screen_len);
2769 kernel_set_cachemode(screen_base, screen_len,
2770 IOMAP_WRITETHROUGH);
2772 #ifdef ATAFB_EXT
2774 else {
2775 /* Map the video memory (physical address given) to somewhere
2776 * in the kernel address space.
2778 external_addr =
2779 ioremap_writethrough((unsigned long)external_addr,
2780 external_len);
2781 if (external_vgaiobase)
2782 external_vgaiobase =
2783 (unsigned long)ioremap(external_vgaiobase, 0x10000);
2784 screen_base =
2785 real_screen_base = external_addr;
2786 screen_len = external_len & PAGE_MASK;
2787 memset (screen_base, 0, external_len);
2789 #endif /* ATAFB_EXT */
2791 strcpy(fb_info.modename, "Atari Builtin ");
2792 fb_info.changevar = NULL;
2793 fb_info.fbops = &atafb_ops;
2794 fb_info.disp = &disp;
2795 fb_info.currcon = -1;
2796 fb_info.switch_con = &atafb_switch;
2797 fb_info.updatevar = &fb_update_var;
2798 fb_info.flags = FBINFO_FLAG_DEFAULT;
2799 do_fb_set_var(&atafb_predefined[default_par-1], 1);
2800 strcat(fb_info.modename, fb_var_names[default_par-1][0]);
2802 atafb_get_var(&disp.var, -1, &fb_info);
2803 atafb_set_disp(-1, &fb_info);
2804 do_install_cmap(0, &fb_info);
2806 if (register_framebuffer(&fb_info) < 0) {
2807 #ifdef ATAFB_EXT
2808 if (external_addr) {
2809 iounmap(external_addr);
2810 external_addr = NULL;
2812 if (external_vgaiobase) {
2813 iounmap((void*)external_vgaiobase);
2814 external_vgaiobase = 0;
2816 #endif
2817 return -EINVAL;
2820 printk("Determined %dx%d, depth %d\n",
2821 disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
2822 if ((disp.var.xres != disp.var.xres_virtual) ||
2823 (disp.var.yres != disp.var.yres_virtual))
2824 printk(" virtual %dx%d\n",
2825 disp.var.xres_virtual, disp.var.yres_virtual);
2826 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2827 fb_info.node, fb_info.modename, screen_len>>10);
2829 /* TODO: This driver cannot be unloaded yet */
2830 return 0;
2834 #ifdef ATAFB_EXT
2835 static void __init atafb_setup_ext(char *spec)
2837 int xres, xres_virtual, yres, depth, planes;
2838 unsigned long addr, len;
2839 char *p;
2841 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2842 * <screen mem addr>
2843 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2844 * [;<xres-virtual>]]]]]
2846 * 09/23/97 Juergen
2847 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
2849 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
2851 if (!(p = strsep(&spec, ";")) || !*p)
2852 return;
2853 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2854 if (xres <= 0)
2855 return;
2857 if (!(p = strsep(&spec, ";")) || !*p)
2858 return;
2859 yres = simple_strtoul(p, NULL, 10);
2860 if (yres <= 0)
2861 return;
2863 if (!(p = strsep(&spec, ";")) || !*p)
2864 return;
2865 depth = simple_strtoul(p, NULL, 10);
2866 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2867 depth != 16 && depth != 24)
2868 return;
2870 if (!(p = strsep(&spec, ";")) || !*p)
2871 return;
2872 if (*p == 'i')
2873 planes = FB_TYPE_INTERLEAVED_PLANES;
2874 else if (*p == 'p')
2875 planes = FB_TYPE_PACKED_PIXELS;
2876 else if (*p == 'n')
2877 planes = FB_TYPE_PLANES;
2878 else if (*p == 't')
2879 planes = -1; /* true color */
2880 else
2881 return;
2884 if (!(p = strsep(&spec, ";")) || !*p)
2885 return;
2886 addr = simple_strtoul(p, NULL, 0);
2888 if (!(p = strsep(&spec, ";")) || !*p)
2889 len = xres*yres*depth/8;
2890 else
2891 len = simple_strtoul(p, NULL, 0);
2893 if ((p = strsep(&spec, ";")) && *p) {
2894 external_vgaiobase=simple_strtoul(p, NULL, 0);
2897 if ((p = strsep(&spec, ";")) && *p) {
2898 external_bitspercol = simple_strtoul(p, NULL, 0);
2899 if (external_bitspercol > 8)
2900 external_bitspercol = 8;
2901 else if (external_bitspercol < 1)
2902 external_bitspercol = 1;
2905 if ((p = strsep(&spec, ";")) && *p) {
2906 if (!strcmp(p, "vga"))
2907 external_card_type = IS_VGA;
2908 if (!strcmp(p, "mv300"))
2909 external_card_type = IS_MV300;
2912 if ((p = strsep(&spec, ";")) && *p) {
2913 xres_virtual = simple_strtoul(p, NULL, 10);
2914 if (xres_virtual < xres)
2915 xres_virtual = xres;
2916 if (xres_virtual*yres*depth/8 > len)
2917 len=xres_virtual*yres*depth/8;
2920 external_xres = xres;
2921 external_xres_virtual = xres_virtual;
2922 external_yres = yres;
2923 external_depth = depth;
2924 external_pmode = planes;
2925 external_addr = (void *)addr;
2926 external_len = len;
2928 if (external_card_type == IS_MV300)
2929 switch (external_depth) {
2930 case 1:
2931 MV300_reg = MV300_reg_1bit;
2932 break;
2933 case 4:
2934 MV300_reg = MV300_reg_4bit;
2935 break;
2936 case 8:
2937 MV300_reg = MV300_reg_8bit;
2938 break;
2941 #endif /* ATAFB_EXT */
2944 static void __init atafb_setup_int(char *spec)
2946 /* Format to config extended internal video hardware like OverScan:
2947 "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2948 Explanation:
2949 <xres>: x-resolution
2950 <yres>: y-resolution
2951 The following are only needed if you have an overscan which
2952 needs a black border:
2953 <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2954 <yres_max>: max. number of lines your OverScan hardware would allow
2955 <offset>: Offset from physical beginning to visible beginning
2956 of screen in bytes
2958 int xres;
2959 char *p;
2961 if (!(p = strsep(&spec, ";")) || !*p)
2962 return;
2963 xres = simple_strtoul(p, NULL, 10);
2964 if (!(p = strsep(&spec, ";")) || !*p)
2965 return;
2966 sttt_xres=xres;
2967 tt_yres=st_yres=simple_strtoul(p, NULL, 10);
2968 if ((p=strsep(&spec, ";")) && *p) {
2969 sttt_xres_virtual=simple_strtoul(p, NULL, 10);
2971 if ((p=strsep(&spec, ";")) && *p) {
2972 sttt_yres_virtual=simple_strtoul(p, NULL, 0);
2974 if ((p=strsep(&spec, ";")) && *p) {
2975 ovsc_offset=simple_strtoul(p, NULL, 0);
2978 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2979 use_hwscroll=0;
2983 #ifdef ATAFB_FALCON
2984 static void __init atafb_setup_mcap(char *spec)
2986 char *p;
2987 int vmin, vmax, hmin, hmax;
2989 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
2990 * <V*> vertical freq. in Hz
2991 * <H*> horizontal freq. in kHz
2993 if (!(p = strsep(&spec, ";")) || !*p)
2994 return;
2995 vmin = simple_strtoul(p, NULL, 10);
2996 if (vmin <= 0)
2997 return;
2998 if (!(p = strsep(&spec, ";")) || !*p)
2999 return;
3000 vmax = simple_strtoul(p, NULL, 10);
3001 if (vmax <= 0 || vmax <= vmin)
3002 return;
3003 if (!(p = strsep(&spec, ";")) || !*p)
3004 return;
3005 hmin = 1000 * simple_strtoul(p, NULL, 10);
3006 if (hmin <= 0)
3007 return;
3008 if (!(p = strsep(&spec, "")) || !*p)
3009 return;
3010 hmax = 1000 * simple_strtoul(p, NULL, 10);
3011 if (hmax <= 0 || hmax <= hmin)
3012 return;
3014 fb_info.monspecs.vfmin = vmin;
3015 fb_info.monspecs.vfmax = vmax;
3016 fb_info.monspecs.hfmin = hmin;
3017 fb_info.monspecs.hfmax = hmax;
3019 #endif /* ATAFB_FALCON */
3022 static void __init atafb_setup_user(char *spec)
3024 /* Format of user defined video mode is: <xres>;<yres>;<depth>
3026 char *p;
3027 int xres, yres, depth, temp;
3029 if (!(p = strsep(&spec, ";")) || !*p)
3030 return;
3031 xres = simple_strtoul(p, NULL, 10);
3032 if (!(p = strsep(&spec, ";")) || !*p)
3033 return;
3034 yres = simple_strtoul(p, NULL, 10);
3035 if (!(p = strsep(&spec, "")) || !*p)
3036 return;
3037 depth = simple_strtoul(p, NULL, 10);
3038 if ((temp=get_video_mode("user0"))) {
3039 default_par=temp;
3040 atafb_predefined[default_par-1].xres = xres;
3041 atafb_predefined[default_par-1].yres = yres;
3042 atafb_predefined[default_par-1].bits_per_pixel = depth;
3046 int __init atafb_setup( char *options )
3048 char *this_opt;
3049 int temp;
3051 fb_info.fontname[0] = '\0';
3053 if (!options || !*options)
3054 return 0;
3056 while ((this_opt = strsep(&options, ",")) != NULL) {
3057 if (!*this_opt) continue;
3058 if ((temp=get_video_mode(this_opt)))
3059 default_par=temp;
3060 else if (! strcmp(this_opt, "inverse"))
3061 inverse=1;
3062 else if (!strncmp(this_opt, "font:", 5))
3063 strcpy(fb_info.fontname, this_opt+5);
3064 else if (! strncmp(this_opt, "hwscroll_",9)) {
3065 hwscroll=simple_strtoul(this_opt+9, NULL, 10);
3066 if (hwscroll < 0)
3067 hwscroll = 0;
3068 if (hwscroll > 200)
3069 hwscroll = 200;
3071 #ifdef ATAFB_EXT
3072 else if (!strcmp(this_opt,"mv300")) {
3073 external_bitspercol = 8;
3074 external_card_type = IS_MV300;
3076 else if (!strncmp(this_opt,"external:",9))
3077 atafb_setup_ext(this_opt+9);
3078 #endif
3079 else if (!strncmp(this_opt,"internal:",9))
3080 atafb_setup_int(this_opt+9);
3081 #ifdef ATAFB_FALCON
3082 else if (!strncmp(this_opt, "eclock:", 7)) {
3083 fext.f = simple_strtoul(this_opt+7, NULL, 10);
3084 /* external pixelclock in kHz --> ps */
3085 fext.t = 1000000000/fext.f;
3086 fext.f *= 1000;
3088 else if (!strncmp(this_opt, "monitorcap:", 11))
3089 atafb_setup_mcap(this_opt+11);
3090 #endif
3091 else if (!strcmp(this_opt, "keep"))
3092 DontCalcRes = 1;
3093 else if (!strncmp(this_opt, "R", 1))
3094 atafb_setup_user(this_opt+1);
3096 return 0;
3099 #ifdef MODULE
3100 MODULE_LICENSE("GPL");
3102 int init_module(void)
3104 return atafb_init();
3106 #endif /* MODULE */