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/sched.h>
 
  53 #include <linux/errno.h>
 
  54 #include <linux/string.h>
 
  56 #include <linux/slab.h>
 
  57 #include <linux/delay.h>
 
  58 #include <linux/init.h>
 
  59 #include <linux/interrupt.h>
 
  61 #include <asm/setup.h>
 
  62 #include <asm/uaccess.h>
 
  63 #include <asm/pgtable.h>
 
  67 #include <asm/atarihw.h>
 
  68 #include <asm/atariints.h>
 
  69 #include <asm/atari_stram.h>
 
  72 #include <asm/atarikb.h>
 
  74 #include <video/fbcon.h>
 
  75 #include <video/fbcon-cfb8.h>
 
  76 #include <video/fbcon-cfb16.h>
 
  77 #include <video/fbcon-iplan2p2.h>
 
  78 #include <video/fbcon-iplan2p4.h>
 
  79 #include <video/fbcon-iplan2p8.h>
 
  80 #include <video/fbcon-mfb.h>
 
  83 #define SWITCH_ACIA 0x01                /* modes for switch on OverScan */
 
  84 #define SWITCH_SND6 0x40
 
  85 #define SWITCH_SND7 0x80
 
  86 #define SWITCH_NONE 0x00
 
  89 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
 
  92 static int default_par=0;       /* default resolution (0=none) */
 
  94 static unsigned long default_mem_req=0;
 
  96 static int hwscroll=-1;
 
  98 static int use_hwscroll = 1;
 
 100 static int sttt_xres=640,st_yres=400,tt_yres=480;
 
 101 static int sttt_xres_virtual=640,sttt_yres_virtual=400;
 
 102 static int ovsc_offset=0, ovsc_addlen=0;
 
 104 static struct atafb_par {
 
 107 #if defined ATAFB_TT || defined ATAFB_STE
 
 116                         /* Here are fields for storing a video mode, as direct
 
 117                          * parameters for the hardware.
 
 127                         short hht, hbb, hbe, hdb, hde, hss;
 
 128                         short vft, vbb, vbe, vdb, vde, vss;
 
 129                         /* auxiliary information */
 
 135                 /* Nothing needed for external mode */
 
 139 /* Don't calculate an own resolution, and thus don't change the one found when
 
 140  * booting (currently used for the Falcon to keep settings for internal video
 
 141  * hardware extensions (e.g. ScreenBlaster)  */
 
 142 static int DontCalcRes = 0; 
 
 145 #define HHT hw.falcon.hht
 
 146 #define HBB hw.falcon.hbb
 
 147 #define HBE hw.falcon.hbe
 
 148 #define HDB hw.falcon.hdb
 
 149 #define HDE hw.falcon.hde
 
 150 #define HSS hw.falcon.hss
 
 151 #define VFT hw.falcon.vft
 
 152 #define VBB hw.falcon.vbb
 
 153 #define VBE hw.falcon.vbe
 
 154 #define VDB hw.falcon.vdb
 
 155 #define VDE hw.falcon.vde
 
 156 #define VSS hw.falcon.vss
 
 157 #define VCO_CLOCK25             0x04
 
 158 #define VCO_CSYPOS              0x10
 
 159 #define VCO_VSYPOS              0x20
 
 160 #define VCO_HSYPOS              0x40
 
 161 #define VCO_SHORTOFFS   0x100
 
 162 #define VMO_DOUBLE              0x01
 
 163 #define VMO_INTER               0x02
 
 164 #define VMO_PREMASK             0x0c
 
 167 static struct fb_info fb_info;
 
 169 static void *screen_base;       /* base address of screen */
 
 170 static void *real_screen_base;  /* (only for Overscan) */
 
 172 static int screen_len;
 
 174 static int current_par_valid=0; 
 
 176 static int mono_moni=0;
 
 178 static struct display disp;
 
 182 /* external video handling */
 
 184 static unsigned                 external_xres;
 
 185 static unsigned                 external_xres_virtual;
 
 186 static unsigned                 external_yres;
 
 187 /* not needed - atafb will never support panning/hardwarescroll with external
 
 188  * static unsigned              external_yres_virtual;  
 
 191 static unsigned                 external_depth;
 
 192 static int                              external_pmode;
 
 193 static void *external_addr = 0;
 
 194 static unsigned long    external_len;
 
 195 static unsigned long    external_vgaiobase = 0;
 
 196 static unsigned int             external_bitspercol = 6;
 
 199 JOE <joe@amber.dinoco.de>: 
 
 200 added card type for external driver, is only needed for
 
 204 enum cardtype { IS_VGA, IS_MV300 };
 
 205 static enum cardtype external_card_type = IS_VGA;
 
 208 The MV300 mixes the color registers. So we need an array of munged
 
 209 indices in order to access the correct reg.
 
 211 static int MV300_reg_1bit[2]={0,1};
 
 212 static int MV300_reg_4bit[16]={
 
 213 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
 
 214 static int MV300_reg_8bit[256]={
 
 215 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 
 
 216 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 
 
 217 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 
 
 218 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 
 
 219 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 
 
 220 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 
 
 221 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 
 
 222 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 
 
 223 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 
 
 224 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 
 
 225 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 
 
 226 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 
 
 227 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 
 
 228 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 
 
 229 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 
 
 230 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; 
 
 232 static int *MV300_reg = MV300_reg_8bit;
 
 235 And on the MV300 it's difficult to read out the hardware palette. So we
 
 236 just keep track of the set colors in our own array here, and use that!
 
 239 static struct { unsigned char red,green,blue,pad; } ext_color[256];
 
 240 #endif /* ATAFB_EXT */
 
 243 static int inverse=0;
 
 245 extern int fontheight_8x8;
 
 246 extern int fontwidth_8x8;
 
 247 extern unsigned char fontdata_8x8[];
 
 249 extern int fontheight_8x16;
 
 250 extern int fontwidth_8x16;
 
 251 extern unsigned char fontdata_8x16[];
 
 253 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
 
 256  * int (*detect)( void )
 
 257  *   This function should detect the current video mode settings and
 
 258  *   store them in atafb_predefined[0] for later reference by the
 
 259  *   user. Return the index+1 of an equivalent predefined mode or 0
 
 260  *   if there is no such.
 
 262  * int (*encode_fix)( struct fb_fix_screeninfo *fix,
 
 263  *                    struct atafb_par *par )
 
 264  *   This function should fill in the 'fix' structure based on the
 
 265  *   values in the 'par' structure.
 
 267  * int (*decode_var)( struct fb_var_screeninfo *var,
 
 268  *                    struct atafb_par *par )
 
 269  *   Get the video params out of 'var'. If a value doesn't fit, round
 
 270  *   it up, if it's too big, return EINVAL.
 
 271  *   Round up in the following order: bits_per_pixel, xres, yres, 
 
 272  *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
 
 273  *   horizontal timing, vertical timing.
 
 275  * int (*encode_var)( struct fb_var_screeninfo *var,
 
 276  *                    struct atafb_par *par );
 
 277  *   Fill the 'var' structure based on the values in 'par' and maybe
 
 278  *   other values read out of the hardware.
 
 280  * void (*get_par)( struct atafb_par *par )
 
 281  *   Fill the hardware's 'par' structure.
 
 283  * void (*set_par)( struct atafb_par *par )
 
 284  *   Set the hardware according to 'par'.
 
 286  * int (*getcolreg)( unsigned regno, unsigned *red,
 
 287  *                   unsigned *green, unsigned *blue,
 
 288  *                   unsigned *transp, struct fb_info *info )
 
 289  *   Read a single color register and split it into
 
 290  *   colors/transparent. Return != 0 for invalid regno.
 
 292  * void (*set_screen_base)(void *s_base)
 
 293  *   Set the base address of the displayed frame buffer. Only called
 
 294  *   if yres_virtual > yres or xres_virtual > xres.
 
 296  * int (*blank)( int blank_mode )
 
 297  *   Blank the screen if blank_mode!=0, else unblank. If blank==NULL then
 
 298  *   the caller blanks by setting the CLUT to all black. Return 0 if blanking
 
 299  *   succeeded, !=0 if un-/blanking failed due to e.g. a video mode which
 
 300  *   doesn't support it. Implements VESA suspend and powerdown modes on
 
 301  *   hardware that supports disabling hsync/vsync:
 
 302  *       blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown.
 
 305 static struct fb_hwswitch {
 
 306         int  (*detect)( void );
 
 307         int  (*encode_fix)( struct fb_fix_screeninfo *fix,
 
 308                                                 struct atafb_par *par );
 
 309         int  (*decode_var)( struct fb_var_screeninfo *var,
 
 310                                                 struct atafb_par *par );
 
 311         int  (*encode_var)( struct fb_var_screeninfo *var,
 
 312                                                 struct atafb_par *par );
 
 313         void (*get_par)( struct atafb_par *par );
 
 314         void (*set_par)( struct atafb_par *par );
 
 315         int  (*getcolreg)( unsigned regno, unsigned *red,
 
 316                                            unsigned *green, unsigned *blue,
 
 317                                            unsigned *transp, struct fb_info *info );
 
 318         void (*set_screen_base)(void *s_base);
 
 319         int  (*blank)( int blank_mode );
 
 320         int  (*pan_display)( struct fb_var_screeninfo *var,
 
 321                                                  struct atafb_par *par);
 
 324 static char *autodetect_names[] = {"autodetect", NULL};
 
 325 static char *stlow_names[] = {"stlow", NULL};
 
 326 static char *stmid_names[] = {"stmid", "default5", NULL};
 
 327 static char *sthigh_names[] = {"sthigh", "default4", NULL};
 
 328 static char *ttlow_names[] = {"ttlow", NULL};
 
 329 static char *ttmid_names[]= {"ttmid", "default1", NULL};
 
 330 static char *tthigh_names[]= {"tthigh", "default2", NULL};
 
 331 static char *vga2_names[] = {"vga2", NULL};
 
 332 static char *vga4_names[] = {"vga4", NULL};
 
 333 static char *vga16_names[] = {"vga16", "default3", NULL};
 
 334 static char *vga256_names[] = {"vga256", NULL};
 
 335 static char *falh2_names[] = {"falh2", NULL};
 
 336 static char *falh16_names[] = {"falh16", NULL};
 
 338 static char **fb_var_names[] = {
 
 339         /* Writing the name arrays directly in this array (via "(char *[]){...}")
 
 340          * crashes gcc 2.5.8 (sigsegv) if the inner array
 
 341          * contains more than two items. I've also seen that all elements
 
 342          * were identical to the last (my cross-gcc) :-(*/
 
 357         /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
 
 360 static struct fb_var_screeninfo atafb_predefined[] = {
 
 362          * yres_virtual==0 means use hw-scrolling if possible, else yres
 
 365           0, 0, 0, 0, 0, 0, 0, 0,               /* xres-grayscale */
 
 366           {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},   /* red green blue tran*/
 
 367           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 369           320, 200, 320, 0, 0, 0, 4, 0,
 
 370           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 371           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 373           640, 200, 640, 0, 0, 0, 2, 0,
 
 374           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 375           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 377           640, 400, 640, 0, 0, 0, 1, 0,
 
 378           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 379           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 381           320, 480, 320, 0, 0, 0, 8, 0,
 
 382           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 383           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 385           640, 480, 640, 0, 0, 0, 4, 0,
 
 386           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 387           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 389           1280, 960, 1280, 0, 0, 0, 1, 0,
 
 390           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 391           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 393           640, 480, 640, 0, 0, 0, 1, 0,
 
 394           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 395           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 397           640, 480, 640, 0, 0, 0, 2, 0,
 
 398           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},
 
 399           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 401           640, 480, 640, 0, 0, 0, 4, 0,
 
 402           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 403           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 405           640, 480, 640, 0, 0, 0, 8, 0,
 
 406           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 407           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 409           896, 608, 896, 0, 0, 0, 1, 0,
 
 410           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 411           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 413           896, 608, 896, 0, 0, 0, 4, 0,
 
 414           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 
 415           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 
 418 static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined);
 
 422 get_video_mode(char *vname)
 
 427     name_list=fb_var_names;
 
 428     for (i = 0 ; i < num_atafb_predefined ; i++) {
 
 430         if (! name || ! *name)
 
 433             if (! strcmp(vname, *name))
 
 443 /* ------------------- TT specific functions ---------------------- */
 
 447 static int tt_encode_fix( struct fb_fix_screeninfo *fix,
 
 448                                                   struct atafb_par *par )
 
 453         strcpy(fix->id,"Atari Builtin");
 
 454         fix->smem_start = (unsigned long)real_screen_base;
 
 455         fix->smem_len = screen_len;
 
 456         fix->type=FB_TYPE_INTERLEAVED_PLANES;
 
 458         fix->visual=FB_VISUAL_PSEUDOCOLOR;
 
 459         mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
 
 460         if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
 
 461                 fix->type=FB_TYPE_PACKED_PIXELS;
 
 463                 if (mode == TT_SHIFTER_TTHIGH)
 
 464                         fix->visual=FB_VISUAL_MONO01;
 
 469         fix->line_length = 0;
 
 470         fix->accel = FB_ACCEL_ATARIBLITT;
 
 475 static int tt_decode_var( struct fb_var_screeninfo *var,
 
 476                                                   struct atafb_par *par )
 
 480         int bpp=var->bits_per_pixel;
 
 482         int yres_virtual = var->yres_virtual;
 
 485                 if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
 
 487                 par->hw.tt.mode=TT_SHIFTER_TTHIGH;
 
 492                 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
 
 495                         if (xres > sttt_xres/2 || yres > tt_yres)
 
 497                         par->hw.tt.mode=TT_SHIFTER_TTLOW;
 
 503                         if (xres > sttt_xres || yres > tt_yres)
 
 505                         if (xres > sttt_xres/2 || yres > st_yres/2) {
 
 506                                 par->hw.tt.mode=TT_SHIFTER_TTMID;
 
 512                                 par->hw.tt.mode=TT_SHIFTER_STLOW;
 
 519                         if (xres > sttt_xres || yres > st_yres/2)
 
 521                         par->hw.tt.mode=TT_SHIFTER_STMID;
 
 526                 else if (var->xres > sttt_xres || var->yres > st_yres) {
 
 530                         par->hw.tt.mode=TT_SHIFTER_STHIGH;
 
 536         if (yres_virtual <= 0)
 
 538         else if (yres_virtual < yres)
 
 540         if (var->sync & FB_SYNC_EXT)
 
 545         if (yres_virtual * linelen > screen_len && screen_len)
 
 547         if (yres * linelen > screen_len && screen_len)
 
 549         if (var->yoffset + yres > yres_virtual && yres_virtual)
 
 551         par->yres_virtual = yres_virtual;
 
 552         par->screen_base = screen_base + var->yoffset * linelen;
 
 556 static int tt_encode_var( struct fb_var_screeninfo *var,
 
 557                                                   struct atafb_par *par )
 
 560         memset(var, 0, sizeof(struct fb_var_screeninfo));
 
 563         var->red.msb_right=0;
 
 567         var->left_margin=120;           /* these may be incorrect       */
 
 568         var->right_margin=100;
 
 570         var->lower_margin=16;
 
 577         if (par->hw.tt.sync & 1)
 
 580                 var->sync=FB_SYNC_EXT;
 
 582         switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
 
 583         case TT_SHIFTER_STLOW:
 
 584                 var->xres=sttt_xres/2;
 
 585                 var->xres_virtual=sttt_xres_virtual/2;
 
 587                 var->bits_per_pixel=4;
 
 589         case TT_SHIFTER_STMID:
 
 591                 var->xres_virtual=sttt_xres_virtual;
 
 593                 var->bits_per_pixel=2;
 
 595         case TT_SHIFTER_STHIGH:
 
 597                 var->xres_virtual=sttt_xres_virtual;
 
 599                 var->bits_per_pixel=1;
 
 601         case TT_SHIFTER_TTLOW:
 
 602                 var->xres=sttt_xres/2;
 
 603                 var->xres_virtual=sttt_xres_virtual/2;
 
 605                 var->bits_per_pixel=8;
 
 607         case TT_SHIFTER_TTMID:
 
 609                 var->xres_virtual=sttt_xres_virtual;
 
 611                 var->bits_per_pixel=4;
 
 613         case TT_SHIFTER_TTHIGH:
 
 615                 var->xres=sttt_xres*2;
 
 616                 var->xres_virtual=sttt_xres_virtual*2;
 
 618                 var->bits_per_pixel=1;
 
 621         var->blue=var->green=var->red;
 
 622         var->transp.offset=0;
 
 623         var->transp.length=0;
 
 624         var->transp.msb_right=0;
 
 625         linelen=var->xres_virtual * var->bits_per_pixel / 8;
 
 627                 var->yres_virtual=var->yres;
 
 628         else if (screen_len) {
 
 629                 if (par->yres_virtual)
 
 630                         var->yres_virtual = par->yres_virtual;
 
 632                         /* yres_virtual==0 means use maximum */
 
 633                         var->yres_virtual = screen_len / linelen;
 
 636                         var->yres_virtual = 2 * var->yres;
 
 638                         var->yres_virtual=var->yres+hwscroll * 16;
 
 642                 var->yoffset=(par->screen_base - screen_base)/linelen;
 
 647         var->vmode=FB_VMODE_NONINTERLACED;
 
 652 static void tt_get_par( struct atafb_par *par )
 
 655         par->hw.tt.mode=shifter_tt.tt_shiftmode;
 
 656         par->hw.tt.sync=shifter.syncmode;
 
 657         addr = ((shifter.bas_hi & 0xff) << 16) |
 
 658                ((shifter.bas_md & 0xff) << 8)  |
 
 659                ((shifter.bas_lo & 0xff));
 
 660         par->screen_base = phys_to_virt(addr);
 
 663 static void tt_set_par( struct atafb_par *par )
 
 665         shifter_tt.tt_shiftmode=par->hw.tt.mode;
 
 666         shifter.syncmode=par->hw.tt.sync;
 
 667         /* only set screen_base if really necessary */
 
 668         if (current_par.screen_base != par->screen_base)
 
 669                 fbhw->set_screen_base(par->screen_base);
 
 673 static int tt_getcolreg(unsigned regno, unsigned *red,
 
 674                         unsigned *green, unsigned *blue,
 
 675                         unsigned *transp, struct fb_info *info)
 
 679         if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
 
 683         t = tt_palette[regno];
 
 701 static int tt_setcolreg(unsigned regno, unsigned red,
 
 702                         unsigned green, unsigned blue,
 
 703                         unsigned transp, struct fb_info *info)
 
 705         if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
 
 709         tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
 
 711         if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
 
 712                 TT_SHIFTER_STHIGH && regno == 254)
 
 718 static int tt_detect( void )
 
 720 {       struct atafb_par par;
 
 722         /* Determine the connected monitor: The DMA sound must be
 
 723          * disabled before reading the MFP GPIP, because the Sound
 
 724          * Done Signal and the Monochrome Detect are XORed together!
 
 726          * Even on a TT, we should look if there is a DMA sound. It was
 
 727          * announced that the Eagle is TT compatible, but only the PCM is
 
 730         if (ATARIHW_PRESENT(PCM_8BIT)) { 
 
 731                 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
 
 732                 udelay(20);     /* wait a while for things to settle down */
 
 734         mono_moni = (mfp.par_dt_reg & 0x80) == 0;
 
 737         tt_encode_var(&atafb_predefined[0], &par);
 
 742 #endif /* ATAFB_TT */
 
 744 /* ------------------- Falcon specific functions ---------------------- */
 
 748 static int mon_type;            /* Falcon connected monitor */
 
 749 static int f030_bus_width;      /* Falcon ram bus width (for vid_control) */
 
 755 static struct pixel_clock {
 
 756         unsigned long f;        /* f/[Hz] */
 
 757         unsigned long t;        /* t/[ps] (=1/f) */
 
 758         int right, hsync, left; /* standard timing in clock cycles, not pixel */
 
 759                 /* hsync initialized in falcon_detect() */
 
 760         int sync_mask;          /* or-mask for hw.falcon.sync to set this clock */
 
 761         int control_mask;       /* ditto, for hw.falcon.vid_control */
 
 763 f25  = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25},
 
 764 f32  = {32000000, 31250, 18, 0, 42, 0x0, 0},
 
 765 fext = {       0,     0, 18, 0, 42, 0x1, 0};
 
 767 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
 
 768 static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
 
 770 /* Default hsync timing [mon_type] in picoseconds */
 
 771 static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
 
 773 #ifdef FBCON_HAS_CFB16
 
 774 static u16 fbcon_cfb16_cmap[16];
 
 777 static inline int hxx_prescale(struct falcon_hw *hw)
 
 779         return hw->ste_mode ? 16 :
 
 780                    vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
 
 783 static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
 
 784                                                           struct atafb_par *par )
 
 786         strcpy(fix->id, "Atari Builtin");
 
 787         fix->smem_start = (unsigned long)real_screen_base;
 
 788         fix->smem_len = screen_len;
 
 789         fix->type = FB_TYPE_INTERLEAVED_PLANES;
 
 791         fix->visual = FB_VISUAL_PSEUDOCOLOR;
 
 795         if (par->hw.falcon.mono) {
 
 796                 fix->type = FB_TYPE_PACKED_PIXELS;
 
 798                 /* no smooth scrolling with longword aligned video mem */
 
 801         else if (par->hw.falcon.f_shift & 0x100) {
 
 802                 fix->type = FB_TYPE_PACKED_PIXELS;
 
 804                 /* Is this ok or should it be DIRECTCOLOR? */
 
 805                 fix->visual = FB_VISUAL_TRUECOLOR;
 
 808         fix->line_length = 0;
 
 809         fix->accel = FB_ACCEL_ATARIBLITT;
 
 814 static int falcon_decode_var( struct fb_var_screeninfo *var,
 
 815                                                           struct atafb_par *par )
 
 817         int bpp = var->bits_per_pixel;
 
 818         int xres = var->xres;
 
 819         int yres = var->yres;
 
 820         int xres_virtual = var->xres_virtual;
 
 821         int yres_virtual = var->yres_virtual;
 
 822         int left_margin, right_margin, hsync_len;
 
 823         int upper_margin, lower_margin, vsync_len;
 
 825         int interlace = 0, doubleline = 0;
 
 826         struct pixel_clock *pclock;
 
 827         int plen; /* width of pixel in clock cycles */
 
 834         Get the video params out of 'var'. If a value doesn't fit, round
 
 835         it up, if it's too big, return EINVAL.
 
 836         Round up in the following order: bits_per_pixel, xres, yres, 
 
 837         xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
 
 838         horizontal timing, vertical timing.
 
 840         There is a maximum of screen resolution determined by pixelclock
 
 841         and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
 
 842         In interlace mode this is     "     *    "     *vfmin <= pixelclock.
 
 843         Additional constraints: hfreq.
 
 844         Frequency range for multisync monitors is given via command line.
 
 845         For TV and SM124 both frequencies are fixed.
 
 847         X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
 
 848         Y % 16 == 0 to fit 8x16 font
 
 851         Currently interlace and doubleline mode in var are ignored. 
 
 852         On SM124 and TV only the standard resolutions can be used.
 
 855         /* Reject uninitialized mode */
 
 856         if (!xres || !yres || !bpp)
 
 859         if (mon_type == F_MON_SM && bpp != 1) {
 
 864                 par->hw.falcon.f_shift = 0x400;
 
 865                 par->hw.falcon.st_shift = 0x200;
 
 869                 par->hw.falcon.f_shift = 0x000;
 
 870                 par->hw.falcon.st_shift = 0x100;
 
 874                 par->hw.falcon.f_shift = 0x000;
 
 875                 par->hw.falcon.st_shift = 0x000;
 
 879                 par->hw.falcon.f_shift = 0x010;
 
 881         else if (bpp <= 16) {
 
 882                 bpp = 16; /* packed pixel mode */
 
 883                 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
 
 887         par->hw.falcon.bpp = bpp;
 
 889         if (mon_type == F_MON_SM || DontCalcRes) {
 
 890                 /* Skip all calculations. VGA/TV/SC1224 only supported. */
 
 891                 struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 
 893                 if (bpp > myvar->bits_per_pixel ||
 
 894                         var->xres > myvar->xres ||
 
 895                         var->yres > myvar->yres)
 
 897                 fbhw->get_par(par);     /* Current par will be new par */
 
 898                 goto set_screen_base;   /* Don't forget this */
 
 901         /* Only some fixed resolutions < 640x400 */
 
 904         else if (xres <= 640 && bpp != 16)
 
 908         else if (yres <= 240)
 
 910         else if (yres <= 400)
 
 913         /* 2 planes must use STE compatibility mode */
 
 914         par->hw.falcon.ste_mode = bpp==2;
 
 915         par->hw.falcon.mono = bpp==1;
 
 917         /* Total and visible scanline length must be a multiple of one longword,
 
 918          * this and the console fontwidth yields the alignment for xres and
 
 920          * TODO: this way "odd" fontheights are not supported
 
 922          * Special case in STE mode: blank and graphic positions don't align,
 
 923          * avoid trash at right margin
 
 925         if (par->hw.falcon.ste_mode)
 
 926                 xres = (xres + 63) & ~63;
 
 928                 xres = (xres + 31) & ~31;
 
 930                 xres = (xres + 15) & ~15;
 
 932                 yres = (yres + 15) & ~15;
 
 934                 yres = (yres + 7) & ~7;
 
 936         if (xres_virtual < xres)
 
 939                 xres_virtual = (xres_virtual + 31) & ~31;
 
 941                 xres_virtual = (xres_virtual + 15) & ~15;
 
 943         if (yres_virtual <= 0)
 
 945         else if (yres_virtual < yres)
 
 948         /* backward bug-compatibility */
 
 949         if (var->pixclock > 1)
 
 952         par->hw.falcon.line_width = bpp * xres / 16;
 
 953         par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
 
 955         /* single or double pixel width */
 
 956         xstretch = (xres < 640) ? 2 : 1;
 
 958 #if 0 /* SM124 supports only 640x400, this is rejected above */
 
 959         if (mon_type == F_MON_SM) {
 
 960                 if (xres != 640 && yres != 400)
 
 964                 /* SM124-mode is special */
 
 965                 par->hw.falcon.ste_mode = 1;
 
 966                 par->hw.falcon.f_shift = 0x000;
 
 967                 par->hw.falcon.st_shift = 0x200;
 
 968                 left_margin = hsync_len = 128 / plen;
 
 970                 /* TODO set all margins */
 
 974         if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
 
 976                 if (var->pixclock > f32.t * plen)
 
 981                 if (var->pixclock == 0) {
 
 982                         /* set some minimal margins which center the screen */
 
 985                         hsync_len = pclock->hsync / plen;
 
 988                         vsync_len = interlace ? 3 : 4;
 
 990                         left_margin = var->left_margin;
 
 991                         right_margin = var->right_margin;
 
 992                         hsync_len = var->hsync_len;
 
 993                         upper_margin = var->upper_margin;
 
 994                         lower_margin = var->lower_margin;
 
 995                         vsync_len = var->vsync_len;
 
 996                         if (var->vmode & FB_VMODE_INTERLACED) {
 
 997                                 upper_margin = (upper_margin + 1) / 2;
 
 998                                 lower_margin = (lower_margin + 1) / 2;
 
 999                                 vsync_len = (vsync_len + 1) / 2;
 
1000                         } else if (var->vmode & FB_VMODE_DOUBLE) {
 
1010                         xstretch = 2; /* Double pixel width only for hicolor */
 
1011                 /* Default values are used for vert./hor. timing if no pixelclock given. */
 
1012                 if (var->pixclock == 0) {
 
1015                         /* Choose master pixelclock depending on hor. timing */
 
1016                         plen = 1 * xstretch;
 
1017                         if ((plen * xres + f25.right+f25.hsync+f25.left) *
 
1018                             fb_info.monspecs.hfmin < f25.f)
 
1020                         else if ((plen * xres + f32.right+f32.hsync+f32.left) * 
 
1021                             fb_info.monspecs.hfmin < f32.f)
 
1023                         else if ((plen * xres + fext.right+fext.hsync+fext.left) * 
 
1024                             fb_info.monspecs.hfmin < fext.f
 
1030                         left_margin = pclock->left / plen;
 
1031                         right_margin = pclock->right / plen;
 
1032                         hsync_len = pclock->hsync / plen;
 
1033                         linesize = left_margin + xres + right_margin + hsync_len;
 
1039                         /* Choose largest pixelclock <= wanted clock */
 
1041                         unsigned long pcl = ULONG_MAX;
 
1043                         for (i=1; i <= 4; i *= 2) {
 
1044                                 if (f25.t*i >= var->pixclock && f25.t*i < pcl) {
 
1048                                 if (f32.t*i >= var->pixclock && f32.t*i < pcl) {
 
1052                                 if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) {
 
1059                         plen = pcl / pclock->t;
 
1061                         left_margin = var->left_margin;
 
1062                         right_margin = var->right_margin;
 
1063                         hsync_len = var->hsync_len;
 
1064                         upper_margin = var->upper_margin;
 
1065                         lower_margin = var->lower_margin;
 
1066                         vsync_len = var->vsync_len;
 
1067                         /* Internal unit is [single lines per (half-)frame] */
 
1068                         if (var->vmode & FB_VMODE_INTERLACED) {
 
1069                                 /* # lines in half frame */
 
1070                                 /* External unit is [lines per full frame] */
 
1071                                 upper_margin = (upper_margin + 1) / 2;
 
1072                                 lower_margin = (lower_margin + 1) / 2;
 
1073                                 vsync_len = (vsync_len + 1) / 2;
 
1075                         else if (var->vmode & FB_VMODE_DOUBLE) {
 
1076                                 /* External unit is [double lines per frame] */
 
1082                 if (pclock == &fext)
 
1083                         longoffset = 1; /* VIDEL doesn't synchronize on short offset */
 
1085         /* Is video bus bandwidth (32MB/s) too low for this resolution? */
 
1086         /* this is definitely wrong if bus clock != 32MHz */
 
1087         if (pclock->f / plen / 8 * bpp > 32000000L)
 
1093         /* include sync lengths in right/lower margin for all calculations */
 
1094         right_margin += hsync_len;
 
1095         lower_margin += vsync_len;
 
1097         /* ! In all calculations of margins we use # of lines in half frame
 
1098          * (which is a full frame in non-interlace mode), so we can switch
 
1099          * between interlace and non-interlace without messing around
 
1103         /* Set base_offset 128 and video bus width */
 
1104         par->hw.falcon.vid_control = mon_type | f030_bus_width;
 
1106                 par->hw.falcon.vid_control |= VCO_SHORTOFFS;    /* base_offset 64 */
 
1107         if (var->sync & FB_SYNC_HOR_HIGH_ACT)
 
1108                 par->hw.falcon.vid_control |= VCO_HSYPOS;
 
1109         if (var->sync & FB_SYNC_VERT_HIGH_ACT)
 
1110                 par->hw.falcon.vid_control |= VCO_VSYPOS;
 
1112         par->hw.falcon.vid_control |= pclock->control_mask;
 
1113         /* External or internal clock */
 
1114         par->hw.falcon.sync = pclock->sync_mask | 0x2;
 
1115         /* Pixellength and prescale */
 
1116         par->hw.falcon.vid_mode = (2/plen) << 2;
 
1118                 par->hw.falcon.vid_mode |= VMO_DOUBLE;
 
1120                 par->hw.falcon.vid_mode |= VMO_INTER;
 
1122         /*********************
 
1123         Horizontal timing: unit = [master clock cycles]
 
1124         unit of hxx-registers: [master clock cycles * prescale]
 
1125         Hxx-registers are 9 bit wide
 
1127         1 line = ((hht + 2) * 2 * prescale) clock cycles
 
1129         graphic output = hdb & 0x200 ?
 
1130                ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
 
1131                ( hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
 
1132         (this must be a multiple of plen*128/bpp, on VGA pixels
 
1133          to the right may be cut off with a bigger right margin)
 
1135         start of graphics relative to start of 1st halfline = hdb & 0x200 ?
 
1136                (hdb - hht - 2) * prescale + hdboff :
 
1137                hdb * prescale + hdboff
 
1139         end of graphics relative to start of 1st halfline =
 
1140                (hde + hht + 2) * prescale + hdeoff
 
1141         *********************/
 
1142         /* Calculate VIDEL registers */
 
1144         int hdb_off, hde_off, base_off;
 
1145         int gstart, gend1, gend2, align;
 
1147         prescale = hxx_prescale(&par->hw.falcon);
 
1148         base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
 
1150         /* Offsets depend on video mode */
 
1151         /* Offsets are in clock cycles, divide by prescale to
 
1152          * calculate hd[be]-registers
 
1154         if (par->hw.falcon.f_shift & 0x100) {
 
1157                 hdb_off = (base_off + 16 * plen) + prescale;
 
1161                 hde_off = ((128 / bpp + 2) * plen);
 
1162                 if (par->hw.falcon.ste_mode)
 
1163                         hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
 
1165                         hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
 
1168         gstart = (prescale/2 + plen * left_margin) / prescale;
 
1169         /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
 
1170         gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
 
1171         /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
 
1172         gend2 = gstart + xres * plen / prescale;
 
1173         par->HHT = plen * (left_margin + xres + right_margin) /
 
1175 /*      par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
 
1177         par->HDB = gstart - hdb_off/prescale;
 
1179         if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
 
1180         par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
 
1181         par->HBB = gend2 - par->HHT - 2;
 
1183         /* One more Videl constraint: data fetch of two lines must not overlap */
 
1184         if ((par->HDB & 0x200)  &&  (par->HDB & ~0x200) - par->HDE <= 5) {
 
1185                 /* if this happens increase margins, decrease hfreq. */
 
1188         if (hde_off % prescale)
 
1189                 par->HBB++;             /* compensate for non matching hde and hbb */
 
1190         par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
 
1191         if (par->HSS < par->HBB)
 
1192                 par->HSS = par->HBB;
 
1195         /*  check hor. frequency */
 
1196         hfreq = pclock->f / ((par->HHT+2)*prescale*2);
 
1197         if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) {
 
1198                 /* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
 
1199                 /* Too high -> enlarge margin */
 
1204         if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin)
 
1208         /* All Vxx must be odd in non-interlace, since frame starts in the middle
 
1209          * of the first displayed line!
 
1210          * One frame consists of VFT+1 half lines. VFT+1 must be even in
 
1211          * non-interlace, odd in interlace mode for synchronisation.
 
1212          * Vxx-registers are 11 bit wide
 
1214         par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
 
1215         par->VDB = par->VBE;
 
1217         if (!interlace) par->VDE <<= 1;
 
1218         if (doubleline) par->VDE <<= 1;  /* VDE now half lines per (half-)frame */
 
1219         par->VDE += par->VDB;
 
1220         par->VBB = par->VDE;
 
1221         par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
 
1222         par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
 
1223         /* vbb,vss,vft must be even in interlace mode */
 
1230         /* V-frequency check, hope I didn't create any loop here. */
 
1231         /* Interlace and doubleline are mutually exclusive. */
 
1232         vfreq = (hfreq * 2) / (par->VFT + 1);
 
1233         if      (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) {
 
1234                 /* Too high -> try again with doubleline */
 
1238         else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) {
 
1239                 /* Too low -> try again with interlace */
 
1243         else if (vfreq < fb_info.monspecs.vfmin && doubleline) {
 
1244                 /* Doubleline too low -> clear doubleline and enlarge margins */
 
1248                      (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax;
 
1251                 upper_margin += lines;
 
1252                 lower_margin += lines;
 
1255         else if (vfreq > fb_info.monspecs.vfmax && doubleline) {
 
1256                 /* Doubleline too high -> enlarge margins */
 
1259                      (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
 
1262                 upper_margin += lines;
 
1263                 lower_margin += lines;
 
1266         else if (vfreq > fb_info.monspecs.vfmax && interlace) {
 
1267                 /* Interlace, too high -> enlarge margins */
 
1270                      (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax;
 
1273                 upper_margin += lines;
 
1274                 lower_margin += lines;
 
1277         else if (vfreq < fb_info.monspecs.vfmin ||
 
1278                  vfreq > fb_info.monspecs.vfmax)
 
1282         linelen = xres_virtual * bpp / 8;
 
1283         if (yres_virtual * linelen > screen_len && screen_len)
 
1285         if (yres * linelen > screen_len && screen_len)
 
1287         if (var->yoffset + yres > yres_virtual && yres_virtual)
 
1289         par->yres_virtual = yres_virtual;
 
1290         par->screen_base = screen_base + var->yoffset * linelen;
 
1291         par->hw.falcon.xoffset = 0;
 
1296 static int falcon_encode_var( struct fb_var_screeninfo *var,
 
1297                                                           struct atafb_par *par )
 
1299 /* !!! only for VGA !!! */
 
1302         int hdb_off, hde_off, base_off;
 
1303         struct falcon_hw *hw = &par->hw.falcon;
 
1305         memset(var, 0, sizeof(struct fb_var_screeninfo));
 
1306         /* possible frequencies: 25.175 or 32MHz */
 
1307         var->pixclock = hw->sync & 0x1 ? fext.t :
 
1308                         hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
 
1314         if (hw->vid_control & VCO_HSYPOS)
 
1315                 var->sync |= FB_SYNC_HOR_HIGH_ACT;
 
1316         if (hw->vid_control & VCO_VSYPOS)
 
1317                 var->sync |= FB_SYNC_VERT_HIGH_ACT;
 
1319         var->vmode = FB_VMODE_NONINTERLACED;
 
1320         if (hw->vid_mode & VMO_INTER)
 
1321                 var->vmode |= FB_VMODE_INTERLACED;
 
1322         if (hw->vid_mode & VMO_DOUBLE)
 
1323                 var->vmode |= FB_VMODE_DOUBLE;
 
1325         /* visible y resolution:
 
1326          * Graphics display starts at line VDB and ends at line
 
1327          * VDE. If interlace mode off unit of VC-registers is
 
1328          * half lines, else lines.
 
1330         var->yres = hw->vde - hw->vdb;
 
1331         if (!(var->vmode & FB_VMODE_INTERLACED))
 
1333         if (var->vmode & FB_VMODE_DOUBLE)
 
1336         /* to get bpp, we must examine f_shift and st_shift.
 
1337          * f_shift is valid if any of bits no. 10, 8 or 4
 
1338          * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
 
1339          * if bit 10 set then bit 8 and bit 4 don't care...
 
1340          * If all these bits are 0 get display depth from st_shift
 
1341          * (as for ST and STE)
 
1343         if (hw->f_shift & 0x400)                /* 2 colors */
 
1344                 var->bits_per_pixel = 1;
 
1345         else if (hw->f_shift & 0x100)   /* hicolor */
 
1346                 var->bits_per_pixel = 16;
 
1347         else if (hw->f_shift & 0x010)   /* 8 bitplanes */
 
1348                 var->bits_per_pixel = 8;
 
1349         else if (hw->st_shift == 0)
 
1350                 var->bits_per_pixel = 4;
 
1351         else if (hw->st_shift == 0x100)
 
1352                 var->bits_per_pixel = 2;
 
1353         else /* if (hw->st_shift == 0x200) */
 
1354                 var->bits_per_pixel = 1;
 
1356         var->xres = hw->line_width * 16 / var->bits_per_pixel;
 
1357         var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
 
1359                 var->xres_virtual += 16;
 
1361         if (var->bits_per_pixel == 16) {
 
1364                 var->red.msb_right=0;
 
1365                 var->green.offset=5;
 
1366                 var->green.length=6;
 
1367                 var->green.msb_right=0;
 
1370                 var->blue.msb_right=0;
 
1374                 var->red.length = hw->ste_mode ? 4 : 6;
 
1375                 var->red.msb_right=0;
 
1377                 var->blue=var->green=var->red;
 
1379         var->transp.offset=0;
 
1380         var->transp.length=0;
 
1381         var->transp.msb_right=0;
 
1383         linelen = var->xres_virtual * var->bits_per_pixel / 8;
 
1385                 if (par->yres_virtual)
 
1386                         var->yres_virtual = par->yres_virtual;
 
1388                         /* yres_virtual==0 means use maximum */
 
1389                         var->yres_virtual = screen_len / linelen;
 
1393                         var->yres_virtual = 2 * var->yres;
 
1395                         var->yres_virtual=var->yres+hwscroll * 16;
 
1397         var->xoffset=0; /* TODO change this */
 
1400         prescale = hxx_prescale(hw);
 
1401         plen = 4 >> (hw->vid_mode >> 2 & 0x3);
 
1402         base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
 
1403         if (hw->f_shift & 0x100) {
 
1405                 hdb_off = (base_off + 16 * plen) + prescale;
 
1408                 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
 
1410                         hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
 
1413                         hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
 
1417         /* Right margin includes hsync */
 
1418         var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
 
1419                                            (hw->hdb & 0x200 ? 2+hw->hht : 0));
 
1420         if (hw->ste_mode || mon_type!=F_MON_VGA)
 
1421                 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
 
1423                 /* can't use this in ste_mode, because hbb is +1 off */
 
1424                 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
 
1425         var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
 
1427         /* Lower margin includes vsync */
 
1428         var->upper_margin = hw->vdb / 2 ;  /* round down to full lines */
 
1429         var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
 
1430         var->vsync_len    = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
 
1431         if (var->vmode & FB_VMODE_INTERLACED) {
 
1432                 var->upper_margin *= 2;
 
1433                 var->lower_margin *= 2;
 
1434                 var->vsync_len *= 2;
 
1436         else if (var->vmode & FB_VMODE_DOUBLE) {
 
1437                 var->upper_margin = (var->upper_margin + 1) / 2;
 
1438                 var->lower_margin = (var->lower_margin + 1) / 2;
 
1439                 var->vsync_len = (var->vsync_len + 1) / 2;
 
1442         var->pixclock *= plen;
 
1443         var->left_margin /= plen;
 
1444         var->right_margin /= plen;
 
1445         var->hsync_len /= plen;
 
1447         var->right_margin -= var->hsync_len;
 
1448         var->lower_margin -= var->vsync_len;
 
1451                 var->yoffset=(par->screen_base - screen_base)/linelen;
 
1454         var->nonstd=0;  /* what is this for? */
 
1460 static int f_change_mode = 0;
 
1461 static struct falcon_hw f_new_mode;
 
1462 static int f_pan_display = 0;
 
1464 static void falcon_get_par( struct atafb_par *par )
 
1467         struct falcon_hw *hw = &par->hw.falcon;
 
1469         hw->line_width = shifter_f030.scn_width;
 
1470         hw->line_offset = shifter_f030.off_next;
 
1471         hw->st_shift = videl.st_shift & 0x300;
 
1472         hw->f_shift = videl.f_shift;
 
1473         hw->vid_control = videl.control;
 
1474         hw->vid_mode = videl.mode;
 
1475         hw->sync = shifter.syncmode & 0x1;
 
1476         hw->xoffset = videl.xoffset & 0xf;
 
1477         hw->hht = videl.hht;
 
1478         hw->hbb = videl.hbb;
 
1479         hw->hbe = videl.hbe;
 
1480         hw->hdb = videl.hdb;
 
1481         hw->hde = videl.hde;
 
1482         hw->hss = videl.hss;
 
1483         hw->vft = videl.vft;
 
1484         hw->vbb = videl.vbb;
 
1485         hw->vbe = videl.vbe;
 
1486         hw->vdb = videl.vdb;
 
1487         hw->vde = videl.vde;
 
1488         hw->vss = videl.vss;
 
1490         addr = (shifter.bas_hi & 0xff) << 16 |
 
1491                (shifter.bas_md & 0xff) << 8  |
 
1492                (shifter.bas_lo & 0xff);
 
1493         par->screen_base = phys_to_virt(addr);
 
1495         /* derived parameters */
 
1496         hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
 
1497         hw->mono = (hw->f_shift & 0x400) ||
 
1498                    ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
 
1501 static void falcon_set_par( struct atafb_par *par )
 
1505         /* only set screen_base if really necessary */
 
1506         if (current_par.screen_base != par->screen_base)
 
1507                 fbhw->set_screen_base(par->screen_base);
 
1509         /* Don't touch any other registers if we keep the default resolution */
 
1513         /* Tell vbl-handler to change video mode.
 
1514          * We change modes only on next VBL, to avoid desynchronisation
 
1515          * (a shift to the right and wrap around by a random number of pixels
 
1516          * in all monochrome modes).
 
1517          * This seems to work on my Falcon.
 
1519         f_new_mode = par->hw.falcon;
 
1524 static irqreturn_t falcon_vbl_switcher( int irq, void *dummy )
 
1526         struct falcon_hw *hw = &f_new_mode;
 
1528         if (f_change_mode) {
 
1531                 if (hw->sync & 0x1) {
 
1532                         /* Enable external pixelclock. This code only for ScreenWonder */
 
1533                         *(volatile unsigned short*)0xffff9202 = 0xffbf;
 
1536                         /* Turn off external clocks. Read sets all output bits to 1. */
 
1537                         *(volatile unsigned short*)0xffff9202;
 
1539                 shifter.syncmode = hw->sync;
 
1541                 videl.hht = hw->hht;
 
1542                 videl.hbb = hw->hbb;
 
1543                 videl.hbe = hw->hbe;
 
1544                 videl.hdb = hw->hdb;
 
1545                 videl.hde = hw->hde;
 
1546                 videl.hss = hw->hss;
 
1547                 videl.vft = hw->vft;
 
1548                 videl.vbb = hw->vbb;
 
1549                 videl.vbe = hw->vbe;
 
1550                 videl.vdb = hw->vdb;
 
1551                 videl.vde = hw->vde;
 
1552                 videl.vss = hw->vss;
 
1554                 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
 
1556                         videl.st_shift = hw->st_shift; /* write enables STE palette */
 
1560                          * set st_shift 0, so we can tell the screen-depth if f_shift==0.
 
1561                          * Writing 0 to f_shift enables 4 plane Falcon mode but
 
1562                          * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
 
1563                          * with Falcon palette.
 
1566                         /* now back to Falcon palette mode */
 
1567                         videl.f_shift = hw->f_shift;
 
1569                 /* writing to st_shift changed scn_width and vid_mode */
 
1570                 videl.xoffset = hw->xoffset;
 
1571                 shifter_f030.scn_width = hw->line_width;
 
1572                 shifter_f030.off_next = hw->line_offset;
 
1573                 videl.control = hw->vid_control;
 
1574                 videl.mode = hw->vid_mode;
 
1576         if (f_pan_display) {
 
1578                 videl.xoffset = current_par.hw.falcon.xoffset;
 
1579                 shifter_f030.off_next = current_par.hw.falcon.line_offset;
 
1585 static int falcon_pan_display( struct fb_var_screeninfo *var,
 
1586                                                            struct atafb_par *par )
 
1589         int bpp = fb_display[fb_info.currcon].var.bits_per_pixel;
 
1592                 var->xoffset = up(var->xoffset, 32);
 
1594                 par->hw.falcon.xoffset = var->xoffset & 15;
 
1596                 par->hw.falcon.xoffset = 0;
 
1597                 var->xoffset = up(var->xoffset, 2);
 
1599         par->hw.falcon.line_offset = bpp *
 
1600                 (fb_display[fb_info.currcon].var.xres_virtual - fb_display[fb_info.currcon].var.xres) / 16;
 
1601         if (par->hw.falcon.xoffset)
 
1602                 par->hw.falcon.line_offset -= bpp;
 
1603         xoffset = var->xoffset - par->hw.falcon.xoffset;
 
1605         par->screen_base = screen_base +
 
1606                 (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + xoffset) * bpp / 8;
 
1607         if (fbhw->set_screen_base)
 
1608                 fbhw->set_screen_base (par->screen_base);
 
1610                 return -EINVAL; /* shouldn't happen */
 
1616 static int falcon_getcolreg( unsigned regno, unsigned *red,
 
1617                                  unsigned *green, unsigned *blue,
 
1618                                  unsigned *transp, struct fb_info *info )
 
1619 {       unsigned long col;
 
1623         /* This works in STE-mode (with 4bit/color) since f030_col-registers
 
1624          * hold up to 6bit/color.
 
1625          * Even with hicolor r/g/b=5/6/5 bit!
 
1627         col = f030_col[regno];
 
1628         *red = (col >> 16) & 0xff00;
 
1629         *green = (col >> 8) & 0xff00;
 
1630         *blue = (col << 8) & 0xff00;
 
1636 static int falcon_setcolreg( unsigned regno, unsigned red,
 
1637                                                          unsigned green, unsigned blue,
 
1638                                                          unsigned transp, struct fb_info *info )
 
1642         f030_col[regno] = (((red & 0xfc00) << 16) |
 
1643                            ((green & 0xfc00) << 8) |
 
1644                            ((blue & 0xfc00) >> 8));
 
1646                 shifter_tt.color_reg[regno] =
 
1647                         (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
 
1648                         (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
 
1649                         ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
 
1650 #ifdef FBCON_HAS_CFB16
 
1651                 fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
 
1652                                            ((green & 0xfc00) >> 5) |
 
1653                                            ((blue & 0xf800) >> 11));
 
1660 static int falcon_blank( int blank_mode )
 
1662 /* ++guenther: we can switch off graphics by changing VDB and VDE,
 
1663  * so VIDEL doesn't hog the bus while saving.
 
1664  * (this may affect usleep()).
 
1666         int vdb, vss, hbe, hss;
 
1668         if (mon_type == F_MON_SM)       /* this doesn't work on SM124 */
 
1671         vdb = current_par.VDB;
 
1672         vss = current_par.VSS;
 
1673         hbe = current_par.HBE;
 
1674         hss = current_par.HSS;
 
1676         if (blank_mode >= 1) {
 
1677                 /* disable graphics output (this speeds up the CPU) ... */
 
1678                 vdb = current_par.VFT + 1;
 
1679                 /* ... and blank all lines */
 
1680                 hbe = current_par.HHT + 2;
 
1682         /* use VESA suspend modes on VGA monitors */
 
1683         if (mon_type == F_MON_VGA) {
 
1684                 if (blank_mode == 2 || blank_mode == 4)
 
1685                         vss = current_par.VFT + 1;
 
1686                 if (blank_mode == 3 || blank_mode == 4)
 
1687                         hss = current_par.HHT + 2;
 
1699 static int falcon_detect( void )
 
1701         struct atafb_par par;
 
1704         /* Determine connected monitor and set monitor parameters */
 
1705         fhw = *(unsigned char*)0xffff8006;
 
1706         mon_type = fhw >> 6 & 0x3;
 
1707         /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
 
1708         f030_bus_width = fhw << 6 & 0x80;
 
1711                 fb_info.monspecs.vfmin = 70;
 
1712                 fb_info.monspecs.vfmax = 72;
 
1713                 fb_info.monspecs.hfmin = 35713;
 
1714                 fb_info.monspecs.hfmax = 35715;
 
1719                 fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */
 
1720                 fb_info.monspecs.vfmax = 60;
 
1721                 fb_info.monspecs.hfmin = 15620;
 
1722                 fb_info.monspecs.hfmax = 15755;
 
1725         /* initialize hsync-len */
 
1726         f25.hsync = h_syncs[mon_type] / f25.t;
 
1727         f32.hsync = h_syncs[mon_type] / f32.t;
 
1729                 fext.hsync = h_syncs[mon_type] / fext.t;
 
1731         falcon_get_par(&par);
 
1732         falcon_encode_var(&atafb_predefined[0], &par);
 
1734         /* Detected mode is always the "autodetect" slot */
 
1738 #endif /* ATAFB_FALCON */
 
1740 /* ------------------- ST(E) specific functions ---------------------- */
 
1744 static int stste_encode_fix( struct fb_fix_screeninfo *fix,
 
1745                                                          struct atafb_par *par )
 
1750         strcpy(fix->id,"Atari Builtin");
 
1751         fix->smem_start = (unsigned long)real_screen_base;
 
1752         fix->smem_len = screen_len;
 
1753         fix->type = FB_TYPE_INTERLEAVED_PLANES;
 
1755         fix->visual = FB_VISUAL_PSEUDOCOLOR;
 
1756         mode = par->hw.st.mode & 3;
 
1757         if (mode == ST_HIGH) {
 
1758                 fix->type = FB_TYPE_PACKED_PIXELS;
 
1760                 fix->visual = FB_VISUAL_MONO10;
 
1762         if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
 
1770         fix->line_length = 0;
 
1771         fix->accel = FB_ACCEL_ATARIBLITT;
 
1776 static int stste_decode_var( struct fb_var_screeninfo *var,
 
1777                                                   struct atafb_par *par )
 
1781         int bpp=var->bits_per_pixel;
 
1783         int yres_virtual = var->yres_virtual;
 
1786                 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
 
1788                 par->hw.st.mode=ST_HIGH;
 
1793                 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
 
1796                         if (xres > sttt_xres/2 || yres > st_yres/2)
 
1798                         par->hw.st.mode=ST_LOW;
 
1804                         if (xres > sttt_xres || yres > st_yres/2)
 
1806                         par->hw.st.mode=ST_MID;
 
1814         if (yres_virtual <= 0)
 
1816         else if (yres_virtual < yres)
 
1817                 yres_virtual = yres;
 
1818         if (var->sync & FB_SYNC_EXT)
 
1819                 par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
 
1821                 par->hw.st.sync=(par->hw.st.sync & ~1);
 
1823         if (yres_virtual * linelen > screen_len && screen_len)
 
1825         if (yres * linelen > screen_len && screen_len)
 
1827         if (var->yoffset + yres > yres_virtual && yres_virtual)
 
1829         par->yres_virtual = yres_virtual;
 
1830         par->screen_base=screen_base+ var->yoffset*linelen;
 
1834 static int stste_encode_var( struct fb_var_screeninfo *var,
 
1835                                                   struct atafb_par *par )
 
1838         memset(var, 0, sizeof(struct fb_var_screeninfo));
 
1840         var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
 
1841         var->red.msb_right=0;
 
1844         var->pixclock=31041;
 
1845         var->left_margin=120;           /* these are incorrect */
 
1846         var->right_margin=100;
 
1847         var->upper_margin=8;
 
1848         var->lower_margin=16;
 
1855         if (!(par->hw.st.sync & 1))
 
1858                 var->sync=FB_SYNC_EXT;
 
1860         switch (par->hw.st.mode & 3) {
 
1862                 var->xres=sttt_xres/2;
 
1863                 var->yres=st_yres/2;
 
1864                 var->bits_per_pixel=4;
 
1867                 var->xres=sttt_xres;
 
1868                 var->yres=st_yres/2;
 
1869                 var->bits_per_pixel=2;
 
1872                 var->xres=sttt_xres;
 
1874                 var->bits_per_pixel=1;
 
1877         var->blue=var->green=var->red;
 
1878         var->transp.offset=0;
 
1879         var->transp.length=0;
 
1880         var->transp.msb_right=0;
 
1881         var->xres_virtual=sttt_xres_virtual;
 
1882         linelen=var->xres_virtual * var->bits_per_pixel / 8;
 
1883         ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
 
1886                 var->yres_virtual=var->yres;
 
1887         else if (screen_len) {
 
1888                 if (par->yres_virtual)
 
1889                         var->yres_virtual = par->yres_virtual;
 
1891                         /* yres_virtual==0 means use maximum */
 
1892                         var->yres_virtual = screen_len / linelen;
 
1896                         var->yres_virtual = 2 * var->yres;
 
1898                         var->yres_virtual=var->yres+hwscroll * 16;
 
1902                 var->yoffset=(par->screen_base - screen_base)/linelen;
 
1907         var->vmode=FB_VMODE_NONINTERLACED;
 
1912 static void stste_get_par( struct atafb_par *par )
 
1915         par->hw.st.mode=shifter_tt.st_shiftmode;
 
1916         par->hw.st.sync=shifter.syncmode;
 
1917         addr = ((shifter.bas_hi & 0xff) << 16) |
 
1918                ((shifter.bas_md & 0xff) << 8);
 
1919         if (ATARIHW_PRESENT(EXTD_SHIFTER))
 
1920                 addr |= (shifter.bas_lo & 0xff);
 
1921         par->screen_base = phys_to_virt(addr);
 
1924 static void stste_set_par( struct atafb_par *par )
 
1926         shifter_tt.st_shiftmode=par->hw.st.mode;
 
1927         shifter.syncmode=par->hw.st.sync;
 
1928         /* only set screen_base if really necessary */
 
1929         if (current_par.screen_base != par->screen_base)
 
1930                 fbhw->set_screen_base(par->screen_base);
 
1934 static int stste_getcolreg(unsigned regno, unsigned *red,
 
1935                            unsigned *green, unsigned *blue,
 
1936                            unsigned *transp, struct fb_info *info)
 
1942         col = shifter_tt.color_reg[regno];
 
1943         if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
 
1944                 t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
 
1946                 *red = t | (t << 8);
 
1947                 t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
 
1949                 *green = t | (t << 8);
 
1950                 t = ((col << 1) & 0xe) | ((col >> 3) & 1);
 
1952                 *blue = t | (t << 8);
 
1955                 t = (col >> 7) & 0xe;
 
1957                 *red = t | (t << 8);
 
1958                 t = (col >> 3) & 0xe;
 
1960                 *green = t | (t << 8);
 
1961                 t = (col << 1) & 0xe;
 
1963                 *blue = t | (t << 8);
 
1970 static int stste_setcolreg(unsigned regno, unsigned red,
 
1971                            unsigned green, unsigned blue,
 
1972                            unsigned transp, struct fb_info *info)
 
1979         if (ATARIHW_PRESENT(EXTD_SHIFTER))
 
1980                 shifter_tt.color_reg[regno] =
 
1981                         (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
 
1982                         (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
 
1983                         ((blue & 0xe) >> 1) | ((blue & 1) << 3);
 
1985                 shifter_tt.color_reg[regno] =
 
1986                         ((red & 0xe) << 7) |
 
1987                         ((green & 0xe) << 3) |
 
1988                         ((blue & 0xe) >> 1);
 
1993 static int stste_detect( void )
 
1995 {       struct atafb_par par;
 
1997         /* Determine the connected monitor: The DMA sound must be
 
1998          * disabled before reading the MFP GPIP, because the Sound
 
1999          * Done Signal and the Monochrome Detect are XORed together!
 
2001         if (ATARIHW_PRESENT(PCM_8BIT)) {
 
2002                 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
 
2003                 udelay(20);     /* wait a while for things to settle down */
 
2005         mono_moni = (mfp.par_dt_reg & 0x80) == 0;
 
2007         stste_get_par(&par);
 
2008         stste_encode_var(&atafb_predefined[0], &par);
 
2010         if (!ATARIHW_PRESENT(EXTD_SHIFTER))
 
2015 static void stste_set_screen_base(void *s_base)
 
2018         addr= virt_to_phys(s_base);
 
2019         /* Setup Screen Memory */
 
2020         shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
 
2021         shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
 
2022         if (ATARIHW_PRESENT(EXTD_SHIFTER))
 
2023                 shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
 
2026 #endif /* ATAFB_STE */
 
2028 /* Switching the screen size should be done during vsync, otherwise
 
2029  * the margins may get messed up. This is a well known problem of
 
2030  * the ST's video system.
 
2032  * Unfortunately there is hardly any way to find the vsync, as the
 
2033  * vertical blank interrupt is no longer in time on machines with
 
2034  * overscan type modifications.
 
2036  * We can, however, use Timer B to safely detect the black shoulder,
 
2037  * but then we've got to guess an appropriate delay to find the vsync.
 
2038  * This might not work on every machine.
 
2040  * martin_rogge @ ki.maus.de, 8th Aug 1995
 
2043 #define LINE_DELAY  (mono_moni ? 30 : 70)
 
2044 #define SYNC_DELAY  (mono_moni ? 1500 : 2000)
 
2046 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
 
2047 static void st_ovsc_switch(void)
 
2049     unsigned long flags;
 
2050     register unsigned char old, new;
 
2052     if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
 
2054     local_irq_save(flags);
 
2056     mfp.tim_ct_b = 0x10;
 
2057     mfp.active_edge |= 8;
 
2059     mfp.tim_dt_b = 0xf0;
 
2061     while (mfp.tim_dt_b > 1)    /* TOS does it this way, don't ask why */
 
2068     } while (old != new);
 
2069     mfp.tim_ct_b = 0x10;
 
2072     if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
 
2073         acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE;
 
2074     if (atari_switches & ATARI_SWITCH_OVSC_MIDI)
 
2075         acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID;
 
2076     if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) {
 
2077         sound_ym.rd_data_reg_sel = 14;
 
2078         sound_ym.wd_data = sound_ym.rd_data_reg_sel |
 
2079                            ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
 
2080                            ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
 
2082     local_irq_restore(flags);
 
2085 /* ------------------- External Video ---------------------- */
 
2089 static int ext_encode_fix( struct fb_fix_screeninfo *fix,
 
2090                                                    struct atafb_par *par )
 
2093         strcpy(fix->id,"Unknown Extern");
 
2094         fix->smem_start = (unsigned long)external_addr;
 
2095         fix->smem_len = PAGE_ALIGN(external_len);
 
2096         if (external_depth == 1) {
 
2097                 fix->type = FB_TYPE_PACKED_PIXELS;
 
2098                 /* The letters 'n' and 'i' in the "atavideo=external:" stand
 
2099                  * for "normal" and "inverted", rsp., in the monochrome case */
 
2101                         (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
 
2102                          external_pmode == FB_TYPE_PACKED_PIXELS) ?
 
2107                 /* Use STATIC if we don't know how to access color registers */
 
2108                 int visual = external_vgaiobase ?
 
2109                                          FB_VISUAL_PSEUDOCOLOR :
 
2110                                          FB_VISUAL_STATIC_PSEUDOCOLOR;
 
2111                 switch (external_pmode) {
 
2112                     case -1:              /* truecolor */
 
2113                         fix->type=FB_TYPE_PACKED_PIXELS;
 
2114                         fix->visual=FB_VISUAL_TRUECOLOR;
 
2116                     case FB_TYPE_PACKED_PIXELS:
 
2117                         fix->type=FB_TYPE_PACKED_PIXELS;
 
2120                     case FB_TYPE_PLANES:
 
2121                         fix->type=FB_TYPE_PLANES;
 
2124                     case FB_TYPE_INTERLEAVED_PLANES:
 
2125                         fix->type=FB_TYPE_INTERLEAVED_PLANES;
 
2134         fix->line_length = 0;
 
2139 static int ext_decode_var( struct fb_var_screeninfo *var,
 
2140                                                    struct atafb_par *par )
 
2142         struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 
2144         if (var->bits_per_pixel > myvar->bits_per_pixel ||
 
2145                 var->xres > myvar->xres ||
 
2146                 var->xres_virtual > myvar->xres_virtual ||
 
2147                 var->yres > myvar->yres ||
 
2155 static int ext_encode_var( struct fb_var_screeninfo *var,
 
2156                                                    struct atafb_par *par )
 
2158         memset(var, 0, sizeof(struct fb_var_screeninfo));
 
2160         var->red.length=(external_pmode == -1) ? external_depth/3 : 
 
2161                         (external_vgaiobase ? external_bitspercol : 0);
 
2162         var->red.msb_right=0;
 
2165         var->pixclock=31041;
 
2166         var->left_margin=120;           /* these are surely incorrect   */
 
2167         var->right_margin=100;
 
2168         var->upper_margin=8;
 
2169         var->lower_margin=16;
 
2178         var->xres = external_xres;
 
2179         var->yres = external_yres;
 
2180         var->xres_virtual = external_xres_virtual;
 
2181         var->bits_per_pixel = external_depth;
 
2183         var->blue=var->green=var->red;
 
2184         var->transp.offset=0;
 
2185         var->transp.length=0;
 
2186         var->transp.msb_right=0;
 
2187         var->yres_virtual=var->yres;
 
2192         var->vmode=FB_VMODE_NONINTERLACED;
 
2197 static void ext_get_par( struct atafb_par *par )
 
2199         par->screen_base = external_addr;
 
2202 static void ext_set_par( struct atafb_par *par )
 
2206 #define OUTB(port,val) \
 
2207         *((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
 
2209         (*((unsigned volatile char *) ((port)+external_vgaiobase)))
 
2212                 unsigned char tmp=INB(0x3da);   \
 
2216 static int ext_getcolreg( unsigned regno, unsigned *red,
 
2217                                                   unsigned *green, unsigned *blue,
 
2218                                                   unsigned *transp, struct fb_info *info )
 
2220         if (! external_vgaiobase)
 
2223             *red   = ext_color[regno].red;
 
2224             *green = ext_color[regno].green;
 
2225             *blue  = ext_color[regno].blue;
 
2230 static int ext_setcolreg( unsigned regno, unsigned red,
 
2231                                                   unsigned green, unsigned blue,
 
2232                                                   unsigned transp, struct fb_info *info )
 
2234 {       unsigned char colmask = (1 << external_bitspercol) - 1;
 
2236         if (! external_vgaiobase)
 
2239         ext_color[regno].red = red;
 
2240         ext_color[regno].green = green;
 
2241         ext_color[regno].blue = blue;
 
2243         switch (external_card_type) {
 
2247             OUTB(0x3c9, red & colmask);
 
2249             OUTB(0x3c9, green & colmask);
 
2251             OUTB(0x3c9, blue & colmask);
 
2256             OUTB((MV300_reg[regno] << 2)+1, red);
 
2257             OUTB((MV300_reg[regno] << 2)+1, green);
 
2258             OUTB((MV300_reg[regno] << 2)+1, blue);
 
2267 static int ext_detect( void )
 
2270         struct fb_var_screeninfo *myvar = &atafb_predefined[0];
 
2271         struct atafb_par dummy_par;
 
2273         myvar->xres = external_xres;
 
2274         myvar->xres_virtual = external_xres_virtual;
 
2275         myvar->yres = external_yres;
 
2276         myvar->bits_per_pixel = external_depth;
 
2277         ext_encode_var(myvar, &dummy_par);
 
2281 #endif /* ATAFB_EXT */
 
2283 /* ------ This is the same for most hardware types -------- */
 
2285 static void set_screen_base(void *s_base)
 
2288         addr= virt_to_phys(s_base);
 
2289         /* Setup Screen Memory */
 
2290         shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
 
2291         shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
 
2292         shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
 
2296 static int pan_display( struct fb_var_screeninfo *var,
 
2297                         struct atafb_par *par )
 
2299         if (!fbhw->set_screen_base ||
 
2300                 (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset))
 
2302         var->xoffset = up(var->xoffset, 16);
 
2303         par->screen_base = screen_base +
 
2304                 (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + var->xoffset)
 
2305                 * fb_display[fb_info.currcon].var.bits_per_pixel / 8;
 
2306         fbhw->set_screen_base (par->screen_base);
 
2311 /* ------------ Interfaces to hardware functions ------------ */
 
2315 static struct fb_hwswitch tt_switch = {
 
2316         tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
 
2317         tt_get_par, tt_set_par, tt_getcolreg, 
 
2318         set_screen_base, NULL, pan_display
 
2323 static struct fb_hwswitch falcon_switch = {
 
2324         falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
 
2325         falcon_get_par, falcon_set_par, falcon_getcolreg,
 
2326         set_screen_base, falcon_blank, falcon_pan_display
 
2331 static struct fb_hwswitch st_switch = {
 
2332         stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
 
2333         stste_get_par, stste_set_par, stste_getcolreg,
 
2334         stste_set_screen_base, NULL, pan_display
 
2339 static struct fb_hwswitch ext_switch = {
 
2340         ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
 
2341         ext_get_par, ext_set_par, ext_getcolreg, NULL, NULL, NULL
 
2347 static void atafb_get_par( struct atafb_par *par )
 
2349         if (current_par_valid) {
 
2357 static void atafb_set_par( struct atafb_par *par )
 
2361         current_par_valid=1;
 
2366 /* =========================================================== */
 
2367 /* ============== Hardware Independent Functions ============= */
 
2368 /* =========================================================== */
 
2371 /* used for hardware scrolling */
 
2374 fb_update_var(int con, struct fb_info *info)
 
2376         int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual*
 
2377                         fb_display[con].var.bits_per_pixel>>3;
 
2379         current_par.screen_base=screen_base + off;
 
2381         if (fbhw->set_screen_base)
 
2382                 fbhw->set_screen_base(current_par.screen_base);
 
2387 do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
 
2390         struct atafb_par par;
 
2391         if ((err=fbhw->decode_var(var, &par)))
 
2393         activate=var->activate;
 
2394         if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
 
2395                 atafb_set_par(&par);
 
2396         fbhw->encode_var(var, &par);
 
2397         var->activate=activate;
 
2402 atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
 
2404         struct atafb_par par;
 
2406                 atafb_get_par(&par);
 
2409                 if ((err=fbhw->decode_var(&fb_display[con].var,&par)))
 
2412         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
2413         return fbhw->encode_fix(fix, &par);
 
2417 atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 
2419         struct atafb_par par;
 
2421                 atafb_get_par(&par);
 
2422                 fbhw->encode_var(var, &par);
 
2425                 *var=fb_display[con].var;
 
2430 atafb_set_disp(int con, struct fb_info *info)
 
2432         struct fb_fix_screeninfo fix;
 
2433         struct fb_var_screeninfo var;
 
2434         struct display *display;
 
2437                 display = &fb_display[con];
 
2439                 display = &disp;        /* used during initialization */
 
2441         atafb_get_fix(&fix, con, info);
 
2442         atafb_get_var(&var, con, info);
 
2445         info->screen_base = (void *)fix.smem_start;
 
2446         display->visual = fix.visual;
 
2447         display->type = fix.type;
 
2448         display->type_aux = fix.type_aux;
 
2449         display->ypanstep = fix.ypanstep;
 
2450         display->ywrapstep = fix.ywrapstep;
 
2451         display->line_length = fix.line_length;
 
2452         if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
 
2453                 fix.visual != FB_VISUAL_DIRECTCOLOR)
 
2454                 display->can_soft_blank = 0;
 
2456                 display->can_soft_blank = 1;
 
2458             (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
 
2460             case FB_TYPE_INTERLEAVED_PLANES:
 
2461                 switch (var.bits_per_pixel) {
 
2462 #ifdef FBCON_HAS_IPLAN2P2
 
2464                         display->dispsw = &fbcon_iplan2p2;
 
2467 #ifdef FBCON_HAS_IPLAN2P4
 
2469                         display->dispsw = &fbcon_iplan2p4;
 
2472 #ifdef FBCON_HAS_IPLAN2P8
 
2474                         display->dispsw = &fbcon_iplan2p8;
 
2479             case FB_TYPE_PACKED_PIXELS:
 
2480                 switch (var.bits_per_pixel) {
 
2481 #ifdef FBCON_HAS_MFB
 
2483                         display->dispsw = &fbcon_mfb;
 
2486 #ifdef FBCON_HAS_CFB8
 
2488                         display->dispsw = &fbcon_cfb8;
 
2491 #ifdef FBCON_HAS_CFB16
 
2493                         display->dispsw = &fbcon_cfb16;
 
2494                         display->dispsw_data = fbcon_cfb16_cmap;
 
2503 atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 
2505         int err,oldxres,oldyres,oldbpp,oldxres_virtual,
 
2506             oldyres_virtual,oldyoffset;
 
2507         if ((err=do_fb_set_var(var, con==info->currcon)))
 
2509         if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
 
2510                 oldxres=fb_display[con].var.xres;
 
2511                 oldyres=fb_display[con].var.yres;
 
2512                 oldxres_virtual=fb_display[con].var.xres_virtual;
 
2513                 oldyres_virtual=fb_display[con].var.yres_virtual;
 
2514                 oldbpp=fb_display[con].var.bits_per_pixel;
 
2515                 oldyoffset=fb_display[con].var.yoffset;
 
2516                 fb_display[con].var=*var;
 
2517                 if (oldxres != var->xres || oldyres != var->yres 
 
2518                     || oldxres_virtual != var->xres_virtual
 
2519                     || oldyres_virtual != var->yres_virtual
 
2520                     || oldbpp != var->bits_per_pixel
 
2521                     || oldyoffset != var->yoffset) {
 
2522                         atafb_set_disp(con, info);
 
2523                         (*fb_info.changevar)(con);
 
2524                         fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
 
2525                         do_install_cmap(con, info);
 
2535 atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
 
2537         if (con == info->currcon) /* current console ? */
 
2538                 return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
 
2540                 if (fb_display[con].cmap.len) /* non default colormap ? */
 
2541                         fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 
2543                         fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
 
2544                                      cmap, kspc ? 0 : 2);
 
2549 atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 
2551         int xoffset = var->xoffset;
 
2552         int yoffset = var->yoffset;
 
2555         if (   xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
 
2556             || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
 
2559         if (con == info->currcon) {
 
2560                 if (fbhw->pan_display) {
 
2561                         if ((err = fbhw->pan_display(var, ¤t_par)))
 
2567         fb_display[con].var.xoffset = var->xoffset;
 
2568         fb_display[con].var.yoffset = var->yoffset;
 
2573 atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 
2576 #ifdef FBCMD_GET_CURRENTPAR
 
2577         case FBCMD_GET_CURRENTPAR:
 
2578                 if (copy_to_user((void *)arg, (void *)¤t_par,
 
2579                                  sizeof(struct atafb_par)))
 
2583 #ifdef FBCMD_SET_CURRENTPAR
 
2584         case FBCMD_SET_CURRENTPAR:
 
2585                 if (copy_from_user((void *)¤t_par, (void *)arg,
 
2586                                    sizeof(struct atafb_par)))
 
2588                 atafb_set_par(¤t_par);
 
2595 /* (un)blank/poweroff
 
2603 atafb_blank(int blank, struct fb_info *info)
 
2605         unsigned short black[16];
 
2606         struct fb_cmap cmap;
 
2607         if (fbhw->blank && !fbhw->blank(blank))
 
2610                 memset(black, 0, 16*sizeof(unsigned short));
 
2617                 fb_set_cmap(&cmap, 1, info);
 
2620                 do_install_cmap(info->currcon, info);
 
2624 static struct fb_ops atafb_ops = {
 
2625         .owner =        THIS_MODULE,
 
2626         .fb_get_fix =   atafb_get_fix,
 
2627         .fb_get_var =   atafb_get_var,
 
2628         .fb_set_var =   atafb_set_var,
 
2629         .fb_get_cmap =  atafb_get_cmap,
 
2630         .fb_set_cmap =  gen_set_cmap,
 
2631         .fb_pan_display =atafb_pan_display,
 
2632         .fb_blank =     atafb_blank,
 
2633         .fb_ioctl =     atafb_ioctl,
 
2637 check_default_par( int detected_mode )
 
2639         char default_name[10];
 
2641         struct fb_var_screeninfo var;
 
2642         unsigned long min_mem;
 
2644         /* First try the user supplied mode */
 
2646                 var=atafb_predefined[default_par-1];
 
2647                 var.activate = FB_ACTIVATE_TEST;
 
2648                 if (do_fb_set_var(&var,1))
 
2649                         default_par=0;          /* failed */
 
2651         /* Next is the autodetected one */
 
2652         if (! default_par) {
 
2653                 var=atafb_predefined[detected_mode-1]; /* autodetect */
 
2654                 var.activate = FB_ACTIVATE_TEST;
 
2655                 if (!do_fb_set_var(&var,1))
 
2656                         default_par=detected_mode;
 
2658         /* If that also failed, try some default modes... */
 
2659         if (! default_par) {
 
2660                 /* try default1, default2... */
 
2661                 for (i=1 ; i < 10 ; i++) {
 
2662                         sprintf(default_name,"default%d",i);
 
2663                         default_par=get_video_mode(default_name);
 
2665                                 panic("can't set default video mode");
 
2666                         var=atafb_predefined[default_par-1];
 
2667                         var.activate = FB_ACTIVATE_TEST;
 
2668                         if (! do_fb_set_var(&var,1))
 
2672         min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
 
2673         if (default_mem_req < min_mem)
 
2674                 default_mem_req=min_mem;
 
2678 atafb_switch(int con, struct fb_info *info)
 
2680         /* Do we have to save the colormap ? */
 
2681         if (fb_display[info->currcon].cmap.len)
 
2682                 fb_get_cmap(&fb_display[info->currcon].cmap, 1, fbhw->getcolreg,
 
2684         do_fb_set_var(&fb_display[con].var,1);
 
2686         /* Install new colormap */
 
2687         do_install_cmap(con, info);
 
2691 int __init atafb_init(void)
 
2695         unsigned long mem_req;
 
2702                 if (external_addr) {
 
2704                         atafb_ops.fb_setcolreg = &ext_setcolreg;
 
2709                 if (ATARIHW_PRESENT(TT_SHIFTER)) {
 
2711                         atafb_ops.fb_setcolreg = &tt_setcolreg;
 
2716                 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
 
2717                         fbhw = &falcon_switch;
 
2718                         atafb_ops.fb_setcolreg = &falcon_setcolreg;
 
2719                         request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO,
 
2720                                     "framebuffer/modeswitch", falcon_vbl_switcher);
 
2725                 if (ATARIHW_PRESENT(STND_SHIFTER) ||
 
2726                     ATARIHW_PRESENT(EXTD_SHIFTER)) {
 
2728                         atafb_ops.fb_setcolreg = &stste_setcolreg;
 
2732                 atafb_ops.fb_setcolreg = &stste_setcolreg;
 
2733                 printk("Cannot determine video hardware; defaulting to ST(e)\n");
 
2734 #else /* ATAFB_STE */
 
2735                 /* no default driver included */
 
2736                 /* Nobody will ever see this message :-) */
 
2737                 panic("Cannot initialize video hardware");
 
2741         /* Multisync monitor capabilities */
 
2742         /* Atari-TOS defaults if no boot option present */
 
2743         if (fb_info.monspecs.hfmin == 0) {
 
2744             fb_info.monspecs.hfmin = 31000;
 
2745             fb_info.monspecs.hfmax = 32000;
 
2746             fb_info.monspecs.vfmin = 58;
 
2747             fb_info.monspecs.vfmax = 62;
 
2750         detected_mode = fbhw->detect();
 
2751         check_default_par(detected_mode);
 
2753         if (!external_addr) {
 
2754 #endif /* ATAFB_EXT */
 
2755                 mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
 
2756                 mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
 
2757                 screen_base = atari_stram_alloc(mem_req, "atafb");
 
2759                         panic("Cannot allocate screen memory");
 
2760                 memset(screen_base, 0, mem_req);
 
2761                 pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
 
2763                 real_screen_base=screen_base+ovsc_offset;
 
2764                 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
 
2766                 if (CPU_IS_040_OR_060) {
 
2767                         /* On a '040+, the cache mode of video RAM must be set to
 
2768                          * write-through also for internal video hardware! */
 
2769                         cache_push(virt_to_phys(screen_base), screen_len);
 
2770                         kernel_set_cachemode(screen_base, screen_len,
 
2771                                              IOMAP_WRITETHROUGH);
 
2776                 /* Map the video memory (physical address given) to somewhere
 
2777                  * in the kernel address space.
 
2780                   ioremap_writethrough((unsigned long)external_addr,
 
2782                 if (external_vgaiobase)
 
2783                         external_vgaiobase =
 
2784                           (unsigned long)ioremap(external_vgaiobase, 0x10000);
 
2786                 real_screen_base = external_addr;
 
2787                 screen_len       = external_len & PAGE_MASK;
 
2788                 memset (screen_base, 0, external_len);
 
2790 #endif /* ATAFB_EXT */
 
2792         strcpy(fb_info.modename, "Atari Builtin ");
 
2793         fb_info.changevar = NULL;
 
2794         fb_info.fbops = &atafb_ops;
 
2795         fb_info.disp = &disp;
 
2796         fb_info.currcon = -1;
 
2797         fb_info.switch_con = &atafb_switch;
 
2798         fb_info.updatevar = &fb_update_var;
 
2799         fb_info.flags = FBINFO_FLAG_DEFAULT;
 
2800         do_fb_set_var(&atafb_predefined[default_par-1], 1);
 
2801         strcat(fb_info.modename, fb_var_names[default_par-1][0]);
 
2803         atafb_get_var(&disp.var, -1, &fb_info);
 
2804         atafb_set_disp(-1, &fb_info);
 
2805         do_install_cmap(0, &fb_info);
 
2807         if (register_framebuffer(&fb_info) < 0) {
 
2809                 if (external_addr) {
 
2810                         iounmap(external_addr);
 
2811                         external_addr = NULL;
 
2813                 if (external_vgaiobase) {
 
2814                         iounmap((void*)external_vgaiobase);
 
2815                         external_vgaiobase = 0;
 
2821         printk("Determined %dx%d, depth %d\n",
 
2822                disp.var.xres, disp.var.yres, disp.var.bits_per_pixel);
 
2823         if ((disp.var.xres != disp.var.xres_virtual) ||
 
2824             (disp.var.yres != disp.var.yres_virtual))
 
2825            printk("   virtual %dx%d\n",
 
2826                           disp.var.xres_virtual, disp.var.yres_virtual);
 
2827         printk("fb%d: %s frame buffer device, using %dK of video memory\n",
 
2828                fb_info.node, fb_info.modename, screen_len>>10);
 
2830         /* TODO: This driver cannot be unloaded yet */
 
2836 static void __init atafb_setup_ext(char *spec)
 
2838         int             xres, xres_virtual, yres, depth, planes;
 
2839         unsigned long addr, len;
 
2842         /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
 
2844          *            [;<screen mem length>[;<vgaiobase>[;<bits-per-col>[;<colorreg-type>
 
2845          *            [;<xres-virtual>]]]]]
 
2848          * <xres_virtual>:      hardware's x-resolution (f.e. ProMST)
 
2850          * Even xres_virtual is available, we neither support panning nor hw-scrolling!
 
2852         if (!(p = strsep(&spec, ";")) || !*p)
 
2854         xres_virtual = xres = simple_strtoul(p, NULL, 10);
 
2858         if (!(p = strsep(&spec, ";")) || !*p)
 
2860         yres = simple_strtoul(p, NULL, 10);
 
2864         if (!(p = strsep(&spec, ";")) || !*p)
 
2866         depth = simple_strtoul(p, NULL, 10);
 
2867         if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
 
2868                 depth != 16 && depth != 24)
 
2871         if (!(p = strsep(&spec, ";")) || !*p)
 
2874                 planes = FB_TYPE_INTERLEAVED_PLANES;
 
2876                 planes = FB_TYPE_PACKED_PIXELS;
 
2878                 planes = FB_TYPE_PLANES;
 
2880                 planes = -1; /* true color */
 
2885         if (!(p = strsep(&spec, ";")) || !*p)
 
2887         addr = simple_strtoul(p, NULL, 0);
 
2889         if (!(p = strsep(&spec, ";")) || !*p)
 
2890                 len = xres*yres*depth/8;
 
2892                 len = simple_strtoul(p, NULL, 0);
 
2894         if ((p = strsep(&spec, ";")) && *p) {
 
2895                 external_vgaiobase=simple_strtoul(p, NULL, 0);
 
2898         if ((p = strsep(&spec, ";")) && *p) {
 
2899                 external_bitspercol = simple_strtoul(p, NULL, 0);
 
2900                 if (external_bitspercol > 8)
 
2901                         external_bitspercol = 8;
 
2902                 else if (external_bitspercol < 1)
 
2903                         external_bitspercol = 1;
 
2906         if ((p = strsep(&spec, ";")) && *p) {
 
2907                 if (!strcmp(p, "vga"))
 
2908                         external_card_type = IS_VGA;
 
2909                 if (!strcmp(p, "mv300"))
 
2910                         external_card_type = IS_MV300;
 
2913         if ((p = strsep(&spec, ";")) && *p) {
 
2914                 xres_virtual = simple_strtoul(p, NULL, 10);
 
2915                 if (xres_virtual < xres)
 
2916                         xres_virtual = xres;
 
2917                 if (xres_virtual*yres*depth/8 > len)
 
2918                         len=xres_virtual*yres*depth/8;
 
2921         external_xres  = xres;
 
2922         external_xres_virtual  = xres_virtual;
 
2923         external_yres  = yres;
 
2924         external_depth = depth;
 
2925         external_pmode = planes;
 
2926         external_addr  = (void *)addr;
 
2929         if (external_card_type == IS_MV300)
 
2930           switch (external_depth) {
 
2932               MV300_reg = MV300_reg_1bit;
 
2935               MV300_reg = MV300_reg_4bit;
 
2938               MV300_reg = MV300_reg_8bit;
 
2942 #endif /* ATAFB_EXT */
 
2945 static void __init atafb_setup_int(char *spec)
 
2947         /* Format to config extended internal video hardware like OverScan:
 
2948         "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
 
2950         <xres>: x-resolution 
 
2951         <yres>: y-resolution
 
2952         The following are only needed if you have an overscan which
 
2953         needs a black border:
 
2954         <xres_max>: max. length of a line in pixels your OverScan hardware would allow
 
2955         <yres_max>: max. number of lines your OverScan hardware would allow
 
2956         <offset>: Offset from physical beginning to visible beginning
 
2962         if (!(p = strsep(&spec, ";")) || !*p)
 
2964         xres = simple_strtoul(p, NULL, 10);
 
2965         if (!(p = strsep(&spec, ";")) || !*p)
 
2968         tt_yres=st_yres=simple_strtoul(p, NULL, 10);
 
2969         if ((p=strsep(&spec, ";")) && *p) {
 
2970                 sttt_xres_virtual=simple_strtoul(p, NULL, 10);
 
2972         if ((p=strsep(&spec, ";")) && *p) {
 
2973                 sttt_yres_virtual=simple_strtoul(p, NULL, 0);
 
2975         if ((p=strsep(&spec, ";")) && *p) {
 
2976                 ovsc_offset=simple_strtoul(p, NULL, 0);
 
2979         if (ovsc_offset || (sttt_yres_virtual != st_yres))
 
2985 static void __init atafb_setup_mcap(char *spec)
 
2988         int vmin, vmax, hmin, hmax;
 
2990         /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
 
2991          * <V*> vertical freq. in Hz
 
2992          * <H*> horizontal freq. in kHz
 
2994         if (!(p = strsep(&spec, ";")) || !*p)
 
2996         vmin = simple_strtoul(p, NULL, 10);
 
2999         if (!(p = strsep(&spec, ";")) || !*p)
 
3001         vmax = simple_strtoul(p, NULL, 10);
 
3002         if (vmax <= 0 || vmax <= vmin)
 
3004         if (!(p = strsep(&spec, ";")) || !*p)
 
3006         hmin = 1000 * simple_strtoul(p, NULL, 10);
 
3009         if (!(p = strsep(&spec, "")) || !*p)
 
3011         hmax = 1000 * simple_strtoul(p, NULL, 10);
 
3012         if (hmax <= 0 || hmax <= hmin)
 
3015         fb_info.monspecs.vfmin = vmin;
 
3016         fb_info.monspecs.vfmax = vmax;
 
3017         fb_info.monspecs.hfmin = hmin;
 
3018         fb_info.monspecs.hfmax = hmax;
 
3020 #endif /* ATAFB_FALCON */
 
3023 static void __init atafb_setup_user(char *spec)
 
3025         /* Format of user defined video mode is: <xres>;<yres>;<depth>
 
3028         int xres, yres, depth, temp;
 
3030         if (!(p = strsep(&spec, ";")) || !*p)
 
3032         xres = simple_strtoul(p, NULL, 10);
 
3033         if (!(p = strsep(&spec, ";")) || !*p)
 
3035         yres = simple_strtoul(p, NULL, 10);
 
3036         if (!(p = strsep(&spec, "")) || !*p)
 
3038         depth = simple_strtoul(p, NULL, 10);
 
3039         if ((temp=get_video_mode("user0"))) {
 
3041                 atafb_predefined[default_par-1].xres = xres;
 
3042                 atafb_predefined[default_par-1].yres = yres;
 
3043                 atafb_predefined[default_par-1].bits_per_pixel = depth;
 
3047 int __init atafb_setup( char *options )
 
3052     fb_info.fontname[0] = '\0';
 
3054     if (!options || !*options)
 
3057     while ((this_opt = strsep(&options, ",")) != NULL) {         
 
3058         if (!*this_opt) continue;
 
3059         if ((temp=get_video_mode(this_opt)))
 
3061         else if (! strcmp(this_opt, "inverse"))
 
3063         else if (!strncmp(this_opt, "font:", 5))
 
3064            strcpy(fb_info.fontname, this_opt+5);
 
3065         else if (! strncmp(this_opt, "hwscroll_",9)) {
 
3066                 hwscroll=simple_strtoul(this_opt+9, NULL, 10);
 
3073         else if (!strcmp(this_opt,"mv300")) {
 
3074                 external_bitspercol = 8;
 
3075                 external_card_type = IS_MV300;
 
3077         else if (!strncmp(this_opt,"external:",9))
 
3078                 atafb_setup_ext(this_opt+9);
 
3080         else if (!strncmp(this_opt,"internal:",9))
 
3081                 atafb_setup_int(this_opt+9);
 
3083         else if (!strncmp(this_opt, "eclock:", 7)) {
 
3084                 fext.f = simple_strtoul(this_opt+7, NULL, 10);
 
3085                 /* external pixelclock in kHz --> ps */
 
3086                 fext.t = 1000000000/fext.f;
 
3089         else if (!strncmp(this_opt, "monitorcap:", 11))
 
3090                 atafb_setup_mcap(this_opt+11);
 
3092         else if (!strcmp(this_opt, "keep"))
 
3094         else if (!strncmp(this_opt, "R", 1))
 
3095                 atafb_setup_user(this_opt+1);
 
3101 MODULE_LICENSE("GPL");
 
3103 int init_module(void)
 
3105         return atafb_init();