root/arch/m68k/atari/atafb.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_video_mode
  2. tt_encode_fix
  3. tt_decode_var
  4. tt_encode_var
  5. tt_get_par
  6. tt_set_par
  7. tt_getcolreg
  8. tt_setcolreg
  9. tt_detect
  10. hxx_prescale
  11. falcon_encode_fix
  12. falcon_decode_var
  13. falcon_encode_var
  14. falcon_get_par
  15. falcon_set_par
  16. falcon_vbl_switcher
  17. falcon_pan_display
  18. falcon_getcolreg
  19. falcon_setcolreg
  20. falcon_blank
  21. falcon_detect
  22. stste_encode_fix
  23. stste_decode_var
  24. stste_encode_var
  25. stste_get_par
  26. stste_set_par
  27. stste_getcolreg
  28. stste_setcolreg
  29. stste_detect
  30. stste_set_screen_base
  31. st_ovsc_switch
  32. ext_encode_fix
  33. ext_decode_var
  34. ext_encode_var
  35. ext_get_par
  36. ext_set_par
  37. ext_getcolreg
  38. ext_setcolreg
  39. ext_detect
  40. set_screen_base
  41. pan_display
  42. atari_fb_get_par
  43. atari_fb_set_par
  44. fb_update_var
  45. do_fb_set_var
  46. get_default_colormap
  47. do_fb_get_cmap
  48. do_fb_set_cmap
  49. do_install_cmap
  50. memcpy_fs
  51. copy_cmap
  52. alloc_cmap
  53. atari_fb_get_fix
  54. atari_fb_get_var
  55. atari_fb_set_disp
  56. atari_fb_set_var
  57. atari_fb_get_cmap
  58. atari_fb_set_cmap
  59. atari_fb_pan_display
  60. atari_fb_ioctl
  61. check_default_par
  62. atafb_switch
  63. atafb_blank
  64. atari_fb_init
  65. strtoke
  66. atari_video_setup

   1 /*
   2  * atari/atafb.c -- Low level implementation of Atari frame buffer device
   3  *
   4  *  Copyright (C) 1994 Martin Schaller & Roman Hodek
   5  *  
   6  * This file is subject to the terms and conditions of the GNU General Public
   7  * License.  See the file README.legal in the main directory of this archive
   8  * for more details.
   9  *
  10  * History:
  11  *   - 03 Jan 95: Original version by Martin Schaller: The TT driver and
  12  *                all the device independent stuff
  13  *   - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch)
  14  *                and wrote the Falcon, ST(E), and External drivers
  15  *                based on the original TT driver.
  16  *   - 07 May 95: Martin: Added colormap operations for the external driver
  17  *   - 21 May 95: Martin: Added support for overscan
  18  *                Andreas: some bug fixes for this
  19  *   -    Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>:
  20  *                Programmable Falcon video modes
  21  *                (thanks to Christian Cartus for documentation
  22  *                of VIDEL registers).
  23  *   - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]"
  24  *                on minor 24...31. "user0" may be set on commandline by
  25  *                "R<x>;<y>;<depth>". (Makes sense only on Falcon)
  26  *                Video mode switch on Falcon now done at next VBL interrupt
  27  *                to avoid the annoying right shift of the screen.
  28  *
  29  *
  30  * To do:
  31  *   - For the Falcon it is not possible to set random video modes on
  32  *     SM124 and SC/TV, only the bootup resolution is supported.
  33  *
  34  */
  35 
  36 #define ATAFB_TT
  37 #define ATAFB_STE
  38 #define ATAFB_EXT
  39 #define ATAFB_FALCON
  40 
  41 #include <linux/kernel.h>
  42 #include <linux/errno.h>
  43 #include <linux/string.h>
  44 #include <linux/mm.h>
  45 #include <linux/tty.h>
  46 #include <linux/malloc.h>
  47 #include <linux/delay.h>
  48 
  49 #include <asm/segment.h>
  50 #include <asm/pgtable.h>
  51 #include <asm/irq.h>
  52 
  53 #include <asm/atarihw.h>
  54 #include <asm/atariints.h>
  55 #include <asm/bootinfo.h>
  56 
  57 #include <linux/fb.h>
  58 #include <asm/atarikb.h>
  59 
  60 #define SWITCH_ACIA 0x01                /* modes for switch on OverScan */
  61 #define SWITCH_SND6 0x40
  62 #define SWITCH_SND7 0x80
  63 #define SWITCH_NONE 0x00
  64 
  65 
  66 #define arraysize(x)                    (sizeof(x)/sizeof(*(x)))
  67 
  68 #define up(x, r) (((x) + (r) - 1) & ~((r)-1))
  69 
  70 
  71 static int default_par=0;       /* default resolution (0=none) */
  72 
  73 static int node;                /* node of the /dev/fb?current file */
  74 
  75 static unsigned long default_mem_req=0;
  76 
  77 static int hwscroll=-1;
  78 
  79 static int use_hwscroll = 1;
  80 
  81 static int sttt_xres=640,st_yres=400,tt_yres=480;
  82 static int sttt_xres_virtual=640,sttt_yres_virtual=400;
  83 static int ovsc_offset=0, ovsc_addlen=0;
  84 int        ovsc_switchmode=0;
  85 
  86 #ifdef ATAFB_FALCON
  87 static int pwrsave = 0; /* use VESA suspend mode instead of blanking only? */
  88 #endif
  89 
  90 static struct atari_fb_par {
  91         unsigned long screen_base;
  92         int vyres;
  93         union {
  94                 struct {
  95                         int mode;
  96                         int sync;
  97                 } tt, st;
  98                 struct falcon_hw {
  99                         /* Here are fields for storing a video mode, as direct
 100                          * parameters for the hardware.
 101                          */
 102                         short sync;
 103                         short line_width;
 104                         short line_offset;
 105                         short st_shift;
 106                         short f_shift;
 107                         short vid_control;
 108                         short vid_mode;
 109                         short xoffset;
 110                         short hht, hbb, hbe, hdb, hde, hss;
 111                         short vft, vbb, vbe, vdb, vde, vss;
 112                         /* auxiliary informations */
 113                         short mono;
 114                         short ste_mode;
 115                         short bpp;
 116                 } falcon;
 117                 /* Nothing needed for external mode */
 118         } hw;
 119 } current_par;
 120 
 121 /* Don't calculate an own resolution, and thus don't change the one found when
 122  * booting (currently used for the Falcon to keep settings for internal video
 123  * hardware extensions (e.g. ScreenBlaster)  */
 124 static int DontCalcRes = 0; 
 125 
 126 #define HHT hw.falcon.hht
 127 #define HBB hw.falcon.hbb
 128 #define HBE hw.falcon.hbe
 129 #define HDB hw.falcon.hdb
 130 #define HDE hw.falcon.hde
 131 #define HSS hw.falcon.hss
 132 #define VFT hw.falcon.vft
 133 #define VBB hw.falcon.vbb
 134 #define VBE hw.falcon.vbe
 135 #define VDB hw.falcon.vdb
 136 #define VDE hw.falcon.vde
 137 #define VSS hw.falcon.vss
 138 #define VCO_CLOCK25             0x04
 139 #define VCO_CSYPOS              0x10
 140 #define VCO_VSYPOS              0x20
 141 #define VCO_HSYPOS              0x40
 142 #define VCO_SHORTOFFS   0x100
 143 #define VMO_DOUBLE              0x01
 144 #define VMO_INTER               0x02
 145 #define VMO_PREMASK             0x0c
 146 
 147 static struct fb_info fb_info;
 148 
 149 static unsigned long screen_base;       /* base address of screen */
 150 static unsigned long real_screen_base;  /* (only for Overscan) */
 151 
 152 static int screen_len;
 153 
 154 static int current_par_valid=0; 
 155 
 156 static int currcon=0;
 157 
 158 static int mono_moni=0;
 159 
 160 static struct display disp[MAX_NR_CONSOLES];
 161 
 162 
 163 #ifdef ATAFB_EXT
 164 /* external video handling */
 165 
 166 static unsigned                 external_xres;
 167 static unsigned                 external_yres;
 168 static unsigned                 external_depth;
 169 static int                              external_pmode;
 170 static unsigned long    external_addr = 0;
 171 static unsigned long    external_len;
 172 static unsigned long    external_vgaiobase = 0;
 173 static unsigned int             external_bitspercol = 6;
 174 
 175 /* 
 176 ++JOE <joe@amber.dinoco.de>: 
 177 added card type for external driver, is only needed for
 178 colormap handling.
 179 */
 180 
 181 enum cardtype { IS_VGA, IS_MV300 };
 182 static enum cardtype external_card_type = IS_VGA;
 183 
 184 /*
 185 The MV300 mixes the color registers. So we need an array of munged
 186 indices in order to acces the correct reg.
 187 */
 188 static int MV300_reg_1bit[2]={0,1};
 189 static int MV300_reg_4bit[16]={
 190 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
 191 static int MV300_reg_8bit[256]={
 192 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 
 193 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, 
 194 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, 
 195 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, 
 196 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, 
 197 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, 
 198 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, 
 199 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, 
 200 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, 
 201 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, 
 202 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, 
 203 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, 
 204 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, 
 205 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, 
 206 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, 
 207 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; 
 208 
 209 static int *MV300_reg = MV300_reg_8bit;
 210 
 211 /*
 212 And on the MV300 it's difficult to read out the hardware palette. So we
 213 just keep track of the set colors in our own array here, and use that!
 214 */
 215 
 216 struct { unsigned char red,green,blue,pad; } MV300_color[256];
 217 #endif /* ATAFB_EXT */
 218 
 219 
 220 int inverse=0;
 221 
 222 extern int fontheight_8x8;
 223 extern int fontwidth_8x8;
 224 extern unsigned char fontdata_8x8[];
 225 
 226 extern int fontheight_8x16;
 227 extern int fontwidth_8x16;
 228 extern unsigned char fontdata_8x16[];
 229 
 230 /* import first 16 colors from fbcon.c */
 231 extern unsigned short packed16_cmap[16];
 232 
 233 
 234 /* ++roman: This structure abstracts from the underlying hardware (ST(e),
 235  * TT, or Falcon.
 236  *
 237  * int (*detect)( void )
 238  *   This function should detect the current video mode settings and
 239  *   store them in atari_fb_predefined[0] for later reference by the
 240  *   user. Return the index+1 of an equivalent predefined mode or 0
 241  *   if there is no such.
 242  * 
 243  * int (*encode_fix)( struct fb_fix_screeninfo *fix,
 244  *                    struct atari_fb_par *par )
 245  *   This function should fill in the 'fix' structure based on the
 246  *   values in the 'par' structure.
 247  *   
 248  * int (*decode_var)( struct fb_var_screeninfo *var,
 249  *                    struct atari_fb_par *par )
 250  *   Get the video params out of 'var'. If a value doesn't fit, round
 251  *   it up, if it's too big, return EINVAL.
 252  *   Round up in the following order: bits_per_pixel, xres, yres, 
 253  *   xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
 254  *   horizontal timing, vertical timing.
 255  *
 256  * int (*encode_var)( struct fb_var_screeninfo *var,
 257  *                    struct atari_fb_par *par );
 258  *   Fill the 'var' structure based on the values in 'par' and maybe
 259  *   other values read out of the hardware.
 260  *   
 261  * void (*get_par)( struct atari_fb_par *par )
 262  *   Fill the hardware's 'par' structure.
 263  *   
 264  * void (*set_par)( struct atari_fb_par *par )
 265  *   Set the hardware according to 'par'.
 266  *   
 267  * int (*setcolreg)( unsigned regno, unsigned red,
 268  *                   unsigned green, unsigned blue,
 269  *                   unsigned transp )
 270  *   Set a single color register. The values supplied are already
 271  *   rounded down to the hardware's capabilities (according to the
 272  *   entries in the var structure). Return != 0 for invalid regno.
 273  *
 274  * int (*getcolreg)( unsigned regno, unsigned *red,
 275  *                   unsigned *green, unsigned *blue,
 276  *                   unsigned *transp )
 277  *   Read a single color register and split it into
 278  *   colors/transparent. Return != 0 for invalid regno.
 279  *
 280  * void (*set_screen_base)( unsigned long s_base )
 281  *   Set the base address of the displayed frame buffer. Only called
 282  *   if yres_virtual > yres or xres_virtual > xres.
 283  *
 284  * int (*blank)( int blank_mode )
 285  *   Blank the screen if blank_mode != 0, else unblank. If NULL then blanking
 286  *   is done by setting the CLUT to black. Return != 0 if un-/blanking
 287  *   failed due to e.g. video mode which doesn't support it.
 288  */
 289 
 290 static struct fb_hwswitch {
 291         int  (*detect)( void );
 292         int  (*encode_fix)( struct fb_fix_screeninfo *fix,
 293                                                 struct atari_fb_par *par );
 294         int  (*decode_var)( struct fb_var_screeninfo *var,
 295                                                 struct atari_fb_par *par );
 296         int  (*encode_var)( struct fb_var_screeninfo *var,
 297                                                 struct atari_fb_par *par );
 298         void (*get_par)( struct atari_fb_par *par );
 299         void (*set_par)( struct atari_fb_par *par );
 300         int  (*getcolreg)( unsigned regno, unsigned *red,
 301                                            unsigned *green, unsigned *blue,
 302                                            unsigned *transp );
 303         int  (*setcolreg)( unsigned regno, unsigned red,
 304                                            unsigned green, unsigned blue,
 305                                            unsigned transp );
 306         void (*set_screen_base)( unsigned long s_base );
 307         int  (*blank)( int blank_mode );
 308         int  (*pan_display)( struct fb_var_screeninfo *var,
 309                                                  struct atari_fb_par *par);
 310 } *fbhw;
 311 
 312 static char *autodetect_names[] = {"autodetect", NULL};
 313 static char *stlow_names[] = {"stlow", NULL};
 314 static char *stmid_names[] = {"stmid", "default5", NULL};
 315 static char *sthigh_names[] = {"sthigh", "default4", NULL};
 316 static char *ttlow_names[] = {"ttlow", NULL};
 317 static char *ttmid_names[]= {"ttmid", "default1", NULL};
 318 static char *tthigh_names[]= {"tthigh", "default2", NULL};
 319 static char *vga2_names[] = {"vga2", NULL};
 320 static char *vga4_names[] = {"vga4", NULL};
 321 static char *vga16_names[] = {"vga16", "default3", NULL};
 322 static char *vga256_names[] = {"vga256", NULL};
 323 static char *falh2_names[] = {"falh2", NULL};
 324 static char *falh16_names[] = {"falh16", NULL};
 325 static char *user0_names[] = {"user0", NULL};
 326 static char *user1_names[] = {"user1", NULL};
 327 static char *user2_names[] = {"user2", NULL};
 328 static char *user3_names[] = {"user3", NULL};
 329 static char *user4_names[] = {"user4", NULL};
 330 static char *user5_names[] = {"user5", NULL};
 331 static char *user6_names[] = {"user6", NULL};
 332 static char *user7_names[] = {"user7", NULL};
 333 static char *dummy_names[] = {"dummy", NULL};
 334 
 335 char **fb_var_names[] = {
 336         /* Writing the name arrays directly in this array (via "(char *[]){...}")
 337          * crashes gcc 2.5.8 (sigsegv) if the inner array
 338          * contains more than two items. I've also seen that all elements
 339          * were identical to the last (my cross-gcc) :-(*/
 340         autodetect_names,
 341         stlow_names,
 342         stmid_names,
 343         sthigh_names,
 344         ttlow_names,
 345         ttmid_names,
 346         tthigh_names,
 347         vga2_names,
 348         vga4_names,
 349         vga16_names,
 350         vga256_names,
 351         falh2_names,
 352         falh16_names,
 353         dummy_names, dummy_names, dummy_names, dummy_names,
 354         dummy_names, dummy_names, dummy_names, dummy_names,
 355         dummy_names, dummy_names,
 356         user0_names,
 357         user1_names,
 358         user2_names,
 359         user3_names,
 360         user4_names,
 361         user5_names,
 362         user6_names,
 363         user7_names,
 364         NULL
 365         /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */
 366 };
 367 
 368 struct fb_var_screeninfo atari_fb_predefined[] = {
 369         { /* autodetect */
 370           0, 0, 0, 0, 0, 0, 0, 0,               /* xres-grayscale */
 371           {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},   /* red green blue tran*/
 372           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 373         { /* st low */
 374           320, 200, 320, 200, 0, 0, 4, 0,               /* xres-grayscale */
 375           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},   /* red green blue tran*/
 376           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 377         { /* st mid */
 378           640, 200, 640, 200, 0, 0, 2, 0,               /* xres-grayscale */
 379           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},   /* red green blue tran*/
 380           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 381         { /* st high */
 382           640, 400, 640, 400, 0, 0, 1, 0,               /* xres-grayscale */
 383           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},   /* red green blue tran*/
 384           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 385         { /* tt low */
 386           320, 480, 320, 480, 0, 0, 8, 0,               /* xres-grayscale */
 387           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},   /* red green blue tran*/
 388           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 389         { /* tt mid */
 390           640, 480, 640, 480, 0, 0, 4, 0,               /* xres-grayscale */
 391           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},   /* red green blue tran*/
 392           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 393         { /* tt high */
 394           1280, 960, 1280, 960, 0, 0, 1, 0,             /* xres-grayscale */
 395           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},   /* red green blue tran*/
 396           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 397         { /* vga2 */
 398           640, 480, 640, 480, 0, 0, 1, 0,               /* xres-grayscale */
 399           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},   /* red green blue tran*/
 400           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 401         { /* vga4 */
 402           640, 480, 640, 480, 0, 0, 2, 0,               /* xres-grayscale */
 403           {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0},   /* red green blue tran*/
 404           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 405         { /* vga16 */
 406           640, 480, 640, 480, 0, 0, 4, 0,               /* xres-grayscale */
 407           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},   /* red green blue tran*/
 408           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 409         { /* vga256 */
 410           640, 480, 640, 480, 0, 0, 8, 0,               /* xres-grayscale */
 411           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},   /* red green blue tran*/
 412           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 413         { /* falh2 */
 414           896, 608, 896, 608, 0, 0, 1, 0,               /* xres-grayscale */
 415           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},   /* red green blue tran*/
 416           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 417         { /* falh16 */
 418           896, 608, 896, 608, 0, 0, 4, 0,               /* xres-grayscale */
 419           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},   /* red green blue tran*/
 420           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 421         /* Minor 14..23 free for more standard video modes */
 422         { 0, },
 423         { 0, },
 424         { 0, },
 425         { 0, },
 426         { 0, },
 427         { 0, },
 428         { 0, },
 429         { 0, },
 430         { 0, },
 431         { 0, },
 432         /* Minor 24..31 reserved for user defined video modes */
 433         { /* user0, initialized to Rx;y;d from commandline, if supplied */
 434           0, 0, 0, 0, 0, 0, 0, 0,
 435           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 436           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 437         { /* user1 */
 438           0, 0, 0, 0, 0, 0, 0, 0,
 439           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 440           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 441         { /* user2 */
 442           0, 0, 0, 0, 0, 0, 0, 0,
 443           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 444           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 445         { /* user3 */
 446           0, 0, 0, 0, 0, 0, 0, 0,
 447           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 448           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 449         { /* user4 */
 450           0, 0, 0, 0, 0, 0, 0, 0,
 451           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 452           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 453         { /* user5 */
 454           0, 0, 0, 0, 0, 0, 0, 0,
 455           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 456           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 457         { /* user6 */
 458           0, 0, 0, 0, 0, 0, 0, 0,
 459           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 460           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 },
 461         { /* user7 */
 462           0, 0, 0, 0, 0, 0, 0, 0,
 463           {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
 464           0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }
 465 };
 466 
 467 int num_atari_fb_predefined=arraysize(atari_fb_predefined);
 468 
 469 
 470 static int
 471 get_video_mode(char *vname)
     /* [previous][next][first][last][top][bottom][index][help] */
 472 {
 473     char ***name_list;
 474     char **name;
 475     int i;
 476     name_list=fb_var_names;
 477     for (i = 0 ; i < num_atari_fb_predefined ; i++) {
 478         name=*(name_list++);
 479         if (! name || ! *name)
 480             break;
 481         while (*name) {
 482             if (! strcmp(vname, *name))
 483                 return i+1;
 484             name++;
 485         }
 486     }
 487     return 0;
 488 }
 489 
 490 
 491 
 492 /* ------------------- TT specific functions ---------------------- */
 493 
 494 #ifdef ATAFB_TT
 495 
 496 static int tt_encode_fix( struct fb_fix_screeninfo *fix,
     /* [previous][next][first][last][top][bottom][index][help] */
 497                                                   struct atari_fb_par *par )
 498 
 499 {
 500         int mode, i;
 501 
 502         strcpy(fix->id,"Atari Builtin");
 503         fix->smem_start=real_screen_base;
 504         fix->smem_len = screen_len;
 505         fix->type=FB_TYPE_INTERLEAVED_PLANES;
 506         fix->type_aux=2;
 507         fix->visual=FB_VISUAL_PSEUDOCOLOR;
 508         mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK;
 509         if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) {
 510                 fix->type=FB_TYPE_PACKED_PIXELS;
 511                 fix->type_aux=0;
 512                 if (mode == TT_SHIFTER_TTHIGH)
 513                         fix->visual=FB_VISUAL_MONO01;
 514         }
 515         fix->xpanstep=0;
 516         fix->ypanstep=1;
 517         fix->ywrapstep=0;
 518         for (i=0; i<arraysize(fix->reserved); i++)
 519                 fix->reserved[i]=0;
 520         return 0;
 521 }
 522 
 523 
 524 static int tt_decode_var( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
 525                                                   struct atari_fb_par *par )
 526 {
 527         int xres=var->xres;
 528         int yres=var->yres;
 529         int bpp=var->bits_per_pixel;
 530         int linelen;
 531 
 532         if (mono_moni) {
 533                 if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2)
 534                         return -EINVAL;
 535                 par->hw.tt.mode=TT_SHIFTER_TTHIGH;
 536                 xres=sttt_xres*2;
 537                 yres=tt_yres*2;
 538                 bpp=1;
 539         } else {
 540                 if (bpp > 8 || xres > sttt_xres || yres > tt_yres)
 541                         return -EINVAL;
 542                 if (bpp > 4) {
 543                         if (xres > sttt_xres/2 || yres > tt_yres)
 544                                 return -EINVAL;
 545                         par->hw.tt.mode=TT_SHIFTER_TTLOW;
 546                         xres=sttt_xres/2;
 547                         yres=tt_yres;
 548                         bpp=8;
 549                 }
 550                 else if (bpp > 2) {
 551                         if (xres > sttt_xres || yres > tt_yres)
 552                                 return -EINVAL;
 553                         if (xres > sttt_xres/2 || yres > st_yres/2) {
 554                                 par->hw.tt.mode=TT_SHIFTER_TTMID;
 555                                 xres=sttt_xres;
 556                                 yres=tt_yres;
 557                                 bpp=4;
 558                         }
 559                         else {
 560                                 par->hw.tt.mode=TT_SHIFTER_STLOW;
 561                                 xres=sttt_xres/2;
 562                                 yres=st_yres/2;
 563                                 bpp=4;
 564                         }
 565                 }
 566                 else if (bpp > 1) {
 567                         if (xres > sttt_xres || yres > st_yres/2)
 568                                 return -EINVAL;
 569                         par->hw.tt.mode=TT_SHIFTER_STMID;
 570                         xres=sttt_xres;
 571                         yres=st_yres/2;
 572                         bpp=2;
 573                 }
 574                 else if (var->xres > sttt_xres || var->yres > st_yres) {
 575                         return -EINVAL;
 576                 }
 577                 else {
 578                         par->hw.tt.mode=TT_SHIFTER_STHIGH;
 579                         xres=sttt_xres;
 580                         yres=st_yres;
 581                         bpp=1;
 582                 }
 583         }
 584         if (var->sync & FB_SYNC_EXT)
 585                 par->hw.tt.sync=0;
 586         else
 587                 par->hw.tt.sync=1;
 588         linelen=xres*bpp/8;
 589         if ((var->yoffset + yres)*linelen > screen_len && screen_len)
 590                 return -EINVAL;
 591         par->screen_base=screen_base+ var->yoffset*linelen;
 592         return 0;
 593 }
 594 
 595 static int tt_encode_var( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
 596                                                   struct atari_fb_par *par )
 597 {
 598         int linelen, i;
 599         var->red.offset=0;
 600         var->red.length=4;
 601         var->red.msb_right=0;
 602         var->grayscale=0;
 603 
 604         var->pixclock=31041;
 605         var->left_margin=120;           /* these may be incorrect       */
 606         var->right_margin=100;
 607         var->upper_margin=8;
 608         var->lower_margin=16;
 609         var->hsync_len=140;
 610         var->vsync_len=30;
 611 
 612         var->height=-1;
 613         var->width=-1;
 614 
 615         if (par->hw.tt.sync & 1)
 616                 var->sync=0;
 617         else
 618                 var->sync=FB_SYNC_EXT;
 619 
 620         switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) {
 621         case TT_SHIFTER_STLOW:
 622                 var->xres=sttt_xres/2;
 623                 var->xres_virtual=sttt_xres_virtual/2;
 624                 var->yres=st_yres/2;
 625                 var->bits_per_pixel=4;
 626                 break;
 627         case TT_SHIFTER_STMID:
 628                 var->xres=sttt_xres;
 629                 var->xres_virtual=sttt_xres_virtual;
 630                 var->yres=st_yres/2;
 631                 var->bits_per_pixel=2;
 632                 break;
 633         case TT_SHIFTER_STHIGH:
 634                 var->xres=sttt_xres;
 635                 var->xres_virtual=sttt_xres_virtual;
 636                 var->yres=st_yres;
 637                 var->bits_per_pixel=1;
 638                 break;
 639         case TT_SHIFTER_TTLOW:
 640                 var->xres=sttt_xres/2;
 641                 var->xres_virtual=sttt_xres_virtual/2;
 642                 var->yres=tt_yres;
 643                 var->bits_per_pixel=8;
 644                 break;
 645         case TT_SHIFTER_TTMID:
 646                 var->xres=sttt_xres;
 647                 var->xres_virtual=sttt_xres_virtual;
 648                 var->yres=tt_yres;
 649                 var->bits_per_pixel=4;
 650                 break;
 651         case TT_SHIFTER_TTHIGH:
 652                 var->red.length=0;
 653                 var->xres=sttt_xres*2;
 654                 var->xres_virtual=sttt_xres_virtual*2;
 655                 var->yres=tt_yres*2;
 656                 var->bits_per_pixel=1;
 657                 break;
 658         }               
 659         var->blue=var->green=var->red;
 660         var->transp.offset=0;
 661         var->transp.length=0;
 662         var->transp.msb_right=0;
 663         linelen=var->xres_virtual * var->bits_per_pixel / 8;
 664         if (! use_hwscroll)
 665                 var->yres_virtual=var->yres;
 666         else if (screen_len)
 667                 var->yres_virtual=screen_len/linelen;
 668         else {
 669                 if (hwscroll < 0)
 670                         var->yres_virtual = 2 * var->yres;
 671                 else
 672                         var->yres_virtual=var->yres+hwscroll * 16;
 673         }
 674         var->xoffset=0;
 675         if (screen_base)
 676                 var->yoffset=(par->screen_base - screen_base)/linelen;
 677         else
 678                 var->yoffset=0;
 679         var->nonstd=0;
 680         var->activate=0;
 681         var->vmode=FB_VMODE_NONINTERLACED;
 682         for (i=0; i<arraysize(var->reserved); i++)
 683                 var->reserved[i]=0;
 684         return 0;
 685 }
 686 
 687 
 688 static void tt_get_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
 689 {
 690         unsigned long addr;
 691         par->hw.tt.mode=shifter_tt.tt_shiftmode;
 692         par->hw.tt.sync=shifter.syncmode;
 693         addr = ((shifter.bas_hi & 0xff) << 16) |
 694                ((shifter.bas_md & 0xff) << 8)  |
 695                ((shifter.bas_lo & 0xff));
 696         par->screen_base = PTOV(addr);
 697 }
 698 
 699 static void tt_set_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
 700 {
 701         shifter_tt.tt_shiftmode=par->hw.tt.mode;
 702         shifter.syncmode=par->hw.tt.sync;
 703         /* only set screen_base if really necessary */
 704         if (current_par.screen_base != par->screen_base)
 705                 fbhw->set_screen_base(par->screen_base);
 706 }
 707 
 708 
 709 static int tt_getcolreg( unsigned regno, unsigned *red,
     /* [previous][next][first][last][top][bottom][index][help] */
 710                                                  unsigned *green, unsigned *blue,
 711                                                  unsigned *transp )
 712 {
 713         if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
 714                 regno += 254;
 715         if (regno > 255)
 716                 return 1;
 717         *blue = tt_palette[regno];
 718         *green = (*blue >> 4) & 0xf;
 719         *red = (*blue >> 8) & 0xf;
 720         *blue &= 0xf;
 721         *transp = 0;
 722         return 0;
 723 }
 724 
 725 
 726 static int tt_setcolreg( unsigned regno, unsigned red,
     /* [previous][next][first][last][top][bottom][index][help] */
 727                                                  unsigned green, unsigned blue,
 728                                                  unsigned transp )
 729 {
 730         if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
 731                 regno += 254;
 732         if (regno > 255)
 733                 return 1;
 734         tt_palette[regno] = (red << 8) | (green << 4) | blue;
 735         if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
 736                 TT_SHIFTER_STHIGH && regno == 254)
 737                 tt_palette[0] = 0;
 738         return 0;
 739 }
 740 
 741                                                   
 742 static int tt_detect( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 743 
 744 {       struct atari_fb_par par;
 745 
 746         /* Determine the connected monitor: The DMA sound must be
 747          * disabled before reading the MFP GPIP, because the Sound
 748          * Done Signal and the Monochrome Detect are XORed together!
 749          *
 750          * Even on a TT, we should look if there is a DMA sound. It was
 751          * announced that the Eagle is TT compatible, but only the PCM is
 752          * missing...
 753          */
 754         if (ATARIHW_PRESENT(PCM_8BIT)) { 
 755                 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
 756                 udelay(20);     /* wait a while for things to settle down */
 757         }
 758         mono_moni = (mfp.par_dt_reg & 0x80) == 0;
 759 
 760         tt_get_par(&par);
 761         tt_encode_var(&atari_fb_predefined[0], &par);
 762 
 763         return 1;
 764 }
 765 
 766 #endif /* ATAFB_TT */
 767 
 768 /* ------------------- Falcon specific functions ---------------------- */
 769 
 770 #ifdef ATAFB_FALCON
 771 
 772 static int mon_type;            /* Falcon connected monitor */
 773 static int f030_bus_width;      /* Falcon ram bus width (for vid_control) */
 774 #define F_MON_SM        0
 775 #define F_MON_SC        1
 776 #define F_MON_VGA       2
 777 #define F_MON_TV        3
 778 
 779 /* Multisync monitor capabilities */
 780 /* Atari-TOS defaults if no boot option present */
 781 static long vfmin=58, vfmax=62, hfmin=31000, hfmax=32000;
 782 
 783 static struct pixel_clock {
 784         unsigned long f;        /* f/[Hz] */
 785         unsigned long t;        /* t/[ps] (=1/f) */
 786         short right, hsync, left;       /* standard timing in clock cycles, not pixel */
 787                 /* hsync initialized in falcon_detect() */
 788         short sync_mask;        /* or-mask for hw.falcon.sync to set this clock */
 789         short control_mask; /* ditto, for hw.falcon.vid_control */
 790 }
 791 f25  = {25175000, 39722, 18, 0, 42, 0x0, VCO_CLOCK25},
 792 f32  = {32000000, 31250, 18, 0, 42, 0x0, 0},
 793 fext = {       0,     0, 18, 0, 42, 0x1, 0};
 794 
 795 /* VIDEL-prescale values [mon_type][pixel_length from VCO] */
 796 static short vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
 797 
 798 /* Default hsync timing [mon_type] in picoseconds */
 799 static long h_syncs[4] = {3000000, 4700000, 4000000, 4700000};
 800 
 801 
 802 static inline int hxx_prescale(struct falcon_hw *hw)
     /* [previous][next][first][last][top][bottom][index][help] */
 803 {
 804         return hw->ste_mode ? 16 :
 805                    vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3];
 806 }
 807 
 808 static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
     /* [previous][next][first][last][top][bottom][index][help] */
 809                                                           struct atari_fb_par *par )
 810 {
 811         int i;
 812 
 813         strcpy(fix->id, "Atari Builtin");
 814         fix->smem_start = real_screen_base;
 815         fix->smem_len = screen_len;
 816         fix->type = FB_TYPE_INTERLEAVED_PLANES;
 817         fix->type_aux = 2;
 818         fix->visual = FB_VISUAL_PSEUDOCOLOR;
 819         if (par->hw.falcon.mono) {
 820                 fix->type = FB_TYPE_PACKED_PIXELS;
 821                 fix->type_aux = 0;
 822         }
 823         else if (par->hw.falcon.f_shift & 0x100) {
 824                 fix->type = FB_TYPE_PACKED_PIXELS;
 825                 fix->type_aux = 0;
 826                 fix->visual = FB_VISUAL_TRUECOLOR;  /* is this ok or should this be DIRECTCOLOR? */
 827         }
 828         if (par->hw.falcon.mono)
 829                 /* no smooth scrolling possible with longword aligned video mem */
 830                 fix->xpanstep = 32;
 831         else
 832                 fix->xpanstep = 1;
 833         fix->ypanstep = 1;
 834         fix->ywrapstep = 0;
 835         for (i=0; i<arraysize(fix->reserved); i++)
 836                 fix->reserved[i]=0;
 837         return 0;
 838 }
 839 
 840 
 841 static int falcon_decode_var( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
 842                                                           struct atari_fb_par *par )
 843 {
 844         int use_default_timing = 0;
 845         int bpp = var->bits_per_pixel;
 846         int xres = var->xres;
 847         int yres = var->yres;
 848         int xres_virtual = var->xres_virtual;
 849         int yres_virtual = var->yres_virtual;
 850         int left_margin, right_margin, hsync_len;
 851         int upper_margin, lower_margin, vsync_len;
 852         int linelen;
 853         int interlace = 0, doubleline = 0;
 854         struct pixel_clock *pclock;
 855         int plen; /* width of pixel in clock cycles */
 856         int xstretch;
 857         int prescale;
 858         int longoffset = 0;
 859         int hfreq, vfreq;
 860 
 861 /*
 862         Get the video params out of 'var'. If a value doesn't fit, round
 863         it up, if it's too big, return EINVAL.
 864         Round up in the following order: bits_per_pixel, xres, yres, 
 865         xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, 
 866         horizontal timing, vertical timing.
 867 
 868         There is a maximum of screen resolution determined by pixelclock
 869         and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock.
 870         In interlace mode this is     "     *    "     *vfmin <= pixelclock.
 871         Additional constraints: hfreq.
 872         Frequency range for multisync monitors is given via command line.
 873         For TV and SM124 both frequencies are fixed.
 874 
 875         X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0)
 876         Y % 16 == 0 to fit 8x16 font
 877         Y % 8 == 0 if Y<400
 878 
 879         Currently interlace and doubleline mode in var are ignored. 
 880         On SM124 and TV only the standard resolutions can be used.
 881 */
 882 
 883         /* Reject uninitialized mode */
 884         if (!xres || !yres || !bpp)
 885                 return -EINVAL;
 886 
 887         if (mon_type == F_MON_SM && bpp != 1) {
 888                 return -EINVAL;
 889         }
 890         else if (bpp <= 1) {
 891                 bpp = 1;
 892                 par->hw.falcon.f_shift = 0x400;
 893                 par->hw.falcon.st_shift = 0x200;
 894         }
 895         else if (bpp <= 2) {
 896                 bpp = 2;
 897                 par->hw.falcon.f_shift = 0x000;
 898                 par->hw.falcon.st_shift = 0x100;
 899         }
 900         else if (bpp <= 4) {
 901                 bpp = 4;
 902                 par->hw.falcon.f_shift = 0x000;
 903                 par->hw.falcon.st_shift = 0x000;
 904         }
 905         else if (bpp <= 8) {
 906                 bpp = 8;
 907                 par->hw.falcon.f_shift = 0x010;
 908         }
 909         else if (bpp <= 16) {
 910                 bpp = 16; /* packed pixel mode */
 911                 par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */
 912         }
 913         else
 914                 return -EINVAL;
 915         par->hw.falcon.bpp = bpp;
 916 
 917         if (mon_type != F_MON_VGA || DontCalcRes) {
 918                 /* Skip all calculations, VGA multisync only yet */
 919                 struct fb_var_screeninfo *myvar = &atari_fb_predefined[0];
 920                 
 921                 if (bpp > myvar->bits_per_pixel ||
 922                         var->xres > myvar->xres ||
 923                         var->yres > myvar->yres)
 924                         return -EINVAL;
 925                 fbhw->get_par(par);     /* Current par will be new par */
 926                 goto set_screen_base;   /* Don't forget this */
 927         }
 928 
 929         /* Only some fixed resolutions < 640x480 */
 930         if (xres <= 320)
 931                 xres = 320;
 932         else if (xres <= 640 && bpp != 16)
 933                 xres = 640;
 934         if (yres <= 200)
 935                 yres = 200;
 936         else if (yres <= 240)
 937                 yres = 240;
 938         else if (yres <= 400)
 939                 yres = 400;
 940         else if (yres <= 480)
 941                 yres = 480;
 942 
 943         /* 2 planes must use STE compatibility mode */
 944         par->hw.falcon.ste_mode = bpp==2;
 945         par->hw.falcon.mono = bpp==1;
 946 
 947         /* Total and visible scanline length must be a multiple of one longword,
 948          * this and the console fontwidth yields the alignment for xres and
 949          * xres_virtual.
 950          *
 951          * Special case in STE mode: blank and graphic positions don't align,
 952          * avoid trash at right margin
 953          */
 954         if (par->hw.falcon.ste_mode)
 955                 xres = (xres + 63) & ~63;
 956         else if (bpp == 1)
 957                 xres = (xres + 31) & ~31;
 958         else
 959                 xres = (xres + 15) & ~15;
 960         if (yres >= 400)
 961                 yres = (yres + 15) & ~15;
 962         else
 963                 yres = (yres + 7) & ~7;
 964 
 965         if (xres_virtual < xres)
 966                 xres_virtual = xres;
 967         else if (bpp == 1)
 968                 xres_virtual = (xres_virtual + 31) & ~31;
 969         else
 970                 xres_virtual = (xres_virtual + 15) & ~15;
 971         /* <=0 : yres_virtual determined by screensize */
 972         if (yres_virtual < yres && yres_virtual > 0)
 973                 yres_virtual = yres;
 974 
 975         par->hw.falcon.line_width = bpp * xres / 16;
 976         par->hw.falcon.line_offset = bpp * (xres_virtual - xres) / 16;
 977 
 978         /* single or double pixel width */
 979         xstretch = (xres == 320) ? 2 : 1;
 980 
 981         /* Default values are used for vert./hor. timing if no pixelclock given. */
 982         if (var->pixclock == 0)
 983                 use_default_timing = 1;
 984 
 985 #if 0 /* currently unused */
 986         if (mon_type == F_MON_SM) {
 987                 if (xres != 640 && yres != 400)
 988                         return -EINVAL;
 989                 plen = 1;
 990                 pclock = &f32;
 991                 /* SM124-mode is special */
 992                 par->hw.falcon.ste_mode = 1;
 993                 par->hw.falcon.f_shift = 0x000;
 994                 par->hw.falcon.st_shift = 0x200;
 995                 left_margin = hsync_len = 128 / plen;
 996                 right_margin = 0;
 997                 /* TODO set all margins */
 998         }
 999         else if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
1000                 plen = 2 * xstretch;
1001                 pclock = &f32;
1002                 hsync_len = 150 / plen;
1003                 if (yres > 240)
1004                         interlace = 1;
1005                 /* TODO set margins */
1006         }
1007         else
1008 #endif
1009         {       /* F_MON_VGA */
1010                 if (bpp == 16)
1011                         xstretch = 2; /* hicolor only double pixel width */
1012                 if (use_default_timing) {
1013                         int linesize;
1014 
1015                         /* Choose master pixelclock depending on hor. timing */
1016                         plen = 1 * xstretch;
1017                         if ((plen * xres + f25.right+f25.hsync+f25.left) * hfmin < f25.f)
1018                                 pclock = &f25;
1019                         else if ((plen * xres + f32.right+f32.hsync+f32.left) * hfmin < f32.f)
1020                                 pclock = &f32;
1021                         else if ((plen * xres + fext.right+fext.hsync+fext.left) * hfmin < fext.f
1022                                  && fext.f)
1023                                 pclock = &fext;
1024                         else
1025                                 return -EINVAL;
1026 
1027                         left_margin = pclock->left / plen;
1028                         right_margin = pclock->right / plen;
1029                         hsync_len = pclock->hsync / plen;
1030                         linesize = left_margin + xres + right_margin + hsync_len;
1031                         upper_margin = 31;
1032                         lower_margin = 11;
1033                         vsync_len = 3;
1034                 }
1035                 else {
1036 #if 0 /* TODO enable this (untested yet) */
1037                         /* Round down pixelclock */
1038                         int i; unsigned long pcl=0;
1039                         for (i=1; i<=4; i*=2) {
1040                                 if (f25.t*i<=var->pixclock && pcl<f25.t*i) {
1041                                         pcl=f25.t*i; pclock=&f25;
1042                                 }
1043                                 if (f32.t*i<=var->pixclock && pcl<f32.t*i) {
1044                                         pcl=f32.t*i; pclock=&f32;
1045                                 }
1046                                 if (fext.t && fext.t*i<=var->pixclock && pcl<fext.t*i) {
1047                                         pcl=fext.t*i; pclock=&fext;
1048                                 }
1049                         }
1050                         if (!pcl)
1051                                 return -EINVAL;
1052                         plen = pcl / pclock->t;
1053 
1054 #else
1055                         if (var->pixclock == f25.t || var->pixclock == 2*f25.t)
1056                                 pclock = &f25;
1057                         else if (var->pixclock == f32.t || var->pixclock == 2*f32.t)
1058                                 pclock = &f32;
1059                         else if ((var->pixclock == fext.t || var->pixclock == 2*fext.t) && fext.t) {
1060                                 pclock = &fext;
1061                         }
1062                         else
1063                                 return -EINVAL;
1064                         plen = var->pixclock / pclock->t;
1065 #endif
1066 
1067                         left_margin = var->left_margin;
1068                         right_margin = var->right_margin;
1069                         hsync_len = var->hsync_len;
1070                         upper_margin = var->upper_margin;
1071                         lower_margin = var->lower_margin;
1072                         vsync_len = var->vsync_len;
1073                         if (var->vmode & FB_VMODE_INTERLACED) {
1074                                 /* # lines in half frame */
1075                                 upper_margin = (upper_margin + 1) / 2;
1076                                 lower_margin = (lower_margin + 1) / 2;
1077                                 vsync_len = (vsync_len + 1) / 2;
1078                         }
1079                 }
1080                 if (pclock == &fext)
1081                         longoffset = 1; /* VIDEL doesn't synchronize on short offset */
1082         }
1083         /* Is video bus bandwidth (32MB/s) too low for this resolution? */
1084         /* this is definitely wrong if bus clock != 32MHz */
1085         if (pclock->f / plen / 8 * bpp > 32000000L)
1086                 return -EINVAL;
1087 
1088         if (vsync_len < 1)
1089                 vsync_len = 1;
1090 
1091         /* include sync lengths in right/lower margin for all calculations */
1092         right_margin += hsync_len;
1093         lower_margin += vsync_len;
1094 
1095         /* ! In all calculations of margins we use # of lines in half frame
1096          * (which is a full frame in non-interlace mode), so we can switch
1097          * between interlace and non-interlace without messing around
1098          * with these.
1099          */
1100   again:
1101         /* Set base_offset 128 and video bus width */
1102         par->hw.falcon.vid_control = mon_type | f030_bus_width;
1103         if (!longoffset)
1104                 par->hw.falcon.vid_control |= VCO_SHORTOFFS;    /* base_offset 64 */
1105         if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1106                 par->hw.falcon.vid_control |= VCO_HSYPOS;
1107         if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1108                 par->hw.falcon.vid_control |= VCO_VSYPOS;
1109         /* Pixelclock */
1110         par->hw.falcon.vid_control |= pclock->control_mask;
1111         /* External or internal clock */
1112         par->hw.falcon.sync = pclock->sync_mask | 0x2;
1113         /* Pixellength and prescale */
1114         par->hw.falcon.vid_mode = (2/plen) << 2;
1115         if (doubleline)
1116                 par->hw.falcon.vid_mode |= VMO_DOUBLE;
1117         if (interlace)
1118                 par->hw.falcon.vid_mode |= VMO_INTER;
1119 
1120         /*********************
1121         Horizontal timing: unit = [master clock cycles]
1122         unit of hxx-registers: [master clock cycles * prescale]
1123         Hxx-registers are 9-bit wide
1124 
1125         1 line = ((hht + 2) * 2 * prescale) clock cycles
1126 
1127         graphic output = hdb & 0x200 ?
1128                ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff:
1129                ( hht + 2  - hdb + hde) * prescale - hdboff + hdeoff
1130         (this must be a multiple of plen*128/bpp, on VGA pixels
1131          to the right may be cut off with a bigger right margin)
1132 
1133         start of graphics relative to start of 1st halfline = hdb & 0x200 ?
1134                (hdb - hht - 2) * prescale + hdboff :
1135                hdb * prescale + hdboff
1136 
1137         end of graphics relative to start of 1st halfline =
1138                (hde + hht + 2) * prescale + hdeoff
1139         *********************/
1140         /* Calculate VIDEL registers */
1141         {
1142         int hdb_off, hde_off, base_off;
1143         int gstart, gend1, gend2, align;
1144 
1145         prescale = hxx_prescale(&par->hw.falcon);
1146         base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
1147 
1148         /* Offsets depend on video mode */
1149         /* Offsets are in clock cycles, divide by prescale to
1150          * calculate hd[be]-registers
1151          */
1152         if (par->hw.falcon.f_shift & 0x100) {
1153                 align = 1;
1154                 hde_off = 0;
1155                 hdb_off = (base_off + 16 * plen) + prescale;
1156         }
1157         else {
1158                 align = 128 / bpp;
1159                 hde_off = ((128 / bpp + 2) * plen);
1160                 if (par->hw.falcon.ste_mode)
1161                         hdb_off = (64 + base_off + (128 / bpp + 2) * plen) + prescale;
1162                 else
1163                         hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale;
1164         }
1165 
1166         gstart = (prescale/2 + plen * left_margin) / prescale;
1167         /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
1168         gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale;
1169         /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
1170         gend2 = gstart + xres * plen / prescale;
1171         par->HHT = plen * (left_margin + xres + right_margin) /
1172                            (2 * prescale) - 2;
1173 /*      par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
1174 
1175         par->HDB = gstart - hdb_off/prescale;
1176         par->HBE = gstart;
1177         if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200;
1178         par->HDE = gend1 - par->HHT - 2 - hde_off/prescale;
1179         par->HBB = gend2 - par->HHT - 2;
1180 #if 0
1181         /* One more Videl constraint: data fetch of two lines must not overlap */
1182         if (par->HDB & 0x200  &&  par->HDB & ~0x200 - par->HDE <= 5) {
1183                 /* if this happens increase margins, decrease hfreq. */
1184         }
1185 #endif
1186         if (hde_off % prescale)
1187                 par->HBB++;             /* compensate for non matching hde and hbb */
1188         par->HSS = par->HHT + 2 - plen * hsync_len / prescale;
1189         if (par->HSS < par->HBB)
1190                 par->HSS = par->HBB;
1191         }
1192 
1193         /*  check hor. frequency */
1194         hfreq = pclock->f / ((par->HHT+2)*prescale*2);
1195         if (hfreq > hfmax && mon_type!=F_MON_VGA) {
1196                 /* ++guenther:   ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */
1197                 /* Too high -> enlarge margin */
1198                 left_margin += 1;
1199                 right_margin += 1;
1200                 goto again;
1201         }
1202         if (hfreq > hfmax || hfreq < hfmin)
1203                 return -EINVAL;
1204 
1205         /* Vxx-registers */
1206         /* All Vxx must be odd in non-interlace, since frame starts in the middle
1207          * of the first displayed line!
1208          * One frame consists of VFT+1 half lines. VFT+1 must be even in
1209          * non-interlace, odd in interlace mode for synchronisation.
1210          * Vxx-registers are 11-bit wide
1211          */
1212         par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
1213         par->VDB = par->VBE;
1214         par->VDE = yres;
1215         if (!interlace) par->VDE <<= 1;
1216         if (doubleline) par->VDE <<= 1;  /* VDE now half lines per (half-)frame */
1217         par->VDE += par->VDB;
1218         par->VBB = par->VDE;
1219         par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
1220         par->VSS = par->VFT+1 - (vsync_len * 2 - 1);
1221         /* vbb,vss,vft must be even in interlace mode */
1222         if (interlace) {
1223                 par->VBB++;
1224                 par->VSS++;
1225                 par->VFT++;
1226         }
1227 
1228         /* V-frequency check, hope I didn't create any loop here. */
1229         /* Interlace and doubleline are mutually exclusive. */
1230         vfreq = (hfreq * 2) / (par->VFT + 1);
1231         if      (vfreq > vfmax && !doubleline && !interlace) {
1232                 /* Too high -> try again with doubleline */
1233                 doubleline = 1;
1234                 goto again;
1235         }
1236         else if (vfreq < vfmin && !interlace && !doubleline) {
1237                 /* Too low -> try again with interlace */
1238                 interlace = 1;
1239                 goto again;
1240         }
1241         else if (vfreq < vfmin && doubleline) {
1242                 /* Doubleline too low -> clear doubleline and enlarge margins */
1243                 int lines;
1244                 doubleline = 0;
1245                 for (lines=0; (hfreq*2)/(par->VFT+1+4*lines-2*yres)>vfmax; lines++)
1246                         ;
1247                 upper_margin += lines;
1248                 lower_margin += lines;
1249                 goto again;
1250         }
1251         else if (vfreq > vfmax && interlace) {
1252                 /* Interlace, too high -> enlarge margins */
1253                 int lines;
1254                 for (lines=0; (hfreq*2)/(par->VFT+1+4*lines)>vfmax; lines++)
1255                         ;
1256                 upper_margin += lines;
1257                 lower_margin += lines;
1258                 goto again;
1259         }
1260         else if (vfreq < vfmin || vfreq > vfmax)
1261                 return -EINVAL;
1262 
1263   set_screen_base:
1264         linelen = xres_virtual * bpp / 8;
1265         if ((var->yoffset + yres)*linelen > screen_len && screen_len)
1266                 return -EINVAL;
1267         if (var->yres_virtual * linelen > screen_len && screen_len)
1268                 return -EINVAL;
1269         if (var->yres * linelen > screen_len && screen_len)
1270                 return -EINVAL;
1271         par->vyres = yres_virtual;
1272         par->screen_base = screen_base + var->yoffset * linelen;
1273         par->hw.falcon.xoffset = 0;
1274 
1275         return 0;
1276 }
1277 
1278 static int falcon_encode_var( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
1279                                                           struct atari_fb_par *par )
1280 {
1281 /* !!! only for VGA !!! */
1282         int linelen, i;
1283         int prescale, plen;
1284         int hdb_off, hde_off, base_off;
1285         struct falcon_hw *hw = &par->hw.falcon;
1286 
1287         /* possible frequencies: 25.175 or 32MHz */
1288         var->pixclock = hw->sync & 0x1 ? fext.t :
1289                         hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;
1290 
1291         var->height=-1;
1292         var->width=-1;
1293 
1294         var->sync=0;
1295         if (hw->vid_control & VCO_HSYPOS)
1296                 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1297         if (hw->vid_control & VCO_VSYPOS)
1298                 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1299 
1300         var->vmode = FB_VMODE_NONINTERLACED;
1301         if (hw->vid_mode & VMO_INTER)
1302                 var->vmode |= FB_VMODE_INTERLACED;
1303         if (hw->vid_mode & VMO_DOUBLE)
1304                 var->vmode |= FB_VMODE_DOUBLE;
1305         
1306         /* visible y resolution:
1307          * Graphics display starts at line VDB and ends at line
1308          * VDE. If interlace mode off unit of VC-registers is
1309          * half lines, else lines.
1310          */
1311         var->yres = hw->vde - hw->vdb;
1312         if (!(var->vmode & FB_VMODE_INTERLACED))
1313                 var->yres >>= 1;
1314         if (var->vmode & FB_VMODE_DOUBLE)
1315                 var->yres >>= 1;
1316 
1317         /* to get bpp, we must examine f_shift and st_shift.
1318          * f_shift is valid if any of bits no. 10, 8 or 4
1319          * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.
1320          * if bit 10 set then bit 8 and bit 4 don't care...
1321          * If all these bits are 0 get display depth from st_shift
1322          * (as for ST and STE)
1323          */
1324         if (hw->f_shift & 0x400)                /* 2 colors */
1325                 var->bits_per_pixel = 1;
1326         else if (hw->f_shift & 0x100)   /* hicolor */
1327                 var->bits_per_pixel = 16;
1328         else if (hw->f_shift & 0x010)   /* 8 bitplanes */
1329                 var->bits_per_pixel = 8;
1330         else if (hw->st_shift == 0)
1331                 var->bits_per_pixel = 4;
1332         else if (hw->st_shift == 0x100)
1333                 var->bits_per_pixel = 2;
1334         else /* if (hw->st_shift == 0x200) */
1335                 var->bits_per_pixel = 1;
1336 
1337         var->xres = hw->line_width * 16 / var->bits_per_pixel;
1338         var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;
1339         if (hw->xoffset)
1340                 var->xres_virtual += 16;
1341 
1342         if (var->bits_per_pixel == 16) {
1343                 var->red.offset=11;
1344                 var->red.length=5;
1345                 var->red.msb_right=0;
1346                 var->green.offset=5;
1347                 var->green.length=6;
1348                 var->green.msb_right=0;
1349                 var->blue.offset=0;
1350                 var->blue.length=5;
1351                 var->blue.msb_right=0;
1352         }
1353         else {
1354                 var->red.offset=0;
1355                 var->red.length = hw->ste_mode ? 4 : 6;
1356                 var->red.msb_right=0;
1357                 var->grayscale=0;
1358                 var->blue=var->green=var->red;
1359         }
1360         var->transp.offset=0;
1361         var->transp.length=0;
1362         var->transp.msb_right=0;
1363 
1364         linelen = var->xres_virtual * var->bits_per_pixel / 8;
1365         if (screen_len)
1366                 if (par->vyres)
1367                         var->yres_virtual = par->vyres;
1368                 else
1369                         var->yres_virtual=screen_len/linelen;
1370         else {
1371                 if (hwscroll < 0)
1372                         var->yres_virtual = 2 * var->yres;
1373                 else
1374                         var->yres_virtual=var->yres+hwscroll * 16;
1375         }
1376         var->xoffset=0; /* TODO change this */
1377 
1378         /* hdX-offsets */
1379         prescale = hxx_prescale(hw);
1380         plen = 4 >> (hw->vid_mode >> 2 & 0x3);
1381         base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;
1382         if (hw->f_shift & 0x100) {
1383                 hde_off = 0;
1384                 hdb_off = (base_off + 16 * plen) + prescale;
1385         }
1386         else {
1387                 hde_off = ((128 / var->bits_per_pixel + 2) * plen);
1388                 if (hw->ste_mode)
1389                         hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)
1390                                          + prescale;
1391                 else
1392                         hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)
1393                                          + prescale;
1394         }
1395 
1396         /* Right margin includes hsync */
1397         var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -
1398                                            (hw->hdb & 0x200 ? 2+hw->hht : 0));
1399         if (hw->ste_mode || mon_type!=F_MON_VGA)
1400                 var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;
1401         else
1402                 /* cant use this in ste_mode, because hbb is +1 off */
1403                 var->right_margin = prescale * (hw->hht + 2 - hw->hbb);
1404         var->hsync_len = prescale * (hw->hht + 2 - hw->hss);
1405 
1406         /* Lower margin includes vsync */
1407         var->upper_margin = hw->vdb / 2 ;  /* round down to full lines */
1408         var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */
1409         var->vsync_len    = (hw->vft+1 - hw->vss + 1) / 2; /* round up */
1410         if (var->vmode & FB_VMODE_INTERLACED) {
1411                 var->upper_margin *= 2;
1412                 var->lower_margin *= 2;
1413                 var->vsync_len *= 2;
1414         }
1415 
1416         var->pixclock *= plen;
1417         var->left_margin /= plen;
1418         var->right_margin /= plen;
1419         var->hsync_len /= plen;
1420 
1421         var->right_margin -= var->hsync_len;
1422         var->lower_margin -= var->vsync_len;
1423 
1424         if (screen_base)
1425                 var->yoffset=(par->screen_base - screen_base)/linelen;
1426         else
1427                 var->yoffset=0;
1428         var->nonstd=0;  /* what is this for? */
1429         var->activate=0;
1430         for (i=0; i<arraysize(var->reserved); i++)
1431                 var->reserved[i]=0;
1432         return 0;
1433 }
1434 
1435 
1436 static int f_change_mode = 0;
1437 static struct falcon_hw f_new_mode;
1438 static int f_pan_display = 0;
1439 
1440 static void falcon_get_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
1441 {
1442         unsigned long addr;
1443         struct falcon_hw *hw = &par->hw.falcon;
1444 
1445         hw->line_width = shifter_f030.scn_width;
1446         hw->line_offset = shifter_f030.off_next;
1447         hw->st_shift = videl.st_shift & 0x300;
1448         hw->f_shift = videl.f_shift;
1449         hw->vid_control = videl.control;
1450         hw->vid_mode = videl.mode;
1451         hw->sync = shifter.syncmode & 0x1;
1452         hw->xoffset = videl.xoffset & 0xf;
1453         hw->hht = videl.hht;
1454         hw->hbb = videl.hbb;
1455         hw->hbe = videl.hbe;
1456         hw->hdb = videl.hdb;
1457         hw->hde = videl.hde;
1458         hw->hss = videl.hss;
1459         hw->vft = videl.vft;
1460         hw->vbb = videl.vbb;
1461         hw->vbe = videl.vbe;
1462         hw->vdb = videl.vdb;
1463         hw->vde = videl.vde;
1464         hw->vss = videl.vss;
1465 
1466         addr = (shifter.bas_hi & 0xff) << 16 |
1467                (shifter.bas_md & 0xff) << 8  |
1468                (shifter.bas_lo & 0xff);
1469         par->screen_base = PTOV(addr);
1470 
1471         /* derived parameters */
1472         hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
1473         hw->mono = (hw->f_shift & 0x400) ||
1474                    ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200);
1475 }
1476 
1477 static void falcon_set_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
1478 {
1479         f_change_mode = 0;
1480 
1481         /* only set screen_base if really necessary */
1482         if (current_par.screen_base != par->screen_base)
1483                 fbhw->set_screen_base(par->screen_base);
1484 
1485         /* Don't touch any other registers if we keep the default resolution */
1486         if (DontCalcRes)
1487                 return;
1488 
1489         /* Tell vbl-handler to change video mode.
1490          * We change modes only on next VBL, to avoid desynchronisation
1491          * (a shift to the right and wrap around by a random number of pixels
1492          * in all monochrome modes).
1493          * This seems to work on my Falcon.
1494          */
1495         f_new_mode = par->hw.falcon;
1496         f_change_mode = 1;
1497 }
1498 
1499 
1500 static void falcon_vbl_switcher( int irq, struct pt_regs *fp, void *dummy )
     /* [previous][next][first][last][top][bottom][index][help] */
1501 {
1502         struct falcon_hw *hw = &f_new_mode;
1503 
1504         if (f_change_mode) {
1505                 f_change_mode = 0;
1506 
1507                 if (hw->sync & 0x1) {
1508                         /* Enable external pixelclock. This code only for ScreenWonder */
1509                         *(volatile unsigned short*)0xffff9202 = 0xffbf;
1510                 }
1511                 else {
1512                         /* Turn off external clocks. Read sets all output bits to 1. */
1513                         *(volatile unsigned short*)0xffff9202;
1514                 }
1515                 shifter.syncmode = hw->sync;
1516 
1517                 videl.hht = hw->hht;
1518                 videl.hbb = hw->hbb;
1519                 videl.hbe = hw->hbe;
1520                 videl.hdb = hw->hdb;
1521                 videl.hde = hw->hde;
1522                 videl.hss = hw->hss;
1523                 videl.vft = hw->vft;
1524                 videl.vbb = hw->vbb;
1525                 videl.vbe = hw->vbe;
1526                 videl.vdb = hw->vdb;
1527                 videl.vde = hw->vde;
1528                 videl.vss = hw->vss;
1529 
1530                 /*f030_sreg[2] = 0;*/
1531 
1532                 videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */
1533                 if (hw->ste_mode) {
1534                         videl.st_shift = hw->st_shift; /* write enables STE palette */
1535                 }
1536                 else {
1537                         /* IMPORTANT:
1538                          * set st_shift 0, so we can tell the screen-depth if f_shift==0.
1539                          * Writing 0 to f_shift enables 4 plane Falcon mode but
1540                          * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible
1541                          * with Falcon palette.
1542                          */
1543                         videl.st_shift = 0;
1544                         /* now back to Falcon palette mode */
1545                         videl.f_shift = hw->f_shift;
1546                 }
1547                 /* writing to st_shift changed scn_width and vid_mode */
1548                 videl.xoffset = hw->xoffset;
1549                 shifter_f030.scn_width = hw->line_width;
1550                 shifter_f030.off_next = hw->line_offset;
1551                 videl.control = hw->vid_control;
1552                 videl.mode = hw->vid_mode;
1553         }
1554         if (f_pan_display) {
1555                 f_pan_display = 0;
1556                 videl.xoffset = current_par.hw.falcon.xoffset;
1557                 shifter_f030.off_next = current_par.hw.falcon.line_offset;
1558         }
1559 }
1560 
1561 
1562 static int falcon_pan_display( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
1563                                                            struct atari_fb_par *par )
1564 {
1565         int xoffset;
1566 
1567         if (disp[currcon].var.bits_per_pixel == 1)
1568                 var->xoffset = up(var->xoffset, 32);
1569         par->hw.falcon.xoffset = var->xoffset & 15;
1570         par->hw.falcon.line_offset = disp[currcon].var.bits_per_pixel *
1571                   (disp[currcon].var.xres_virtual - disp[currcon].var.xres) / 16;
1572         if (par->hw.falcon.xoffset)
1573                 par->hw.falcon.line_offset -= disp[currcon].var.bits_per_pixel;
1574         xoffset = var->xoffset - par->hw.falcon.xoffset;
1575 
1576         par->screen_base
1577                 = screen_base + (var->yoffset * disp[currcon].var.xres_virtual +
1578                                 xoffset) * disp[currcon].var.bits_per_pixel / 8;
1579         if (fbhw->set_screen_base)
1580                 fbhw->set_screen_base (par->screen_base);
1581         else
1582                 return -EINVAL; /* shouldn't happen */
1583         f_pan_display = 1;
1584         return 0;
1585 }
1586 
1587 
1588 static int falcon_getcolreg( unsigned regno, unsigned *red,
     /* [previous][next][first][last][top][bottom][index][help] */
1589                                  unsigned *green, unsigned *blue,
1590                                  unsigned *transp )
1591 {       unsigned long col;
1592         
1593         if (regno > 255)
1594                 return 1;
1595         /* This works in STE-mode (with 4bit/color) since f030_col-registers
1596          * hold up to 6bit/color.
1597          * Even with hicolor r/g/b=5/6/5 bit!
1598          */
1599         col = f030_col[regno];
1600         *red = (col >> 26) & 0x3f;
1601         *green = (col >> 18) & 0x3f;
1602         *blue = (col >> 2) & 0x3f;
1603         *transp = 0;
1604         return 0;
1605 }
1606 
1607 
1608 static int falcon_setcolreg( unsigned regno, unsigned red,
     /* [previous][next][first][last][top][bottom][index][help] */
1609                                                          unsigned green, unsigned blue,
1610                                                          unsigned transp )
1611 {
1612         if (regno > 255)
1613                 return 1;
1614         f030_col[regno] = (red << 26) | (green << 18) | (blue << 2);
1615         if (regno < 16) {
1616                 shifter_tt.color_reg[regno] =
1617                         (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1618                         (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1619                         ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1620                 packed16_cmap[regno] = (red << 11) | (green << 5) | blue;
1621         }
1622         return 0;
1623 }
1624 
1625 
1626 static int falcon_blank( int blank_mode )
     /* [previous][next][first][last][top][bottom][index][help] */
1627 {
1628 /* ++guenther: we can switch off graphics by changing VDB and VDE,
1629  * so VIDEL doesn't hog the bus while saving.
1630  * (this affects usleep()).
1631  */
1632         if (mon_type == F_MON_SM)       /* this doesn't work on SM124 */
1633                 return 1;
1634         if (blank_mode) {
1635                 /* disable graphics output (this speeds up the CPU) ... */
1636                 videl.vdb = current_par.VFT + 1;
1637                 /* ... and blank all lines */
1638                 videl.hbe = current_par.HHT + 2;
1639                 /* VESA suspend mode, switch off HSYNC */
1640                 if (pwrsave && mon_type == F_MON_VGA)
1641                         videl.hss = current_par.HHT + 2;
1642         }
1643         else {
1644                 videl.vdb = current_par.VDB;
1645                 videl.hbe = current_par.HBE;
1646                 videl.hss = current_par.HSS;
1647         }
1648         return 0;
1649 }
1650 
1651  
1652 static int falcon_detect( void )
     /* [previous][next][first][last][top][bottom][index][help] */
1653 {
1654         struct atari_fb_par par;
1655         unsigned char fhw;
1656 
1657         /* Determine connected monitor and set monitor parameters */
1658         fhw = *(unsigned char*)0xffff8006;
1659         mon_type = fhw >> 6 & 0x3;
1660         /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */
1661         f030_bus_width = fhw << 6 & 0x80;
1662         switch (mon_type) {
1663         case F_MON_SM:
1664                 vfmin = 70;
1665                 vfmax = 72;
1666                 hfmin = 35713;
1667                 hfmax = 35715;
1668                 break;
1669         case F_MON_SC:
1670         case F_MON_TV:
1671                 vfmin = 50;
1672                 vfmax = 60;
1673                 hfmin = 15624;
1674                 hfmax = 15626;
1675                 break;
1676         }
1677         /* initialize hsync-len */
1678         f25.hsync = h_syncs[mon_type] / f25.t;
1679         f32.hsync = h_syncs[mon_type] / f32.t;
1680         if (fext.t)
1681                 fext.hsync = h_syncs[mon_type] / fext.t;
1682 
1683         falcon_get_par(&par);
1684         falcon_encode_var(&atari_fb_predefined[0], &par);
1685 
1686         /* Detected mode is always the "autodetect" slot */
1687         return 1;
1688 }
1689 
1690 #endif /* ATAFB_FALCON */
1691 
1692 /* ------------------- ST(E) specific functions ---------------------- */
1693 
1694 #ifdef ATAFB_STE
1695 
1696 static int stste_encode_fix( struct fb_fix_screeninfo *fix,
     /* [previous][next][first][last][top][bottom][index][help] */
1697                                                          struct atari_fb_par *par )
1698 
1699 {
1700         int mode, i;
1701 
1702         strcpy(fix->id,"Atari Builtin");
1703         fix->smem_start=real_screen_base;
1704         fix->smem_len=screen_len;
1705         fix->type=FB_TYPE_INTERLEAVED_PLANES;
1706         fix->type_aux=2;
1707         fix->visual=FB_VISUAL_PSEUDOCOLOR;
1708         mode = par->hw.st.mode & 3;
1709         if (mode == ST_HIGH) {
1710                 fix->type=FB_TYPE_PACKED_PIXELS;
1711                 fix->type_aux=0;
1712                 fix->visual=FB_VISUAL_MONO10;
1713         }
1714         fix->xpanstep = 0;
1715         if (ATARIHW_PRESENT(EXTD_SHIFTER))
1716                 fix->ypanstep = 1;
1717         else
1718                 fix->ypanstep = 0;
1719         fix->ywrapstep = 0;
1720         for (i=0; i<arraysize(fix->reserved); i++)
1721                 fix->reserved[i]=0;
1722         return 0;
1723 }
1724 
1725 
1726 static int stste_decode_var( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
1727                                                   struct atari_fb_par *par )
1728 {
1729         int xres=var->xres;
1730         int yres=var->yres;
1731         int bpp=var->bits_per_pixel;
1732         int linelen;
1733 
1734         if (mono_moni) {
1735                 if (bpp > 1 || xres > sttt_xres || yres > st_yres)
1736                         return -EINVAL;
1737                 par->hw.st.mode=ST_HIGH;
1738                 xres=sttt_xres;
1739                 yres=st_yres;
1740                 bpp=1;
1741         } else {
1742                 if (bpp > 4 || xres > sttt_xres || yres > st_yres)
1743                         return -EINVAL;
1744                 if (bpp > 2) {
1745                         if (xres > sttt_xres/2 || yres > st_yres/2)
1746                                 return -EINVAL;
1747                         par->hw.st.mode=ST_LOW;
1748                         xres=sttt_xres/2;
1749                         yres=st_yres/2;
1750                         bpp=4;
1751                 }
1752                 else if (bpp > 1) {
1753                         if (xres > sttt_xres || yres > st_yres/2)
1754                                 return -EINVAL;
1755                         par->hw.st.mode=ST_MID;
1756                         xres=sttt_xres;
1757                         yres=st_yres/2;
1758                         bpp=2;
1759                 }
1760                 else
1761                         return -EINVAL;
1762         }
1763         if (var->sync & FB_SYNC_EXT)
1764                 par->hw.st.sync=(par->hw.st.sync & ~1) | 1;
1765         else
1766                 par->hw.st.sync=(par->hw.st.sync & ~1);
1767         linelen=xres*bpp/8;
1768         if ((var->yoffset + yres)*linelen > screen_len && screen_len)
1769                 return -EINVAL;
1770         par->screen_base=screen_base+ var->yoffset*linelen;
1771         return 0;
1772 }
1773 
1774 static int stste_encode_var( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
1775                                                   struct atari_fb_par *par )
1776 {
1777         int linelen, i;
1778         var->red.offset=0;
1779         var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3;
1780         var->red.msb_right=0;
1781         var->grayscale=0;
1782 
1783         var->pixclock=31041;
1784         var->left_margin=120;           /* these are incorrect */
1785         var->right_margin=100;
1786         var->upper_margin=8;
1787         var->lower_margin=16;
1788         var->hsync_len=140;
1789         var->vsync_len=30;
1790 
1791         var->height=-1;
1792         var->width=-1;
1793 
1794         if (!(par->hw.st.sync & 1))
1795                 var->sync=0;
1796         else
1797                 var->sync=FB_SYNC_EXT;
1798 
1799         switch (par->hw.st.mode & 3) {
1800         case ST_LOW:
1801                 var->xres=sttt_xres/2;
1802                 var->yres=st_yres/2;
1803                 var->bits_per_pixel=4;
1804                 break;
1805         case ST_MID:
1806                 var->xres=sttt_xres;
1807                 var->yres=st_yres/2;
1808                 var->bits_per_pixel=2;
1809                 break;
1810         case ST_HIGH:
1811                 var->xres=sttt_xres;
1812                 var->yres=st_yres;
1813                 var->bits_per_pixel=1;
1814                 break;
1815         }               
1816         var->blue=var->green=var->red;
1817         var->transp.offset=0;
1818         var->transp.length=0;
1819         var->transp.msb_right=0;
1820         var->xres_virtual=sttt_xres_virtual;
1821         linelen=var->xres_virtual * var->bits_per_pixel / 8;
1822         ovsc_addlen=linelen*(sttt_yres_virtual - st_yres);
1823         
1824         if (! use_hwscroll)
1825                 var->yres_virtual=var->yres;
1826         else if (screen_len)
1827                 var->yres_virtual=screen_len/linelen;
1828         else {
1829                 if (hwscroll < 0)
1830                         var->yres_virtual = 2 * var->yres;
1831                 else
1832                         var->yres_virtual=var->yres+hwscroll * 16;
1833         }
1834         var->xoffset=0;
1835         if (screen_base)
1836                 var->yoffset=(par->screen_base - screen_base)/linelen;
1837         else
1838                 var->yoffset=0;
1839         var->nonstd=0;
1840         var->activate=0;
1841         var->vmode=FB_VMODE_NONINTERLACED;
1842         for (i=0; i<arraysize(var->reserved); i++)
1843                 var->reserved[i]=0;
1844         return 0;
1845 }
1846 
1847 
1848 static void stste_get_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
1849 {
1850         unsigned long addr;
1851         par->hw.st.mode=shifter_tt.st_shiftmode;
1852         par->hw.st.sync=shifter.syncmode;
1853         addr = ((shifter.bas_hi & 0xff) << 16) |
1854                ((shifter.bas_md & 0xff) << 8);
1855         if (ATARIHW_PRESENT(EXTD_SHIFTER))
1856                 addr |= (shifter.bas_lo & 0xff);
1857         par->screen_base = PTOV(addr);
1858 }
1859 
1860 static void stste_set_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
1861 {
1862         shifter_tt.st_shiftmode=par->hw.st.mode;
1863         shifter.syncmode=par->hw.st.sync;
1864         /* only set screen_base if really necessary */
1865         if (current_par.screen_base != par->screen_base)
1866                 fbhw->set_screen_base(par->screen_base);
1867 }
1868 
1869 
1870 static int stste_getcolreg( unsigned regno, unsigned *red,
     /* [previous][next][first][last][top][bottom][index][help] */
1871                                                         unsigned *green, unsigned *blue,
1872                                                         unsigned *transp )
1873 {       unsigned col;
1874         
1875         if (regno > 15)
1876                 return 1;
1877         col = shifter_tt.color_reg[regno];
1878         if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
1879                 *red = ((col >> 7) & 0xe) | ((col >> 11) & 1);
1880                 *green = ((col >> 3) & 0xe) | ((col >> 7) & 1);
1881                 *blue = ((col << 1) & 0xe) | ((col >> 3) & 1);
1882         }
1883         else {
1884                 *red = (col >> 8) & 0x7;
1885                 *green = (col >> 4) & 0x7;
1886                 *blue = col & 0x7;
1887         }
1888         *transp = 0;
1889         return 0;
1890 }
1891 
1892 
1893 static int stste_setcolreg( unsigned regno, unsigned red,
     /* [previous][next][first][last][top][bottom][index][help] */
1894                                                  unsigned green, unsigned blue,
1895                                                  unsigned transp )
1896 {
1897         if (regno > 15)
1898                 return 1;
1899         if (ATARIHW_PRESENT(EXTD_SHIFTER))
1900                 shifter_tt.color_reg[regno] =
1901                         (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
1902                         (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
1903                         ((blue & 0xe) >> 1) | ((blue & 1) << 3);
1904         else
1905                 shifter_tt.color_reg[regno] =
1906                         ((red & 0x7) << 8) |
1907                         ((green & 0x7) << 4) |
1908                         (blue & 0x7);
1909         return 0;
1910 }
1911 
1912                                                   
1913 static int stste_detect( void )
     /* [previous][next][first][last][top][bottom][index][help] */
1914 
1915 {       struct atari_fb_par par;
1916 
1917         /* Determine the connected monitor: The DMA sound must be
1918          * disabled before reading the MFP GPIP, because the Sound
1919          * Done Signal and the Monochrome Detect are XORed together!
1920          */
1921         if (ATARIHW_PRESENT(PCM_8BIT)) {
1922                 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1923                 udelay(20);     /* wait a while for things to settle down */
1924         }
1925         mono_moni = (mfp.par_dt_reg & 0x80) == 0;
1926 
1927         stste_get_par(&par);
1928         stste_encode_var(&atari_fb_predefined[0], &par);
1929 
1930         if (!ATARIHW_PRESENT(EXTD_SHIFTER))
1931                 use_hwscroll = 0;
1932         return 1;
1933 }
1934 
1935 static void stste_set_screen_base(unsigned long s_base)
     /* [previous][next][first][last][top][bottom][index][help] */
1936 {
1937         unsigned long addr;
1938         addr= VTOP(s_base);
1939         /* Setup Screen Memory */
1940         shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
1941         shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
1942         if (ATARIHW_PRESENT(EXTD_SHIFTER))
1943                 shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
1944 }
1945 
1946 #endif /* ATAFB_STE */
1947 
1948 /* Switching the screen size should be done during vsync, otherwise
1949  * the margins may get messed up. This is a well known problem of
1950  * the ST's video system.
1951  *
1952  * Unfortunately there is hardly any way to find the vsync, as the
1953  * vertical blank interrupt is no longer in time on machines with
1954  * overscan type modifications.
1955  *
1956  * We can, however, use Timer B to safely detect the black shoulder,
1957  * but then we've got to guess an appropriate delay to find the vsync.
1958  * This might not work on every machine.
1959  *
1960  * martin_rogge @ ki.maus.de, 8th Aug 1995
1961  */
1962 
1963 #define LINE_DELAY  (mono_moni ? 30 : 70)
1964 #define SYNC_DELAY  (mono_moni ? 1500 : 2000)
1965 
1966 /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */
1967 static void st_ovsc_switch(int switchmode)
     /* [previous][next][first][last][top][bottom][index][help] */
1968 {
1969     unsigned long flags;
1970     register unsigned char old, new;
1971 
1972     if ((switchmode & (SWITCH_ACIA | SWITCH_SND6 | SWITCH_SND7)) == 0)
1973         return;
1974     save_flags(flags);
1975     cli();
1976 
1977     mfp.tim_ct_b = 0x10;
1978     mfp.active_edge |= 8;
1979     mfp.tim_ct_b = 0;
1980     mfp.tim_dt_b = 0xf0;
1981     mfp.tim_ct_b = 8;
1982     while (mfp.tim_dt_b > 1)    /* TOS does it this way, don't ask why */
1983         ;
1984     new = mfp.tim_dt_b;
1985     do {
1986         udelay(LINE_DELAY);
1987         old = new;
1988         new = mfp.tim_dt_b;
1989     } while (old != new);
1990     mfp.tim_ct_b = 0x10;
1991     udelay(SYNC_DELAY);
1992 
1993     if (switchmode == SWITCH_ACIA)
1994         acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RHTID|ACIA_RIE);
1995     else {
1996         sound_ym.rd_data_reg_sel = 14;
1997         sound_ym.wd_data = sound_ym.rd_data_reg_sel | switchmode;
1998     }
1999     restore_flags(flags);
2000 }
2001 
2002 /* ------------------- External Video ---------------------- */
2003 
2004 #ifdef ATAFB_EXT
2005 
2006 static int ext_encode_fix( struct fb_fix_screeninfo *fix,
     /* [previous][next][first][last][top][bottom][index][help] */
2007                                                    struct atari_fb_par *par )
2008 
2009 {
2010         int i;
2011 
2012         strcpy(fix->id,"Unknown Extern");
2013         fix->smem_start=external_addr;
2014         fix->smem_len=(external_len + PAGE_SIZE -1) & PAGE_MASK;
2015         if (external_depth == 1) {
2016                 fix->type = FB_TYPE_PACKED_PIXELS;
2017                 /* The letters 'n' and 'i' in the "atavideo=external:" stand
2018                  * for "normal" and "inverted", rsp., in the monochrome case */
2019                 fix->visual =
2020                         (external_pmode == FB_TYPE_INTERLEAVED_PLANES ||
2021                          external_pmode == FB_TYPE_PACKED_PIXELS) ?
2022                                 FB_VISUAL_MONO10 :
2023                                         FB_VISUAL_MONO01;
2024         }
2025         else {
2026                 switch (external_pmode) {
2027                         /* All visuals are STATIC, because we don't know how to change
2028                          * colors :-(
2029                          */
2030                     case -1:              /* truecolor */
2031                         fix->type=FB_TYPE_PACKED_PIXELS;
2032                         fix->visual=FB_VISUAL_TRUECOLOR;
2033                         break;
2034                     case FB_TYPE_PACKED_PIXELS:
2035                         fix->type=FB_TYPE_PACKED_PIXELS;
2036                         fix->visual=FB_VISUAL_STATIC_PSEUDOCOLOR;
2037                         break;
2038                     case FB_TYPE_PLANES:
2039                         fix->type=FB_TYPE_PLANES;
2040                         fix->visual=FB_VISUAL_STATIC_PSEUDOCOLOR;
2041                         break;
2042                     case FB_TYPE_INTERLEAVED_PLANES:
2043                         fix->type=FB_TYPE_INTERLEAVED_PLANES;
2044                         fix->type_aux=2;
2045                         fix->visual=FB_VISUAL_STATIC_PSEUDOCOLOR;
2046                         break;
2047                 }
2048         }
2049         fix->xpanstep = 0;
2050         fix->ypanstep = 0;
2051         fix->ywrapstep = 0;
2052         for (i=0; i<arraysize(fix->reserved); i++)
2053                 fix->reserved[i]=0;
2054         return 0;
2055 }
2056 
2057 
2058 static int ext_decode_var( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
2059                                                    struct atari_fb_par *par )
2060 {
2061         struct fb_var_screeninfo *myvar = &atari_fb_predefined[0];
2062         
2063         if (var->bits_per_pixel > myvar->bits_per_pixel ||
2064                 var->xres > myvar->xres ||
2065                 var->yres > myvar->yres ||
2066                 var->xoffset > 0 ||
2067                 var->yoffset > 0)
2068                 return -EINVAL;
2069         return 0;
2070 }
2071 
2072 
2073 static int ext_encode_var( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
2074                                                    struct atari_fb_par *par )
2075 {
2076         int i;
2077 
2078         var->red.offset=0;
2079         var->red.length=(external_pmode == -1) ? external_depth/3 : 
2080                         (external_vgaiobase ? external_bitspercol : 0);
2081         var->red.msb_right=0;
2082         var->grayscale=0;
2083 
2084         var->pixclock=31041;
2085         var->left_margin=120;           /* these are surely incorrect   */
2086         var->right_margin=100;
2087         var->upper_margin=8;
2088         var->lower_margin=16;
2089         var->hsync_len=140;
2090         var->vsync_len=30;
2091 
2092         var->height=-1;
2093         var->width=-1;
2094 
2095         var->sync=0;
2096 
2097         var->xres = external_xres;
2098         var->yres = external_yres;
2099         var->bits_per_pixel = external_depth;
2100         
2101         var->blue=var->green=var->red;
2102         var->transp.offset=0;
2103         var->transp.length=0;
2104         var->transp.msb_right=0;
2105         var->xres_virtual=var->xres;
2106         var->yres_virtual=var->yres;
2107         var->xoffset=0;
2108         var->yoffset=0;
2109         var->nonstd=0;
2110         var->activate=0;
2111         var->vmode=FB_VMODE_NONINTERLACED;
2112         for (i=0; i<arraysize(var->reserved); i++)
2113                 var->reserved[i]=0;
2114         return 0;
2115 }
2116 
2117 
2118 static void ext_get_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
2119 {
2120         par->screen_base = external_addr;
2121 }
2122 
2123 static void ext_set_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
2124 {
2125 }
2126 
2127 #define OUTB(port,val) \
2128         *((unsigned volatile char *) ((port)+external_vgaiobase))=(val)
2129 #define INB(port) \
2130         (*((unsigned volatile char *) ((port)+external_vgaiobase)))
2131 #define DACDelay                                \
2132         do {                                    \
2133                 unsigned char tmp=INB(0x3da);   \
2134                 tmp=INB(0x3da);                 \
2135         } while (0)
2136 
2137 static int ext_getcolreg( unsigned regno, unsigned *red,
     /* [previous][next][first][last][top][bottom][index][help] */
2138                                                   unsigned *green, unsigned *blue,
2139                                                   unsigned *transp )
2140 
2141 {       unsigned char colmask = (1 << external_bitspercol) - 1;
2142                 
2143         if (! external_vgaiobase)
2144                 return 1;
2145 
2146         switch (external_card_type) {
2147           case IS_VGA:
2148             OUTB(0x3c7, regno);
2149             DACDelay;
2150             *red=INB(0x3c9) & colmask;
2151             DACDelay;
2152             *green=INB(0x3c9) & colmask;
2153             DACDelay;
2154             *blue=INB(0x3c9) & colmask;
2155             DACDelay;
2156             return 0;
2157             
2158           case IS_MV300:
2159             *red = MV300_color[regno].red;
2160             *green = MV300_color[regno].green;
2161             *blue = MV300_color[regno].blue;
2162             *transp=0;
2163             return 0;
2164 
2165           default:
2166             return 1;
2167           }
2168 }
2169         
2170 static int ext_setcolreg( unsigned regno, unsigned red,
     /* [previous][next][first][last][top][bottom][index][help] */
2171                                                   unsigned green, unsigned blue,
2172                                                   unsigned transp )
2173 
2174 {       unsigned char colmask = (1 << external_bitspercol) - 1;
2175 
2176         if (! external_vgaiobase)
2177                 return 1;
2178 
2179         switch (external_card_type) {
2180           case IS_VGA:
2181             OUTB(0x3c8, regno);
2182             DACDelay;
2183             OUTB(0x3c9, red & colmask);
2184             DACDelay;
2185             OUTB(0x3c9, green & colmask);
2186             DACDelay;
2187             OUTB(0x3c9, blue & colmask);
2188             DACDelay;
2189             return 0;
2190 
2191           case IS_MV300:
2192             MV300_color[regno].red = red;
2193             MV300_color[regno].green = green;
2194             MV300_color[regno].blue = blue;
2195             OUTB((MV300_reg[regno] << 2)+1, red);
2196             OUTB((MV300_reg[regno] << 2)+1, green);
2197             OUTB((MV300_reg[regno] << 2)+1, blue);
2198             return 0;
2199 
2200           default:
2201             return 1;
2202           }
2203 }
2204         
2205 
2206 static int ext_detect( void )
     /* [previous][next][first][last][top][bottom][index][help] */
2207 
2208 {
2209         struct fb_var_screeninfo *myvar = &atari_fb_predefined[0];
2210         struct atari_fb_par dummy_par;
2211 
2212         myvar->xres = external_xres;
2213         myvar->yres = external_yres;
2214         myvar->bits_per_pixel = external_depth;
2215         ext_encode_var(myvar, &dummy_par);
2216         return 1;
2217 }
2218 
2219 #endif /* ATAFB_EXT */
2220 
2221 /* ------ This is the same for most hardware types -------- */
2222 
2223 static void set_screen_base(unsigned long s_base)
     /* [previous][next][first][last][top][bottom][index][help] */
2224 {
2225         unsigned long addr;
2226         addr= VTOP(s_base);
2227         /* Setup Screen Memory */
2228         shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
2229         shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
2230         shifter.bas_lo=(unsigned char)  (addr & 0x0000ff);
2231 }
2232 
2233 
2234 static int pan_display( struct fb_var_screeninfo *var,
     /* [previous][next][first][last][top][bottom][index][help] */
2235                         struct atari_fb_par *par )
2236 {
2237         if (var->xoffset)
2238                 return -EINVAL;
2239         par->screen_base
2240                 = screen_base + (var->yoffset * disp[currcon].var.xres_virtual
2241                                                  * disp[currcon].var.bits_per_pixel / 8);
2242         if (fbhw->set_screen_base)
2243                 fbhw->set_screen_base (par->screen_base);
2244         else
2245                 return -EINVAL;
2246         return 0;
2247 }
2248 
2249 
2250 /* ------------ Interfaces to hardware functions ------------ */
2251 
2252 
2253 #ifdef ATAFB_TT
2254 struct fb_hwswitch tt_switch = {
2255         tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var,
2256         tt_get_par, tt_set_par, tt_getcolreg, tt_setcolreg,
2257         set_screen_base, NULL, pan_display
2258 };
2259 #endif
2260 
2261 #ifdef ATAFB_FALCON
2262 struct fb_hwswitch falcon_switch = {
2263         falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var,
2264         falcon_get_par, falcon_set_par, falcon_getcolreg,
2265         falcon_setcolreg, set_screen_base, falcon_blank, falcon_pan_display
2266 };
2267 #endif
2268 
2269 #ifdef ATAFB_STE
2270 struct fb_hwswitch st_switch = {
2271         stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var,
2272         stste_get_par, stste_set_par, stste_getcolreg, stste_setcolreg,
2273         stste_set_screen_base, NULL, pan_display
2274 };
2275 #endif
2276 
2277 #ifdef ATAFB_EXT
2278 struct fb_hwswitch ext_switch = {
2279         ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var,
2280         ext_get_par, ext_set_par, ext_getcolreg, ext_setcolreg, NULL, NULL, NULL
2281 };
2282 #endif
2283 
2284 
2285 
2286 static void atari_fb_get_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
2287 {
2288         if (current_par_valid) {
2289                 *par=current_par;
2290         }
2291         else
2292                 fbhw->get_par(par);
2293 }
2294 
2295 
2296 static void atari_fb_set_par( struct atari_fb_par *par )
     /* [previous][next][first][last][top][bottom][index][help] */
2297 {
2298         fbhw->set_par(par);
2299         current_par=*par;
2300         current_par_valid=1;
2301 }
2302 
2303 
2304 
2305 /* =========================================================== */
2306 /* ============== Hardware Independent Functions ============= */
2307 /* =========================================================== */
2308 
2309 
2310 /* used for hardware scrolling */
2311 
2312 static int
2313 fb_update_var(int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2314 {
2315         int off=disp[con].var.yoffset*disp[con].var.xres_virtual*
2316                         disp[con].var.bits_per_pixel>>3;
2317 
2318         current_par.screen_base=screen_base + off;
2319 
2320         if (fbhw->set_screen_base)
2321                 fbhw->set_screen_base(current_par.screen_base);
2322         return 0;
2323 }
2324 
2325 static int
2326 do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
     /* [previous][next][first][last][top][bottom][index][help] */
2327 {
2328         int err,activate;
2329         struct atari_fb_par par;
2330         if ((err=fbhw->decode_var(var, &par)))
2331                 return err;
2332         activate=var->activate;
2333         if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive)
2334                 atari_fb_set_par(&par);
2335         fbhw->encode_var(var, &par);
2336         var->activate=activate;
2337         return 0;
2338 }
2339 
2340 /* Functions for handling colormap */
2341 
2342 /* there seems to be a bug in gcc 2.5.8 which inhibits using an other solution */
2343 /* I always get a sigsegv */
2344 
2345 static short red16[]=
2346         { 0x0000,0x0000,0x0000,0x0000,0xc000,0xc000,0xc000,0xc000,
2347           0x8000,0x0000,0x0000,0x0000,0xffff,0xffff,0xffff,0xffff};
2348 static short green16[]=
2349         { 0x0000,0x0000,0xc000,0xc000,0x0000,0x0000,0xc000,0xc000,
2350           0x8000,0x0000,0xffff,0xffff,0x0000,0x0000,0xffff,0xffff};
2351 static short blue16[]=
2352         { 0x0000,0xc000,0x0000,0xc000,0x0000,0xc000,0x0000,0xc000,
2353           0x8000,0xffff,0x0000,0xffff,0x0000,0xffff,0x0000,0xffff};
2354 
2355 static short red4[]=
2356         { 0x0000,0xc000,0x8000,0xffff};
2357 static short green4[]=
2358         { 0x0000,0xc000,0x8000,0xffff};
2359 static short blue4[]=
2360         { 0x0000,0xc000,0x8000,0xffff};
2361 
2362 static short red2[]=
2363         { 0x0000,0xffff};
2364 static short green2[]=
2365         { 0x0000,0xffff};
2366 static short blue2[]=
2367         { 0x0000,0xffff};
2368 
2369 struct fb_cmap default_16_colors = { 0, 16, red16, green16, blue16, NULL };
2370 struct fb_cmap default_4_colors = { 0, 4, red4, green4, blue4, NULL };
2371 struct fb_cmap default_2_colors = { 0, 2, red2, green2, blue2, NULL };
2372 
2373 static struct fb_cmap *
2374 get_default_colormap(int bpp)
     /* [previous][next][first][last][top][bottom][index][help] */
2375 {
2376         if (bpp == 1)
2377                 return &default_2_colors;
2378         if (bpp == 2)
2379                 return &default_4_colors;
2380         return &default_16_colors;
2381 }
2382 
2383 #define CNVT_TOHW(val,width)    (((val) << (width)) + 0x7fff - (val)) >> 16
2384 #define CNVT_FROMHW(val,width) ((width)?((((val) << 16) - (val)) / ((1<<(width))-1)):0)
2385 
2386 
2387 static int
2388 do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc)
     /* [previous][next][first][last][top][bottom][index][help] */
2389 {
2390         int i,start;
2391         unsigned short *red,*green,*blue,*transp;
2392         unsigned int hred,hgreen,hblue,htransp;
2393 
2394         red=cmap->red;
2395         green=cmap->green;
2396         blue=cmap->blue;
2397         transp=cmap->transp;
2398         start=cmap->start;
2399         if (start < 0)
2400                 return EINVAL;
2401         for (i=0 ; i < cmap->len ; i++) {
2402                 if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
2403                         return 0;
2404                 hred=CNVT_FROMHW(hred,var->red.length);
2405                 hgreen=CNVT_FROMHW(hgreen,var->green.length);
2406                 hblue=CNVT_FROMHW(hblue,var->blue.length);
2407                 htransp=CNVT_FROMHW(htransp,var->transp.length);
2408                 if (kspc) {
2409                         *red=hred;
2410                         *green=hgreen;
2411                         *blue=hblue;
2412                         if (transp) *transp=htransp;
2413                 }
2414                 else {
2415                         put_fs_word(hred, red);
2416                         put_fs_word(hgreen, green);
2417                         put_fs_word(hblue, blue);
2418                         if (transp) put_fs_word(htransp, transp);
2419                 }
2420                 red++;
2421                 green++;
2422                 blue++;
2423                 if (transp) transp++;
2424         }
2425         return 0;
2426 }
2427 
2428 static int
2429 do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc)
     /* [previous][next][first][last][top][bottom][index][help] */
2430 {
2431         int i,start;
2432         unsigned short *red,*green,*blue,*transp;
2433         unsigned int hred,hgreen,hblue,htransp;
2434 
2435         red=cmap->red;
2436         green=cmap->green;
2437         blue=cmap->blue;
2438         transp=cmap->transp;
2439         start=cmap->start;
2440 
2441         if (start < 0)
2442                 return -EINVAL;
2443         for (i=0 ; i < cmap->len ; i++) {
2444                 if (kspc) {
2445                         hred=*red;
2446                         hgreen=*green;
2447                         hblue=*blue;
2448                         htransp=(transp) ? *transp : 0;
2449                 }
2450                 else {
2451                         hred=get_fs_word(red);
2452                         hgreen=get_fs_word(green);
2453                         hblue=get_fs_word(blue);
2454                         htransp=(transp)?get_fs_word(transp):0;
2455                 }
2456                 hred=CNVT_TOHW(hred,var->red.length);
2457                 hgreen=CNVT_TOHW(hgreen,var->green.length);
2458                 hblue=CNVT_TOHW(hblue,var->blue.length);
2459                 htransp=CNVT_TOHW(htransp,var->transp.length);
2460                 red++;
2461                 green++;
2462                 blue++;
2463                 if (transp) transp++;
2464                 if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
2465                         return 0;
2466         }
2467         return 0;
2468 }
2469 
2470 static void
2471 do_install_cmap(int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2472 {
2473         if (con != currcon)
2474                 return;
2475         if (disp[con].cmap.len)
2476                 do_fb_set_cmap(&disp[con].cmap, &(disp[con].var), 1);
2477         else
2478                 do_fb_set_cmap(get_default_colormap(
2479                                 disp[con].var.bits_per_pixel), &(disp[con].var), 1);            
2480 }
2481 
2482 static void
2483 memcpy_fs(int fsfromto, void *to, void *from, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
2484 {
2485         switch (fsfromto) {
2486         case 0:
2487                 memcpy(to,from,len);
2488                 return;
2489         case 1:
2490                 memcpy_fromfs(to,from,len);
2491                 return;
2492         case 2:
2493                 memcpy_tofs(to,from,len);
2494                 return;
2495         }
2496 }
2497 
2498 static void
2499 copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
     /* [previous][next][first][last][top][bottom][index][help] */
2500 {
2501         int size;
2502         int tooff=0, fromoff=0;
2503 
2504         if (to->start > from->start)
2505                 fromoff=to->start-from->start;
2506         else
2507                 tooff=from->start-to->start;                    
2508         size=to->len-tooff;
2509         if (size > from->len-fromoff)
2510                 size=from->len-fromoff;
2511         if (size < 0)
2512                 return;
2513         size*=sizeof(unsigned short);
2514         memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
2515         memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
2516         memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
2517         if (from->transp && to->transp)
2518                 memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
2519 }
2520  
2521 static int
2522 alloc_cmap(struct fb_cmap *cmap,int len,int transp)
     /* [previous][next][first][last][top][bottom][index][help] */
2523 {
2524         int size=len*sizeof(unsigned short);
2525         if (cmap->len != len) {
2526                 if (cmap->red)
2527                         kfree(cmap->red);
2528                 if (cmap->green)
2529                         kfree(cmap->green);
2530                 if (cmap->blue)
2531                         kfree(cmap->blue);
2532                 if (cmap->transp)
2533                         kfree(cmap->transp);
2534                 cmap->red=cmap->green=cmap->blue=cmap->transp=NULL;
2535                 cmap->len=0;
2536                 if (! len)
2537                         return 0;
2538                 if (! (cmap->red=kmalloc(size, GFP_ATOMIC)))
2539                         return -1;
2540                 if (! (cmap->green=kmalloc(size, GFP_ATOMIC)))
2541                         return -1;
2542                 if (! (cmap->blue=kmalloc(size, GFP_ATOMIC)))
2543                         return -1;
2544                 if (transp) {
2545                         if (! (cmap->transp=kmalloc(size, GFP_ATOMIC)))
2546                                 return -1;
2547                 }
2548                 else
2549                         cmap->transp=NULL;
2550         }
2551         cmap->start=0;
2552         cmap->len=len;
2553         copy_cmap(get_default_colormap(len), cmap, 0);
2554         return 0;
2555 }       
2556 
2557 static int
2558 atari_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2559 {
2560         struct atari_fb_par par;
2561         if (con == -1)
2562                 atari_fb_get_par(&par);
2563         else
2564                 fbhw->decode_var(&disp[con].var,&par);
2565         return fbhw->encode_fix(fix, &par);
2566 }
2567         
2568 static int
2569 atari_fb_get_var(struct fb_var_screeninfo *var, int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2570 {
2571         struct atari_fb_par par;
2572         if (con == -1) {
2573                 atari_fb_get_par(&par);
2574                 fbhw->encode_var(var, &par);
2575         }
2576         else
2577                 *var=disp[con].var;
2578         return 0;
2579 }
2580 
2581 static void
2582 atari_fb_set_disp(int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2583 {
2584         struct fb_fix_screeninfo fix;
2585 
2586         atari_fb_get_fix(&fix, con);
2587         if (con == -1)
2588                 con=0;
2589         disp[con].screen_base = (u_char *)fix.smem_start;
2590         disp[con].visual = fix.visual;
2591         disp[con].type = fix.type;
2592         disp[con].type_aux = fix.type_aux;
2593         disp[con].ypanstep = fix.ypanstep;
2594         disp[con].ywrapstep = fix.ywrapstep;
2595         if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
2596                 fix.visual != FB_VISUAL_DIRECTCOLOR)
2597                 disp[con].can_soft_blank = 0;
2598         else
2599                 disp[con].can_soft_blank = 1;
2600         disp[con].inverse =
2601             (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
2602 }
2603 
2604 static int
2605 atari_fb_set_var(struct fb_var_screeninfo *var, int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2606 {
2607         int err,oldxres,oldyres,oldbpp,oldxres_virtual,oldyoffset;
2608         if ((err=do_fb_set_var(var, con==currcon)))
2609                 return err;
2610         if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
2611                 oldxres=disp[con].var.xres;
2612                 oldyres=disp[con].var.yres;
2613                 oldxres_virtual=disp[con].var.xres_virtual;
2614                 oldbpp=disp[con].var.bits_per_pixel;
2615                 oldyoffset=disp[con].var.yoffset;
2616                 disp[con].var=*var;
2617                 if (oldxres != var->xres || oldyres != var->yres 
2618                     || oldxres_virtual != var->xres_virtual
2619                     || oldbpp != var->bits_per_pixel
2620                     || oldyoffset != var->yoffset) {
2621                         atari_fb_set_disp(con);
2622                         (*fb_info.changevar)(con);
2623                         alloc_cmap(&disp[con].cmap, 0, 0);
2624                         do_install_cmap(con);
2625                 }
2626         }
2627         var->activate=0;
2628         return 0;
2629 }
2630 
2631 
2632 
2633 static int
2634 atari_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2635 {
2636         if (con == currcon) /* current console ? */
2637                 return do_fb_get_cmap(cmap, &(disp[con].var), kspc);
2638         else
2639                 if (disp[con].cmap.len) /* non default colormap ? */
2640                         copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
2641                 else
2642                         copy_cmap(get_default_colormap(
2643                             disp[con].var.bits_per_pixel), cmap, kspc ? 0 : 2);
2644         return 0;
2645 }
2646 
2647 static int
2648 atari_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2649 {
2650         int err;
2651         if (! disp[con].cmap.len) { /* no colormap allocated ? */
2652                 if ((err = alloc_cmap(&disp[con].cmap, 
2653                                         1 << disp[con].var.bits_per_pixel, 0)))
2654                 return err;
2655         }
2656         if (con == currcon) /* current console ? */
2657                 return do_fb_set_cmap(cmap, &(disp[con].var), kspc);
2658         else
2659                 copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
2660         return 0;
2661 }
2662 
2663 static int
2664 atari_fb_pan_display(struct fb_var_screeninfo *var, int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2665 {
2666         int xoffset = var->xoffset;
2667         int yoffset = var->yoffset;
2668         int err;
2669 
2670         if (   xoffset < 0 || xoffset + disp[con].var.xres > disp[con].var.xres_virtual
2671             || yoffset < 0 || yoffset + disp[con].var.yres > disp[con].var.yres_virtual)
2672                 return -EINVAL;
2673 
2674         if (con == currcon) {
2675                 if (fbhw->pan_display) {
2676                         if ((err = fbhw->pan_display(var, &current_par)))
2677                                 return err;
2678                 }
2679                 else
2680                         return -EINVAL;
2681         }
2682         disp[con].var.xoffset = var->xoffset;
2683         disp[con].var.yoffset = var->yoffset;
2684         return 0;
2685 }
2686 
2687 static int
2688 atari_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
     /* [previous][next][first][last][top][bottom][index][help] */
2689                unsigned long arg, int con)
2690 {
2691         int i;
2692 
2693         switch (cmd) {
2694 #ifdef FBCMD_GET_CURRENTPAR
2695         case FBCMD_GET_CURRENTPAR:
2696                 if ((i = verify_area(VERIFY_WRITE, (void *)arg,
2697                                                          sizeof(struct atari_fb_par))))
2698                         return i;
2699                 memcpy_tofs((void *)arg, (void *)&current_par,
2700                                         sizeof(struct atari_fb_par));
2701                 return 0;
2702 #endif
2703 #ifdef FBCMD_SET_CURRENTPAR
2704         case FBCMD_SET_CURRENTPAR:
2705                 if ((i = verify_area(VERIFY_READ, (void *)arg,
2706                                                          sizeof(struct atari_fb_par))))
2707                         return i;
2708                 memcpy_fromfs((void *)&current_par, (void *)arg,
2709                                         sizeof(struct atari_fb_par));
2710                 atari_fb_set_par(&current_par);
2711                 return 0;
2712 #endif
2713         }
2714         return -EINVAL;
2715 }
2716 
2717 static struct fb_ops atari_fb_ops = {
2718         atari_fb_get_fix, atari_fb_get_var, atari_fb_set_var, atari_fb_get_cmap,
2719         atari_fb_set_cmap, atari_fb_pan_display, atari_fb_ioctl 
2720 };
2721 
2722 static void
2723 check_default_par( int detected_mode )
     /* [previous][next][first][last][top][bottom][index][help] */
2724 {
2725         char default_name[10];
2726         int i;
2727         struct fb_var_screeninfo var;
2728         unsigned long min_mem;
2729 
2730         /* First try the user supplied mode */
2731         if (default_par) {
2732                 var=atari_fb_predefined[default_par-1];
2733                 var.activate = FB_ACTIVATE_TEST;
2734                 if (do_fb_set_var(&var,1))
2735                         default_par=0;          /* failed */
2736         }
2737         /* Next is the autodetected one */
2738         if (! default_par) {
2739                 var=atari_fb_predefined[detected_mode-1]; /* autodetect */
2740                 var.activate = FB_ACTIVATE_TEST;
2741                 if (!do_fb_set_var(&var,1))
2742                         default_par=detected_mode;
2743         }
2744         /* If that also failed, try some default modes... */
2745         if (! default_par) {
2746                 /* try default1, default2... */
2747                 for (i=1 ; i < 10 ; i++) {
2748                         sprintf(default_name,"default%d",i);
2749                         default_par=get_video_mode(default_name);
2750                         if (! default_par)
2751                                 panic("can't set default video mode\n");
2752                         var=atari_fb_predefined[default_par-1];
2753                         var.activate = FB_ACTIVATE_TEST;
2754                         if (! do_fb_set_var(&var,1))
2755                                 break;  /* ok */
2756                 }
2757         }
2758         min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8;
2759         if (default_mem_req < min_mem)
2760                 default_mem_req=min_mem;
2761 }
2762 
2763 static int
2764 atafb_switch(int con)
     /* [previous][next][first][last][top][bottom][index][help] */
2765 {
2766         /* Do we have to save the colormap ? */
2767         if (disp[currcon].cmap.len)
2768                 do_fb_get_cmap(&disp[currcon].cmap, &(disp[currcon].var), 1);
2769         do_fb_set_var(&disp[con].var,1);
2770         currcon=con;
2771         /* Install new colormap */
2772         do_install_cmap(con);
2773         return 0;
2774 }
2775 
2776 static void
2777 atafb_blank(int blank)
     /* [previous][next][first][last][top][bottom][index][help] */
2778 {
2779         unsigned short black[16];
2780         struct fb_cmap cmap;
2781         if (fbhw->blank && !fbhw->blank(blank))
2782                 return;
2783         if (blank) {
2784                 memset(black, 0, 16*sizeof(unsigned short));
2785                 cmap.red=black;
2786                 cmap.green=black;
2787                 cmap.blue=black;
2788                 cmap.transp=NULL;
2789                 cmap.start=0;
2790                 cmap.len=16;
2791                 do_fb_set_cmap(&cmap, &(disp[currcon].var), 1);
2792         }
2793         else
2794                 do_install_cmap(currcon);
2795 }
2796 
2797 struct fb_info *
2798 atari_fb_init(long *mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
2799 {
2800         int err;
2801         int pad;
2802         int detected_mode;
2803         unsigned long mem_req;
2804         struct fb_var_screeninfo *var;
2805         
2806         err=register_framebuffer("Atari Builtin", &node, &atari_fb_ops, 
2807                         num_atari_fb_predefined, atari_fb_predefined);
2808         if (err < 0)
2809                 panic ("Cannot register frame buffer\n");
2810         do {
2811 #ifdef ATAFB_EXT
2812                 if (external_addr) {
2813                         fbhw = &ext_switch;
2814                         break;
2815                 }
2816 #endif
2817 #ifdef ATAFB_TT
2818                 if (ATARIHW_PRESENT(TT_SHIFTER)) {
2819                         fbhw = &tt_switch;
2820                         break;
2821                 }
2822 #endif
2823 #ifdef ATAFB_FALCON
2824                 if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
2825                         fbhw = &falcon_switch;
2826                         add_isr(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO, NULL,
2827                                         "framebuffer/modeswitch");
2828                         break;
2829                 }
2830 #endif
2831 #ifdef ATAFB_STE
2832                 if (ATARIHW_PRESENT(STND_SHIFTER) ||
2833                     ATARIHW_PRESENT(EXTD_SHIFTER)) {
2834                         fbhw = &st_switch;
2835                         break;
2836                 }
2837                 fbhw = &st_switch;
2838                 printk("Cannot determine video hardware; defaulting to ST(e)\n");
2839 #else /* ATAFB_STE */
2840                 /* no default driver included */
2841                 /* Nobody will ever see this message :-) */
2842                 panic("Cannot initialize video hardware\n");
2843 #endif
2844         } while (0);
2845         detected_mode = fbhw->detect();
2846         check_default_par(detected_mode);
2847 #ifdef ATAFB_EXT
2848         if (!external_addr) {
2849 #endif /* ATAFB_EXT */
2850                 mem_req = default_mem_req + ovsc_offset +
2851                         ovsc_addlen;
2852                 mem_req = ((mem_req + PAGE_SIZE - 1) & PAGE_MASK) + PAGE_SIZE;
2853                 screen_base = (unsigned long) atari_stram_alloc(mem_req, mem_start);
2854                 memset((char *) screen_base, 0, mem_req);
2855                 pad = ((screen_base + PAGE_SIZE-1) & PAGE_MASK) - screen_base;
2856                 screen_base+=pad;
2857                 real_screen_base=screen_base+ovsc_offset;
2858                 screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
2859                 st_ovsc_switch(ovsc_switchmode);
2860                 if (m68k_is040or060) {
2861                         /* On a '040+, the cache mode of video RAM must be set to
2862                          * write-through also for internal video hardware! */
2863                         cache_push( VTOP(screen_base), screen_len );
2864                         kernel_set_cachemode( screen_base, screen_len,
2865                                                                   KERNELMAP_NO_COPYBACK );
2866                 }
2867 #ifdef ATAFB_EXT
2868         }
2869         else {
2870                 /* Map the video memory (physical address given) to somewhere
2871                  * in the kernel address space.
2872                  */
2873                 *mem_start = (*mem_start+PAGE_SIZE-1) & ~(PAGE_SIZE-1);
2874                 external_addr = kernel_map(external_addr, external_len,
2875                                                                         KERNELMAP_NO_COPYBACK, mem_start);
2876                 if (external_vgaiobase)
2877                         external_vgaiobase = kernel_map(external_vgaiobase,
2878                                 0x10000, KERNELMAP_NOCACHE_SER, mem_start);
2879                 screen_base      =
2880                 real_screen_base = external_addr;
2881                 screen_len       = external_len & PAGE_MASK;
2882                 memset ((char *) screen_base, 0, external_len);
2883         }
2884 #endif /* ATAFB_EXT */
2885 
2886         strcpy(fb_info.modename, "Atari Builtin ");
2887         fb_info.disp=disp;
2888         fb_info.switch_con=&atafb_switch;
2889         fb_info.updatevar=&fb_update_var;
2890         fb_info.blank=&atafb_blank;
2891         var=atari_fb_predefined+default_par-1;
2892         do_fb_set_var(var,1);
2893         strcat(fb_info.modename,fb_var_names[default_par-1][0]);
2894 
2895         atari_fb_get_var(&disp[0].var, -1);
2896         atari_fb_set_disp(-1);
2897         printk("Determined %dx%d, depth %d\n",
2898                disp[0].var.xres, disp[0].var.yres, disp[0].var.bits_per_pixel );
2899         do_install_cmap(0);
2900         return &fb_info;
2901 }
2902 
2903 /* a strtok which returns empty strings, too */
2904 
2905 static char * strtoke(char * s,const char * ct)
     /* [previous][next][first][last][top][bottom][index][help] */
2906 {
2907   char *sbegin, *send;
2908   static char *ssave = NULL;
2909   
2910   sbegin  = s ? s : ssave;
2911   if (!sbegin) {
2912           return NULL;
2913   }
2914   if (*sbegin == '\0') {
2915     ssave = NULL;
2916     return NULL;
2917   }
2918   send = strpbrk(sbegin, ct);
2919   if (send && *send != '\0')
2920     *send++ = '\0';
2921   ssave = send;
2922   return sbegin;
2923 }
2924 
2925 void atari_video_setup( char *options, int *ints )
     /* [previous][next][first][last][top][bottom][index][help] */
2926 {
2927     char *this_opt;
2928     int temp;
2929     char ext_str[80], int_str[100];
2930     char mcap_spec[80];
2931     char user_mode[80];
2932 
2933         ext_str[0]          =
2934         int_str[0]          =
2935         mcap_spec[0]        =
2936         user_mode[0]        =
2937         fb_info.fontname[0] = '\0';
2938 
2939     if (!options || !*options)
2940                 return;
2941      
2942     for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
2943         if (!*this_opt) continue;
2944         if ((temp=get_video_mode(this_opt)))
2945                 default_par=temp;
2946         else if (! strcmp(this_opt, "inverse"))
2947                 inverse=1;
2948         else if (!strncmp(this_opt, "font:", 5))
2949            strcpy(fb_info.fontname, this_opt+5);
2950         else if (! strncmp(this_opt, "hwscroll_",9)) {
2951                 hwscroll=simple_strtoul(this_opt+9, NULL, 10);
2952                 if (hwscroll < 0)
2953                         hwscroll = 0;
2954                 if (hwscroll > 200)
2955                         hwscroll = 200;
2956         }
2957         else if (! strncmp(this_opt, "sw_",3)) {
2958                 if (! strcmp(this_opt+3, "acia"))
2959                         ovsc_switchmode = SWITCH_ACIA;
2960                 else if (! strcmp(this_opt+3, "snd6"))
2961                         ovsc_switchmode = SWITCH_SND6;
2962                 else if (! strcmp(this_opt+3, "snd7"))
2963                         ovsc_switchmode = SWITCH_SND7;
2964                 else ovsc_switchmode = SWITCH_NONE;
2965         }
2966 #ifdef ATAFB_EXT
2967         else if (!strcmp(this_opt,"mv300")) {
2968                 external_bitspercol = 8;
2969                 external_card_type = IS_MV300;
2970         }
2971         else if (!strncmp(this_opt,"external:",9))
2972                 strcpy(ext_str, this_opt+9);
2973 #endif
2974         else if (!strncmp(this_opt,"internal:",9))
2975                 strcpy(int_str, this_opt+9);
2976 #ifdef ATAFB_FALCON
2977         else if (!strcmp(this_opt, "pwrsave"))
2978                 pwrsave = 1;
2979         else if (!strncmp(this_opt, "eclock:", 7)) {
2980                 fext.f = simple_strtoul(this_opt+7, NULL, 10);
2981                 /* external pixelclock in kHz --> ps */
2982                 fext.t = (2000000000UL/fext.f+1)/2;
2983                 fext.f *= 1000;
2984         }
2985         else if (!strncmp(this_opt, "monitorcap:", 11))
2986                 strcpy(mcap_spec, this_opt+11);
2987 #endif
2988         else if (!strcmp(this_opt, "keep"))
2989                 DontCalcRes = 1;
2990         else if (!strncmp(this_opt, "R", 1))
2991                 strcpy(user_mode, this_opt+1);
2992     }
2993 
2994     if (*int_str) {
2995         /* Format to config extended internal video hardware like OverScan:
2996         "<switch-type>,internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>"
2997         Explanation:
2998         <switch-type> type to switch on higher resolution
2999                         sw_acia : via keyboard ACIA
3000                         sw_snd6 : via bit 6 of the soundchip port
3001                         sw_snd7 : via bit 7 of the soundchip port
3002         <xres>: x-resolution 
3003         <yres>: y-resolution
3004         The following are only needed if you have an overscan which
3005         needs a black border:
3006         <xres_max>: max. length of a line in pixels your OverScan hardware would allow
3007         <yres_max>: max. number of lines your OverScan hardware would allow
3008         <offset>: Offset from physical beginning to visible beginning
3009                   of screen in bytes
3010         */
3011         int xres;
3012         char *p;
3013 
3014         if (!(p = strtoke(int_str, ";")) ||!*p) goto int_invalid;
3015         xres = simple_strtoul(p, NULL, 10);
3016         if (!(p = strtoke(NULL, ";")) || !*p) goto int_invalid;
3017         sttt_xres=xres;
3018         tt_yres=st_yres=simple_strtoul(p, NULL, 10);
3019         if ((p=strtoke(NULL, ";")) && *p) {
3020                 sttt_xres_virtual=simple_strtoul(p, NULL, 10);
3021         }
3022         if ((p=strtoke(NULL, ";")) && *p) {
3023                 sttt_yres_virtual=simple_strtoul(p, NULL, 0);
3024         }
3025         if ((p=strtoke(NULL, ";")) && *p) {
3026                 ovsc_offset=simple_strtoul(p, NULL, 0);
3027         }
3028 
3029         if (ovsc_offset || (sttt_yres_virtual != st_yres))
3030                 use_hwscroll=0;
3031     }
3032     else 
3033       int_invalid:      ovsc_switchmode = SWITCH_NONE;
3034 
3035 #ifdef ATAFB_EXT
3036     if (*ext_str) {
3037         int             xres, yres, depth, planes;
3038         unsigned long addr, len;
3039         char *p;
3040 
3041         /* Format is: <xres>;<yres>;<depth>;<plane organ.>;
3042          *            <screen mem addr>
3043          *            [;<screen mem length>[;<vgaiobase>[;<colorreg-type>]]]
3044          */
3045         if (!(p = strtoke(ext_str, ";")) ||!*p) goto ext_invalid;
3046         xres = simple_strtoul(p, NULL, 10);
3047         if (xres <= 0) goto ext_invalid;
3048 
3049         if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3050         yres = simple_strtoul(p, NULL, 10);
3051         if (yres <= 0) goto ext_invalid;
3052 
3053         if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3054         depth = simple_strtoul(p, NULL, 10);
3055         if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
3056                 depth != 16 && depth != 24) goto ext_invalid;
3057 
3058         if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3059         if (*p == 'i')
3060                 planes = FB_TYPE_INTERLEAVED_PLANES;
3061         else if (*p == 'p')
3062                 planes = FB_TYPE_PACKED_PIXELS;
3063         else if (*p == 'n')
3064                 planes = FB_TYPE_PLANES;
3065         else if (*p == 't')
3066                 planes = -1; /* true color */
3067         else
3068                 goto ext_invalid;
3069 
3070 
3071         if (!(p = strtoke(NULL, ";")) ||!*p) goto ext_invalid;
3072         addr = simple_strtoul(p, NULL, 0);
3073 
3074         if (!(p = strtoke(NULL, ";")) ||!*p)
3075                 len = xres*yres*depth/8;
3076         else
3077                 len = simple_strtoul(p, NULL, 0);
3078 
3079         if ((p = strtoke(NULL, ";")) && *p)
3080                 external_vgaiobase=simple_strtoul(p, NULL, 0);
3081 
3082         if ((p = strtoke(NULL, ";")) && *p) {
3083                 external_bitspercol = simple_strtoul(p, NULL, 0);
3084                 if (external_bitspercol > 8)
3085                         external_bitspercol = 8;
3086                 else if (external_bitspercol < 1)
3087                         external_bitspercol = 1;
3088         }
3089         
3090         if ((p = strtoke(NULL, ";")) && *p) {
3091                 if (!strcmp(this_opt, "vga"))
3092                         external_card_type = IS_VGA;
3093                 if (!strcmp(this_opt, "mv300"))
3094                         external_card_type = IS_MV300;
3095         }
3096 
3097         external_xres  = xres;
3098         external_yres  = yres;
3099         external_depth = depth;
3100         external_pmode = planes;
3101         external_addr  = addr;
3102         external_len   = len;
3103                 
3104         if (external_card_type == IS_MV300)
3105           switch (external_depth) {
3106             case 1:
3107               MV300_reg = MV300_reg_1bit;
3108               break;
3109             case 4:
3110               MV300_reg = MV300_reg_4bit;
3111               break;
3112             case 8:
3113               MV300_reg = MV300_reg_8bit;
3114               break;
3115             }
3116 
3117       ext_invalid:
3118         ;
3119     }
3120 #endif /* ATAFB_EXT */
3121 
3122 #ifdef ATAFB_FALCON
3123     if (*mcap_spec) {
3124         char *p;
3125         int vmin, vmax, hmin, hmax;
3126 
3127         /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>
3128          * <V*> vertical freq. in Hz
3129          * <H*> horizontal freq. in kHz
3130          */
3131         if (!(p = strtoke(mcap_spec, ";")) || !*p) goto cap_invalid;
3132         vmin = simple_strtoul(p, NULL, 10);
3133         if (vmin <= 0) goto cap_invalid;
3134         if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
3135         vmax = simple_strtoul(p, NULL, 10);
3136         if (vmax <= 0 || vmax <= vmin) goto cap_invalid;
3137         if (!(p = strtoke(NULL, ";")) || !*p) goto cap_invalid;
3138         hmin = 1000 * simple_strtoul(p, NULL, 10);
3139         if (hmin <= 0) goto cap_invalid;
3140         if (!(p = strtoke(NULL, "")) || !*p) goto cap_invalid;
3141         hmax = 1000 * simple_strtoul(p, NULL, 10);
3142         if (hmax <= 0 || hmax <= hmin) goto cap_invalid;
3143 
3144         vfmin = vmin;
3145         vfmax = vmax;
3146         hfmin = hmin;
3147         hfmax = hmax;
3148       cap_invalid:
3149         ;
3150     }
3151 #endif
3152 
3153         if (*user_mode) {
3154                 /* Format of user defined video mode is: <xres>;<yres>;<depth>
3155                  */
3156                 char *p;
3157                 int xres, yres, depth, temp;
3158 
3159                 if (!(p = strtoke(user_mode, ";")) || !*p) goto user_invalid;
3160                 xres = simple_strtoul(p, NULL, 10);
3161                 if (!(p = strtoke(NULL, ";")) || !*p) goto user_invalid;
3162                 yres = simple_strtoul(p, NULL, 10);
3163                 if (!(p = strtoke(NULL, "")) || !*p) goto user_invalid;
3164                 depth = simple_strtoul(p, NULL, 10);
3165                 if ((temp=get_video_mode("user0"))) {
3166                         default_par=temp;
3167                         atari_fb_predefined[default_par-1].xres = xres;
3168                         atari_fb_predefined[default_par-1].yres = yres;
3169                         atari_fb_predefined[default_par-1].bits_per_pixel = depth;
3170                 }
3171 
3172           user_invalid:
3173                 ;
3174         }
3175 }

/* [previous][next][first][last][top][bottom][index][help] */