Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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