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