2 * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device
4 * Copyright (C) 1994 Martin Schaller & Roman Hodek
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
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
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
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.
50 #include <linux/module.h>
51 #include <linux/kernel.h>
52 #include <linux/errno.h>
53 #include <linux/string.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>
66 #include <asm/atarihw.h>
67 #include <asm/atariints.h>
68 #include <asm/atari_stram.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 {
106 #if defined ATAFB_TT || defined ATAFB_STE
115 /* Here are fields for storing a video mode, as direct
116 * parameters for the hardware.
126 short hht, hbb, hbe, hdb, hde, hss;
127 short vft, vbb, vbe, vdb, vde, vss;
128 /* auxiliary information */
134 /* Nothing needed for external mode */
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;
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
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;
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
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),
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);
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) :-(*/
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
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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);
421 get_video_mode(char *vname)
426 name_list=fb_var_names;
427 for (i = 0 ; i < num_atafb_predefined ; i++) {
429 if (! name || ! *name)
432 if (! strcmp(vname, *name))
442 /* ------------------- TT specific functions ---------------------- */
446 static int tt_encode_fix( struct fb_fix_screeninfo *fix,
447 struct atafb_par *par )
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;
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;
462 if (mode == TT_SHIFTER_TTHIGH)
463 fix->visual=FB_VISUAL_MONO01;
468 fix->line_length = 0;
469 fix->accel = FB_ACCEL_ATARIBLITT;
474 static int tt_decode_var( struct fb_var_screeninfo *var,
475 struct atafb_par *par )
479 int bpp=var->bits_per_pixel;
481 int yres_virtual = var->yres_virtual;
484 if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
486 par->hw.tt.mode=TT_SHIFTER_TTHIGH;
491 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
494 if (xres > sttt_xres/2 || yres > tt_yres)
496 par->hw.tt.mode=TT_SHIFTER_TTLOW;
502 if (xres > sttt_xres || yres > tt_yres)
504 if (xres > sttt_xres/2 || yres > st_yres/2) {
505 par->hw.tt.mode=TT_SHIFTER_TTMID;
511 par->hw.tt.mode=TT_SHIFTER_STLOW;
518 if (xres > sttt_xres || yres > st_yres/2)
520 par->hw.tt.mode=TT_SHIFTER_STMID;
525 else if (var->xres > sttt_xres || var->yres > st_yres) {
529 par->hw.tt.mode=TT_SHIFTER_STHIGH;
535 if (yres_virtual <= 0)
537 else if (yres_virtual < yres)
539 if (var->sync & FB_SYNC_EXT)
544 if (yres_virtual * linelen > screen_len && screen_len)
546 if (yres * linelen > screen_len && screen_len)
548 if (var->yoffset + yres > yres_virtual && yres_virtual)
550 par->yres_virtual = yres_virtual;
551 par->screen_base = screen_base + var->yoffset * linelen;
555 static int tt_encode_var( struct fb_var_screeninfo *var,
556 struct atafb_par *par )
559 memset(var, 0, sizeof(struct fb_var_screeninfo));
562 var->red.msb_right=0;
566 var->left_margin=120; /* these may be incorrect */
567 var->right_margin=100;
569 var->lower_margin=16;
576 if (par->hw.tt.sync & 1)
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;
586 var->bits_per_pixel=4;
588 case TT_SHIFTER_STMID:
590 var->xres_virtual=sttt_xres_virtual;
592 var->bits_per_pixel=2;
594 case TT_SHIFTER_STHIGH:
596 var->xres_virtual=sttt_xres_virtual;
598 var->bits_per_pixel=1;
600 case TT_SHIFTER_TTLOW:
601 var->xres=sttt_xres/2;
602 var->xres_virtual=sttt_xres_virtual/2;
604 var->bits_per_pixel=8;
606 case TT_SHIFTER_TTMID:
608 var->xres_virtual=sttt_xres_virtual;
610 var->bits_per_pixel=4;
612 case TT_SHIFTER_TTHIGH:
614 var->xres=sttt_xres*2;
615 var->xres_virtual=sttt_xres_virtual*2;
617 var->bits_per_pixel=1;
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;
626 var->yres_virtual=var->yres;
627 else if (screen_len) {
628 if (par->yres_virtual)
629 var->yres_virtual = par->yres_virtual;
631 /* yres_virtual==0 means use maximum */
632 var->yres_virtual = screen_len / linelen;
635 var->yres_virtual = 2 * var->yres;
637 var->yres_virtual=var->yres+hwscroll * 16;
641 var->yoffset=(par->screen_base - screen_base)/linelen;
646 var->vmode=FB_VMODE_NONINTERLACED;
651 static void tt_get_par( struct atafb_par *par )
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)
678 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
682 t = tt_palette[regno];
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)
708 tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
710 if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
711 TT_SHIFTER_STHIGH && regno == 254)
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
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;
736 tt_encode_var(&atafb_predefined[0], &par);
741 #endif /* ATAFB_TT */
743 /* ------------------- Falcon specific functions ---------------------- */
747 static int mon_type; /* Falcon connected monitor */
748 static int f030_bus_width; /* Falcon ram bus width (for vid_control) */
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];
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;
790 fix->visual = FB_VISUAL_PSEUDOCOLOR;
794 if (par->hw.falcon.mono) {
795 fix->type = FB_TYPE_PACKED_PIXELS;
797 /* no smooth scrolling with longword aligned video mem */
800 else if (par->hw.falcon.f_shift & 0x100) {
801 fix->type = FB_TYPE_PACKED_PIXELS;
803 /* Is this ok or should it be DIRECTCOLOR? */
804 fix->visual = FB_VISUAL_TRUECOLOR;
807 fix->line_length = 0;
808 fix->accel = FB_ACCEL_ATARIBLITT;
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;
824 int interlace = 0, doubleline = 0;
825 struct pixel_clock *pclock;
826 int plen; /* width of pixel in clock cycles */
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
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)
858 if (mon_type == F_MON_SM && bpp != 1) {
863 par->hw.falcon.f_shift = 0x400;
864 par->hw.falcon.st_shift = 0x200;
868 par->hw.falcon.f_shift = 0x000;
869 par->hw.falcon.st_shift = 0x100;
873 par->hw.falcon.f_shift = 0x000;
874 par->hw.falcon.st_shift = 0x000;
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 */
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)
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 */
903 else if (xres <= 640 && bpp != 16)
907 else if (yres <= 240)
909 else if (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
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;
927 xres = (xres + 31) & ~31;
929 xres = (xres + 15) & ~15;
931 yres = (yres + 15) & ~15;
933 yres = (yres + 7) & ~7;
935 if (xres_virtual < xres)
938 xres_virtual = (xres_virtual + 31) & ~31;
940 xres_virtual = (xres_virtual + 15) & ~15;
942 if (yres_virtual <= 0)
944 else if (yres_virtual < yres)
947 /* backward bug-compatibility */
948 if (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)
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;
969 /* TODO set all margins */
973 if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
975 if (var->pixclock > f32.t * plen)
980 if (var->pixclock == 0) {
981 /* set some minimal margins which center the screen */
984 hsync_len = pclock->hsync / plen;
987 vsync_len = interlace ? 3 : 4;
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) {
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) {
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)
1019 else if ((plen * xres + f32.right+f32.hsync+f32.left) *
1020 fb_info.monspecs.hfmin < f32.f)
1022 else if ((plen * xres + fext.right+fext.hsync+fext.left) *
1023 fb_info.monspecs.hfmin < fext.f
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;
1038 /* Choose largest pixelclock <= wanted clock */
1040 unsigned long pcl = ULONG_MAX;
1042 for (i=1; i <= 4; i *= 2) {
1043 if (f25.t*i >= var->pixclock && f25.t*i < pcl) {
1047 if (f32.t*i >= var->pixclock && f32.t*i < pcl) {
1051 if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) {
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] */
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)
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
1102 /* Set base_offset 128 and video bus width */
1103 par->hw.falcon.vid_control = mon_type | f030_bus_width;
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;
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;
1117 par->hw.falcon.vid_mode |= VMO_DOUBLE;
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) {
1156 hdb_off = (base_off + 16 * plen) + prescale;
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;
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) /
1174 /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1176 par->HDB = gstart - hdb_off/prescale;
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;
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. */
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 */
1203 if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
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;
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 */
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 */
1237 else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
1238 /* Too low -> try again with interlace */
1242 else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
1243 /* Doubleline too low -> clear doubleline and enlarge margins */
1247 (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax;
1250 upper_margin += lines;
1251 lower_margin += lines;
1254 else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
1255 /* Doubleline too high -> enlarge margins */
1258 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1261 upper_margin += lines;
1262 lower_margin += lines;
1265 else if (vfreq > fb_info.monspecs.vfmax && interlace) {
1266 /* Interlace, too high -> enlarge margins */
1269 (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
1272 upper_margin += lines;
1273 lower_margin += lines;
1276 else if (vfreq < fb_info.monspecs.vfmin ||
1277 vfreq > fb_info.monspecs.vfmax)
1281 linelen = xres_virtual * bpp / 8;
1282 if (yres_virtual * linelen > screen_len && screen_len)
1284 if (yres * linelen > screen_len && screen_len)
1286 if (var->yoffset + yres > yres_virtual && yres_virtual)
1288 par->yres_virtual = yres_virtual;
1289 par->screen_base = screen_base + var->yoffset * linelen;
1290 par->hw.falcon.xoffset = 0;
1295 static int falcon_encode_var( struct fb_var_screeninfo *var,
1296 struct atafb_par *par )
1298 /* !!! only for VGA !!! */
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;
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))
1332 if (var->vmode & FB_VMODE_DOUBLE)
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;
1358 var->xres_virtual += 16;
1360 if (var->bits_per_pixel == 16) {
1363 var->red.msb_right=0;
1364 var->green.offset=5;
1365 var->green.length=6;
1366 var->green.msb_right=0;
1369 var->blue.msb_right=0;
1373 var->red.length = hw->ste_mode ? 4 : 6;
1374 var->red.msb_right=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;
1384 if (par->yres_virtual)
1385 var->yres_virtual = par->yres_virtual;
1387 /* yres_virtual==0 means use maximum */
1388 var->yres_virtual = screen_len / linelen;
1392 var->yres_virtual = 2 * var->yres;
1394 var->yres_virtual=var->yres+hwscroll * 16;
1396 var->xoffset=0; /* TODO change this */
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) {
1404 hdb_off = (base_off + 16 * plen) + prescale;
1407 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1409 hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1412 hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
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;
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;
1450 var->yoffset=(par->screen_base - screen_base)/linelen;
1453 var->nonstd=0; /* what is this for? */
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 )
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 )
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 */
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;
1523 static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
1525 struct falcon_hw *hw = &f_new_mode;
1527 if (f_change_mode) {
1530 if (hw->sync & 0x1) {
1531 /* Enable external pixelclock. This code only for ScreenWonder */
1532 *(volatile unsigned short*)0xffff9202 = 0xffbf;
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 */
1555 videl.st_shift = hw->st_shift; /* write enables STE palette */
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.
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) {
1577 videl.xoffset = current_par.hw.falcon.xoffset;
1578 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1584 static int falcon_pan_display( struct fb_var_screeninfo *var,
1585 struct atafb_par *par )
1588 int bpp = fb_display[fb_info.currcon].var.bits_per_pixel;
1591 var->xoffset = up(var->xoffset, 32);
1593 par->hw.falcon.xoffset = var->xoffset & 15;
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);
1609 return -EINVAL; /* shouldn't happen */
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;
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;
1635 static int falcon_setcolreg( unsigned regno, unsigned red,
1636 unsigned green, unsigned blue,
1637 unsigned transp, struct fb_info *info )
1641 f030_col[regno] = (((red & 0xfc00) << 16) |
1642 ((green & 0xfc00) << 8) |
1643 ((blue & 0xfc00) >> 8));
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));
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 */
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;
1698 static int falcon_detect( void )
1700 struct atafb_par par;
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;
1710 fb_info.monspecs.vfmin = 70;
1711 fb_info.monspecs.vfmax = 72;
1712 fb_info.monspecs.hfmin = 35713;
1713 fb_info.monspecs.hfmax = 35715;
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;
1724 /* initialize hsync-len */
1725 f25.hsync = h_syncs[mon_type] / f25.t;
1726 f32.hsync = h_syncs[mon_type] / f32.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 */
1737 #endif /* ATAFB_FALCON */
1739 /* ------------------- ST(E) specific functions ---------------------- */
1743 static int stste_encode_fix( struct fb_fix_screeninfo *fix,
1744 struct atafb_par *par )
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;
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;
1759 fix->visual = FB_VISUAL_MONO10;
1761 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1769 fix->line_length = 0;
1770 fix->accel = FB_ACCEL_ATARIBLITT;
1775 static int stste_decode_var( struct fb_var_screeninfo *var,
1776 struct atafb_par *par )
1780 int bpp=var->bits_per_pixel;
1782 int yres_virtual = var->yres_virtual;
1785 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1787 par->hw.st.mode=ST_HIGH;
1792 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1795 if (xres > sttt_xres/2 || yres > st_yres/2)
1797 par->hw.st.mode=ST_LOW;
1803 if (xres > sttt_xres || yres > st_yres/2)
1805 par->hw.st.mode=ST_MID;
1813 if (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;
1820 par->hw.st.sync=(par->hw.st.sync & ~1);
1822 if (yres_virtual * linelen > screen_len && screen_len)
1824 if (yres * linelen > screen_len && screen_len)
1826 if (var->yoffset + yres > yres_virtual && yres_virtual)
1828 par->yres_virtual = yres_virtual;
1829 par->screen_base=screen_base+ var->yoffset*linelen;
1833 static int stste_encode_var( struct fb_var_screeninfo *var,
1834 struct atafb_par *par )
1837 memset(var, 0, sizeof(struct fb_var_screeninfo));
1839 var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1840 var->red.msb_right=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;
1854 if (!(par->hw.st.sync & 1))
1857 var->sync=FB_SYNC_EXT;
1859 switch (par->hw.st.mode & 3) {
1861 var->xres=sttt_xres/2;
1862 var->yres=st_yres/2;
1863 var->bits_per_pixel=4;
1866 var->xres=sttt_xres;
1867 var->yres=st_yres/2;
1868 var->bits_per_pixel=2;
1871 var->xres=sttt_xres;
1873 var->bits_per_pixel=1;
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);
1885 var->yres_virtual=var->yres;
1886 else if (screen_len) {
1887 if (par->yres_virtual)
1888 var->yres_virtual = par->yres_virtual;
1890 /* yres_virtual==0 means use maximum */
1891 var->yres_virtual = screen_len / linelen;
1895 var->yres_virtual = 2 * var->yres;
1897 var->yres_virtual=var->yres+hwscroll * 16;
1901 var->yoffset=(par->screen_base - screen_base)/linelen;
1906 var->vmode=FB_VMODE_NONINTERLACED;
1911 static void stste_get_par( struct atafb_par *par )
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)
1941 col = shifter_tt.color_reg[regno];
1942 if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1943 t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
1945 *red = t | (t << 8);
1946 t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
1948 *green = t | (t << 8);
1949 t = ((col << 1) & 0xe) | ((col >> 3) & 1);
1951 *blue = t | (t << 8);
1954 t = (col >> 7) & 0xe;
1956 *red = t | (t << 8);
1957 t = (col >> 3) & 0xe;
1959 *green = t | (t << 8);
1960 t = (col << 1) & 0xe;
1962 *blue = t | (t << 8);
1969 static int stste_setcolreg(unsigned regno, unsigned red,
1970 unsigned green, unsigned blue,
1971 unsigned transp, struct fb_info *info)
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);
1984 shifter_tt.color_reg[regno] =
1985 ((red & 0xe) << 7) |
1986 ((green & 0xe) << 3) |
1987 ((blue & 0xe) >> 1);
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))
2014 static void stste_set_screen_base(void *s_base)
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))
2053 local_irq_save(flags);
2055 mfp.tim_ct_b = 0x10;
2056 mfp.active_edge |= 8;
2058 mfp.tim_dt_b = 0xf0;
2060 while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
2067 } while (old != new);
2068 mfp.tim_ct_b = 0x10;
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 ---------------------- */
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 */
2100 (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2101 external_pmode == FB_TYPE_PACKED_PIXELS) ?
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;
2115 case FB_TYPE_PACKED_PIXELS:
2116 fix->type=FB_TYPE_PACKED_PIXELS;
2119 case FB_TYPE_PLANES:
2120 fix->type=FB_TYPE_PLANES;
2123 case FB_TYPE_INTERLEAVED_PLANES:
2124 fix->type=FB_TYPE_INTERLEAVED_PLANES;
2133 fix->line_length = 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 ||
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));
2159 var->red.length=(external_pmode == -1) ? external_depth/3 :
2160 (external_vgaiobase ? external_bitspercol : 0);
2161 var->red.msb_right=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;
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;
2191 var->vmode=FB_VMODE_NONINTERLACED;
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)
2208 (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2211 unsigned char tmp=INB(0x3da); \
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)
2222 *red = ext_color[regno].red;
2223 *green = ext_color[regno].green;
2224 *blue = ext_color[regno].blue;
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)
2238 ext_color[regno].red = red;
2239 ext_color[regno].green = green;
2240 ext_color[regno].blue = blue;
2242 switch (external_card_type) {
2246 OUTB(0x3c9, red & colmask);
2248 OUTB(0x3c9, green & colmask);
2250 OUTB(0x3c9, blue & colmask);
2255 OUTB((MV300_reg[regno] << 2)+1, red);
2256 OUTB((MV300_reg[regno] << 2)+1, green);
2257 OUTB((MV300_reg[regno] << 2)+1, blue);
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);
2280 #endif /* ATAFB_EXT */
2282 /* ------ This is the same for most hardware types -------- */
2284 static void set_screen_base(void *s_base)
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))
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);
2310 /* ------------ Interfaces to hardware functions ------------ */
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
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
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
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
2346 static void atafb_get_par( struct atafb_par *par )
2348 if (current_par_valid) {
2356 static void atafb_set_par( struct atafb_par *par )
2360 current_par_valid=1;
2365 /* =========================================================== */
2366 /* ============== Hardware Independent Functions ============= */
2367 /* =========================================================== */
2370 /* used for hardware scrolling */
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);
2386 do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
2389 struct atafb_par par;
2390 if ((err=fbhw->decode_var(var, &par)))
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;
2401 atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
2403 struct atafb_par par;
2405 atafb_get_par(&par);
2408 if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
2411 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
2412 return fbhw->encode_fix(fix, &par);
2416 atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
2418 struct atafb_par par;
2420 atafb_get_par(&par);
2421 fbhw->encode_var(var, &par);
2424 *var=fb_display[con].var;
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;
2436 display = &fb_display[con];
2438 display = &disp; /* used during initialization */
2440 atafb_get_fix(&fix, con, info);
2441 atafb_get_var(&var, con, info);
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;
2455 display->can_soft_blank = 1;
2457 (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
2459 case FB_TYPE_INTERLEAVED_PLANES:
2460 switch (var.bits_per_pixel) {
2461 #ifdef FBCON_HAS_IPLAN2P2
2463 display->dispsw = &fbcon_iplan2p2;
2466 #ifdef FBCON_HAS_IPLAN2P4
2468 display->dispsw = &fbcon_iplan2p4;
2471 #ifdef FBCON_HAS_IPLAN2P8
2473 display->dispsw = &fbcon_iplan2p8;
2478 case FB_TYPE_PACKED_PIXELS:
2479 switch (var.bits_per_pixel) {
2480 #ifdef FBCON_HAS_MFB
2482 display->dispsw = &fbcon_mfb;
2485 #ifdef FBCON_HAS_CFB8
2487 display->dispsw = &fbcon_cfb8;
2490 #ifdef FBCON_HAS_CFB16
2492 display->dispsw = &fbcon_cfb16;
2493 display->dispsw_data = fbcon_cfb16_cmap;
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)))
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);
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);
2539 if (fb_display[con].cmap.len) /* non default colormap ? */
2540 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
2542 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
2543 cmap, kspc ? 0 : 2);
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;
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)
2558 if (con == info->currcon) {
2559 if (fbhw->pan_display) {
2560 if ((err = fbhw->pan_display(var, ¤t_par)))
2566 fb_display[con].var.xoffset = var->xoffset;
2567 fb_display[con].var.yoffset = var->yoffset;
2572 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2575 #ifdef FBCMD_GET_CURRENTPAR
2576 case FBCMD_GET_CURRENTPAR:
2577 if (copy_to_user((void *)arg, (void *)¤t_par,
2578 sizeof(struct atafb_par)))
2582 #ifdef FBCMD_SET_CURRENTPAR
2583 case FBCMD_SET_CURRENTPAR:
2584 if (copy_from_user((void *)¤t_par, (void *)arg,
2585 sizeof(struct atafb_par)))
2587 atafb_set_par(¤t_par);
2594 /* (un)blank/poweroff
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))
2609 memset(black, 0, 16*sizeof(unsigned short));
2616 fb_set_cmap(&cmap, 1, info);
2619 do_install_cmap(info->currcon, info);
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,
2636 check_default_par( int detected_mode )
2638 char default_name[10];
2640 struct fb_var_screeninfo var;
2641 unsigned long min_mem;
2643 /* First try the user supplied mode */
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);
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))
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;
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,
2683 do_fb_set_var(&fb_display[con].var,1);
2685 /* Install new colormap */
2686 do_install_cmap(con, info);
2690 int __init atafb_init(void)
2694 unsigned long mem_req;
2701 if (external_addr) {
2703 atafb_ops.fb_setcolreg = &ext_setcolreg;
2708 if (ATARIHW_PRESENT(TT_SHIFTER)) {
2710 atafb_ops.fb_setcolreg = &tt_setcolreg;
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);
2724 if (ATARIHW_PRESENT(STND_SHIFTER) ||
2725 ATARIHW_PRESENT(EXTD_SHIFTER)) {
2727 atafb_ops.fb_setcolreg = &stste_setcolreg;
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");
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);
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");
2758 panic("Cannot allocate screen memory");
2759 memset(screen_base, 0, mem_req);
2760 pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
2762 real_screen_base=screen_base+ovsc_offset;
2763 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
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);
2775 /* Map the video memory (physical address given) to somewhere
2776 * in the kernel address space.
2779 ioremap_writethrough((unsigned long)external_addr,
2781 if (external_vgaiobase)
2782 external_vgaiobase =
2783 (unsigned long)ioremap(external_vgaiobase, 0x10000);
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) {
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;
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 */
2835 static void __init atafb_setup_ext(char *spec)
2837 int xres, xres_virtual, yres, depth, planes;
2838 unsigned long addr, len;
2841 /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
2843 * [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
2844 * [;<xres-virtual>]]]]]
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)
2853 xres_virtual = xres = simple_strtoul(p, NULL, 10);
2857 if (!(p = strsep(&spec, ";")) || !*p)
2859 yres = simple_strtoul(p, NULL, 10);
2863 if (!(p = strsep(&spec, ";")) || !*p)
2865 depth = simple_strtoul(p, NULL, 10);
2866 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
2867 depth != 16 && depth != 24)
2870 if (!(p = strsep(&spec, ";")) || !*p)
2873 planes = FB_TYPE_INTERLEAVED_PLANES;
2875 planes = FB_TYPE_PACKED_PIXELS;
2877 planes = FB_TYPE_PLANES;
2879 planes = -1; /* true color */
2884 if (!(p = strsep(&spec, ";")) || !*p)
2886 addr = simple_strtoul(p, NULL, 0);
2888 if (!(p = strsep(&spec, ";")) || !*p)
2889 len = xres*yres*depth/8;
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;
2928 if (external_card_type == IS_MV300)
2929 switch (external_depth) {
2931 MV300_reg = MV300_reg_1bit;
2934 MV300_reg = MV300_reg_4bit;
2937 MV300_reg = MV300_reg_8bit;
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>"
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
2961 if (!(p = strsep(&spec, ";")) || !*p)
2963 xres = simple_strtoul(p, NULL, 10);
2964 if (!(p = strsep(&spec, ";")) || !*p)
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))
2984 static void __init atafb_setup_mcap(char *spec)
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)
2995 vmin = simple_strtoul(p, NULL, 10);
2998 if (!(p = strsep(&spec, ";")) || !*p)
3000 vmax = simple_strtoul(p, NULL, 10);
3001 if (vmax <= 0 || vmax <= vmin)
3003 if (!(p = strsep(&spec, ";")) || !*p)
3005 hmin = 1000 * simple_strtoul(p, NULL, 10);
3008 if (!(p = strsep(&spec, "")) || !*p)
3010 hmax = 1000 * simple_strtoul(p, NULL, 10);
3011 if (hmax <= 0 || hmax <= hmin)
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>
3027 int xres, yres, depth, temp;
3029 if (!(p = strsep(&spec, ";")) || !*p)
3031 xres = simple_strtoul(p, NULL, 10);
3032 if (!(p = strsep(&spec, ";")) || !*p)
3034 yres = simple_strtoul(p, NULL, 10);
3035 if (!(p = strsep(&spec, "")) || !*p)
3037 depth = simple_strtoul(p, NULL, 10);
3038 if ((temp=get_video_mode("user0"))) {
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 )
3051 fb_info.fontname[0] = '\0';
3053 if (!options || !*options)
3056 while ((this_opt = strsep(&options, ",")) != NULL) {
3057 if (!*this_opt) continue;
3058 if ((temp=get_video_mode(this_opt)))
3060 else if (! strcmp(this_opt, "inverse"))
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);
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);
3079 else if (!strncmp(this_opt,"internal:",9))
3080 atafb_setup_int(this_opt+9);
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;
3088 else if (!strncmp(this_opt, "monitorcap:", 11))
3089 atafb_setup_mcap(this_opt+11);
3091 else if (!strcmp(this_opt, "keep"))
3093 else if (!strncmp(this_opt, "R", 1))
3094 atafb_setup_user(this_opt+1);
3100 MODULE_LICENSE("GPL");
3102 int init_module(void)
3104 return atafb_init();