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