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