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