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