2.2.0-final
[davej-history.git] / drivers / video / atafb.c
blobf33d118b7bb817e419c2dda34de8cc3a8a82e8f2
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/tty.h>
57 #include <linux/malloc.h>
58 #include <linux/delay.h>
59 #include <linux/init.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-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 arraysize(x) (sizeof(x)/sizeof(*(x)))
90 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
93 static int default_par=0; /* default resolution (0=none) */
95 static unsigned long default_mem_req=0;
97 static int hwscroll=-1;
99 static int use_hwscroll = 1;
101 static int sttt_xres=640,st_yres=400,tt_yres=480;
102 static int sttt_xres_virtual=640,sttt_yres_virtual=400;
103 static int ovsc_offset=0, ovsc_addlen=0;
105 static struct atafb_par {
106 unsigned long screen_base;
107 int yres_virtual;
108 #if defined ATAFB_TT || defined ATAFB_STE
109 union {
110 struct {
111 int mode;
112 int sync;
113 } tt, st;
114 #endif
115 #ifdef ATAFB_FALCON
116 struct falcon_hw {
117 /* Here are fields for storing a video mode, as direct
118 * parameters for the hardware.
120 short sync;
121 short line_width;
122 short line_offset;
123 short st_shift;
124 short f_shift;
125 short vid_control;
126 short vid_mode;
127 short xoffset;
128 short hht, hbb, hbe, hdb, hde, hss;
129 short vft, vbb, vbe, vdb, vde, vss;
130 /* auxiliary information */
131 short mono;
132 short ste_mode;
133 short bpp;
134 } falcon;
135 #endif
136 /* Nothing needed for external mode */
137 } hw;
138 } current_par;
140 /* Don't calculate an own resolution, and thus don't change the one found when
141 * booting (currently used for the Falcon to keep settings for internal video
142 * hardware extensions (e.g. ScreenBlaster) */
143 static int DontCalcRes = 0;
145 #ifdef ATAFB_FALCON
146 #define HHT hw.falcon.hht
147 #define HBB hw.falcon.hbb
148 #define HBE hw.falcon.hbe
149 #define HDB hw.falcon.hdb
150 #define HDE hw.falcon.hde
151 #define HSS hw.falcon.hss
152 #define VFT hw.falcon.vft
153 #define VBB hw.falcon.vbb
154 #define VBE hw.falcon.vbe
155 #define VDB hw.falcon.vdb
156 #define VDE hw.falcon.vde
157 #define VSS hw.falcon.vss
158 #define VCO_CLOCK25 0x04
159 #define VCO_CSYPOS 0x10
160 #define VCO_VSYPOS 0x20
161 #define VCO_HSYPOS 0x40
162 #define VCO_SHORTOFFS 0x100
163 #define VMO_DOUBLE 0x01
164 #define VMO_INTER 0x02
165 #define VMO_PREMASK 0x0c
166 #endif
168 static struct fb_info fb_info;
170 static unsigned long screen_base; /* base address of screen */
171 static unsigned long real_screen_base; /* (only for Overscan) */
173 static int screen_len;
175 static int current_par_valid=0;
177 static int currcon=0;
179 static int mono_moni=0;
181 static struct display disp;
184 #ifdef ATAFB_EXT
185 /* external video handling */
187 static unsigned external_xres;
188 static unsigned external_xres_virtual;
189 static unsigned external_yres;
190 /* not needed - atafb will never support panning/hardwarescroll with external
191 * static unsigned external_yres_virtual;
194 static unsigned external_depth;
195 static int external_pmode;
196 static unsigned long external_addr = 0;
197 static unsigned long external_len;
198 static unsigned long external_vgaiobase = 0;
199 static unsigned int external_bitspercol = 6;
202 JOE <joe@amber.dinoco.de>:
203 added card type for external driver, is only needed for
204 colormap handling.
207 enum cardtype { IS_VGA, IS_MV300 };
208 static enum cardtype external_card_type = IS_VGA;
211 The MV300 mixes the color registers. So we need an array of munged
212 indices in order to acces the correct reg.
214 static int MV300_reg_1bit[2]={0,1};
215 static int MV300_reg_4bit[16]={
216 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
217 static int MV300_reg_8bit[256]={
218 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
219 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
220 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
221 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
222 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
223 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
224 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
225 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
226 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
227 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
228 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
229 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
230 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
231 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
232 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
233 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 };
235 static int *MV300_reg = MV300_reg_8bit;
238 And on the MV300 it's difficult to read out the hardware palette. So we
239 just keep track of the set colors in our own array here, and use that!
242 static struct { unsigned char red,green,blue,pad; } ext_color[256];
243 #endif /* ATAFB_EXT */
246 static int inverse=0;
248 extern int fontheight_8x8;
249 extern int fontwidth_8x8;
250 extern unsigned char fontdata_8x8[];
252 extern int fontheight_8x16;
253 extern int fontwidth_8x16;
254 extern unsigned char fontdata_8x16[];
256 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
257 * TT, or Falcon.
259 * int (*detect)( void )
260 * This function should detect the current video mode settings and
261 * store them in atafb_predefined[0] for later reference by the
262 * user. Return the index+1 of an equivalent predefined mode or 0
263 * if there is no such.
265 * int (*encode_fix)( struct fb_fix_screeninfo *fix,
266 * struct atafb_par *par )
267 * This function should fill in the 'fix' structure based on the
268 * values in the 'par' structure.
270 * int (*decode_var)( struct fb_var_screeninfo *var,
271 * struct atafb_par *par )
272 * Get the video params out of 'var'. If a value doesn't fit, round
273 * it up, if it's too big, return EINVAL.
274 * Round up in the following order: bits_per_pixel, xres, yres,
275 * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
276 * horizontal timing, vertical timing.
278 * int (*encode_var)( struct fb_var_screeninfo *var,
279 * struct atafb_par *par );
280 * Fill the 'var' structure based on the values in 'par' and maybe
281 * other values read out of the hardware.
283 * void (*get_par)( struct atafb_par *par )
284 * Fill the hardware's 'par' structure.
286 * void (*set_par)( struct atafb_par *par )
287 * Set the hardware according to 'par'.
289 * int (*setcolreg)( unsigned regno, unsigned red,
290 * unsigned green, unsigned blue,
291 * unsigned transp, struct fb_info *info )
292 * Set a single color register. The values supplied are already
293 * rounded down to the hardware's capabilities (according to the
294 * entries in the var structure). Return != 0 for invalid regno.
296 * int (*getcolreg)( unsigned regno, unsigned *red,
297 * unsigned *green, unsigned *blue,
298 * unsigned *transp, struct fb_info *info )
299 * Read a single color register and split it into
300 * colors/transparent. Return != 0 for invalid regno.
302 * void (*set_screen_base)( unsigned long s_base )
303 * Set the base address of the displayed frame buffer. Only called
304 * if yres_virtual > yres or xres_virtual > xres.
306 * int (*blank)( int blank_mode )
307 * Blank the screen if blank_mode!=0, else unblank. If blank==NULL then
308 * the caller blanks by setting the CLUT to all black. Return 0 if blanking
309 * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
310 * doesn't support it. Implements VESA suspend and powerdown modes on
311 * hardware that supports disabling hsync/vsync:
312 * blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown.
315 static struct fb_hwswitch {
316 int (*detect)( void );
317 int (*encode_fix)( struct fb_fix_screeninfo *fix,
318 struct atafb_par *par );
319 int (*decode_var)( struct fb_var_screeninfo *var,
320 struct atafb_par *par );
321 int (*encode_var)( struct fb_var_screeninfo *var,
322 struct atafb_par *par );
323 void (*get_par)( struct atafb_par *par );
324 void (*set_par)( struct atafb_par *par );
325 int (*getcolreg)( unsigned regno, unsigned *red,
326 unsigned *green, unsigned *blue,
327 unsigned *transp, struct fb_info *info );
328 int (*setcolreg)( unsigned regno, unsigned red,
329 unsigned green, unsigned blue,
330 unsigned transp, struct fb_info *info );
331 void (*set_screen_base)( unsigned long s_base );
332 int (*blank)( int blank_mode );
333 int (*pan_display)( struct fb_var_screeninfo *var,
334 struct atafb_par *par);
335 } *fbhw;
337 static char *autodetect_names[] = {"autodetect", NULL};
338 static char *stlow_names[] = {"stlow", NULL};
339 static char *stmid_names[] = {"stmid", "default5", NULL};
340 static char *sthigh_names[] = {"sthigh", "default4", NULL};
341 static char *ttlow_names[] = {"ttlow", NULL};
342 static char *ttmid_names[]= {"ttmid", "default1", NULL};
343 static char *tthigh_names[]= {"tthigh", "default2", NULL};
344 static char *vga2_names[] = {"vga2", NULL};
345 static char *vga4_names[] = {"vga4", NULL};
346 static char *vga16_names[] = {"vga16", "default3", NULL};
347 static char *vga256_names[] = {"vga256", NULL};
348 static char *falh2_names[] = {"falh2", NULL};
349 static char *falh16_names[] = {"falh16", NULL};
351 static char **fb_var_names[] = {
352 /* Writing the name arrays directly in this array (via "(char *[]){...}")
353 * crashes gcc 2.5.8 (sigsegv) if the inner array
354 * contains more than two items. I've also seen that all elements
355 * were identical to the last (my cross-gcc) :-(*/
356 autodetect_names,
357 stlow_names,
358 stmid_names,
359 sthigh_names,
360 ttlow_names,
361 ttmid_names,
362 tthigh_names,
363 vga2_names,
364 vga4_names,
365 vga16_names,
366 vga256_names,
367 falh2_names,
368 falh16_names,
369 NULL
370 /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
373 static struct fb_var_screeninfo atafb_predefined[] = {
375 * yres_virtual==0 means use hw-scrolling if possible, else yres
377 { /* autodetect */
378 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */
379 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/
380 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
381 { /* st low */
382 320, 200, 320, 0, 0, 0, 4, 0,
383 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
384 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
385 { /* st mid */
386 640, 200, 640, 0, 0, 0, 2, 0,
387 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
388 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
389 { /* st high */
390 640, 400, 640, 0, 0, 0, 1, 0,
391 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
392 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
393 { /* tt low */
394 320, 480, 320, 0, 0, 0, 8, 0,
395 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
396 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
397 { /* tt mid */
398 640, 480, 640, 0, 0, 0, 4, 0,
399 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
400 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
401 { /* tt high */
402 1280, 960, 1280, 0, 0, 0, 1, 0,
403 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
404 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
405 { /* vga2 */
406 640, 480, 640, 0, 0, 0, 1, 0,
407 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
408 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
409 { /* vga4 */
410 640, 480, 640, 0, 0, 0, 2, 0,
411 {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
412 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
413 { /* vga16 */
414 640, 480, 640, 0, 0, 0, 4, 0,
415 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
416 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
417 { /* vga256 */
418 640, 480, 640, 0, 0, 0, 8, 0,
419 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
420 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
421 { /* falh2 */
422 896, 608, 896, 0, 0, 0, 1, 0,
423 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
424 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
425 { /* falh16 */
426 896, 608, 896, 0, 0, 0, 4, 0,
427 {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
428 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
431 static int num_atafb_predefined=arraysize(atafb_predefined);
434 static int
435 get_video_mode(char *vname)
437 char ***name_list;
438 char **name;
439 int i;
440 name_list=fb_var_names;
441 for (i = 0 ; i < num_atafb_predefined ; i++) {
442 name=*(name_list++);
443 if (! name || ! *name)
444 break;
445 while (*name) {
446 if (! strcmp(vname, *name))
447 return i+1;
448 name++;
451 return 0;
456 /* ------------------- TT specific functions ---------------------- */
458 #ifdef ATAFB_TT
460 static int tt_encode_fix( struct fb_fix_screeninfo *fix,
461 struct atafb_par *par )
464 int mode;
466 strcpy(fix->id,"Atari Builtin");
467 fix->smem_start = (char *)real_screen_base;
468 fix->smem_len = screen_len;
469 fix->type=FB_TYPE_INTERLEAVED_PLANES;
470 fix->type_aux=2;
471 fix->visual=FB_VISUAL_PSEUDOCOLOR;
472 mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
473 if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
474 fix->type=FB_TYPE_PACKED_PIXELS;
475 fix->type_aux=0;
476 if (mode == TT_SHIFTER_TTHIGH)
477 fix->visual=FB_VISUAL_MONO01;
479 fix->xpanstep=0;
480 fix->ypanstep=1;
481 fix->ywrapstep=0;
482 fix->line_length = 0;
483 fix->accel = FB_ACCEL_ATARIBLITT;
484 return 0;
488 static int tt_decode_var( struct fb_var_screeninfo *var,
489 struct atafb_par *par )
491 int xres=var->xres;
492 int yres=var->yres;
493 int bpp=var->bits_per_pixel;
494 int linelen;
495 int yres_virtual = var->yres_virtual;
497 if (mono_moni) {
498 if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
499 return -EINVAL;
500 par->hw.tt.mode=TT_SHIFTER_TTHIGH;
501 xres=sttt_xres*2;
502 yres=tt_yres*2;
503 bpp=1;
504 } else {
505 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
506 return -EINVAL;
507 if (bpp > 4) {
508 if (xres > sttt_xres/2 || yres > tt_yres)
509 return -EINVAL;
510 par->hw.tt.mode=TT_SHIFTER_TTLOW;
511 xres=sttt_xres/2;
512 yres=tt_yres;
513 bpp=8;
515 else if (bpp > 2) {
516 if (xres > sttt_xres || yres > tt_yres)
517 return -EINVAL;
518 if (xres > sttt_xres/2 || yres > st_yres/2) {
519 par->hw.tt.mode=TT_SHIFTER_TTMID;
520 xres=sttt_xres;
521 yres=tt_yres;
522 bpp=4;
524 else {
525 par->hw.tt.mode=TT_SHIFTER_STLOW;
526 xres=sttt_xres/2;
527 yres=st_yres/2;
528 bpp=4;
531 else if (bpp > 1) {
532 if (xres > sttt_xres || yres > st_yres/2)
533 return -EINVAL;
534 par->hw.tt.mode=TT_SHIFTER_STMID;
535 xres=sttt_xres;
536 yres=st_yres/2;
537 bpp=2;
539 else if (var->xres > sttt_xres || var->yres > st_yres) {
540 return -EINVAL;
542 else {
543 par->hw.tt.mode=TT_SHIFTER_STHIGH;
544 xres=sttt_xres;
545 yres=st_yres;
546 bpp=1;
549 if (yres_virtual <= 0)
550 yres_virtual = 0;
551 else if (yres_virtual < yres)
552 yres_virtual = yres;
553 if (var->sync & FB_SYNC_EXT)
554 par->hw.tt.sync=0;
555 else
556 par->hw.tt.sync=1;
557 linelen=xres*bpp/8;
558 if (yres_virtual * linelen > screen_len && screen_len)
559 return -EINVAL;
560 if (yres * linelen > screen_len && screen_len)
561 return -EINVAL;
562 if (var->yoffset + yres > yres_virtual && yres_virtual)
563 return -EINVAL;
564 par->yres_virtual = yres_virtual;
565 par->screen_base = screen_base + var->yoffset * linelen;
566 return 0;
569 static int tt_encode_var( struct fb_var_screeninfo *var,
570 struct atafb_par *par )
572 int linelen;
573 memset(var, 0, sizeof(struct fb_var_screeninfo));
574 var->red.offset=0;
575 var->red.length=4;
576 var->red.msb_right=0;
577 var->grayscale=0;
579 var->pixclock=31041;
580 var->left_margin=120; /* these may be incorrect */
581 var->right_margin=100;
582 var->upper_margin=8;
583 var->lower_margin=16;
584 var->hsync_len=140;
585 var->vsync_len=30;
587 var->height=-1;
588 var->width=-1;
590 if (par->hw.tt.sync & 1)
591 var->sync=0;
592 else
593 var->sync=FB_SYNC_EXT;
595 switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
596 case TT_SHIFTER_STLOW:
597 var->xres=sttt_xres/2;
598 var->xres_virtual=sttt_xres_virtual/2;
599 var->yres=st_yres/2;
600 var->bits_per_pixel=4;
601 break;
602 case TT_SHIFTER_STMID:
603 var->xres=sttt_xres;
604 var->xres_virtual=sttt_xres_virtual;
605 var->yres=st_yres/2;
606 var->bits_per_pixel=2;
607 break;
608 case TT_SHIFTER_STHIGH:
609 var->xres=sttt_xres;
610 var->xres_virtual=sttt_xres_virtual;
611 var->yres=st_yres;
612 var->bits_per_pixel=1;
613 break;
614 case TT_SHIFTER_TTLOW:
615 var->xres=sttt_xres/2;
616 var->xres_virtual=sttt_xres_virtual/2;
617 var->yres=tt_yres;
618 var->bits_per_pixel=8;
619 break;
620 case TT_SHIFTER_TTMID:
621 var->xres=sttt_xres;
622 var->xres_virtual=sttt_xres_virtual;
623 var->yres=tt_yres;
624 var->bits_per_pixel=4;
625 break;
626 case TT_SHIFTER_TTHIGH:
627 var->red.length=0;
628 var->xres=sttt_xres*2;
629 var->xres_virtual=sttt_xres_virtual*2;
630 var->yres=tt_yres*2;
631 var->bits_per_pixel=1;
632 break;
634 var->blue=var->green=var->red;
635 var->transp.offset=0;
636 var->transp.length=0;
637 var->transp.msb_right=0;
638 linelen=var->xres_virtual * var->bits_per_pixel / 8;
639 if (! use_hwscroll)
640 var->yres_virtual=var->yres;
641 else if (screen_len) {
642 if (par->yres_virtual)
643 var->yres_virtual = par->yres_virtual;
644 else
645 /* yres_virtual==0 means use maximum */
646 var->yres_virtual = screen_len / linelen;
647 } else {
648 if (hwscroll < 0)
649 var->yres_virtual = 2 * var->yres;
650 else
651 var->yres_virtual=var->yres+hwscroll * 16;
653 var->xoffset=0;
654 if (screen_base)
655 var->yoffset=(par->screen_base - screen_base)/linelen;
656 else
657 var->yoffset=0;
658 var->nonstd=0;
659 var->activate=0;
660 var->vmode=FB_VMODE_NONINTERLACED;
661 return 0;
665 static void tt_get_par( struct atafb_par *par )
667 unsigned long addr;
668 par->hw.tt.mode=shifter_tt.tt_shiftmode;
669 par->hw.tt.sync=shifter.syncmode;
670 addr = ((shifter.bas_hi & 0xff) << 16) |
671 ((shifter.bas_md & 0xff) << 8) |
672 ((shifter.bas_lo & 0xff));
673 par->screen_base = phys_to_virt(addr);
676 static void tt_set_par( struct atafb_par *par )
678 shifter_tt.tt_shiftmode=par->hw.tt.mode;
679 shifter.syncmode=par->hw.tt.sync;
680 /* only set screen_base if really necessary */
681 if (current_par.screen_base != par->screen_base)
682 fbhw->set_screen_base(par->screen_base);
686 static int tt_getcolreg(unsigned regno, unsigned *red,
687 unsigned *green, unsigned *blue,
688 unsigned *transp, struct fb_info *info)
690 int t, col;
692 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
693 regno += 254;
694 if (regno > 255)
695 return 1;
696 t = tt_palette[regno];
697 col = t & 15;
698 col |= col << 4;
699 col |= col << 8;
700 *blue = col;
701 col = (t >> 4) & 15;
702 col |= col << 4;
703 col |= col << 8;
704 *green = col;
705 col = (t >> 8) & 15;
706 col |= col << 4;
707 col |= col << 8;
708 *red = col;
709 *transp = 0;
710 return 0;
714 static int tt_setcolreg(unsigned regno, unsigned red,
715 unsigned green, unsigned blue,
716 unsigned transp, struct fb_info *info)
718 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
719 regno += 254;
720 if (regno > 255)
721 return 1;
722 tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
723 (blue >> 12));
724 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
725 TT_SHIFTER_STHIGH && regno == 254)
726 tt_palette[0] = 0;
727 return 0;
731 static int tt_detect( void )
733 { struct atafb_par par;
735 /* Determine the connected monitor: The DMA sound must be
736 * disabled before reading the MFP GPIP, because the Sound
737 * Done Signal and the Monochrome Detect are XORed together!
739 * Even on a TT, we should look if there is a DMA sound. It was
740 * announced that the Eagle is TT compatible, but only the PCM is
741 * missing...
743 if (ATARIHW_PRESENT(PCM_8BIT)) {
744 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
745 udelay(20); /* wait a while for things to settle down */
747 mono_moni = (mfp.par_dt_reg & 0x80) == 0;
749 tt_get_par(&par);
750 tt_encode_var(&atafb_predefined[0], &par);
752 return 1;
755 #endif /* ATAFB_TT */
757 /* ------------------- Falcon specific functions ---------------------- */
759 #ifdef ATAFB_FALCON
761 static int mon_type; /* Falcon connected monitor */
762 static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
763 #define F_MON_SM 0
764 #define F_MON_SC 1
765 #define F_MON_VGA 2
766 #define F_MON_TV 3
768 static struct pixel_clock {
769 unsigned long f; /* f/[Hz] */
770 unsigned long t; /* t/[ps] (=1/f) */
771 int right, hsync, left; /* standard timing in clock cycles, not pixel */
772 /* hsync initialized in falcon_detect() */
773 int sync_mask; /* or-mask for hw.falcon.sync to set this clock */
774 int control_mask; /* ditto, for hw.falcon.vid_control */
776 f25 = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25},
777 f32 = {32000000, 31250, 18, 0, 42, 0x0, 0},
778 fext = { 0, 0, 18, 0, 42, 0x1, 0};
780 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
781 static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
783 /* Default hsync timing [mon_type] in picoseconds */
784 static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
786 #ifdef FBCON_HAS_CFB16
787 static u16 fbcon_cfb16_cmap[16];
788 #endif
790 static inline int hxx_prescale(struct falcon_hw *hw)
792 return hw->ste_mode ? 16 :
793 vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
796 static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
797 struct atafb_par *par )
799 strcpy(fix->id, "Atari Builtin");
800 fix->smem_start = (char *)real_screen_base;
801 fix->smem_len = screen_len;
802 fix->type = FB_TYPE_INTERLEAVED_PLANES;
803 fix->type_aux = 2;
804 fix->visual = FB_VISUAL_PSEUDOCOLOR;
805 fix->xpanstep = 1;
806 fix->ypanstep = 1;
807 fix->ywrapstep = 0;
808 if (par->hw.falcon.mono) {
809 fix->type = FB_TYPE_PACKED_PIXELS;
810 fix->type_aux = 0;
811 /* no smooth scrolling with longword aligned video mem */
812 fix->xpanstep = 32;
814 else if (par->hw.falcon.f_shift & 0x100) {
815 fix->type = FB_TYPE_PACKED_PIXELS;
816 fix->type_aux = 0;
817 /* Is this ok or should it be DIRECTCOLOR? */
818 fix->visual = FB_VISUAL_TRUECOLOR;
819 fix->xpanstep = 2;
821 fix->line_length = 0;
822 fix->accel = FB_ACCEL_ATARIBLITT;
823 return 0;
827 static int falcon_decode_var( struct fb_var_screeninfo *var,
828 struct atafb_par *par )
830 int bpp = var->bits_per_pixel;
831 int xres = var->xres;
832 int yres = var->yres;
833 int xres_virtual = var->xres_virtual;
834 int yres_virtual = var->yres_virtual;
835 int left_margin, right_margin, hsync_len;
836 int upper_margin, lower_margin, vsync_len;
837 int linelen;
838 int interlace = 0, doubleline = 0;
839 struct pixel_clock *pclock;
840 int plen; /* width of pixel in clock cycles */
841 int xstretch;
842 int prescale;
843 int longoffset = 0;
844 int hfreq, vfreq;
847 Get the video params out of 'var'. If a value doesn't fit, round
848 it up, if it's too big, return EINVAL.
849 Round up in the following order: bits_per_pixel, xres, yres,
850 xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields,
851 horizontal timing, vertical timing.
853 There is a maximum of screen resolution determined by pixelclock
854 and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
855 In interlace mode this is " * " *vfmin <= pixelclock.
856 Additional constraints: hfreq.
857 Frequency range for multisync monitors is given via command line.
858 For TV and SM124 both frequencies are fixed.
860 X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
861 Y % 16 == 0 to fit 8x16 font
862 Y % 8 == 0 if Y<400
864 Currently interlace and doubleline mode in var are ignored.
865 On SM124 and TV only the standard resolutions can be used.
868 /* Reject uninitialized mode */
869 if (!xres || !yres || !bpp)
870 return -EINVAL;
872 if (mon_type == F_MON_SM && bpp != 1) {
873 return -EINVAL;
875 else if (bpp <= 1) {
876 bpp = 1;
877 par->hw.falcon.f_shift = 0x400;
878 par->hw.falcon.st_shift = 0x200;
880 else if (bpp <= 2) {
881 bpp = 2;
882 par->hw.falcon.f_shift = 0x000;
883 par->hw.falcon.st_shift = 0x100;
885 else if (bpp <= 4) {
886 bpp = 4;
887 par->hw.falcon.f_shift = 0x000;
888 par->hw.falcon.st_shift = 0x000;
890 else if (bpp <= 8) {
891 bpp = 8;
892 par->hw.falcon.f_shift = 0x010;
894 else if (bpp <= 16) {
895 bpp = 16; /* packed pixel mode */
896 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
898 else
899 return -EINVAL;
900 par->hw.falcon.bpp = bpp;
902 if (mon_type == F_MON_SM || DontCalcRes) {
903 /* Skip all calculations. VGA/TV/SC1224 only supported. */
904 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
906 if (bpp > myvar->bits_per_pixel ||
907 var->xres > myvar->xres ||
908 var->yres > myvar->yres)
909 return -EINVAL;
910 fbhw->get_par(par); /* Current par will be new par */
911 goto set_screen_base; /* Don't forget this */
914 /* Only some fixed resolutions < 640x400 */
915 if (xres <= 320)
916 xres = 320;
917 else if (xres <= 640 && bpp != 16)
918 xres = 640;
919 if (yres <= 200)
920 yres = 200;
921 else if (yres <= 240)
922 yres = 240;
923 else if (yres <= 400)
924 yres = 400;
926 /* 2 planes must use STE compatibility mode */
927 par->hw.falcon.ste_mode = bpp==2;
928 par->hw.falcon.mono = bpp==1;
930 /* Total and visible scanline length must be a multiple of one longword,
931 * this and the console fontwidth yields the alignment for xres and
932 * xres_virtual.
933 * TODO: this way "odd" fontheights are not supported
935 * Special case in STE mode: blank and graphic positions don't align,
936 * avoid trash at right margin
938 if (par->hw.falcon.ste_mode)
939 xres = (xres + 63) & ~63;
940 else if (bpp == 1)
941 xres = (xres + 31) & ~31;
942 else
943 xres = (xres + 15) & ~15;
944 if (yres >= 400)
945 yres = (yres + 15) & ~15;
946 else
947 yres = (yres + 7) & ~7;
949 if (xres_virtual < xres)
950 xres_virtual = xres;
951 else if (bpp == 1)
952 xres_virtual = (xres_virtual + 31) & ~31;
953 else
954 xres_virtual = (xres_virtual + 15) & ~15;
956 if (yres_virtual <= 0)
957 yres_virtual = 0;
958 else if (yres_virtual < yres)
959 yres_virtual = yres;
961 /* backward bug-compatibility */
962 if (var->pixclock > 1)
963 var->pixclock -= 1;
965 par->hw.falcon.line_width = bpp * xres / 16;
966 par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
968 /* single or double pixel width */
969 xstretch = (xres < 640) ? 2 : 1;
971 #if 0 /* SM124 supports only 640x400, this is rejected above */
972 if (mon_type == F_MON_SM) {
973 if (xres != 640 && yres != 400)
974 return -EINVAL;
975 plen = 1;
976 pclock = &f32;
977 /* SM124-mode is special */
978 par->hw.falcon.ste_mode = 1;
979 par->hw.falcon.f_shift = 0x000;
980 par->hw.falcon.st_shift = 0x200;
981 left_margin = hsync_len = 128 / plen;
982 right_margin = 0;
983 /* TODO set all margins */
985 else
986 #endif
987 if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
988 plen = 2 * xstretch;
989 if (var->pixclock > f32.t * plen)
990 return -EINVAL;
991 pclock = &f32;
992 if (yres > 240)
993 interlace = 1;
994 if (var->pixclock == 0) {
995 /* set some minimal margins which center the screen */
996 left_margin = 32;
997 right_margin = 18;
998 hsync_len = pclock->hsync / plen;
999 upper_margin = 31;
1000 lower_margin = 14;
1001 vsync_len = interlace ? 3 : 4;
1002 } else {
1003 left_margin = var->left_margin;
1004 right_margin = var->right_margin;
1005 hsync_len = var->hsync_len;
1006 upper_margin = var->upper_margin;
1007 lower_margin = var->lower_margin;
1008 vsync_len = var->vsync_len;
1009 if (var->vmode & FB_VMODE_INTERLACED) {
1010 upper_margin = (upper_margin + 1) / 2;
1011 lower_margin = (lower_margin + 1) / 2;
1012 vsync_len = (vsync_len + 1) / 2;
1013 } else if (var->vmode & FB_VMODE_DOUBLE) {
1014 upper_margin *= 2;
1015 lower_margin *= 2;
1016 vsync_len *= 2;
1020 else
1021 { /* F_MON_VGA */
1022 if (bpp == 16)
1023 xstretch = 2; /* Double pixel width only for hicolor */
1024 /* Default values are used for vert./hor. timing if no pixelclock given. */
1025 if (var->pixclock == 0) {
1026 int linesize;
1028 /* Choose master pixelclock depending on hor. timing */
1029 plen = 1 * xstretch;
1030 if ((plen * xres + f25.right+f25.hsync+f25.left) *
1031 fb_info.monspecs.hfmin < f25.f)
1032 pclock = &f25;
1033 else if ((plen * xres + f32.right+f32.hsync+f32.left) *
1034 fb_info.monspecs.hfmin < f32.f)
1035 pclock = &f32;
1036 else if ((plen * xres + fext.right+fext.hsync+fext.left) *
1037 fb_info.monspecs.hfmin < fext.f
1038 && fext.f)
1039 pclock = &fext;
1040 else
1041 return -EINVAL;
1043 left_margin = pclock->left / plen;
1044 right_margin = pclock->right / plen;
1045 hsync_len = pclock->hsync / plen;
1046 linesize = left_margin + xres + right_margin + hsync_len;
1047 upper_margin = 31;
1048 lower_margin = 11;
1049 vsync_len = 3;
1051 else {
1052 /* Choose largest pixelclock <= wanted clock */
1053 int i;
1054 unsigned long pcl = ULONG_MAX;
1055 pclock = 0;
1056 for (i=1; i <= 4; i *= 2) {
1057 if (f25.t*i >= var->pixclock && f25.t*i < pcl) {
1058 pcl = f25.t * i;
1059 pclock = &f25;
1061 if (f32.t*i >= var->pixclock && f32.t*i < pcl) {
1062 pcl = f32.t * i;
1063 pclock = &f32;
1065 if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) {
1066 pcl = fext.t * i;
1067 pclock = &fext;
1070 if (!pclock)
1071 return -EINVAL;
1072 plen = pcl / pclock->t;
1074 left_margin = var->left_margin;
1075 right_margin = var->right_margin;
1076 hsync_len = var->hsync_len;
1077 upper_margin = var->upper_margin;
1078 lower_margin = var->lower_margin;
1079 vsync_len = var->vsync_len;
1080 /* Internal unit is [single lines per (half-)frame] */
1081 if (var->vmode & FB_VMODE_INTERLACED) {
1082 /* # lines in half frame */
1083 /* External unit is [lines per full frame] */
1084 upper_margin = (upper_margin + 1) / 2;
1085 lower_margin = (lower_margin + 1) / 2;
1086 vsync_len = (vsync_len + 1) / 2;
1088 else if (var->vmode & FB_VMODE_DOUBLE) {
1089 /* External unit is [double lines per frame] */
1090 upper_margin *= 2;
1091 lower_margin *= 2;
1092 vsync_len *= 2;
1095 if (pclock == &fext)
1096 longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1098 /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1099 /* this is definitely wrong if bus clock != 32MHz */
1100 if (pclock->f / plen / 8 * bpp > 32000000L)
1101 return -EINVAL;
1103 if (vsync_len < 1)
1104 vsync_len = 1;
1106 /* include sync lengths in right/lower margin for all calculations */
1107 right_margin += hsync_len;
1108 lower_margin += vsync_len;
1110 /* ! In all calculations of margins we use # of lines in half frame
1111 * (which is a full frame in non-interlace mode), so we can switch
1112 * between interlace and non-interlace without messing around
1113 * with these.
1115 again:
1116 /* Set base_offset 128 and video bus width */
1117 par->hw.falcon.vid_control = mon_type | f030_bus_width;
1118 if (!longoffset)
1119 par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */
1120 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1121 par->hw.falcon.vid_control |= VCO_HSYPOS;
1122 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1123 par->hw.falcon.vid_control |= VCO_VSYPOS;
1124 /* Pixelclock */
1125 par->hw.falcon.vid_control |= pclock->control_mask;
1126 /* External or internal clock */
1127 par->hw.falcon.sync = pclock->sync_mask | 0x2;
1128 /* Pixellength and prescale */
1129 par->hw.falcon.vid_mode = (2/plen) << 2;
1130 if (doubleline)
1131 par->hw.falcon.vid_mode |= VMO_DOUBLE;
1132 if (interlace)
1133 par->hw.falcon.vid_mode |= VMO_INTER;
1135 /*********************
1136 Horizontal timing: unit = [master clock cycles]
1137 unit of hxx-registers: [master clock cycles * prescale]
1138 Hxx-registers are 9 bit wide
1140 1 line = ((hht + 2) * 2 * prescale) clock cycles
1142 graphic output = hdb & 0x200 ?
1143 ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
1144 ( hht + 2 - hdb + hde) * prescale - hdboff + hdeoff
1145 (this must be a multiple of plen*128/bpp, on VGA pixels
1146 to the right may be cut off with a bigger right margin)
1148 start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1149 (hdb - hht - 2) * prescale + hdboff :
1150 hdb * prescale + hdboff
1152 end of graphics relative to start of 1st halfline =
1153 (hde + hht + 2) * prescale + hdeoff
1154 *********************/
1155 /* Calculate VIDEL registers */
1157 int hdb_off, hde_off, base_off;
1158 int gstart, gend1, gend2, align;
1160 prescale = hxx_prescale(&par->hw.falcon);
1161 base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1163 /* Offsets depend on video mode */
1164 /* Offsets are in clock cycles, divide by prescale to
1165 * calculate hd[be]-registers
1167 if (par->hw.falcon.f_shift & 0x100) {
1168 align = 1;
1169 hde_off = 0;
1170 hdb_off = (base_off + 16 * plen) + prescale;
1172 else {
1173 align = 128 / bpp;
1174 hde_off = ((128 / bpp + 2) * plen);
1175 if (par->hw.falcon.ste_mode)
1176 hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1177 else
1178 hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1181 gstart = (prescale/2 + plen * left_margin) / prescale;
1182 /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1183 gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
1184 /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1185 gend2 = gstart + xres * plen / prescale;
1186 par->HHT = plen * (left_margin + xres + right_margin) /
1187 (2 * prescale) - 2;
1188 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1190 par->HDB = gstart - hdb_off/prescale;
1191 par->HBE = gstart;
1192 if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
1193 par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
1194 par->HBB = gend2 - par->HHT - 2;
1195 #if 0
1196 /* One more Videl constraint: data fetch of two lines must not overlap */
1197 if (par->HDB & 0x200 && par->HDB & ~0x200 - par->HDE <= 5) {
1198 /* if this happens increase margins, decrease hfreq. */
1200 #endif
1201 if (hde_off % prescale)
1202 par->HBB++; /* compensate for non matching hde and hbb */
1203 par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1204 if (par->HSS < par->HBB)
1205 par->HSS = par->HBB;
1208 /* check hor. frequency */
1209 hfreq = pclock->f / ((par->HHT+2)*prescale*2);
1210 if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) {
1211 /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1212 /* Too high -> enlarge margin */
1213 left_margin += 1;
1214 right_margin += 1;
1215 goto again;
1217 if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
1218 return -EINVAL;
1220 /* Vxx-registers */
1221 /* All Vxx must be odd in non-interlace, since frame starts in the middle
1222 * of the first displayed line!
1223 * One frame consists of VFT+1 half lines. VFT+1 must be even in
1224 * non-interlace, odd in interlace mode for synchronisation.
1225 * Vxx-registers are 11 bit wide
1227 par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1228 par->VDB = par->VBE;
1229 par->VDE = yres;
1230 if (!interlace) par->VDE <<= 1;
1231 if (doubleline) par->VDE <<= 1; /* VDE now half lines per (half-)frame */
1232 par->VDE += par->VDB;
1233 par->VBB = par->VDE;
1234 par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1235 par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
1236 /* vbb,vss,vft must be even in interlace mode */
1237 if (interlace) {
1238 par->VBB++;
1239 par->VSS++;
1240 par->VFT++;
1243 /* V-frequency check, hope I didn't create any loop here. */
1244 /* Interlace and doubleline are mutually exclusive. */
1245 vfreq = (hfreq * 2) / (par->VFT + 1);
1246 if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
1247 /* Too high -> try again with doubleline */
1248 doubleline = 1;
1249 goto again;
1251 else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1252 /* Too low -> try again with interlace */
1253 interlace = 1;
1254 goto again;
1256 else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1257 /* Doubleline too low -> clear doubleline and enlarge margins */
1258 int lines;
1259 doubleline = 0;
1260 for (lines=0;
1261 (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax;
1262 lines++)
1264 upper_margin += lines;
1265 lower_margin += lines;
1266 goto again;
1268 else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1269 /* Doubleline too high -> enlarge margins */
1270 int lines;
1271 for (lines=0;
1272 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1273 lines+=2)
1275 upper_margin += lines;
1276 lower_margin += lines;
1277 goto again;
1279 else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1280 /* Interlace, too high -> enlarge margins */
1281 int lines;
1282 for (lines=0;
1283 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1284 lines++)
1286 upper_margin += lines;
1287 lower_margin += lines;
1288 goto again;
1290 else if (vfreq < fb_info.monspecs.vfmin ||
1291 vfreq > fb_info.monspecs.vfmax)
1292 return -EINVAL;
1294 set_screen_base:
1295 linelen = xres_virtual * bpp / 8;
1296 if (yres_virtual * linelen > screen_len && screen_len)
1297 return -EINVAL;
1298 if (yres * linelen > screen_len && screen_len)
1299 return -EINVAL;
1300 if (var->yoffset + yres > yres_virtual && yres_virtual)
1301 return -EINVAL;
1302 par->yres_virtual = yres_virtual;
1303 par->screen_base = screen_base + var->yoffset * linelen;
1304 par->hw.falcon.xoffset = 0;
1306 return 0;
1309 static int falcon_encode_var( struct fb_var_screeninfo *var,
1310 struct atafb_par *par )
1312 /* !!! only for VGA !!! */
1313 int linelen;
1314 int prescale, plen;
1315 int hdb_off, hde_off, base_off;
1316 struct falcon_hw *hw = &par->hw.falcon;
1318 memset(var, 0, sizeof(struct fb_var_screeninfo));
1319 /* possible frequencies: 25.175 or 32MHz */
1320 var->pixclock = hw->sync & 0x1 ? fext.t :
1321 hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1323 var->height=-1;
1324 var->width=-1;
1326 var->sync=0;
1327 if (hw->vid_control & VCO_HSYPOS)
1328 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1329 if (hw->vid_control & VCO_VSYPOS)
1330 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1332 var->vmode = FB_VMODE_NONINTERLACED;
1333 if (hw->vid_mode & VMO_INTER)
1334 var->vmode |= FB_VMODE_INTERLACED;
1335 if (hw->vid_mode & VMO_DOUBLE)
1336 var->vmode |= FB_VMODE_DOUBLE;
1338 /* visible y resolution:
1339 * Graphics display starts at line VDB and ends at line
1340 * VDE. If interlace mode off unit of VC-registers is
1341 * half lines, else lines.
1343 var->yres = hw->vde - hw->vdb;
1344 if (!(var->vmode & FB_VMODE_INTERLACED))
1345 var->yres >>= 1;
1346 if (var->vmode & FB_VMODE_DOUBLE)
1347 var->yres >>= 1;
1349 /* to get bpp, we must examine f_shift and st_shift.
1350 * f_shift is valid if any of bits no. 10, 8 or 4
1351 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1352 * if bit 10 set then bit 8 and bit 4 don't care...
1353 * If all these bits are 0 get display depth from st_shift
1354 * (as for ST and STE)
1356 if (hw->f_shift & 0x400) /* 2 colors */
1357 var->bits_per_pixel = 1;
1358 else if (hw->f_shift & 0x100) /* hicolor */
1359 var->bits_per_pixel = 16;
1360 else if (hw->f_shift & 0x010) /* 8 bitplanes */
1361 var->bits_per_pixel = 8;
1362 else if (hw->st_shift == 0)
1363 var->bits_per_pixel = 4;
1364 else if (hw->st_shift == 0x100)
1365 var->bits_per_pixel = 2;
1366 else /* if (hw->st_shift == 0x200) */
1367 var->bits_per_pixel = 1;
1369 var->xres = hw->line_width * 16 / var->bits_per_pixel;
1370 var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1371 if (hw->xoffset)
1372 var->xres_virtual += 16;
1374 if (var->bits_per_pixel == 16) {
1375 var->red.offset=11;
1376 var->red.length=5;
1377 var->red.msb_right=0;
1378 var->green.offset=5;
1379 var->green.length=6;
1380 var->green.msb_right=0;
1381 var->blue.offset=0;
1382 var->blue.length=5;
1383 var->blue.msb_right=0;
1385 else {
1386 var->red.offset=0;
1387 var->red.length = hw->ste_mode ? 4 : 6;
1388 var->red.msb_right=0;
1389 var->grayscale=0;
1390 var->blue=var->green=var->red;
1392 var->transp.offset=0;
1393 var->transp.length=0;
1394 var->transp.msb_right=0;
1396 linelen = var->xres_virtual * var->bits_per_pixel / 8;
1397 if (screen_len) {
1398 if (par->yres_virtual)
1399 var->yres_virtual = par->yres_virtual;
1400 else
1401 /* yres_virtual==0 means use maximum */
1402 var->yres_virtual = screen_len / linelen;
1404 else {
1405 if (hwscroll < 0)
1406 var->yres_virtual = 2 * var->yres;
1407 else
1408 var->yres_virtual=var->yres+hwscroll * 16;
1410 var->xoffset=0; /* TODO change this */
1412 /* hdX-offsets */
1413 prescale = hxx_prescale(hw);
1414 plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1415 base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1416 if (hw->f_shift & 0x100) {
1417 hde_off = 0;
1418 hdb_off = (base_off + 16 * plen) + prescale;
1420 else {
1421 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1422 if (hw->ste_mode)
1423 hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1424 + prescale;
1425 else
1426 hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1427 + prescale;
1430 /* Right margin includes hsync */
1431 var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1432 (hw->hdb & 0x200 ? 2+hw->hht : 0));
1433 if (hw->ste_mode || mon_type!=F_MON_VGA)
1434 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1435 else
1436 /* can't use this in ste_mode, because hbb is +1 off */
1437 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1438 var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1440 /* Lower margin includes vsync */
1441 var->upper_margin = hw->vdb / 2 ; /* round down to full lines */
1442 var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
1443 var->vsync_len = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
1444 if (var->vmode & FB_VMODE_INTERLACED) {
1445 var->upper_margin *= 2;
1446 var->lower_margin *= 2;
1447 var->vsync_len *= 2;
1449 else if (var->vmode & FB_VMODE_DOUBLE) {
1450 var->upper_margin = (var->upper_margin + 1) / 2;
1451 var->lower_margin = (var->lower_margin + 1) / 2;
1452 var->vsync_len = (var->vsync_len + 1) / 2;
1455 var->pixclock *= plen;
1456 var->left_margin /= plen;
1457 var->right_margin /= plen;
1458 var->hsync_len /= plen;
1460 var->right_margin -= var->hsync_len;
1461 var->lower_margin -= var->vsync_len;
1463 if (screen_base)
1464 var->yoffset=(par->screen_base - screen_base)/linelen;
1465 else
1466 var->yoffset=0;
1467 var->nonstd=0; /* what is this for? */
1468 var->activate=0;
1469 return 0;
1473 static int f_change_mode = 0;
1474 static struct falcon_hw f_new_mode;
1475 static int f_pan_display = 0;
1477 static void falcon_get_par( struct atafb_par *par )
1479 unsigned long addr;
1480 struct falcon_hw *hw = &par->hw.falcon;
1482 hw->line_width = shifter_f030.scn_width;
1483 hw->line_offset = shifter_f030.off_next;
1484 hw->st_shift = videl.st_shift & 0x300;
1485 hw->f_shift = videl.f_shift;
1486 hw->vid_control = videl.control;
1487 hw->vid_mode = videl.mode;
1488 hw->sync = shifter.syncmode & 0x1;
1489 hw->xoffset = videl.xoffset & 0xf;
1490 hw->hht = videl.hht;
1491 hw->hbb = videl.hbb;
1492 hw->hbe = videl.hbe;
1493 hw->hdb = videl.hdb;
1494 hw->hde = videl.hde;
1495 hw->hss = videl.hss;
1496 hw->vft = videl.vft;
1497 hw->vbb = videl.vbb;
1498 hw->vbe = videl.vbe;
1499 hw->vdb = videl.vdb;
1500 hw->vde = videl.vde;
1501 hw->vss = videl.vss;
1503 addr = (shifter.bas_hi & 0xff) << 16 |
1504 (shifter.bas_md & 0xff) << 8 |
1505 (shifter.bas_lo & 0xff);
1506 par->screen_base = phys_to_virt(addr);
1508 /* derived parameters */
1509 hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
1510 hw->mono = (hw->f_shift & 0x400) ||
1511 ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
1514 static void falcon_set_par( struct atafb_par *par )
1516 f_change_mode = 0;
1518 /* only set screen_base if really necessary */
1519 if (current_par.screen_base != par->screen_base)
1520 fbhw->set_screen_base(par->screen_base);
1522 /* Don't touch any other registers if we keep the default resolution */
1523 if (DontCalcRes)
1524 return;
1526 /* Tell vbl-handler to change video mode.
1527 * We change modes only on next VBL, to avoid desynchronisation
1528 * (a shift to the right and wrap around by a random number of pixels
1529 * in all monochrome modes).
1530 * This seems to work on my Falcon.
1532 f_new_mode = par->hw.falcon;
1533 f_change_mode = 1;
1537 static void falcon_vbl_switcher( int irq, void *dummy, struct pt_regs *fp )
1539 struct falcon_hw *hw = &f_new_mode;
1541 if (f_change_mode) {
1542 f_change_mode = 0;
1544 if (hw->sync & 0x1) {
1545 /* Enable external pixelclock. This code only for ScreenWonder */
1546 *(volatile unsigned short*)0xffff9202 = 0xffbf;
1548 else {
1549 /* Turn off external clocks. Read sets all output bits to 1. */
1550 *(volatile unsigned short*)0xffff9202;
1552 shifter.syncmode = hw->sync;
1554 videl.hht = hw->hht;
1555 videl.hbb = hw->hbb;
1556 videl.hbe = hw->hbe;
1557 videl.hdb = hw->hdb;
1558 videl.hde = hw->hde;
1559 videl.hss = hw->hss;
1560 videl.vft = hw->vft;
1561 videl.vbb = hw->vbb;
1562 videl.vbe = hw->vbe;
1563 videl.vdb = hw->vdb;
1564 videl.vde = hw->vde;
1565 videl.vss = hw->vss;
1567 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1568 if (hw->ste_mode) {
1569 videl.st_shift = hw->st_shift; /* write enables STE palette */
1571 else {
1572 /* IMPORTANT:
1573 * set st_shift 0, so we can tell the screen-depth if f_shift==0.
1574 * Writing 0 to f_shift enables 4 plane Falcon mode but
1575 * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
1576 * with Falcon palette.
1578 videl.st_shift = 0;
1579 /* now back to Falcon palette mode */
1580 videl.f_shift = hw->f_shift;
1582 /* writing to st_shift changed scn_width and vid_mode */
1583 videl.xoffset = hw->xoffset;
1584 shifter_f030.scn_width = hw->line_width;
1585 shifter_f030.off_next = hw->line_offset;
1586 videl.control = hw->vid_control;
1587 videl.mode = hw->vid_mode;
1589 if (f_pan_display) {
1590 f_pan_display = 0;
1591 videl.xoffset = current_par.hw.falcon.xoffset;
1592 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1597 static int falcon_pan_display( struct fb_var_screeninfo *var,
1598 struct atafb_par *par )
1600 int xoffset;
1601 int bpp = fb_display[currcon].var.bits_per_pixel;
1603 if (bpp == 1)
1604 var->xoffset = up(var->xoffset, 32);
1605 if (bpp != 16)
1606 par->hw.falcon.xoffset = var->xoffset & 15;
1607 else {
1608 par->hw.falcon.xoffset = 0;
1609 var->xoffset = up(var->xoffset, 2);
1611 par->hw.falcon.line_offset = bpp *
1612 (fb_display[currcon].var.xres_virtual - fb_display[currcon].var.xres) / 16;
1613 if (par->hw.falcon.xoffset)
1614 par->hw.falcon.line_offset -= bpp;
1615 xoffset = var->xoffset - par->hw.falcon.xoffset;
1617 par->screen_base = screen_base +
1618 (var->yoffset * fb_display[currcon].var.xres_virtual + xoffset) * bpp / 8;
1619 if (fbhw->set_screen_base)
1620 fbhw->set_screen_base (par->screen_base);
1621 else
1622 return -EINVAL; /* shouldn't happen */
1623 f_pan_display = 1;
1624 return 0;
1628 static int falcon_getcolreg( unsigned regno, unsigned *red,
1629 unsigned *green, unsigned *blue,
1630 unsigned *transp, struct fb_info *info )
1631 { unsigned long col;
1633 if (regno > 255)
1634 return 1;
1635 /* This works in STE-mode (with 4bit/color) since f030_col-registers
1636 * hold up to 6bit/color.
1637 * Even with hicolor r/g/b=5/6/5 bit!
1639 col = f030_col[regno];
1640 *red = (col >> 16) & 0xff00;
1641 *green = (col >> 8) & 0xff00;
1642 *blue = (col << 8) & 0xff00;
1643 *transp = 0;
1644 return 0;
1648 static int falcon_setcolreg( unsigned regno, unsigned red,
1649 unsigned green, unsigned blue,
1650 unsigned transp, struct fb_info *info )
1652 if (regno > 255)
1653 return 1;
1654 f030_col[regno] = (((red & 0xfc00) << 16) |
1655 ((green & 0xfc00) << 8) |
1656 ((blue & 0xfc00) >> 8));
1657 if (regno < 16) {
1658 shifter_tt.color_reg[regno] =
1659 (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
1660 (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
1661 ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
1662 #ifdef FBCON_HAS_CFB16
1663 fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
1664 ((green & 0xfc00) >> 5) |
1665 ((blue & 0xf800) >> 11));
1666 #endif
1668 return 0;
1672 static int falcon_blank( int blank_mode )
1674 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1675 * so VIDEL doesn't hog the bus while saving.
1676 * (this may affect usleep()).
1678 int vdb, vss, hbe, hss;
1680 if (mon_type == F_MON_SM) /* this doesn't work on SM124 */
1681 return 1;
1683 vdb = current_par.VDB;
1684 vss = current_par.VSS;
1685 hbe = current_par.HBE;
1686 hss = current_par.HSS;
1688 if (blank_mode >= 1) {
1689 /* disable graphics output (this speeds up the CPU) ... */
1690 vdb = current_par.VFT + 1;
1691 /* ... and blank all lines */
1692 hbe = current_par.HHT + 2;
1694 /* use VESA suspend modes on VGA monitors */
1695 if (mon_type == F_MON_VGA) {
1696 if (blank_mode == 2 || blank_mode == 4)
1697 vss = current_par.VFT + 1;
1698 if (blank_mode == 3 || blank_mode == 4)
1699 hss = current_par.HHT + 2;
1702 videl.vdb = vdb;
1703 videl.vss = vss;
1704 videl.hbe = hbe;
1705 videl.hss = hss;
1707 return 0;
1711 static int falcon_detect( void )
1713 struct atafb_par par;
1714 unsigned char fhw;
1716 /* Determine connected monitor and set monitor parameters */
1717 fhw = *(unsigned char*)0xffff8006;
1718 mon_type = fhw >> 6 & 0x3;
1719 /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1720 f030_bus_width = fhw << 6 & 0x80;
1721 switch (mon_type) {
1722 case F_MON_SM:
1723 fb_info.monspecs.vfmin = 70;
1724 fb_info.monspecs.vfmax = 72;
1725 fb_info.monspecs.hfmin = 35713;
1726 fb_info.monspecs.hfmax = 35715;
1727 break;
1728 case F_MON_SC:
1729 case F_MON_TV:
1730 /* PAL...NTSC */
1731 fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
1732 fb_info.monspecs.vfmax = 60;
1733 fb_info.monspecs.hfmin = 15620;
1734 fb_info.monspecs.hfmax = 15755;
1735 break;
1737 /* initialize hsync-len */
1738 f25.hsync = h_syncs[mon_type] / f25.t;
1739 f32.hsync = h_syncs[mon_type] / f32.t;
1740 if (fext.t)
1741 fext.hsync = h_syncs[mon_type] / fext.t;
1743 falcon_get_par(&par);
1744 falcon_encode_var(&atafb_predefined[0], &par);
1746 /* Detected mode is always the "autodetect" slot */
1747 return 1;
1750 #endif /* ATAFB_FALCON */
1752 /* ------------------- ST(E) specific functions ---------------------- */
1754 #ifdef ATAFB_STE
1756 static int stste_encode_fix( struct fb_fix_screeninfo *fix,
1757 struct atafb_par *par )
1760 int mode;
1762 strcpy(fix->id,"Atari Builtin");
1763 fix->smem_start = (char *)real_screen_base;
1764 fix->smem_len = screen_len;
1765 fix->type = FB_TYPE_INTERLEAVED_PLANES;
1766 fix->type_aux = 2;
1767 fix->visual = FB_VISUAL_PSEUDOCOLOR;
1768 mode = par->hw.st.mode & 3;
1769 if (mode == ST_HIGH) {
1770 fix->type = FB_TYPE_PACKED_PIXELS;
1771 fix->type_aux = 0;
1772 fix->visual = FB_VISUAL_MONO10;
1774 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1775 fix->xpanstep = 16;
1776 fix->ypanstep = 1;
1777 } else {
1778 fix->xpanstep = 0;
1779 fix->ypanstep = 0;
1781 fix->ywrapstep = 0;
1782 fix->line_length = 0;
1783 fix->accel = FB_ACCEL_ATARIBLITT;
1784 return 0;
1788 static int stste_decode_var( struct fb_var_screeninfo *var,
1789 struct atafb_par *par )
1791 int xres=var->xres;
1792 int yres=var->yres;
1793 int bpp=var->bits_per_pixel;
1794 int linelen;
1795 int yres_virtual = var->yres_virtual;
1797 if (mono_moni) {
1798 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1799 return -EINVAL;
1800 par->hw.st.mode=ST_HIGH;
1801 xres=sttt_xres;
1802 yres=st_yres;
1803 bpp=1;
1804 } else {
1805 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1806 return -EINVAL;
1807 if (bpp > 2) {
1808 if (xres > sttt_xres/2 || yres > st_yres/2)
1809 return -EINVAL;
1810 par->hw.st.mode=ST_LOW;
1811 xres=sttt_xres/2;
1812 yres=st_yres/2;
1813 bpp=4;
1815 else if (bpp > 1) {
1816 if (xres > sttt_xres || yres > st_yres/2)
1817 return -EINVAL;
1818 par->hw.st.mode=ST_MID;
1819 xres=sttt_xres;
1820 yres=st_yres/2;
1821 bpp=2;
1823 else
1824 return -EINVAL;
1826 if (yres_virtual <= 0)
1827 yres_virtual = 0;
1828 else if (yres_virtual < yres)
1829 yres_virtual = yres;
1830 if (var->sync & FB_SYNC_EXT)
1831 par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
1832 else
1833 par->hw.st.sync=(par->hw.st.sync & ~1);
1834 linelen=xres*bpp/8;
1835 if (yres_virtual * linelen > screen_len && screen_len)
1836 return -EINVAL;
1837 if (yres * linelen > screen_len && screen_len)
1838 return -EINVAL;
1839 if (var->yoffset + yres > yres_virtual && yres_virtual)
1840 return -EINVAL;
1841 par->yres_virtual = yres_virtual;
1842 par->screen_base=screen_base+ var->yoffset*linelen;
1843 return 0;
1846 static int stste_encode_var( struct fb_var_screeninfo *var,
1847 struct atafb_par *par )
1849 int linelen;
1850 memset(var, 0, sizeof(struct fb_var_screeninfo));
1851 var->red.offset=0;
1852 var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1853 var->red.msb_right=0;
1854 var->grayscale=0;
1856 var->pixclock=31041;
1857 var->left_margin=120; /* these are incorrect */
1858 var->right_margin=100;
1859 var->upper_margin=8;
1860 var->lower_margin=16;
1861 var->hsync_len=140;
1862 var->vsync_len=30;
1864 var->height=-1;
1865 var->width=-1;
1867 if (!(par->hw.st.sync & 1))
1868 var->sync=0;
1869 else
1870 var->sync=FB_SYNC_EXT;
1872 switch (par->hw.st.mode & 3) {
1873 case ST_LOW:
1874 var->xres=sttt_xres/2;
1875 var->yres=st_yres/2;
1876 var->bits_per_pixel=4;
1877 break;
1878 case ST_MID:
1879 var->xres=sttt_xres;
1880 var->yres=st_yres/2;
1881 var->bits_per_pixel=2;
1882 break;
1883 case ST_HIGH:
1884 var->xres=sttt_xres;
1885 var->yres=st_yres;
1886 var->bits_per_pixel=1;
1887 break;
1889 var->blue=var->green=var->red;
1890 var->transp.offset=0;
1891 var->transp.length=0;
1892 var->transp.msb_right=0;
1893 var->xres_virtual=sttt_xres_virtual;
1894 linelen=var->xres_virtual * var->bits_per_pixel / 8;
1895 ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
1897 if (! use_hwscroll)
1898 var->yres_virtual=var->yres;
1899 else if (screen_len) {
1900 if (par->yres_virtual)
1901 var->yres_virtual = par->yres_virtual;
1902 else
1903 /* yres_virtual==0 means use maximum */
1904 var->yres_virtual = screen_len / linelen;
1906 else {
1907 if (hwscroll < 0)
1908 var->yres_virtual = 2 * var->yres;
1909 else
1910 var->yres_virtual=var->yres+hwscroll * 16;
1912 var->xoffset=0;
1913 if (screen_base)
1914 var->yoffset=(par->screen_base - screen_base)/linelen;
1915 else
1916 var->yoffset=0;
1917 var->nonstd=0;
1918 var->activate=0;
1919 var->vmode=FB_VMODE_NONINTERLACED;
1920 return 0;
1924 static void stste_get_par( struct atafb_par *par )
1926 unsigned long addr;
1927 par->hw.st.mode=shifter_tt.st_shiftmode;
1928 par->hw.st.sync=shifter.syncmode;
1929 addr = ((shifter.bas_hi & 0xff) << 16) |
1930 ((shifter.bas_md & 0xff) << 8);
1931 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1932 addr |= (shifter.bas_lo & 0xff);
1933 par->screen_base = phys_to_virt(addr);
1936 static void stste_set_par( struct atafb_par *par )
1938 shifter_tt.st_shiftmode=par->hw.st.mode;
1939 shifter.syncmode=par->hw.st.sync;
1940 /* only set screen_base if really necessary */
1941 if (current_par.screen_base != par->screen_base)
1942 fbhw->set_screen_base(par->screen_base);
1946 static int stste_getcolreg(unsigned regno, unsigned *red,
1947 unsigned *green, unsigned *blue,
1948 unsigned *transp, struct fb_info *info)
1950 unsigned col, t;
1952 if (regno > 15)
1953 return 1;
1954 col = shifter_tt.color_reg[regno];
1955 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1956 t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
1957 t |= t << 4;
1958 *red = t | (t << 8);
1959 t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
1960 t |= t << 4;
1961 *green = t | (t << 8);
1962 t = ((col << 1) & 0xe) | ((col >> 3) & 1);
1963 t |= t << 4;
1964 *blue = t | (t << 8);
1966 else {
1967 t = (col >> 7) & 0xe;
1968 t |= t << 4;
1969 *red = t | (t << 8);
1970 t = (col >> 3) & 0xe;
1971 t |= t << 4;
1972 *green = t | (t << 8);
1973 t = (col << 1) & 0xe;
1974 t |= t << 4;
1975 *blue = t | (t << 8);
1977 *transp = 0;
1978 return 0;
1982 static int stste_setcolreg(unsigned regno, unsigned red,
1983 unsigned green, unsigned blue,
1984 unsigned transp, struct fb_info *info)
1986 if (regno > 15)
1987 return 1;
1988 red >>= 12;
1989 blue >>= 12;
1990 green >>= 12;
1991 if (ATARIHW_PRESENT(EXTD_SHIFTER))
1992 shifter_tt.color_reg[regno] =
1993 (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1994 (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1995 ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1996 else
1997 shifter_tt.color_reg[regno] =
1998 ((red & 0xe) << 7) |
1999 ((green & 0xe) << 3) |
2000 ((blue & 0xe) >> 1);
2001 return 0;
2005 static int stste_detect( void )
2007 { struct atafb_par par;
2009 /* Determine the connected monitor: The DMA sound must be
2010 * disabled before reading the MFP GPIP, because the Sound
2011 * Done Signal and the Monochrome Detect are XORed together!
2013 if (ATARIHW_PRESENT(PCM_8BIT)) {
2014 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
2015 udelay(20); /* wait a while for things to settle down */
2017 mono_moni = (mfp.par_dt_reg & 0x80) == 0;
2019 stste_get_par(&par);
2020 stste_encode_var(&atafb_predefined[0], &par);
2022 if (!ATARIHW_PRESENT(EXTD_SHIFTER))
2023 use_hwscroll = 0;
2024 return 1;
2027 static void stste_set_screen_base(unsigned long s_base)
2029 unsigned long addr;
2030 addr= virt_to_phys(s_base);
2031 /* Setup Screen Memory */
2032 shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2033 shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2034 if (ATARIHW_PRESENT(EXTD_SHIFTER))
2035 shifter.bas_lo=(unsigned char) (addr & 0x0000ff);
2038 #endif /* ATAFB_STE */
2040 /* Switching the screen size should be done during vsync, otherwise
2041 * the margins may get messed up. This is a well known problem of
2042 * the ST's video system.
2044 * Unfortunately there is hardly any way to find the vsync, as the
2045 * vertical blank interrupt is no longer in time on machines with
2046 * overscan type modifications.
2048 * We can, however, use Timer B to safely detect the black shoulder,
2049 * but then we've got to guess an appropriate delay to find the vsync.
2050 * This might not work on every machine.
2052 * martin_rogge @ ki.maus.de, 8th Aug 1995
2055 #define LINE_DELAY (mono_moni ? 30 : 70)
2056 #define SYNC_DELAY (mono_moni ? 1500 : 2000)
2058 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
2059 static void st_ovsc_switch(void)
2061 unsigned long flags;
2062 register unsigned char old, new;
2064 if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
2065 return;
2066 save_flags(flags);
2067 cli();
2069 mfp.tim_ct_b = 0x10;
2070 mfp.active_edge |= 8;
2071 mfp.tim_ct_b = 0;
2072 mfp.tim_dt_b = 0xf0;
2073 mfp.tim_ct_b = 8;
2074 while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2076 new = mfp.tim_dt_b;
2077 do {
2078 udelay(LINE_DELAY);
2079 old = new;
2080 new = mfp.tim_dt_b;
2081 } while (old != new);
2082 mfp.tim_ct_b = 0x10;
2083 udelay(SYNC_DELAY);
2085 if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
2086 acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
2087 if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
2088 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
2089 if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
2090 sound_ym.rd_data_reg_sel = 14;
2091 sound_ym.wd_data = sound_ym.rd_data_reg_sel |
2092 ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
2093 ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
2095 restore_flags(flags);
2098 /* ------------------- External Video ---------------------- */
2100 #ifdef ATAFB_EXT
2102 static int ext_encode_fix( struct fb_fix_screeninfo *fix,
2103 struct atafb_par *par )
2106 strcpy(fix->id,"Unknown Extern");
2107 fix->smem_start=(char *)external_addr;
2108 fix->smem_len=(external_len + PAGE_SIZE -1) & PAGE_MASK;
2109 if (external_depth == 1) {
2110 fix->type = FB_TYPE_PACKED_PIXELS;
2111 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2112 * for "normal" and "inverted", rsp., in the monochrome case */
2113 fix->visual =
2114 (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2115 external_pmode == FB_TYPE_PACKED_PIXELS) ?
2116 FB_VISUAL_MONO10 :
2117 FB_VISUAL_MONO01;
2119 else {
2120 /* Use STATIC if we don't know how to access color registers */
2121 int visual = external_vgaiobase ?
2122 FB_VISUAL_PSEUDOCOLOR :
2123 FB_VISUAL_STATIC_PSEUDOCOLOR;
2124 switch (external_pmode) {
2125 case -1: /* truecolor */
2126 fix->type=FB_TYPE_PACKED_PIXELS;
2127 fix->visual=FB_VISUAL_TRUECOLOR;
2128 break;
2129 case FB_TYPE_PACKED_PIXELS:
2130 fix->type=FB_TYPE_PACKED_PIXELS;
2131 fix->visual=visual;
2132 break;
2133 case FB_TYPE_PLANES:
2134 fix->type=FB_TYPE_PLANES;
2135 fix->visual=visual;
2136 break;
2137 case FB_TYPE_INTERLEAVED_PLANES:
2138 fix->type=FB_TYPE_INTERLEAVED_PLANES;
2139 fix->type_aux=2;
2140 fix->visual=visual;
2141 break;
2144 fix->xpanstep = 0;
2145 fix->ypanstep = 0;
2146 fix->ywrapstep = 0;
2147 fix->line_length = 0;
2148 return 0;
2152 static int ext_decode_var( struct fb_var_screeninfo *var,
2153 struct atafb_par *par )
2155 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2157 if (var->bits_per_pixel > myvar->bits_per_pixel ||
2158 var->xres > myvar->xres ||
2159 var->xres_virtual > myvar->xres_virtual ||
2160 var->yres > myvar->yres ||
2161 var->xoffset > 0 ||
2162 var->yoffset > 0)
2163 return -EINVAL;
2164 return 0;
2168 static int ext_encode_var( struct fb_var_screeninfo *var,
2169 struct atafb_par *par )
2171 memset(var, 0, sizeof(struct fb_var_screeninfo));
2172 var->red.offset=0;
2173 var->red.length=(external_pmode == -1) ? external_depth/3 :
2174 (external_vgaiobase ? external_bitspercol : 0);
2175 var->red.msb_right=0;
2176 var->grayscale=0;
2178 var->pixclock=31041;
2179 var->left_margin=120; /* these are surely incorrect */
2180 var->right_margin=100;
2181 var->upper_margin=8;
2182 var->lower_margin=16;
2183 var->hsync_len=140;
2184 var->vsync_len=30;
2186 var->height=-1;
2187 var->width=-1;
2189 var->sync=0;
2191 var->xres = external_xres;
2192 var->yres = external_yres;
2193 var->xres_virtual = external_xres_virtual;
2194 var->bits_per_pixel = external_depth;
2196 var->blue=var->green=var->red;
2197 var->transp.offset=0;
2198 var->transp.length=0;
2199 var->transp.msb_right=0;
2200 var->yres_virtual=var->yres;
2201 var->xoffset=0;
2202 var->yoffset=0;
2203 var->nonstd=0;
2204 var->activate=0;
2205 var->vmode=FB_VMODE_NONINTERLACED;
2206 return 0;
2210 static void ext_get_par( struct atafb_par *par )
2212 par->screen_base = external_addr;
2215 static void ext_set_par( struct atafb_par *par )
2219 #define OUTB(port,val) \
2220 *((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
2221 #define INB(port) \
2222 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2223 #define DACDelay \
2224 do { \
2225 unsigned char tmp=INB(0x3da); \
2226 tmp=INB(0x3da); \
2227 } while (0)
2229 static int ext_getcolreg( unsigned regno, unsigned *red,
2230 unsigned *green, unsigned *blue,
2231 unsigned *transp, struct fb_info *info )
2233 if (! external_vgaiobase)
2234 return 1;
2236 *red = ext_color[regno].red;
2237 *green = ext_color[regno].green;
2238 *blue = ext_color[regno].blue;
2239 *transp=0;
2240 return 0;
2243 static int ext_setcolreg( unsigned regno, unsigned red,
2244 unsigned green, unsigned blue,
2245 unsigned transp, struct fb_info *info )
2247 { unsigned char colmask = (1 << external_bitspercol) - 1;
2249 if (! external_vgaiobase)
2250 return 1;
2252 ext_color[regno].red = red;
2253 ext_color[regno].green = green;
2254 ext_color[regno].blue = blue;
2256 switch (external_card_type) {
2257 case IS_VGA:
2258 OUTB(0x3c8, regno);
2259 DACDelay;
2260 OUTB(0x3c9, red & colmask);
2261 DACDelay;
2262 OUTB(0x3c9, green & colmask);
2263 DACDelay;
2264 OUTB(0x3c9, blue & colmask);
2265 DACDelay;
2266 return 0;
2268 case IS_MV300:
2269 OUTB((MV300_reg[regno] << 2)+1, red);
2270 OUTB((MV300_reg[regno] << 2)+1, green);
2271 OUTB((MV300_reg[regno] << 2)+1, blue);
2272 return 0;
2274 default:
2275 return 1;
2280 static int ext_detect( void )
2283 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
2284 struct atafb_par dummy_par;
2286 myvar->xres = external_xres;
2287 myvar->xres_virtual = external_xres_virtual;
2288 myvar->yres = external_yres;
2289 myvar->bits_per_pixel = external_depth;
2290 ext_encode_var(myvar, &dummy_par);
2291 return 1;
2294 #endif /* ATAFB_EXT */
2296 /* ------ This is the same for most hardware types -------- */
2298 static void set_screen_base(unsigned long s_base)
2300 unsigned long addr;
2301 addr= virt_to_phys(s_base);
2302 /* Setup Screen Memory */
2303 shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2304 shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2305 shifter.bas_lo=(unsigned char) (addr & 0x0000ff);
2309 static int pan_display( struct fb_var_screeninfo *var,
2310 struct atafb_par *par )
2312 if (!fbhw->set_screen_base ||
2313 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
2314 return -EINVAL;
2315 var->xoffset = up(var->xoffset, 16);
2316 par->screen_base = screen_base +
2317 (var->yoffset * fb_display[currcon].var.xres_virtual + var->xoffset)
2318 * fb_display[currcon].var.bits_per_pixel / 8;
2319 fbhw->set_screen_base (par->screen_base);
2320 return 0;
2324 /* ------------ Interfaces to hardware functions ------------ */
2327 #ifdef ATAFB_TT
2328 static struct fb_hwswitch tt_switch = {
2329 tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
2330 tt_get_par, tt_set_par, tt_getcolreg, tt_setcolreg,
2331 set_screen_base, NULL, pan_display
2333 #endif
2335 #ifdef ATAFB_FALCON
2336 static struct fb_hwswitch falcon_switch = {
2337 falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
2338 falcon_get_par, falcon_set_par, falcon_getcolreg,
2339 falcon_setcolreg, set_screen_base, falcon_blank, falcon_pan_display
2341 #endif
2343 #ifdef ATAFB_STE
2344 static struct fb_hwswitch st_switch = {
2345 stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
2346 stste_get_par, stste_set_par, stste_getcolreg, stste_setcolreg,
2347 stste_set_screen_base, NULL, pan_display
2349 #endif
2351 #ifdef ATAFB_EXT
2352 static struct fb_hwswitch ext_switch = {
2353 ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
2354 ext_get_par, ext_set_par, ext_getcolreg, ext_setcolreg, NULL, NULL, NULL
2356 #endif
2360 static void atafb_get_par( struct atafb_par *par )
2362 if (current_par_valid) {
2363 *par=current_par;
2365 else
2366 fbhw->get_par(par);
2370 static void atafb_set_par( struct atafb_par *par )
2372 fbhw->set_par(par);
2373 current_par=*par;
2374 current_par_valid=1;
2379 /* =========================================================== */
2380 /* ============== Hardware Independent Functions ============= */
2381 /* =========================================================== */
2384 /* used for hardware scrolling */
2386 static int
2387 fb_update_var(int con, struct fb_info *info)
2389 int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual*
2390 fb_display[con].var.bits_per_pixel>>3;
2392 current_par.screen_base=screen_base + off;
2394 if (fbhw->set_screen_base)
2395 fbhw->set_screen_base(current_par.screen_base);
2396 return 0;
2399 static int
2400 do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2402 int err,activate;
2403 struct atafb_par par;
2404 if ((err=fbhw->decode_var(var, &par)))
2405 return err;
2406 activate=var->activate;
2407 if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2408 atafb_set_par(&par);
2409 fbhw->encode_var(var, &par);
2410 var->activate=activate;
2411 return 0;
2414 /* Functions for handling colormap */
2416 static void
2417 do_install_cmap(int con, struct fb_info *info)
2419 if (con != currcon)
2420 return;
2421 if (fb_display[con].cmap.len)
2422 fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
2423 else
2424 fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
2425 1, fbhw->setcolreg, info);
2430 * Open/Release the frame buffer device
2433 static int atafb_open(struct fb_info *info, int user)
2436 * Nothing, only a usage count for the moment
2439 MOD_INC_USE_COUNT;
2440 return(0);
2443 static int atafb_release(struct fb_info *info, int user)
2445 MOD_DEC_USE_COUNT;
2446 return(0);
2450 static int
2451 atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
2453 struct atafb_par par;
2454 if (con == -1)
2455 atafb_get_par(&par);
2456 else
2457 fbhw->decode_var(&fb_display[con].var,&par);
2458 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2459 return fbhw->encode_fix(fix, &par);
2462 static int
2463 atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2465 struct atafb_par par;
2466 if (con == -1) {
2467 atafb_get_par(&par);
2468 fbhw->encode_var(var, &par);
2470 else
2471 *var=fb_display[con].var;
2472 return 0;
2475 static void
2476 atafb_set_disp(int con, struct fb_info *info)
2478 struct fb_fix_screeninfo fix;
2479 struct fb_var_screeninfo var;
2480 struct display *display;
2482 if (con >= 0)
2483 display = &fb_display[con];
2484 else
2485 display = &disp; /* used during initialization */
2487 atafb_get_fix(&fix, con, info);
2488 atafb_get_var(&var, con, info);
2489 if (con == -1)
2490 con=0;
2491 display->screen_base = fix.smem_start;
2492 display->visual = fix.visual;
2493 display->type = fix.type;
2494 display->type_aux = fix.type_aux;
2495 display->ypanstep = fix.ypanstep;
2496 display->ywrapstep = fix.ywrapstep;
2497 display->line_length = fix.line_length;
2498 if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
2499 fix.visual != FB_VISUAL_DIRECTCOLOR)
2500 display->can_soft_blank = 0;
2501 else
2502 display->can_soft_blank = 1;
2503 display->inverse =
2504 (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
2505 switch (fix.type) {
2506 case FB_TYPE_INTERLEAVED_PLANES:
2507 switch (var.bits_per_pixel) {
2508 #ifdef FBCON_HAS_IPLAN2P2
2509 case 2:
2510 display->dispsw = &fbcon_iplan2p2;
2511 break;
2512 #endif
2513 #ifdef FBCON_HAS_IPLAN2P4
2514 case 4:
2515 display->dispsw = &fbcon_iplan2p4;
2516 break;
2517 #endif
2518 #ifdef FBCON_HAS_IPLAN2P8
2519 case 8:
2520 display->dispsw = &fbcon_iplan2p8;
2521 break;
2522 #endif
2524 break;
2525 case FB_TYPE_PACKED_PIXELS:
2526 switch (var.bits_per_pixel) {
2527 #ifdef FBCON_HAS_MFB
2528 case 1:
2529 display->dispsw = &fbcon_mfb;
2530 break;
2531 #endif
2532 #ifdef FBCON_HAS_CFB8
2533 case 8:
2534 display->dispsw = &fbcon_cfb8;
2535 break;
2536 #endif
2537 #ifdef FBCON_HAS_CFB16
2538 case 16:
2539 display->dispsw = &fbcon_cfb16;
2540 display->dispsw_data = fbcon_cfb16_cmap;
2541 break;
2542 #endif
2544 break;
2548 static int
2549 atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2551 int err,oldxres,oldyres,oldbpp,oldxres_virtual,
2552 oldyres_virtual,oldyoffset;
2553 if ((err=do_fb_set_var(var, con==currcon)))
2554 return err;
2555 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2556 oldxres=fb_display[con].var.xres;
2557 oldyres=fb_display[con].var.yres;
2558 oldxres_virtual=fb_display[con].var.xres_virtual;
2559 oldyres_virtual=fb_display[con].var.yres_virtual;
2560 oldbpp=fb_display[con].var.bits_per_pixel;
2561 oldyoffset=fb_display[con].var.yoffset;
2562 fb_display[con].var=*var;
2563 if (oldxres != var->xres || oldyres != var->yres
2564 || oldxres_virtual != var->xres_virtual
2565 || oldyres_virtual != var->yres_virtual
2566 || oldbpp != var->bits_per_pixel
2567 || oldyoffset != var->yoffset) {
2568 atafb_set_disp(con, info);
2569 (*fb_info.changevar)(con);
2570 fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
2571 do_install_cmap(con, info);
2574 var->activate=0;
2575 return 0;
2580 static int
2581 atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
2583 if (con == currcon) /* current console ? */
2584 return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
2585 else
2586 if (fb_display[con].cmap.len) /* non default colormap ? */
2587 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
2588 else
2589 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
2590 cmap, kspc ? 0 : 2);
2591 return 0;
2594 static int
2595 atafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
2597 int err;
2598 if (! fb_display[con].cmap.len) { /* no colormap allocated ? */
2599 if ((err = fb_alloc_cmap(&fb_display[con].cmap,
2600 1 << fb_display[con].var.bits_per_pixel,
2601 0)))
2602 return err;
2604 if (con == currcon) /* current console ? */
2605 return fb_set_cmap(cmap, kspc, fbhw->setcolreg, info);
2606 else
2607 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
2608 return 0;
2611 static int
2612 atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2614 int xoffset = var->xoffset;
2615 int yoffset = var->yoffset;
2616 int err;
2618 if ( xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
2619 || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
2620 return -EINVAL;
2622 if (con == currcon) {
2623 if (fbhw->pan_display) {
2624 if ((err = fbhw->pan_display(var, &current_par)))
2625 return err;
2627 else
2628 return -EINVAL;
2630 fb_display[con].var.xoffset = var->xoffset;
2631 fb_display[con].var.yoffset = var->yoffset;
2632 return 0;
2635 static int
2636 atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2637 unsigned long arg, int con, struct fb_info *info)
2639 switch (cmd) {
2640 #ifdef FBCMD_GET_CURRENTPAR
2641 case FBCMD_GET_CURRENTPAR:
2642 if (copy_to_user((void *)arg, (void *)&current_par,
2643 sizeof(struct atafb_par)))
2644 return -EFAULT;
2645 return 0;
2646 #endif
2647 #ifdef FBCMD_SET_CURRENTPAR
2648 case FBCMD_SET_CURRENTPAR:
2649 if (copy_from_user((void *)&current_par, (void *)arg,
2650 sizeof(struct atafb_par)))
2651 return -EFAULT;
2652 atafb_set_par(&current_par);
2653 return 0;
2654 #endif
2656 return -EINVAL;
2659 static struct fb_ops atafb_ops = {
2660 atafb_open, atafb_release, atafb_get_fix, atafb_get_var,
2661 atafb_set_var, atafb_get_cmap, atafb_set_cmap,
2662 atafb_pan_display, atafb_ioctl
2665 static void
2666 check_default_par( int detected_mode )
2668 char default_name[10];
2669 int i;
2670 struct fb_var_screeninfo var;
2671 unsigned long min_mem;
2673 /* First try the user supplied mode */
2674 if (default_par) {
2675 var=atafb_predefined[default_par-1];
2676 var.activate = FB_ACTIVATE_TEST;
2677 if (do_fb_set_var(&var,1))
2678 default_par=0; /* failed */
2680 /* Next is the autodetected one */
2681 if (! default_par) {
2682 var=atafb_predefined[detected_mode-1]; /* autodetect */
2683 var.activate = FB_ACTIVATE_TEST;
2684 if (!do_fb_set_var(&var,1))
2685 default_par=detected_mode;
2687 /* If that also failed, try some default modes... */
2688 if (! default_par) {
2689 /* try default1, default2... */
2690 for (i=1 ; i < 10 ; i++) {
2691 sprintf(default_name,"default%d",i);
2692 default_par=get_video_mode(default_name);
2693 if (! default_par)
2694 panic("can't set default video mode");
2695 var=atafb_predefined[default_par-1];
2696 var.activate = FB_ACTIVATE_TEST;
2697 if (! do_fb_set_var(&var,1))
2698 break; /* ok */
2701 min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
2702 if (default_mem_req < min_mem)
2703 default_mem_req=min_mem;
2706 static int
2707 atafb_switch(int con, struct fb_info *info)
2709 /* Do we have to save the colormap ? */
2710 if (fb_display[currcon].cmap.len)
2711 fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
2712 info);
2713 do_fb_set_var(&fb_display[con].var,1);
2714 currcon=con;
2715 /* Install new colormap */
2716 do_install_cmap(con, info);
2717 return 0;
2720 /* (un)blank/poweroff
2721 * 0 = unblank
2722 * 1 = blank
2723 * 2 = suspend vsync
2724 * 3 = suspend hsync
2725 * 4 = off
2727 static void
2728 atafb_blank(int blank, struct fb_info *info)
2730 unsigned short black[16];
2731 struct fb_cmap cmap;
2732 if (fbhw->blank && !fbhw->blank(blank))
2733 return;
2734 if (blank) {
2735 memset(black, 0, 16*sizeof(unsigned short));
2736 cmap.red=black;
2737 cmap.green=black;
2738 cmap.blue=black;
2739 cmap.transp=NULL;
2740 cmap.start=0;
2741 cmap.len=16;
2742 fb_set_cmap(&cmap, 1, fbhw->setcolreg, info);
2744 else
2745 do_install_cmap(currcon, info);
2748 __initfunc(void atafb_init(void))
2750 int pad;
2751 int detected_mode;
2752 unsigned long mem_req;
2754 if (!MACH_IS_ATARI)
2755 return;
2757 do {
2758 #ifdef ATAFB_EXT
2759 if (external_addr) {
2760 fbhw = &ext_switch;
2761 break;
2763 #endif
2764 #ifdef ATAFB_TT
2765 if (ATARIHW_PRESENT(TT_SHIFTER)) {
2766 fbhw = &tt_switch;
2767 break;
2769 #endif
2770 #ifdef ATAFB_FALCON
2771 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
2772 fbhw = &falcon_switch;
2773 request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
2774 "framebuffer/modeswitch", falcon_vbl_switcher);
2775 break;
2777 #endif
2778 #ifdef ATAFB_STE
2779 if (ATARIHW_PRESENT(STND_SHIFTER) ||
2780 ATARIHW_PRESENT(EXTD_SHIFTER)) {
2781 fbhw = &st_switch;
2782 break;
2784 fbhw = &st_switch;
2785 printk("Cannot determine video hardware; defaulting to ST(e)\n");
2786 #else /* ATAFB_STE */
2787 /* no default driver included */
2788 /* Nobody will ever see this message :-) */
2789 panic("Cannot initialize video hardware");
2790 #endif
2791 } while (0);
2793 /* Multisync monitor capabilities */
2794 /* Atari-TOS defaults if no boot option present */
2795 if (fb_info.monspecs.hfmin == 0) {
2796 fb_info.monspecs.hfmin = 31000;
2797 fb_info.monspecs.hfmax = 32000;
2798 fb_info.monspecs.vfmin = 58;
2799 fb_info.monspecs.vfmax = 62;
2802 detected_mode = fbhw->detect();
2803 check_default_par(detected_mode);
2804 #ifdef ATAFB_EXT
2805 if (!external_addr) {
2806 #endif /* ATAFB_EXT */
2807 mem_req = default_mem_req + ovsc_offset +
2808 ovsc_addlen;
2809 mem_req = ((mem_req + PAGE_SIZE - 1) & PAGE_MASK) + PAGE_SIZE;
2810 screen_base = (unsigned long)atari_stram_alloc(mem_req, NULL,
2811 "atafb");
2812 if (!screen_base)
2813 panic("Cannot allocate screen memory");
2814 memset((char *) screen_base, 0, mem_req);
2815 pad = ((screen_base + PAGE_SIZE-1) & PAGE_MASK) - screen_base;
2816 screen_base+=pad;
2817 real_screen_base=screen_base+ovsc_offset;
2818 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
2819 st_ovsc_switch();
2820 if (CPU_IS_040_OR_060) {
2821 /* On a '040+, the cache mode of video RAM must be set to
2822 * write-through also for internal video hardware! */
2823 cache_push( virt_to_phys(screen_base), screen_len );
2824 kernel_set_cachemode( screen_base, screen_len,
2825 IOMAP_WRITETHROUGH );
2827 #ifdef ATAFB_EXT
2829 else {
2830 /* Map the video memory (physical address given) to somewhere
2831 * in the kernel address space.
2833 external_addr = ioremap_writethrough(external_addr, external_len);
2834 if (external_vgaiobase)
2835 external_vgaiobase = ioremap(external_vgaiobase, 0x10000 );
2836 screen_base =
2837 real_screen_base = external_addr;
2838 screen_len = external_len & PAGE_MASK;
2839 memset ((char *) screen_base, 0, external_len);
2841 #endif /* ATAFB_EXT */
2843 strcpy(fb_info.modename, "Atari Builtin ");
2844 fb_info.changevar = NULL;
2845 fb_info.node = -1;
2846 fb_info.fbops = &atafb_ops;
2847 fb_info.disp = &disp;
2848 fb_info.switch_con = &atafb_switch;
2849 fb_info.updatevar = &fb_update_var;
2850 fb_info.blank = &atafb_blank;
2851 fb_info.flags = FBINFO_FLAG_DEFAULT;
2852 do_fb_set_var(&atafb_predefined[default_par-1], 1);
2853 strcat(fb_info.modename, fb_var_names[default_par-1][0]);
2855 atafb_get_var(&disp.var, -1, &fb_info);
2856 atafb_set_disp(-1, &fb_info);
2857 do_install_cmap(0, &fb_info);
2859 if (register_framebuffer(&fb_info) < 0)
2860 return;
2862 printk("Determined %dx%d, depth %d\n",
2863 disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
2864 if ((disp.var.xres != disp.var.xres_virtual) ||
2865 (disp.var.yres != disp.var.yres_virtual))
2866 printk(" virtual %dx%d\n",
2867 disp.var.xres_virtual, disp.var.yres_virtual);
2868 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2869 GET_FB_IDX(fb_info.node), fb_info.modename, screen_len>>10);
2871 /* TODO: This driver cannot be unloaded yet */
2872 MOD_INC_USE_COUNT;
2875 /* a strtok which returns empty strings, too */
2877 static char * strtoke(char * s,const char * ct)
2879 char *sbegin, *send;
2880 static char *ssave = NULL;
2882 sbegin = s ? s : ssave;
2883 if (!sbegin) {
2884 return NULL;
2886 if (*sbegin == '\0') {
2887 ssave = NULL;
2888 return NULL;
2890 send = strpbrk(sbegin, ct);
2891 if (send && *send != '\0')
2892 *send++ = '\0';
2893 ssave = send;
2894 return sbegin;
2897 __initfunc(void atafb_setup( char *options, int *ints ))
2899 char *this_opt;
2900 int temp;
2901 char ext_str[80], int_str[100];
2902 char mcap_spec[80];
2903 char user_mode[80];
2905 ext_str[0] =
2906 int_str[0] =
2907 mcap_spec[0] =
2908 user_mode[0] =
2909 fb_info.fontname[0] = '\0';
2911 if (!options || !*options)
2912 return;
2914 for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
2915 if (!*this_opt) continue;
2916 if ((temp=get_video_mode(this_opt)))
2917 default_par=temp;
2918 else if (! strcmp(this_opt, "inverse"))
2919 inverse=1;
2920 else if (!strncmp(this_opt, "font:", 5))
2921 strcpy(fb_info.fontname, this_opt+5);
2922 else if (! strncmp(this_opt, "hwscroll_",9)) {
2923 hwscroll=simple_strtoul(this_opt+9, NULL, 10);
2924 if (hwscroll < 0)
2925 hwscroll = 0;
2926 if (hwscroll > 200)
2927 hwscroll = 200;
2929 #ifdef ATAFB_EXT
2930 else if (!strcmp(this_opt,"mv300")) {
2931 external_bitspercol = 8;
2932 external_card_type = IS_MV300;
2934 else if (!strncmp(this_opt,"external:",9))
2935 strcpy(ext_str, this_opt+9);
2936 #endif
2937 else if (!strncmp(this_opt,"internal:",9))
2938 strcpy(int_str, this_opt+9);
2939 #ifdef ATAFB_FALCON
2940 else if (!strncmp(this_opt, "eclock:", 7)) {
2941 fext.f = simple_strtoul(this_opt+7, NULL, 10);
2942 /* external pixelclock in kHz --> ps */
2943 fext.t = 1000000000/fext.f;
2944 fext.f *= 1000;
2946 else if (!strncmp(this_opt, "monitorcap:", 11))
2947 strcpy(mcap_spec, this_opt+11);
2948 #endif
2949 else if (!strcmp(this_opt, "keep"))
2950 DontCalcRes = 1;
2951 else if (!strncmp(this_opt, "R", 1))
2952 strcpy(user_mode, this_opt+1);
2955 if (*int_str) {
2956 /* Format to config extended internal video hardware like OverScan:
2957 "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2958 Explanation:
2959 <xres>: x-resolution
2960 <yres>: y-resolution
2961 The following are only needed if you have an overscan which
2962 needs a black border:
2963 <xres_max>: max. length of a line in pixels your OverScan hardware would allow
2964 <yres_max>: max. number of lines your OverScan hardware would allow
2965 <offset>: Offset from physical beginning to visible beginning
2966 of screen in bytes
2968 int xres;
2969 char *p;
2971 if (!(p = strtoke(int_str, ";")) ||!*p) goto int_invalid;
2972 xres = simple_strtoul(p, NULL, 10);
2973 if (!(p = strtoke(NULL, ";")) || !*p) goto int_invalid;
2974 sttt_xres=xres;
2975 tt_yres=st_yres=simple_strtoul(p, NULL, 10);
2976 if ((p=strtoke(NULL, ";")) && *p) {
2977 sttt_xres_virtual=simple_strtoul(p, NULL, 10);
2979 if ((p=strtoke(NULL, ";")) && *p) {
2980 sttt_yres_virtual=simple_strtoul(p, NULL, 0);
2982 if ((p=strtoke(NULL, ";")) && *p) {
2983 ovsc_offset=simple_strtoul(p, NULL, 0);
2986 if (ovsc_offset || (sttt_yres_virtual != st_yres))
2987 use_hwscroll=0;
2988 int_invalid:
2992 #ifdef ATAFB_EXT
2993 if (*ext_str) {
2994 int xres, xres_virtual, yres, depth, planes;
2995 unsigned long addr, len;
2996 char *p;
2998 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2999 * <screen mem addr>
3000 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
3001 * [;<xres-virtual>]]]]]
3003 * 09/23/97 Juergen
3004 * <xres_virtual>: hardware's x-resolution (f.e. ProMST)
3006 * Even xres_virtual is available, we neither support panning nor hw-scrolling!
3008 if (!(p = strtoke(ext_str, ";")) ||!*p) goto ext_invalid;
3009 xres_virtual = xres = simple_strtoul(p, NULL, 10);
3010 if (xres <= 0) goto ext_invalid;
3012 if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3013 yres = simple_strtoul(p, NULL, 10);
3014 if (yres <= 0) goto ext_invalid;
3016 if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3017 depth = simple_strtoul(p, NULL, 10);
3018 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
3019 depth != 16 && depth != 24) goto ext_invalid;
3021 if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3022 if (*p == 'i')
3023 planes = FB_TYPE_INTERLEAVED_PLANES;
3024 else if (*p == 'p')
3025 planes = FB_TYPE_PACKED_PIXELS;
3026 else if (*p == 'n')
3027 planes = FB_TYPE_PLANES;
3028 else if (*p == 't')
3029 planes = -1; /* true color */
3030 else
3031 goto ext_invalid;
3034 if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3035 addr = simple_strtoul(p, NULL, 0);
3037 if (!(p = strtoke(NULL, ";")) ||!*p)
3038 len = xres*yres*depth/8;
3039 else
3040 len = simple_strtoul(p, NULL, 0);
3042 if ((p = strtoke(NULL, ";")) && *p) {
3043 external_vgaiobase=simple_strtoul(p, NULL, 0);
3046 if ((p = strtoke(NULL, ";")) && *p) {
3047 external_bitspercol = simple_strtoul(p, NULL, 0);
3048 if (external_bitspercol > 8)
3049 external_bitspercol = 8;
3050 else if (external_bitspercol < 1)
3051 external_bitspercol = 1;
3054 if ((p = strtoke(NULL, ";")) && *p) {
3055 if (!strcmp(p, "vga"))
3056 external_card_type = IS_VGA;
3057 if (!strcmp(p, "mv300"))
3058 external_card_type = IS_MV300;
3061 if ((p = strtoke(NULL, ";")) && *p) {
3062 xres_virtual = simple_strtoul(p, NULL, 10);
3063 if (xres_virtual < xres)
3064 xres_virtual = xres;
3065 if (xres_virtual*yres*depth/8 > len)
3066 len=xres_virtual*yres*depth/8;
3069 external_xres = xres;
3070 external_xres_virtual = xres_virtual;
3071 external_yres = yres;
3072 external_depth = depth;
3073 external_pmode = planes;
3074 external_addr = addr;
3075 external_len = len;
3077 if (external_card_type == IS_MV300)
3078 switch (external_depth) {
3079 case 1:
3080 MV300_reg = MV300_reg_1bit;
3081 break;
3082 case 4:
3083 MV300_reg = MV300_reg_4bit;
3084 break;
3085 case 8:
3086 MV300_reg = MV300_reg_8bit;
3087 break;
3090 ext_invalid:
3093 #endif /* ATAFB_EXT */
3095 #ifdef ATAFB_FALCON
3096 if (*mcap_spec) {
3097 char *p;
3098 int vmin, vmax, hmin, hmax;
3100 /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
3101 * <V*> vertical freq. in Hz
3102 * <H*> horizontal freq. in kHz
3104 if (!(p = strtoke(mcap_spec, ";")) || !*p) goto cap_invalid;
3105 vmin = simple_strtoul(p, NULL, 10);
3106 if (vmin <= 0) goto cap_invalid;
3107 if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
3108 vmax = simple_strtoul(p, NULL, 10);
3109 if (vmax <= 0 || vmax <= vmin) goto cap_invalid;
3110 if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
3111 hmin = 1000 * simple_strtoul(p, NULL, 10);
3112 if (hmin <= 0) goto cap_invalid;
3113 if (!(p = strtoke(NULL, "")) || !*p) goto cap_invalid;
3114 hmax = 1000 * simple_strtoul(p, NULL, 10);
3115 if (hmax <= 0 || hmax <= hmin) goto cap_invalid;
3117 fb_info.monspecs.vfmin = vmin;
3118 fb_info.monspecs.vfmax = vmax;
3119 fb_info.monspecs.hfmin = hmin;
3120 fb_info.monspecs.hfmax = hmax;
3121 cap_invalid:
3124 #endif
3126 if (*user_mode) {
3127 /* Format of user defined video mode is: <xres>;<yres>;<depth>
3129 char *p;
3130 int xres, yres, depth, temp;
3132 if (!(p = strtoke(user_mode, ";")) || !*p) goto user_invalid;
3133 xres = simple_strtoul(p, NULL, 10);
3134 if (!(p = strtoke(NULL, ";")) || !*p) goto user_invalid;
3135 yres = simple_strtoul(p, NULL, 10);
3136 if (!(p = strtoke(NULL, "")) || !*p) goto user_invalid;
3137 depth = simple_strtoul(p, NULL, 10);
3138 if ((temp=get_video_mode("user0"))) {
3139 default_par=temp;
3140 atafb_predefined[default_par-1].xres = xres;
3141 atafb_predefined[default_par-1].yres = yres;
3142 atafb_predefined[default_par-1].bits_per_pixel = depth;
3145 user_invalid:
3150 #ifdef MODULE
3151 int init_module(void)
3153 atafb_init();
3154 return 0;
3157 void cleanup_module(void)
3159 /* Not reached because the usecount will never
3160 be decremented to zero */
3161 unregister_framebuffer(&fb_info);
3162 /* atari_stram_free( screen_base ); */
3163 /* TODO: further clean up ... */
3165 #endif /* MODULE */