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