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