1/* 2 * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets 3 * 4 * Copyright 1999-2001 Jeff Garzik <jgarzik@mandrakesoft.com> 5 * 6 * Contributors (thanks, all!) 7 * 8 * Jeff Rugen: 9 * Major contributions; Motorola PowerStack (PPC and PCI) support, 10 * GD54xx, 1280x1024 mode support, change MCLK based on VCLK. 11 * 12 * Geert Uytterhoeven: 13 * Excellent code review. 14 * 15 * Lars Hecking: 16 * Amiga updates and testing. 17 * 18 * Original clgenfb author: Frank Neumann 19 * 20 * Based on retz3fb.c and clgen.c: 21 * Copyright (C) 1997 Jes Sorensen 22 * Copyright (C) 1996 Frank Neumann 23 * 24 *************************************************************** 25 * 26 * Format this code with GNU indent '-kr -i8 -pcs' options. 27 * 28 * This file is subject to the terms and conditions of the GNU General Public 29 * License. See the file COPYING in the main directory of this archive 30 * for more details. 31 * 32 */ 33 34#define CLGEN_VERSION "1.9.9.1" 35 36#include <linux/config.h> 37#include <linux/module.h> 38#include <linux/kernel.h> 39#include <linux/errno.h> 40#include <linux/string.h> 41#include <linux/mm.h> 42#include <linux/tty.h> 43#include <linux/slab.h> 44#include <linux/delay.h> 45#include <linux/fb.h> 46#include <linux/init.h> 47#include <linux/selection.h> 48#include <asm/pgtable.h> 49 50#ifdef CONFIG_ZORRO 51#include <linux/zorro.h> 52#endif 53#ifdef CONFIG_PCI 54#include <linux/pci.h> 55#endif 56#ifdef CONFIG_AMIGA 57#include <asm/amigahw.h> 58#endif 59#ifdef CONFIG_ALL_PPC 60#include <asm/processor.h> 61#define isPReP (_machine == _MACH_prep) 62#else 63#define isPReP 0 64#endif 65 66#include <video/fbcon.h> 67#include <video/fbcon-mfb.h> 68#include <video/fbcon-cfb8.h> 69#include <video/fbcon-cfb16.h> 70#include <video/fbcon-cfb24.h> 71#include <video/fbcon-cfb32.h> 72 73#include "clgenfb.h" 74#include "vga.h" 75 76 77/***************************************************************** 78 * 79 * debugging and utility macros 80 * 81 */ 82 83/* enable debug output? */ 84/* #define CLGEN_DEBUG 1 */ 85 86/* disable runtime assertions? */ 87/* #define CLGEN_NDEBUG */ 88 89/* debug output */ 90#ifdef CLGEN_DEBUG 91#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) 92#else 93#define DPRINTK(fmt, args...) 94#endif 95 96/* debugging assertions */ 97#ifndef CLGEN_NDEBUG 98#define assert(expr) \ 99 if(!(expr)) { \ 100 printk( "Assertion failed! %s,%s,%s,line=%d\n",\ 101 #expr,__FILE__,__FUNCTION__,__LINE__); \ 102 } 103#else 104#define assert(expr) 105#endif 106 107#ifdef TRUE 108#undef TRUE 109#endif 110#ifdef FALSE 111#undef FALSE 112#endif 113#define TRUE 1 114#define FALSE 0 115 116#define MB_ (1024*1024) 117#define KB_ (1024) 118 119#define MAX_NUM_BOARDS 7 120 121 122/***************************************************************** 123 * 124 * chipset information 125 * 126 */ 127 128/* board types */ 129typedef enum { 130 BT_NONE = 0, 131 BT_SD64, 132 BT_PICCOLO, 133 BT_PICASSO, 134 BT_SPECTRUM, 135 BT_PICASSO4, /* GD5446 */ 136 BT_ALPINE, /* GD543x/4x */ 137 BT_GD5480, 138 BT_LAGUNA, /* GD546x */ 139} clgen_board_t; 140 141 142/* 143 * per-board-type information, used for enumerating and abstracting 144 * chip-specific information 145 * NOTE: MUST be in the same order as clgen_board_t in order to 146 * use direct indexing on this array 147 * NOTE: '__initdata' cannot be used as some of this info 148 * is required at runtime. Maybe separate into an init-only and 149 * a run-time table? 150 */ 151static const struct clgen_board_info_rec { 152 clgen_board_t btype; /* chipset enum, not strictly necessary, as 153 * clgen_board_info[] is directly indexed 154 * by this value */ 155 char *name; /* ASCII name of chipset */ 156 long maxclock; /* maximum video clock */ 157 unsigned init_sr07 : 1; /* init SR07 during init_vgachip() */ 158 unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */ 159 unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */ 160 161 /* initial SR07 value, then for each mode */ 162 unsigned char sr07; 163 unsigned char sr07_1bpp; 164 unsigned char sr07_1bpp_mux; 165 unsigned char sr07_8bpp; 166 unsigned char sr07_8bpp_mux; 167 168 unsigned char sr1f; /* SR1F VGA initial register value */ 169} clgen_board_info[] = { 170 { BT_NONE, }, /* dummy record */ 171 { BT_SD64, 172 "CL SD64", 173 140000, /* the SD64/P4 have a higher max. videoclock */ 174 TRUE, 175 TRUE, 176 TRUE, 177 0xF0, 178 0xF0, 179 0, /* unused, does not multiplex */ 180 0xF1, 181 0, /* unused, does not multiplex */ 182 0x20 }, 183 { BT_PICCOLO, 184 "CL Piccolo", 185 90000, 186 TRUE, 187 TRUE, 188 FALSE, 189 0x80, 190 0x80, 191 0, /* unused, does not multiplex */ 192 0x81, 193 0, /* unused, does not multiplex */ 194 0x22 }, 195 { BT_PICASSO, 196 "CL Picasso", 197 90000, 198 TRUE, 199 TRUE, 200 FALSE, 201 0x20, 202 0x20, 203 0, /* unused, does not multiplex */ 204 0x21, 205 0, /* unused, does not multiplex */ 206 0x22 }, 207 { BT_SPECTRUM, 208 "CL Spectrum", 209 90000, 210 TRUE, 211 TRUE, 212 FALSE, 213 0x80, 214 0x80, 215 0, /* unused, does not multiplex */ 216 0x81, 217 0, /* unused, does not multiplex */ 218 0x22 }, 219 { BT_PICASSO4, 220 "CL Picasso4", 221 140000, /* the SD64/P4 have a higher max. videoclock */ 222 TRUE, 223 FALSE, 224 TRUE, 225 0x20, 226 0x20, 227 0, /* unused, does not multiplex */ 228 0x21, 229 0, /* unused, does not multiplex */ 230 0 }, 231 { BT_ALPINE, 232 "CL Alpine", 233 110000, /* 135100 for some, 85500 for others */ 234 TRUE, 235 TRUE, 236 TRUE, 237 0xA0, 238 0xA1, 239 0xA7, 240 0xA1, 241 0xA7, 242 0x1C }, 243 { BT_GD5480, 244 "CL GD5480", 245 90000, 246 TRUE, 247 TRUE, 248 TRUE, 249 0x10, 250 0x11, 251 0, /* unused, does not multiplex */ 252 0x11, 253 0, /* unused, does not multiplex */ 254 0x1C }, 255 { BT_LAGUNA, 256 "CL Laguna", 257 135100, 258 FALSE, 259 FALSE, 260 TRUE, 261 0, /* unused */ 262 0, /* unused */ 263 0, /* unused */ 264 0, /* unused */ 265 0, /* unused */ 266 0 }, /* unused */ 267}; 268 269 270#ifdef CONFIG_PCI 271/* the list of PCI devices for which we probe, and the 272 * order in which we do it */ 273static const struct { 274 clgen_board_t btype; 275 const char *nameOverride; 276 unsigned short device; 277} clgen_pci_probe_list[] __initdata = { 278 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5436 }, 279 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_8 }, 280 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_4 }, 281 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5430 }, /* GD-5440 has identical id */ 282 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_7543 }, 283 { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_7548 }, 284 { BT_GD5480, NULL, PCI_DEVICE_ID_CIRRUS_5480 }, /* MacPicasso probably */ 285 { BT_PICASSO4, NULL, PCI_DEVICE_ID_CIRRUS_5446 }, /* Picasso 4 is a GD5446 */ 286 { BT_LAGUNA, "CL Laguna", PCI_DEVICE_ID_CIRRUS_5462 }, 287 { BT_LAGUNA, "CL Laguna 3D", PCI_DEVICE_ID_CIRRUS_5464 }, 288 { BT_LAGUNA, "CL Laguna 3DA", PCI_DEVICE_ID_CIRRUS_5465 }, 289}; 290#endif /* CONFIG_PCI */ 291 292 293#ifdef CONFIG_ZORRO 294static const struct { 295 clgen_board_t btype; 296 zorro_id id, id2; 297 unsigned long size; 298} clgen_zorro_probe_list[] __initdata = { 299 { BT_SD64, 300 ZORRO_PROD_HELFRICH_SD64_RAM, 301 ZORRO_PROD_HELFRICH_SD64_REG, 302 0x400000 }, 303 { BT_PICCOLO, 304 ZORRO_PROD_HELFRICH_PICCOLO_RAM, 305 ZORRO_PROD_HELFRICH_PICCOLO_REG, 306 0x200000 }, 307 { BT_PICASSO, 308 ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 309 ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, 310 0x200000 }, 311 { BT_SPECTRUM, 312 ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 313 ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, 314 0x200000 }, 315 { BT_PICASSO4, 316 ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 317 0, 318 0x400000 }, 319}; 320#endif /* CONFIG_ZORRO */ 321 322 323 324struct clgenfb_par { 325 struct fb_var_screeninfo var; 326 327 __u32 line_length; /* in BYTES! */ 328 __u32 visual; 329 __u32 type; 330 331 long freq; 332 long nom; 333 long den; 334 long div; 335 long multiplexing; 336 long mclk; 337 long divMCLK; 338 339 long HorizRes; /* The x resolution in pixel */ 340 long HorizTotal; 341 long HorizDispEnd; 342 long HorizBlankStart; 343 long HorizBlankEnd; 344 long HorizSyncStart; 345 long HorizSyncEnd; 346 347 long VertRes; /* the physical y resolution in scanlines */ 348 long VertTotal; 349 long VertDispEnd; 350 long VertSyncStart; 351 long VertSyncEnd; 352 long VertBlankStart; 353 long VertBlankEnd; 354}; 355 356 357 358#ifdef CLGEN_DEBUG 359typedef enum { 360 CRT, 361 SEQ 362} clgen_dbg_reg_class_t; 363#endif /* CLGEN_DEBUG */ 364 365 366 367 368/* info about board */ 369struct clgenfb_info { 370 struct fb_info_gen gen; 371 372 caddr_t fbmem; 373 caddr_t regs; 374 caddr_t mem; 375 unsigned long size; 376 clgen_board_t btype; 377 int smallboard; 378 unsigned char SFR; /* Shadow of special function register */ 379 380 unsigned long fbmem_phys; 381 unsigned long fbregs_phys; 382 383 struct clgenfb_par currentmode; 384 385 struct { u8 red, green, blue, pad; } palette[256]; 386 387 union { 388#ifdef FBCON_HAS_CFB16 389 u16 cfb16[16]; 390#endif 391#ifdef FBCON_HAS_CFB24 392 u32 cfb24[16]; 393#endif 394#ifdef FBCON_HAS_CFB32 395 u32 cfb32[16]; 396#endif 397 } fbcon_cmap; 398 399#ifdef CONFIG_ZORRO 400 unsigned long board_addr, 401 board_size; 402#endif 403 404#ifdef CONFIG_PCI 405 struct pci_dev *pdev; 406#endif 407}; 408 409 410 411 412static struct display disp; 413 414static struct clgenfb_info boards[MAX_NUM_BOARDS]; /* the boards */ 415 416static unsigned clgen_def_mode = 1; 417static int noaccel = 0; 418 419 420 421/* 422 * Predefined Video Modes 423 */ 424 425static const struct { 426 const char *name; 427 struct fb_var_screeninfo var; 428} clgenfb_predefined[] __initdata = 429 430{ 431 {"Autodetect", /* autodetect mode */ 432 {0} 433 }, 434 435 {"640x480", /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */ 436 { 437 640, 480, 640, 480, 0, 0, 8, 0, 438 {0, 8, 0}, 439 {0, 8, 0}, 440 {0, 8, 0}, 441 {0, 0, 0}, 442 0, 0, -1, -1, FB_ACCEL_NONE, 40000, 48, 16, 32, 8, 96, 4, 443 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED 444 } 445 }, 446 447 {"800x600", /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */ 448 { 449 800, 600, 800, 600, 0, 0, 8, 0, 450 {0, 8, 0}, 451 {0, 8, 0}, 452 {0, 8, 0}, 453 {0, 0, 0}, 454 0, 0, -1, -1, FB_ACCEL_NONE, 20000, 128, 16, 24, 2, 96, 6, 455 0, FB_VMODE_NONINTERLACED 456 } 457 }, 458 459 /* 460 Modeline from XF86Config: 461 Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805 462 */ 463 {"1024x768", /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */ 464 { 465 1024, 768, 1024, 768, 0, 0, 8, 0, 466 {0, 8, 0}, 467 {0, 8, 0}, 468 {0, 8, 0}, 469 {0, 0, 0}, 470 0, 0, -1, -1, FB_ACCEL_NONE, 12500, 144, 32, 30, 2, 192, 6, 471 0, FB_VMODE_NONINTERLACED 472 } 473 } 474}; 475 476#define NUM_TOTAL_MODES ARRAY_SIZE(clgenfb_predefined) 477static struct fb_var_screeninfo clgenfb_default; 478 479/* 480 * Frame Buffer Name 481 */ 482 483static const char *clgenfb_name = "CLgen"; 484 485/****************************************************************************/ 486/**** BEGIN PROTOTYPES ******************************************************/ 487 488 489/*--- Interface used by the world ------------------------------------------*/ 490int clgenfb_init (void); 491int clgenfb_setup (char *options); 492 493static int clgenfb_open (struct fb_info *info, int user); 494static int clgenfb_release (struct fb_info *info, int user); 495 496/* function table of the above functions */ 497static struct fb_ops clgenfb_ops = { 498 owner: THIS_MODULE, 499 fb_open: clgenfb_open, 500 fb_release: clgenfb_release, 501 fb_get_fix: fbgen_get_fix, 502 fb_get_var: fbgen_get_var, 503 fb_set_var: fbgen_set_var, 504 fb_get_cmap: fbgen_get_cmap, 505 fb_set_cmap: fbgen_set_cmap, 506 fb_pan_display: fbgen_pan_display, 507}; 508 509/*--- Hardware Specific Routines -------------------------------------------*/ 510static void clgen_detect (void); 511static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par, 512 struct fb_info_gen *info); 513static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par, 514 struct fb_info_gen *info); 515static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par, 516 struct fb_info_gen *info); 517static void clgen_get_par (void *par, struct fb_info_gen *info); 518static void clgen_set_par (const void *par, struct fb_info_gen *info); 519static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green, 520 unsigned *blue, unsigned *transp, 521 struct fb_info *info); 522static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green, 523 unsigned blue, unsigned transp, 524 struct fb_info *info); 525static int clgen_pan_display (const struct fb_var_screeninfo *var, 526 struct fb_info_gen *info); 527static int clgen_blank (int blank_mode, struct fb_info_gen *info); 528 529static void clgen_set_disp (const void *par, struct display *disp, 530 struct fb_info_gen *info); 531 532/* function table of the above functions */ 533static struct fbgen_hwswitch clgen_hwswitch = 534{ 535 clgen_detect, 536 clgen_encode_fix, 537 clgen_decode_var, 538 clgen_encode_var, 539 clgen_get_par, 540 clgen_set_par, 541 clgen_getcolreg, 542 clgen_setcolreg, 543 clgen_pan_display, 544 clgen_blank, 545 clgen_set_disp 546}; 547 548/* Text console acceleration */ 549 550#ifdef FBCON_HAS_CFB8 551static void fbcon_clgen8_bmove (struct display *p, int sy, int sx, 552 int dy, int dx, int height, int width); 553static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p, 554 int sy, int sx, int height, int width); 555 556static struct display_switch fbcon_clgen_8 = { 557 setup: fbcon_cfb8_setup, 558 bmove: fbcon_clgen8_bmove, 559 clear: fbcon_clgen8_clear, 560 putc: fbcon_cfb8_putc, 561 putcs: fbcon_cfb8_putcs, 562 revc: fbcon_cfb8_revc, 563 clear_margins: fbcon_cfb8_clear_margins, 564 fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) 565}; 566#endif 567#ifdef FBCON_HAS_CFB16 568static void fbcon_clgen16_bmove (struct display *p, int sy, int sx, 569 int dy, int dx, int height, int width); 570static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p, 571 int sy, int sx, int height, int width); 572static struct display_switch fbcon_clgen_16 = { 573 setup: fbcon_cfb16_setup, 574 bmove: fbcon_clgen16_bmove, 575 clear: fbcon_clgen16_clear, 576 putc: fbcon_cfb16_putc, 577 putcs: fbcon_cfb16_putcs, 578 revc: fbcon_cfb16_revc, 579 clear_margins: fbcon_cfb16_clear_margins, 580 fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) 581}; 582#endif 583#ifdef FBCON_HAS_CFB32 584static void fbcon_clgen32_bmove (struct display *p, int sy, int sx, 585 int dy, int dx, int height, int width); 586static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p, 587 int sy, int sx, int height, int width); 588static struct display_switch fbcon_clgen_32 = { 589 setup: fbcon_cfb32_setup, 590 bmove: fbcon_clgen32_bmove, 591 clear: fbcon_clgen32_clear, 592 putc: fbcon_cfb32_putc, 593 putcs: fbcon_cfb32_putcs, 594 revc: fbcon_cfb32_revc, 595 clear_margins: fbcon_cfb32_clear_margins, 596 fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) 597}; 598#endif 599 600 601 602/*--- Internal routines ----------------------------------------------------*/ 603static void init_vgachip (struct clgenfb_info *fb_info); 604static void switch_monitor (struct clgenfb_info *fb_info, int on); 605static void WGen (const struct clgenfb_info *fb_info, 606 int regnum, unsigned char val); 607static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum); 608static void AttrOn (const struct clgenfb_info *fb_info); 609static void WHDR (const struct clgenfb_info *fb_info, unsigned char val); 610static void WSFR (struct clgenfb_info *fb_info, unsigned char val); 611static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val); 612static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red, 613 unsigned char green, 614 unsigned char blue); 615static void clgen_WaitBLT (caddr_t regbase); 616static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, 617 u_short destx, u_short desty, 618 u_short width, u_short height, 619 u_short line_length); 620static void clgen_RectFill (struct clgenfb_info *fb_info, u_short x, u_short y, 621 u_short width, u_short height, 622 u_char color, u_short line_length); 623 624static void bestclock (long freq, long *best, 625 long *nom, long *den, 626 long *div, long maxfreq); 627 628#ifdef CLGEN_DEBUG 629static void clgen_dump (void); 630static void clgen_dbg_reg_dump (caddr_t regbase); 631static void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...); 632static void clgen_dbg_print_byte (const char *name, unsigned char val); 633#endif /* CLGEN_DEBUG */ 634 635/*** END PROTOTYPES ********************************************************/ 636/*****************************************************************************/ 637/*** BEGIN Interface Used by the World ***************************************/ 638 639static int opencount = 0; 640 641/*--- Open /dev/fbx ---------------------------------------------------------*/ 642static int clgenfb_open (struct fb_info *info, int user) 643{ 644 if (opencount++ == 0) 645 switch_monitor ((struct clgenfb_info *) info, 1); 646 return 0; 647} 648 649/*--- Close /dev/fbx --------------------------------------------------------*/ 650static int clgenfb_release (struct fb_info *info, int user) 651{ 652 if (--opencount == 0) 653 switch_monitor ((struct clgenfb_info *) info, 0); 654 return 0; 655} 656 657/**** END Interface used by the World *************************************/ 658/****************************************************************************/ 659/**** BEGIN Hardware specific Routines **************************************/ 660 661static void clgen_detect (void) 662{ 663 DPRINTK ("ENTER\n"); 664 DPRINTK ("EXIT\n"); 665} 666 667static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par, 668 struct fb_info_gen *info) 669{ 670 struct clgenfb_par *_par = (struct clgenfb_par *) par; 671 struct clgenfb_info *_info = (struct clgenfb_info *) info; 672 673 DPRINTK ("ENTER\n"); 674 675 memset (fix, 0, sizeof (struct fb_fix_screeninfo)); 676 strcpy (fix->id, clgenfb_name); 677 678 if (_info->btype == BT_GD5480) { 679 /* Select proper byte-swapping aperture */ 680 switch (_par->var.bits_per_pixel) { 681 case 1: 682 case 8: 683 fix->smem_start = _info->fbmem_phys; 684 break; 685 case 16: 686 fix->smem_start = _info->fbmem_phys + 1 * MB_; 687 break; 688 case 24: 689 case 32: 690 fix->smem_start = _info->fbmem_phys + 2 * MB_; 691 break; 692 } 693 } else { 694 fix->smem_start = _info->fbmem_phys; 695 } 696 697 /* monochrome: only 1 memory plane */ 698 /* 8 bit and above: Use whole memory area */ 699 fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4 700 : _info->size; 701 fix->type = _par->type; 702 fix->type_aux = 0; 703 fix->visual = _par->visual; 704 fix->xpanstep = 1; 705 fix->ypanstep = 1; 706 fix->ywrapstep = 0; 707 fix->line_length = _par->line_length; 708 709 fix->mmio_start = 0; 710 fix->mmio_len = 0; 711 fix->accel = FB_ACCEL_NONE; 712 713 DPRINTK ("EXIT\n"); 714 return 0; 715} 716 717 718 719/* Get a good MCLK value */ 720static long clgen_get_mclk (long freq, int bpp, long *div) 721{ 722 long mclk; 723 724 assert (div != NULL); 725 726 /* Calculate MCLK, in case VCLK is high enough to require > 50MHz. 727 * Assume a 64-bit data path for now. The formula is: 728 * ((B * PCLK * 2)/W) * 1.2 729 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */ 730 mclk = ((bpp / 8) * freq * 2) / 4; 731 mclk = (mclk * 12) / 10; 732 if (mclk < 50000) 733 mclk = 50000; 734 DPRINTK ("Use MCLK of %ld kHz\n", mclk); 735 736 /* Calculate value for SR1F. Multiply by 2 so we can round up. */ 737 mclk = ((mclk * 16) / 14318); 738 mclk = (mclk + 1) / 2; 739 DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk); 740 741 /* Determine if we should use MCLK instead of VCLK, and if so, what we 742 * should divide it by to get VCLK */ 743 switch (freq) { 744 case 24751 ... 25249: 745 *div = 2; 746 DPRINTK ("Using VCLK = MCLK/2\n"); 747 break; 748 case 49501 ... 50499: 749 *div = 1; 750 DPRINTK ("Using VCLK = MCLK\n"); 751 break; 752 default: 753 *div = 0; 754 break; 755 } 756 757 return mclk; 758} 759 760static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par, 761 struct fb_info_gen *info) 762{ 763 long freq; 764 long maxclock; 765 int xres, hfront, hsync, hback; 766 int yres, vfront, vsync, vback; 767 int nom, den; /* translyting from pixels->bytes */ 768 int i; 769 static struct { 770 int xres, yres; 771 } modes[] = { { 772 1600, 1280 773 }, { 774 1280, 1024 775 }, { 776 1024, 768 777 }, 778 { 779 800, 600 780 }, { 781 640, 480 782 }, { 783 -1, -1 784 } 785 }; 786 787 struct clgenfb_par *_par = (struct clgenfb_par *) par; 788 struct clgenfb_info *fb_info = (struct clgenfb_info *) info; 789 790 assert (var != NULL); 791 assert (par != NULL); 792 assert (info != NULL); 793 794 DPRINTK ("ENTER\n"); 795 796 DPRINTK ("Requested: %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel); 797 DPRINTK (" virtual: %dx%d\n", var->xres_virtual, var->yres_virtual); 798 DPRINTK (" offset: (%d,%d)\n", var->xoffset, var->yoffset); 799 DPRINTK ("grayscale: %d\n", var->grayscale); 800 801 memset (par, 0, sizeof (struct clgenfb_par)); 802 803 _par->var = *var; 804 805 switch (var->bits_per_pixel) { 806 case 1: 807 nom = 4; 808 den = 8; 809 break; /* 8 pixel per byte, only 1/4th of mem usable */ 810 case 2 ... 8: 811 _par->var.bits_per_pixel = 8; 812 nom = 1; 813 den = 1; 814 break; /* 1 pixel == 1 byte */ 815 case 9 ... 16: 816 _par->var.bits_per_pixel = 16; 817 nom = 2; 818 den = 1; 819 break; /* 2 bytes per pixel */ 820 case 17 ... 24: 821 _par->var.bits_per_pixel = 24; 822 nom = 3; 823 den = 1; 824 break; /* 3 bytes per pixel */ 825 case 25 ... 32: 826 _par->var.bits_per_pixel = 32; 827 nom = 4; 828 den = 1; 829 break; /* 4 bytes per pixel */ 830 default: 831 printk ("clgen: mode %dx%dx%d rejected...color depth not supported.\n", 832 var->xres, var->yres, var->bits_per_pixel); 833 DPRINTK ("EXIT - EINVAL error\n"); 834 return -EINVAL; 835 } 836 837 if (_par->var.xres * nom / den * _par->var.yres > fb_info->size) { 838 printk ("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", 839 var->xres, var->yres, var->bits_per_pixel); 840 DPRINTK ("EXIT - EINVAL error\n"); 841 return -EINVAL; 842 } 843 /* use highest possible virtual resolution */ 844 if (_par->var.xres_virtual == -1 && 845 _par->var.yres_virtual == -1) { 846 printk ("clgen: using maximum available virtual resolution\n"); 847 for (i = 0; modes[i].xres != -1; i++) { 848 if (modes[i].xres * nom / den * modes[i].yres < fb_info->size / 2) 849 break; 850 } 851 if (modes[i].xres == -1) { 852 printk ("clgen: could not find a virtual resolution that fits into video memory!!\n"); 853 DPRINTK ("EXIT - EINVAL error\n"); 854 return -EINVAL; 855 } 856 _par->var.xres_virtual = modes[i].xres; 857 _par->var.yres_virtual = modes[i].yres; 858 859 printk ("clgen: virtual resolution set to maximum of %dx%d\n", 860 _par->var.xres_virtual, _par->var.yres_virtual); 861 } else if (_par->var.xres_virtual == -1) { 862 } else if (_par->var.yres_virtual == -1) { 863 } 864 if (_par->var.xoffset < 0) 865 _par->var.xoffset = 0; 866 if (_par->var.yoffset < 0) 867 _par->var.yoffset = 0; 868 869 /* truncate xoffset and yoffset to maximum if too high */ 870 if (_par->var.xoffset > _par->var.xres_virtual - _par->var.xres) 871 _par->var.xoffset = _par->var.xres_virtual - _par->var.xres - 1; 872 873 if (_par->var.yoffset > _par->var.yres_virtual - _par->var.yres) 874 _par->var.yoffset = _par->var.yres_virtual - _par->var.yres - 1; 875 876 switch (_par->var.bits_per_pixel) { 877 case 1: 878 _par->line_length = _par->var.xres_virtual / 8; 879 _par->visual = FB_VISUAL_MONO10; 880 break; 881 882 case 8: 883 _par->line_length = _par->var.xres_virtual; 884 _par->visual = FB_VISUAL_PSEUDOCOLOR; 885 _par->var.red.offset = 0; 886 _par->var.red.length = 6; 887 _par->var.green.offset = 0; 888 _par->var.green.length = 6; 889 _par->var.blue.offset = 0; 890 _par->var.blue.length = 6; 891 break; 892 893 case 16: 894 _par->line_length = _par->var.xres_virtual * 2; 895 _par->visual = FB_VISUAL_DIRECTCOLOR; 896 if(isPReP) { 897 _par->var.red.offset = 2; 898 _par->var.green.offset = -3; 899 _par->var.blue.offset = 8; 900 } else { 901 _par->var.red.offset = 10; 902 _par->var.green.offset = 5; 903 _par->var.blue.offset = 0; 904 } 905 _par->var.red.length = 5; 906 _par->var.green.length = 5; 907 _par->var.blue.length = 5; 908 break; 909 910 case 24: 911 _par->line_length = _par->var.xres_virtual * 3; 912 _par->visual = FB_VISUAL_DIRECTCOLOR; 913 if(isPReP) { 914 _par->var.red.offset = 8; 915 _par->var.green.offset = 16; 916 _par->var.blue.offset = 24; 917 } else { 918 _par->var.red.offset = 16; 919 _par->var.green.offset = 8; 920 _par->var.blue.offset = 0; 921 } 922 _par->var.red.length = 8; 923 _par->var.green.length = 8; 924 _par->var.blue.length = 8; 925 break; 926 927 case 32: 928 _par->line_length = _par->var.xres_virtual * 4; 929 _par->visual = FB_VISUAL_DIRECTCOLOR; 930 if(isPReP) { 931 _par->var.red.offset = 8; 932 _par->var.green.offset = 16; 933 _par->var.blue.offset = 24; 934 } else { 935 _par->var.red.offset = 16; 936 _par->var.green.offset = 8; 937 _par->var.blue.offset = 0; 938 } 939 _par->var.red.length = 8; 940 _par->var.green.length = 8; 941 _par->var.blue.length = 8; 942 break; 943 944 default: 945 DPRINTK("Unsupported bpp size: %d\n", _par->var.bits_per_pixel); 946 assert (FALSE); 947 /* should never occur */ 948 break; 949 } 950 951 _par->var.red.msb_right = 952 _par->var.green.msb_right = 953 _par->var.blue.msb_right = 954 _par->var.transp.offset = 955 _par->var.transp.length = 956 _par->var.transp.msb_right = 0; 957 958 _par->type = FB_TYPE_PACKED_PIXELS; 959 960 /* convert from ps to kHz */ 961 freq = 1000000000 / var->pixclock; 962 963 DPRINTK ("desired pixclock: %ld kHz\n", freq); 964 965 maxclock = clgen_board_info[fb_info->btype].maxclock; 966 _par->multiplexing = 0; 967 968 /* If the frequency is greater than we can support, we might be able 969 * to use multiplexing for the video mode */ 970 if (freq > maxclock) { 971 switch (fb_info->btype) { 972 case BT_ALPINE: 973 case BT_GD5480: 974 _par->multiplexing = 1; 975 break; 976 977 default: 978 printk (KERN_WARNING "clgen: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock); 979 DPRINTK ("EXIT - return -EINVAL\n"); 980 return -EINVAL; 981 } 982 } 983 984 bestclock (freq, &_par->freq, &_par->nom, &_par->den, &_par->div, 985 maxclock); 986 _par->mclk = clgen_get_mclk (freq, _par->var.bits_per_pixel, &_par->divMCLK); 987 988 xres = _par->var.xres; 989 hfront = _par->var.right_margin; 990 hsync = _par->var.hsync_len; 991 hback = _par->var.left_margin; 992 993 yres = _par->var.yres; 994 vfront = _par->var.lower_margin; 995 vsync = _par->var.vsync_len; 996 vback = _par->var.upper_margin; 997 998 if (_par->var.vmode & FB_VMODE_DOUBLE) { 999 yres *= 2; 1000 vfront *= 2; 1001 vsync *= 2; 1002 vback *= 2; 1003 } else if (_par->var.vmode & FB_VMODE_INTERLACED) { 1004 yres = (yres + 1) / 2; 1005 vfront = (vfront + 1) / 2; 1006 vsync = (vsync + 1) / 2; 1007 vback = (vback + 1) / 2; 1008 } 1009 _par->HorizRes = xres; 1010 _par->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5; 1011 _par->HorizDispEnd = xres / 8 - 1; 1012 _par->HorizBlankStart = xres / 8; 1013 _par->HorizBlankEnd = _par->HorizTotal + 5; /* does not count with "-5" */ 1014 _par->HorizSyncStart = (xres + hfront) / 8 + 1; 1015 _par->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1; 1016 1017 _par->VertRes = yres; 1018 _par->VertTotal = yres + vfront + vsync + vback - 2; 1019 _par->VertDispEnd = yres - 1; 1020 _par->VertBlankStart = yres; 1021 _par->VertBlankEnd = _par->VertTotal; 1022 _par->VertSyncStart = yres + vfront - 1; 1023 _par->VertSyncEnd = yres + vfront + vsync - 1; 1024 1025 if (_par->VertRes >= 1024) { 1026 _par->VertTotal /= 2; 1027 _par->VertSyncStart /= 2; 1028 _par->VertSyncEnd /= 2; 1029 _par->VertDispEnd /= 2; 1030 } 1031 if (_par->multiplexing) { 1032 _par->HorizTotal /= 2; 1033 _par->HorizSyncStart /= 2; 1034 _par->HorizSyncEnd /= 2; 1035 _par->HorizDispEnd /= 2; 1036 } 1037 if (_par->VertRes >= 1280) { 1038 printk (KERN_WARNING "clgen: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n"); 1039 DPRINTK ("EXIT - EINVAL error\n"); 1040 return -EINVAL; 1041 } 1042 DPRINTK ("EXIT\n"); 1043 return 0; 1044} 1045 1046 1047static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par, 1048 struct fb_info_gen *info) 1049{ 1050 DPRINTK ("ENTER\n"); 1051 1052 *var = ((struct clgenfb_par *) par)->var; 1053 1054 DPRINTK ("EXIT\n"); 1055 return 0; 1056} 1057 1058/* get current video mode */ 1059static void clgen_get_par (void *par, struct fb_info_gen *info) 1060{ 1061 struct clgenfb_par *_par = (struct clgenfb_par *) par; 1062 struct clgenfb_info *_info = (struct clgenfb_info *) info; 1063 1064 DPRINTK ("ENTER\n"); 1065 1066 *_par = _info->currentmode; 1067 1068 DPRINTK ("EXIT\n"); 1069} 1070 1071static void clgen_set_mclk (const struct clgenfb_info *fb_info, int val, int div) 1072{ 1073 assert (fb_info != NULL); 1074 1075 if (div == 2) { 1076 /* VCLK = MCLK/2 */ 1077 unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E); 1078 vga_wseq (fb_info->regs, CL_SEQR1E, old | 0x1); 1079 vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f)); 1080 } else if (div == 1) { 1081 /* VCLK = MCLK */ 1082 unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E); 1083 vga_wseq (fb_info->regs, CL_SEQR1E, old & ~0x1); 1084 vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f)); 1085 } else { 1086 vga_wseq (fb_info->regs, CL_SEQR1F, val & 0x3f); 1087 } 1088} 1089 1090/************************************************************************* 1091 clgen_set_par() 1092 1093 actually writes the values for a new video mode into the hardware, 1094**************************************************************************/ 1095static void clgen_set_par (const void *par, struct fb_info_gen *info) 1096{ 1097 unsigned char tmp; 1098 int offset = 0; 1099 struct clgenfb_par *_par = (struct clgenfb_par *) par; 1100 struct clgenfb_info *fb_info = (struct clgenfb_info *) info; 1101 const struct clgen_board_info_rec *bi; 1102 1103 DPRINTK ("ENTER\n"); 1104 DPRINTK ("Requested mode: %dx%dx%d\n", 1105 _par->var.xres, _par->var.yres, _par->var.bits_per_pixel); 1106 DPRINTK ("pixclock: %d\n", _par->var.pixclock); 1107 1108 bi = &clgen_board_info[fb_info->btype]; 1109 1110 1111 /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ 1112 vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ 1113 1114 /* if debugging is enabled, all parameters get output before writing */ 1115 DPRINTK ("CRT0: %ld\n", _par->HorizTotal); 1116 vga_wcrt (fb_info->regs, VGA_CRTC_H_TOTAL, _par->HorizTotal); 1117 1118 DPRINTK ("CRT1: %ld\n", _par->HorizDispEnd); 1119 vga_wcrt (fb_info->regs, VGA_CRTC_H_DISP, _par->HorizDispEnd); 1120 1121 DPRINTK ("CRT2: %ld\n", _par->HorizBlankStart); 1122 vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_START, _par->HorizBlankStart); 1123 1124 DPRINTK ("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32); /* + 128: Compatible read */ 1125 vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_END, 128 + (_par->HorizBlankEnd % 32)); 1126 1127 DPRINTK ("CRT4: %ld\n", _par->HorizSyncStart); 1128 vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_START, _par->HorizSyncStart); 1129 1130 tmp = _par->HorizSyncEnd % 32; 1131 if (_par->HorizBlankEnd & 32) 1132 tmp += 128; 1133 DPRINTK ("CRT5: %d\n", tmp); 1134 vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_END, tmp); 1135 1136 DPRINTK ("CRT6: %ld\n", _par->VertTotal & 0xff); 1137 vga_wcrt (fb_info->regs, VGA_CRTC_V_TOTAL, (_par->VertTotal & 0xff)); 1138 1139 tmp = 16; /* LineCompare bit #9 */ 1140 if (_par->VertTotal & 256) 1141 tmp |= 1; 1142 if (_par->VertDispEnd & 256) 1143 tmp |= 2; 1144 if (_par->VertSyncStart & 256) 1145 tmp |= 4; 1146 if (_par->VertBlankStart & 256) 1147 tmp |= 8; 1148 if (_par->VertTotal & 512) 1149 tmp |= 32; 1150 if (_par->VertDispEnd & 512) 1151 tmp |= 64; 1152 if (_par->VertSyncStart & 512) 1153 tmp |= 128; 1154 DPRINTK ("CRT7: %d\n", tmp); 1155 vga_wcrt (fb_info->regs, VGA_CRTC_OVERFLOW, tmp); 1156 1157 tmp = 0x40; /* LineCompare bit #8 */ 1158 if (_par->VertBlankStart & 512) 1159 tmp |= 0x20; 1160 if (_par->var.vmode & FB_VMODE_DOUBLE) 1161 tmp |= 0x80; 1162 DPRINTK ("CRT9: %d\n", tmp); 1163 vga_wcrt (fb_info->regs, VGA_CRTC_MAX_SCAN, tmp); 1164 1165 DPRINTK ("CRT10: %ld\n", _par->VertSyncStart & 0xff); 1166 vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_START, (_par->VertSyncStart & 0xff)); 1167 1168 DPRINTK ("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16); 1169 vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, (_par->VertSyncEnd % 16 + 64 + 32)); 1170 1171 DPRINTK ("CRT12: %ld\n", _par->VertDispEnd & 0xff); 1172 vga_wcrt (fb_info->regs, VGA_CRTC_V_DISP_END, (_par->VertDispEnd & 0xff)); 1173 1174 DPRINTK ("CRT15: %ld\n", _par->VertBlankStart & 0xff); 1175 vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_START, (_par->VertBlankStart & 0xff)); 1176 1177 DPRINTK ("CRT16: %ld\n", _par->VertBlankEnd & 0xff); 1178 vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_END, (_par->VertBlankEnd & 0xff)); 1179 1180 DPRINTK ("CRT18: 0xff\n"); 1181 vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0xff); 1182 1183 tmp = 0; 1184 if (_par->var.vmode & FB_VMODE_INTERLACED) 1185 tmp |= 1; 1186 if (_par->HorizBlankEnd & 64) 1187 tmp |= 16; 1188 if (_par->HorizBlankEnd & 128) 1189 tmp |= 32; 1190 if (_par->VertBlankEnd & 256) 1191 tmp |= 64; 1192 if (_par->VertBlankEnd & 512) 1193 tmp |= 128; 1194 1195 DPRINTK ("CRT1a: %d\n", tmp); 1196 vga_wcrt (fb_info->regs, CL_CRT1A, tmp); 1197 1198 /* set VCLK0 */ 1199 /* hardware RefClock: 14.31818 MHz */ 1200 /* formula: VClk = (OSC * N) / (D * (1+P)) */ 1201 /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ 1202 1203 vga_wseq (fb_info->regs, CL_SEQRB, _par->nom); 1204 tmp = _par->den << 1; 1205 if (_par->div != 0) 1206 tmp |= 1; 1207 1208 if ((fb_info->btype == BT_SD64) || 1209 (fb_info->btype == BT_ALPINE) || 1210 (fb_info->btype == BT_GD5480)) 1211 tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ 1212 1213 DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp); 1214 vga_wseq (fb_info->regs, CL_SEQR1B, tmp); 1215 1216 if (_par->VertRes >= 1024) 1217 /* 1280x1024 */ 1218 vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc7); 1219 else 1220 /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit 1221 * address wrap, no compat. */ 1222 vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3); 1223 1224/* HAEH? vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20); * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */ 1225 1226 /* don't know if it would hurt to also program this if no interlaced */ 1227 /* mode is used, but I feel better this way.. :-) */ 1228 if (_par->var.vmode & FB_VMODE_INTERLACED) 1229 vga_wcrt (fb_info->regs, VGA_CRTC_REGS, _par->HorizTotal / 2); 1230 else 1231 vga_wcrt (fb_info->regs, VGA_CRTC_REGS, 0x00); /* interlace control */ 1232 1233 vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0); 1234 1235 /* adjust horizontal/vertical sync type (low/high) */ 1236 tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */ 1237 if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT) 1238 tmp |= 0x40; 1239 if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT) 1240 tmp |= 0x80; 1241 WGen (fb_info, VGA_MIS_W, tmp); 1242 1243 vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0); /* Screen A Preset Row-Scan register */ 1244 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0); /* text cursor on and start line */ 1245 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 31); /* text cursor end line */ 1246 1247 /****************************************************** 1248 * 1249 * 1 bpp 1250 * 1251 */ 1252 1253 /* programming for different color depths */ 1254 if (_par->var.bits_per_pixel == 1) { 1255 DPRINTK ("clgen: preparing for 1 bit deep display\n"); 1256 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0); /* mode register */ 1257 1258 /* SR07 */ 1259 switch (fb_info->btype) { 1260 case BT_SD64: 1261 case BT_PICCOLO: 1262 case BT_PICASSO: 1263 case BT_SPECTRUM: 1264 case BT_PICASSO4: 1265 case BT_ALPINE: 1266 case BT_GD5480: 1267 DPRINTK (" (for GD54xx)\n"); 1268 vga_wseq (fb_info->regs, CL_SEQR7, 1269 _par->multiplexing ? 1270 bi->sr07_1bpp_mux : bi->sr07_1bpp); 1271 break; 1272 1273 case BT_LAGUNA: 1274 DPRINTK (" (for GD546x)\n"); 1275 vga_wseq (fb_info->regs, CL_SEQR7, 1276 vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01); 1277 break; 1278 1279 default: 1280 printk (KERN_WARNING "clgen: unknown Board\n"); 1281 break; 1282 } 1283 1284 /* Extended Sequencer Mode */ 1285 switch (fb_info->btype) { 1286 case BT_SD64: 1287 /* setting the SEQRF on SD64 is not necessary (only during init) */ 1288 DPRINTK ("(for SD64)\n"); 1289 vga_wseq (fb_info->regs, CL_SEQR1F, 0x1a); /* MCLK select */ 1290 break; 1291 1292 case BT_PICCOLO: 1293 DPRINTK ("(for Piccolo)\n"); 1294/* ### ueberall 0x22? */ 1295 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */ 1296 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ 1297 break; 1298 1299 case BT_PICASSO: 1300 DPRINTK ("(for Picasso)\n"); 1301 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 22 MCLK select */ 1302 vga_wseq (fb_info->regs, CL_SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */ 1303 break; 1304 1305 case BT_SPECTRUM: 1306 DPRINTK ("(for Spectrum)\n"); 1307/* ### ueberall 0x22? */ 1308 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */ 1309 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */ 1310 break; 1311 1312 case BT_PICASSO4: 1313 case BT_ALPINE: 1314 case BT_GD5480: 1315 case BT_LAGUNA: 1316 DPRINTK (" (for GD54xx)\n"); 1317 /* do nothing */ 1318 break; 1319 1320 default: 1321 printk (KERN_WARNING "clgen: unknown Board\n"); 1322 break; 1323 } 1324 1325 WGen (fb_info, VGA_PEL_MSK, 0x01); /* pixel mask: pass-through for first plane */ 1326 if (_par->multiplexing) 1327 WHDR (fb_info, 0x4a); /* hidden dac reg: 1280x1024 */ 1328 else 1329 WHDR (fb_info, 0); /* hidden dac: nothing */ 1330 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x06); /* memory mode: odd/even, ext. memory */ 1331 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0x01); /* plane mask: only write to first plane */ 1332 offset = _par->var.xres_virtual / 16; 1333 } 1334 1335 /****************************************************** 1336 * 1337 * 8 bpp 1338 * 1339 */ 1340 1341 else if (_par->var.bits_per_pixel == 8) { 1342 DPRINTK ("clgen: preparing for 8 bit deep display\n"); 1343 switch (fb_info->btype) { 1344 case BT_SD64: 1345 case BT_PICCOLO: 1346 case BT_PICASSO: 1347 case BT_SPECTRUM: 1348 case BT_PICASSO4: 1349 case BT_ALPINE: 1350 case BT_GD5480: 1351 DPRINTK (" (for GD54xx)\n"); 1352 vga_wseq (fb_info->regs, CL_SEQR7, 1353 _par->multiplexing ? 1354 bi->sr07_8bpp_mux : bi->sr07_8bpp); 1355 break; 1356 1357 case BT_LAGUNA: 1358 DPRINTK (" (for GD546x)\n"); 1359 vga_wseq (fb_info->regs, CL_SEQR7, 1360 vga_rseq (fb_info->regs, CL_SEQR7) | 0x01); 1361 break; 1362 1363 default: 1364 printk (KERN_WARNING "clgen: unknown Board\n"); 1365 break; 1366 } 1367 1368 switch (fb_info->btype) { 1369 case BT_SD64: 1370 vga_wseq (fb_info->regs, CL_SEQR1F, 0x1d); /* MCLK select */ 1371 break; 1372 1373 case BT_PICCOLO: 1374 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */ 1375 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1376 break; 1377 1378 case BT_PICASSO: 1379 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */ 1380 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1381 break; 1382 1383 case BT_SPECTRUM: 1384 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */ 1385 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1386 break; 1387 1388 case BT_PICASSO4: 1389#ifdef CONFIG_ZORRO 1390 vga_wseq (fb_info->regs, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */ 1391#endif 1392/* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */ 1393 break; 1394 1395 case BT_ALPINE: 1396 DPRINTK (" (for GD543x)\n"); 1397 clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK); 1398 /* We already set SRF and SR1F */ 1399 break; 1400 1401 case BT_GD5480: 1402 case BT_LAGUNA: 1403 DPRINTK (" (for GD54xx)\n"); 1404 /* do nothing */ 1405 break; 1406 1407 default: 1408 printk (KERN_WARNING "clgen: unknown Board\n"); 1409 break; 1410 } 1411 1412 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */ 1413 WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */ 1414 if (_par->multiplexing) 1415 WHDR (fb_info, 0x4a); /* hidden dac reg: 1280x1024 */ 1416 else 1417 WHDR (fb_info, 0); /* hidden dac: nothing */ 1418 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */ 1419 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */ 1420 offset = _par->var.xres_virtual / 8; 1421 } 1422 1423 /****************************************************** 1424 * 1425 * 16 bpp 1426 * 1427 */ 1428 1429 else if (_par->var.bits_per_pixel == 16) { 1430 DPRINTK ("clgen: preparing for 16 bit deep display\n"); 1431 switch (fb_info->btype) { 1432 case BT_SD64: 1433 vga_wseq (fb_info->regs, CL_SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */ 1434 vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e); /* MCLK select */ 1435 break; 1436 1437 case BT_PICCOLO: 1438 vga_wseq (fb_info->regs, CL_SEQR7, 0x87); 1439 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1440 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ 1441 break; 1442 1443 case BT_PICASSO: 1444 vga_wseq (fb_info->regs, CL_SEQR7, 0x27); 1445 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1446 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ 1447 break; 1448 1449 case BT_SPECTRUM: 1450 vga_wseq (fb_info->regs, CL_SEQR7, 0x87); 1451 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1452 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ 1453 break; 1454 1455 case BT_PICASSO4: 1456 vga_wseq (fb_info->regs, CL_SEQR7, 0x27); 1457/* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */ 1458 break; 1459 1460 case BT_ALPINE: 1461 DPRINTK (" (for GD543x)\n"); 1462 if (_par->HorizRes >= 1024) 1463 vga_wseq (fb_info->regs, CL_SEQR7, 0xa7); 1464 else 1465 vga_wseq (fb_info->regs, CL_SEQR7, 0xa3); 1466 clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK); 1467 break; 1468 1469 case BT_GD5480: 1470 DPRINTK (" (for GD5480)\n"); 1471 vga_wseq (fb_info->regs, CL_SEQR7, 0x17); 1472 /* We already set SRF and SR1F */ 1473 break; 1474 1475 case BT_LAGUNA: 1476 DPRINTK (" (for GD546x)\n"); 1477 vga_wseq (fb_info->regs, CL_SEQR7, 1478 vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01); 1479 break; 1480 1481 default: 1482 printk (KERN_WARNING "CLGEN: unknown Board\n"); 1483 break; 1484 } 1485 1486 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */ 1487 WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */ 1488#ifdef CONFIG_PCI 1489 WHDR (fb_info, 0xc0); /* Copy Xbh */ 1490#elif defined(CONFIG_ZORRO) 1491 WHDR (fb_info, 0xa0); /* hidden dac reg: nothing special */ 1492#endif 1493 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */ 1494 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */ 1495 offset = _par->var.xres_virtual / 4; 1496 } 1497 1498 /****************************************************** 1499 * 1500 * 32 bpp 1501 * 1502 */ 1503 1504 else if (_par->var.bits_per_pixel == 32) { 1505 DPRINTK ("clgen: preparing for 24/32 bit deep display\n"); 1506 switch (fb_info->btype) { 1507 case BT_SD64: 1508 vga_wseq (fb_info->regs, CL_SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */ 1509 vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e); /* MCLK select */ 1510 break; 1511 1512 case BT_PICCOLO: 1513 vga_wseq (fb_info->regs, CL_SEQR7, 0x85); 1514 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1515 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ 1516 break; 1517 1518 case BT_PICASSO: 1519 vga_wseq (fb_info->regs, CL_SEQR7, 0x25); 1520 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1521 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ 1522 break; 1523 1524 case BT_SPECTRUM: 1525 vga_wseq (fb_info->regs, CL_SEQR7, 0x85); 1526 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ 1527 vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ 1528 break; 1529 1530 case BT_PICASSO4: 1531 vga_wseq (fb_info->regs, CL_SEQR7, 0x25); 1532/* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */ 1533 break; 1534 1535 case BT_ALPINE: 1536 DPRINTK (" (for GD543x)\n"); 1537 vga_wseq (fb_info->regs, CL_SEQR7, 0xa9); 1538 clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK); 1539 break; 1540 1541 case BT_GD5480: 1542 DPRINTK (" (for GD5480)\n"); 1543 vga_wseq (fb_info->regs, CL_SEQR7, 0x19); 1544 /* We already set SRF and SR1F */ 1545 break; 1546 1547 case BT_LAGUNA: 1548 DPRINTK (" (for GD546x)\n"); 1549 vga_wseq (fb_info->regs, CL_SEQR7, 1550 vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01); 1551 break; 1552 1553 default: 1554 printk (KERN_WARNING "clgen: unknown Board\n"); 1555 break; 1556 } 1557 1558 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */ 1559 WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */ 1560 WHDR (fb_info, 0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */ 1561 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */ 1562 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */ 1563 offset = _par->var.xres_virtual / 4; 1564 } 1565 1566 /****************************************************** 1567 * 1568 * unknown/unsupported bpp 1569 * 1570 */ 1571 1572 else { 1573 printk (KERN_ERR "clgen: What's this?? requested color depth == %d.\n", 1574 _par->var.bits_per_pixel); 1575 } 1576 1577 vga_wcrt (fb_info->regs, VGA_CRTC_OFFSET, offset & 0xff); 1578 tmp = 0x22; 1579 if (offset & 0x100) 1580 tmp |= 0x10; /* offset overflow bit */ 1581 1582 vga_wcrt (fb_info->regs, CL_CRT1B, tmp); /* screen start addr #16-18, fastpagemode cycles */ 1583 1584 if (fb_info->btype == BT_SD64 || 1585 fb_info->btype == BT_PICASSO4 || 1586 fb_info->btype == BT_ALPINE || 1587 fb_info->btype == BT_GD5480) 1588 vga_wcrt (fb_info->regs, CL_CRT1D, 0x00); /* screen start address bit 19 */ 1589 1590 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0); /* text cursor location high */ 1591 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0); /* text cursor location low */ 1592 vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0); /* underline row scanline = at very bottom */ 1593 1594 vga_wattr (fb_info->regs, VGA_ATC_MODE, 1); /* controller mode */ 1595 vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0); /* overscan (border) color */ 1596 vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 15); /* color plane enable */ 1597 vga_wattr (fb_info->regs, CL_AR33, 0); /* pixel panning */ 1598 vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0); /* color select */ 1599 1600 /* [ EGS: SetOffset(); ] */ 1601 /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ 1602 AttrOn (fb_info); 1603 1604 vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0); /* set/reset register */ 1605 vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0); /* set/reset enable */ 1606 vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0); /* color compare */ 1607 vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0); /* data rotate */ 1608 vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0); /* read map select */ 1609 vga_wgfx (fb_info->regs, VGA_GFX_MISC, 1); /* miscellaneous register */ 1610 vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 15); /* color don't care */ 1611 vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 255); /* bit mask */ 1612 1613 vga_wseq (fb_info->regs, CL_SEQR12, 0x0); /* graphics cursor attributes: nothing special */ 1614 1615 /* finally, turn on everything - turn off "FullBandwidth" bit */ 1616 /* also, set "DotClock%2" bit where requested */ 1617 tmp = 0x01; 1618 1619/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ? 1620 if (var->vmode & FB_VMODE_CLOCK_HALVE) 1621 tmp |= 0x08; 1622*/ 1623 1624 vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, tmp); 1625 DPRINTK ("CL_SEQR1: %d\n", tmp); 1626 1627 fb_info->currentmode = *_par; 1628 1629 DPRINTK ("virtual offset: (%d,%d)\n", _par->var.xoffset, _par->var.yoffset); 1630 /* pan to requested offset */ 1631 clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen *) fb_info); 1632 1633#ifdef CLGEN_DEBUG 1634 clgen_dump (); 1635#endif 1636 1637 DPRINTK ("EXIT\n"); 1638 return; 1639} 1640 1641 1642static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green, 1643 unsigned *blue, unsigned *transp, 1644 struct fb_info *info) 1645{ 1646 struct clgenfb_info *fb_info = (struct clgenfb_info *)info; 1647 1648 if (regno > 255) 1649 return 1; 1650 *red = fb_info->palette[regno].red; 1651 *green = fb_info->palette[regno].green; 1652 *blue = fb_info->palette[regno].blue; 1653 *transp = 0; 1654 return 0; 1655} 1656 1657 1658static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green, 1659 unsigned blue, unsigned transp, 1660 struct fb_info *info) 1661{ 1662 struct clgenfb_info *fb_info = (struct clgenfb_info *) info; 1663 1664 if (regno > 255) 1665 return -EINVAL; 1666 1667#ifdef FBCON_HAS_CFB8 1668 switch (fb_info->currentmode.var.bits_per_pixel) { 1669 case 8: 1670 /* "transparent" stuff is completely ignored. */ 1671 WClut (fb_info, regno, red >> 10, green >> 10, blue >> 10); 1672 break; 1673 default: 1674 /* do nothing */ 1675 break; 1676 } 1677#endif /* FBCON_HAS_CFB8 */ 1678 1679 fb_info->palette[regno].red = red; 1680 fb_info->palette[regno].green = green; 1681 fb_info->palette[regno].blue = blue; 1682 1683 if (regno >= 16) 1684 return 0; 1685 1686 switch (fb_info->currentmode.var.bits_per_pixel) { 1687 1688#ifdef FBCON_HAS_CFB16 1689 case 16: 1690 assert (regno < 16); 1691 if(isPReP) { 1692 fb_info->fbcon_cmap.cfb16[regno] = 1693 ((red & 0xf800) >> 9) | 1694 ((green & 0xf800) >> 14) | 1695 ((green & 0xf800) << 2) | 1696 ((blue & 0xf800) >> 3); 1697 } else { 1698 fb_info->fbcon_cmap.cfb16[regno] = 1699 ((red & 0xf800) >> 1) | 1700 ((green & 0xf800) >> 6) | 1701 ((blue & 0xf800) >> 11); 1702 } 1703#endif /* FBCON_HAS_CFB16 */ 1704 1705#ifdef FBCON_HAS_CFB24 1706 case 24: 1707 assert (regno < 16); 1708 fb_info->fbcon_cmap.cfb24[regno] = 1709 (red << fb_info->currentmode.var.red.offset) | 1710 (green << fb_info->currentmode.var.green.offset) | 1711 (blue << fb_info->currentmode.var.blue.offset); 1712 break; 1713#endif /* FBCON_HAS_CFB24 */ 1714 1715#ifdef FBCON_HAS_CFB32 1716 case 32: 1717 assert (regno < 16); 1718 if(isPReP) { 1719 fb_info->fbcon_cmap.cfb32[regno] = 1720 ((red & 0xff00)) | 1721 ((green & 0xff00) << 8) | 1722 ((blue & 0xff00) << 16); 1723 } else { 1724 fb_info->fbcon_cmap.cfb32[regno] = 1725 ((red & 0xff00) << 8) | 1726 ((green & 0xff00)) | 1727 ((blue & 0xff00) >> 8); 1728 } 1729 break; 1730#endif /* FBCON_HAS_CFB32 */ 1731 default: 1732 /* do nothing */ 1733 break; 1734 } 1735 1736 return 0; 1737} 1738 1739/************************************************************************* 1740 clgen_pan_display() 1741 1742 performs display panning - provided hardware permits this 1743**************************************************************************/ 1744static int clgen_pan_display (const struct fb_var_screeninfo *var, 1745 struct fb_info_gen *info) 1746{ 1747 int xoffset = 0; 1748 int yoffset = 0; 1749 unsigned long base; 1750 unsigned char tmp = 0, tmp2 = 0, xpix; 1751 struct clgenfb_info *fb_info = (struct clgenfb_info *) info; 1752 1753 DPRINTK ("ENTER\n"); 1754 1755 /* no range checks for xoffset and yoffset, */ 1756 /* as fbgen_pan_display has already done this */ 1757 1758 fb_info->currentmode.var.xoffset = var->xoffset; 1759 fb_info->currentmode.var.yoffset = var->yoffset; 1760 1761 xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8; 1762 yoffset = var->yoffset; 1763 1764 base = yoffset * fb_info->currentmode.line_length + xoffset; 1765 1766 if (fb_info->currentmode.var.bits_per_pixel == 1) { 1767 /* base is already correct */ 1768 xpix = (unsigned char) (var->xoffset % 8); 1769 } else { 1770 base /= 4; 1771 xpix = (unsigned char) ((xoffset % 4) * 2); 1772 } 1773 1774 /* lower 8 + 8 bits of screen start address */ 1775 vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, (unsigned char) (base & 0xff)); 1776 vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, (unsigned char) (base >> 8)); 1777 1778 /* construct bits 16, 17 and 18 of screen start address */ 1779 if (base & 0x10000) 1780 tmp |= 0x01; 1781 if (base & 0x20000) 1782 tmp |= 0x04; 1783 if (base & 0x40000) 1784 tmp |= 0x08; 1785 1786 tmp2 = (vga_rcrt (fb_info->regs, CL_CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */ 1787 vga_wcrt (fb_info->regs, CL_CRT1B, tmp2); 1788 1789 /* construct bit 19 of screen start address */ 1790 if (clgen_board_info[fb_info->btype].scrn_start_bit19) { 1791 tmp2 = 0; 1792 if (base & 0x80000) 1793 tmp2 = 0x80; 1794 vga_wcrt (fb_info->regs, CL_CRT1D, tmp2); 1795 } 1796 1797 /* write pixel panning value to AR33; this does not quite work in 8bpp */ 1798 /* ### Piccolo..? Will this work? */ 1799 if (fb_info->currentmode.var.bits_per_pixel == 1) 1800 vga_wattr (fb_info->regs, CL_AR33, xpix); 1801 1802 1803 DPRINTK ("EXIT\n"); 1804 return (0); 1805} 1806 1807 1808static int clgen_blank (int blank_mode, struct fb_info_gen *info) 1809{ 1810 /* 1811 * Blank the screen if blank_mode != 0, else unblank. If blank == NULL 1812 * then the caller blanks by setting the CLUT (Color Look Up Table) to all 1813 * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due 1814 * to e.g. a video mode which doesn't support it. Implements VESA suspend 1815 * and powerdown modes on hardware that supports disabling hsync/vsync: 1816 * blank_mode == 2: suspend vsync 1817 * blank_mode == 3: suspend hsync 1818 * blank_mode == 4: powerdown 1819 */ 1820 unsigned char val; 1821 static int current_mode = 0; 1822 struct clgenfb_info *fb_info = (struct clgenfb_info *) info; 1823 1824 DPRINTK ("ENTER, blank mode = %d\n", blank_mode); 1825 1826 if (current_mode == blank_mode) { 1827 DPRINTK ("EXIT, returning 0\n"); 1828 return 0; 1829 } 1830 1831 /* Undo current */ 1832 switch (current_mode) { 1833 case 0: /* Screen is normal */ 1834 break; 1835 case 1: /* Screen is blanked */ 1836 val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE); 1837 vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* clear "FullBandwidth" bit */ 1838 break; 1839 case 2: /* vsync suspended */ 1840 case 3: /* hsync suspended */ 1841 case 4: /* sceen is powered down */ 1842 vga_wgfx (fb_info->regs, CL_GRE, 0x00); 1843 break; 1844 default: 1845 DPRINTK ("EXIT, returning 1\n"); 1846 return 1; 1847 } 1848 1849 /* set new */ 1850 switch (blank_mode) { 1851 case 0: /* Unblank screen */ 1852 break; 1853 case 1: /* Blank screen */ 1854 val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE); 1855 vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val | 0x20); /* set "FullBandwidth" bit */ 1856 break; 1857 case 2: /* suspend vsync */ 1858 vga_wgfx (fb_info->regs, CL_GRE, 0x04); 1859 break; 1860 case 3: /* suspend hsync */ 1861 vga_wgfx (fb_info->regs, CL_GRE, 0x02); 1862 break; 1863 case 4: /* powerdown */ 1864 vga_wgfx (fb_info->regs, CL_GRE, 0x06); 1865 break; 1866 default: 1867 DPRINTK ("EXIT, returning 1\n"); 1868 return 1; 1869 } 1870 1871 current_mode = blank_mode; 1872 DPRINTK ("EXIT, returning 0\n"); 1873 return 0; 1874} 1875/**** END Hardware specific Routines **************************************/ 1876/****************************************************************************/ 1877/**** BEGIN Internal Routines ***********************************************/ 1878 1879static void __init init_vgachip (struct clgenfb_info *fb_info) 1880{ 1881 const struct clgen_board_info_rec *bi; 1882 1883 DPRINTK ("ENTER\n"); 1884 1885 assert (fb_info != NULL); 1886 1887 bi = &clgen_board_info[fb_info->btype]; 1888 1889 /* reset board globally */ 1890 switch (fb_info->btype) { 1891 case BT_PICCOLO: 1892 WSFR (fb_info, 0x01); 1893 udelay (500); 1894 WSFR (fb_info, 0x51); 1895 udelay (500); 1896 break; 1897 case BT_PICASSO: 1898 WSFR2 (fb_info, 0xff); 1899 udelay (500); 1900 break; 1901 case BT_SD64: 1902 case BT_SPECTRUM: 1903 WSFR (fb_info, 0x1f); 1904 udelay (500); 1905 WSFR (fb_info, 0x4f); 1906 udelay (500); 1907 break; 1908 case BT_PICASSO4: 1909 vga_wcrt (fb_info->regs, CL_CRT51, 0x00); /* disable flickerfixer */ 1910 mdelay (100); 1911 vga_wgfx (fb_info->regs, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */ 1912 vga_wgfx (fb_info->regs, CL_GR33, 0x00); /* put blitter into 542x compat */ 1913 vga_wgfx (fb_info->regs, CL_GR31, 0x00); /* mode */ 1914 break; 1915 1916 case BT_GD5480: 1917 vga_wgfx (fb_info->regs, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */ 1918 break; 1919 1920 case BT_ALPINE: 1921 /* Nothing to do to reset the board. */ 1922 break; 1923 1924 default: 1925 printk (KERN_ERR "clgen: Warning: Unknown board type\n"); 1926 break; 1927 } 1928 1929 assert (fb_info->size > 0); /* make sure RAM size set by this point */ 1930 1931 /* assume it's a "large memory" board (2/4 MB) */ 1932 fb_info->smallboard = FALSE; 1933 1934 /* the P4 is not fully initialized here; I rely on it having been */ 1935 /* inited under AmigaOS already, which seems to work just fine */ 1936 /* (Klaus advised to do it this way) */ 1937 1938 if (fb_info->btype != BT_PICASSO4) { 1939 WGen (fb_info, CL_VSSM, 0x10); /* EGS: 0x16 */ 1940 WGen (fb_info, CL_POS102, 0x01); 1941 WGen (fb_info, CL_VSSM, 0x08); /* EGS: 0x0e */ 1942 1943 if (fb_info->btype != BT_SD64) 1944 WGen (fb_info, CL_VSSM2, 0x01); 1945 1946 vga_wseq (fb_info->regs, CL_SEQR0, 0x03); /* reset sequencer logic */ 1947 1948 vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */ 1949 WGen (fb_info, VGA_MIS_W, 0xc1); /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */ 1950 1951/* vga_wgfx (fb_info->regs, CL_GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */ 1952 vga_wseq (fb_info->regs, CL_SEQR6, 0x12); /* unlock all extension registers */ 1953 1954 vga_wgfx (fb_info->regs, CL_GR31, 0x04); /* reset blitter */ 1955 1956 switch (fb_info->btype) { 1957 case BT_GD5480: 1958 vga_wseq (fb_info->regs, CL_SEQRF, 0x98); 1959 break; 1960 case BT_ALPINE: 1961 break; 1962 case BT_SD64: 1963 vga_wseq (fb_info->regs, CL_SEQRF, 0xb8); 1964 break; 1965 default: 1966 vga_wseq (fb_info->regs, CL_SEQR16, 0x0f); 1967 vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); 1968 break; 1969 } 1970 } 1971 vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: nothing */ 1972 vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */ 1973 vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */ 1974 1975 /* controller-internal base address of video memory */ 1976 if (bi->init_sr07) 1977 vga_wseq (fb_info->regs, CL_SEQR7, bi->sr07); 1978 1979 /* vga_wseq (fb_info->regs, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */ 1980 1981 vga_wseq (fb_info->regs, CL_SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */ 1982 vga_wseq (fb_info->regs, CL_SEQR11, 0x00); /* graphics cursor Y position (..."... ) */ 1983 vga_wseq (fb_info->regs, CL_SEQR12, 0x00); /* graphics cursor attributes */ 1984 vga_wseq (fb_info->regs, CL_SEQR13, 0x00); /* graphics cursor pattern address */ 1985 1986 /* writing these on a P4 might give problems.. */ 1987 if (fb_info->btype != BT_PICASSO4) { 1988 vga_wseq (fb_info->regs, CL_SEQR17, 0x00); /* configuration readback and ext. color */ 1989 vga_wseq (fb_info->regs, CL_SEQR18, 0x02); /* signature generator */ 1990 } 1991 1992 /* MCLK select etc. */ 1993 if (bi->init_sr1f) 1994 vga_wseq (fb_info->regs, CL_SEQR1F, bi->sr1f); 1995 1996 vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0x00); /* Screen A preset row scan: none */ 1997 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */ 1998 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 0x00); /* Text cursor end: - */ 1999 vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, 0x00); /* Screen start address high: 0 */ 2000 vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, 0x00); /* Screen start address low: 0 */ 2001 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location high: 0 */ 2002 vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0x00); /* text cursor location low: 0 */ 2003 2004 vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0x00); /* Underline Row scanline: - */ 2005 vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */ 2006 vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */ 2007 /* ### add 0x40 for text modes with > 30 MHz pixclock */ 2008 vga_wcrt (fb_info->regs, CL_CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */ 2009 2010 vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset registes: - */ 2011 vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0x00); /* Set/Reset enable: - */ 2012 vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */ 2013 vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0x00); /* Data Rotate: - */ 2014 vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0x00); /* Read Map Select: - */ 2015 vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */ 2016 vga_wgfx (fb_info->regs, VGA_GFX_MISC, 0x01); /* Miscellaneous: memory map base address, graphics mode */ 2017 vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 0x0f); /* Color Don't care: involve all planes */ 2018 vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 0xff); /* Bit Mask: no mask at all */ 2019 if (fb_info->btype == BT_ALPINE) 2020 vga_wgfx (fb_info->regs, CL_GRB, 0x20); /* (5434 can't have bit 3 set for bitblt) */ 2021 else 2022 vga_wgfx (fb_info->regs, CL_GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */ 2023 2024 vga_wgfx (fb_info->regs, CL_GRC, 0xff); /* Color Key compare: - */ 2025 vga_wgfx (fb_info->regs, CL_GRD, 0x00); /* Color Key compare mask: - */ 2026 vga_wgfx (fb_info->regs, CL_GRE, 0x00); /* Miscellaneous control: - */ 2027 /* vga_wgfx (fb_info->regs, CL_GR10, 0x00); *//* Background color byte 1: - */ 2028/* vga_wgfx (fb_info->regs, CL_GR11, 0x00); */ 2029 2030 vga_wattr (fb_info->regs, VGA_ATC_PALETTE0, 0x00); /* Attribute Controller palette registers: "identity mapping" */ 2031 vga_wattr (fb_info->regs, VGA_ATC_PALETTE1, 0x01); 2032 vga_wattr (fb_info->regs, VGA_ATC_PALETTE2, 0x02); 2033 vga_wattr (fb_info->regs, VGA_ATC_PALETTE3, 0x03); 2034 vga_wattr (fb_info->regs, VGA_ATC_PALETTE4, 0x04); 2035 vga_wattr (fb_info->regs, VGA_ATC_PALETTE5, 0x05); 2036 vga_wattr (fb_info->regs, VGA_ATC_PALETTE6, 0x06); 2037 vga_wattr (fb_info->regs, VGA_ATC_PALETTE7, 0x07); 2038 vga_wattr (fb_info->regs, VGA_ATC_PALETTE8, 0x08); 2039 vga_wattr (fb_info->regs, VGA_ATC_PALETTE9, 0x09); 2040 vga_wattr (fb_info->regs, VGA_ATC_PALETTEA, 0x0a); 2041 vga_wattr (fb_info->regs, VGA_ATC_PALETTEB, 0x0b); 2042 vga_wattr (fb_info->regs, VGA_ATC_PALETTEC, 0x0c); 2043 vga_wattr (fb_info->regs, VGA_ATC_PALETTED, 0x0d); 2044 vga_wattr (fb_info->regs, VGA_ATC_PALETTEE, 0x0e); 2045 vga_wattr (fb_info->regs, VGA_ATC_PALETTEF, 0x0f); 2046 2047 vga_wattr (fb_info->regs, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */ 2048 vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0x00); /* Overscan color reg.: reg. 0 */ 2049 vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */ 2050/* ### vga_wattr (fb_info->regs, CL_AR33, 0x00); * Pixel Panning: - */ 2051 vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0x00); /* Color Select: - */ 2052 2053 WGen (fb_info, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ 2054 2055 if (fb_info->btype != BT_ALPINE && fb_info->btype != BT_GD5480) 2056 WGen (fb_info, VGA_MIS_W, 0xc3); /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */ 2057 2058 vga_wgfx (fb_info->regs, CL_GR31, 0x04); /* BLT Start/status: Blitter reset */ 2059 vga_wgfx (fb_info->regs, CL_GR31, 0x00); /* - " - : "end-of-reset" */ 2060 2061 /* CLUT setup */ 2062 WClut (fb_info, 0, 0x00, 0x00, 0x00); /* background: black */ 2063 WClut (fb_info, 1, 0x3f, 0x3f, 0x3f); /* foreground: white */ 2064 WClut (fb_info, 2, 0x00, 0x20, 0x00); 2065 WClut (fb_info, 3, 0x00, 0x20, 0x20); 2066 WClut (fb_info, 4, 0x20, 0x00, 0x00); 2067 WClut (fb_info, 5, 0x20, 0x00, 0x20); 2068 WClut (fb_info, 6, 0x20, 0x10, 0x00); 2069 WClut (fb_info, 7, 0x20, 0x20, 0x20); 2070 WClut (fb_info, 8, 0x10, 0x10, 0x10); 2071 WClut (fb_info, 9, 0x10, 0x10, 0x30); 2072 WClut (fb_info, 10, 0x10, 0x30, 0x10); 2073 WClut (fb_info, 11, 0x10, 0x30, 0x30); 2074 WClut (fb_info, 12, 0x30, 0x10, 0x10); 2075 WClut (fb_info, 13, 0x30, 0x10, 0x30); 2076 WClut (fb_info, 14, 0x30, 0x30, 0x10); 2077 WClut (fb_info, 15, 0x30, 0x30, 0x30); 2078 2079 /* the rest a grey ramp */ 2080 { 2081 int i; 2082 2083 for (i = 16; i < 256; i++) 2084 WClut (fb_info, i, i >> 2, i >> 2, i >> 2); 2085 } 2086 2087 2088 /* misc... */ 2089 WHDR (fb_info, 0); /* Hidden DAC register: - */ 2090 2091 printk (KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size); 2092 DPRINTK ("EXIT\n"); 2093 return; 2094} 2095 2096static void switch_monitor (struct clgenfb_info *fb_info, int on) 2097{ 2098#ifdef CONFIG_ZORRO /* only works on Zorro boards */ 2099 static int IsOn = 0; 2100 2101 DPRINTK ("ENTER\n"); 2102 2103 if (fb_info->btype == BT_PICASSO4) 2104 return; /* nothing to switch */ 2105 if (fb_info->btype == BT_ALPINE) 2106 return; /* nothing to switch */ 2107 if (fb_info->btype == BT_GD5480) 2108 return; /* nothing to switch */ 2109 if (fb_info->btype == BT_PICASSO) { 2110 if ((on && !IsOn) || (!on && IsOn)) 2111 WSFR (fb_info, 0xff); 2112 2113 DPRINTK ("EXIT\n"); 2114 return; 2115 } 2116 if (on) { 2117 switch (fb_info->btype) { 2118 case BT_SD64: 2119 WSFR (fb_info, fb_info->SFR | 0x21); 2120 break; 2121 case BT_PICCOLO: 2122 WSFR (fb_info, fb_info->SFR | 0x28); 2123 break; 2124 case BT_SPECTRUM: 2125 WSFR (fb_info, 0x6f); 2126 break; 2127 default: /* do nothing */ break; 2128 } 2129 } else { 2130 switch (fb_info->btype) { 2131 case BT_SD64: 2132 WSFR (fb_info, fb_info->SFR & 0xde); 2133 break; 2134 case BT_PICCOLO: 2135 WSFR (fb_info, fb_info->SFR & 0xd7); 2136 break; 2137 case BT_SPECTRUM: 2138 WSFR (fb_info, 0x4f); 2139 break; 2140 default: /* do nothing */ break; 2141 } 2142 } 2143 2144 DPRINTK ("EXIT\n"); 2145#endif /* CONFIG_ZORRO */ 2146} 2147 2148static void clgen_set_disp (const void *par, struct display *disp, 2149 struct fb_info_gen *info) 2150{ 2151 struct clgenfb_par *_par = (struct clgenfb_par *) par; 2152 struct clgenfb_info *fb_info = (struct clgenfb_info *) info; 2153 int accel_text; 2154 2155 DPRINTK ("ENTER\n"); 2156 2157 assert (_par != NULL); 2158 assert (fb_info != NULL); 2159 2160 accel_text = _par->var.accel_flags & FB_ACCELF_TEXT; 2161 2162 printk ("Cirrus Logic video mode: "); 2163 disp->screen_base = (char *) fb_info->fbmem; 2164 switch (_par->var.bits_per_pixel) { 2165#ifdef FBCON_HAS_MFB 2166 case 1: 2167 printk ("monochrome\n"); 2168 if (fb_info->btype == BT_GD5480) 2169 disp->screen_base = (char *) fb_info->fbmem; 2170 disp->dispsw = &fbcon_mfb; 2171 break; 2172#endif 2173#ifdef FBCON_HAS_CFB8 2174 case 8: 2175 printk ("8 bit color depth\n"); 2176 if (fb_info->btype == BT_GD5480) 2177 disp->screen_base = (char *) fb_info->fbmem; 2178 if (accel_text) 2179 disp->dispsw = &fbcon_clgen_8; 2180 else 2181 disp->dispsw = &fbcon_cfb8; 2182 break; 2183#endif 2184#ifdef FBCON_HAS_CFB16 2185 case 16: 2186 printk ("16 bit color depth\n"); 2187 if (accel_text) 2188 disp->dispsw = &fbcon_clgen_16; 2189 else 2190 disp->dispsw = &fbcon_cfb16; 2191 if (fb_info->btype == BT_GD5480) 2192 disp->screen_base = (char *) fb_info->fbmem + 1 * MB_; 2193 disp->dispsw_data = fb_info->fbcon_cmap.cfb16; 2194 break; 2195#endif 2196#ifdef FBCON_HAS_CFB24 2197 case 24: 2198 printk ("24 bit color depth\n"); 2199 disp->dispsw = &fbcon_cfb24; 2200 if (fb_info->btype == BT_GD5480) 2201 disp->screen_base = (char *) fb_info->fbmem + 2 * MB_; 2202 disp->dispsw_data = fb_info->fbcon_cmap.cfb24; 2203 break; 2204#endif 2205#ifdef FBCON_HAS_CFB32 2206 case 32: 2207 printk ("32 bit color depth\n"); 2208 if (accel_text) 2209 disp->dispsw = &fbcon_clgen_32; 2210 else 2211 disp->dispsw = &fbcon_cfb32; 2212 if (fb_info->btype == BT_GD5480) 2213 disp->screen_base = (char *) fb_info->fbmem + 2 * MB_; 2214 disp->dispsw_data = fb_info->fbcon_cmap.cfb32; 2215 break; 2216#endif 2217 2218 default: 2219 printk ("unsupported color depth\n"); 2220 disp->dispsw = &fbcon_dummy; 2221 disp->dispsw_data = NULL; 2222 break; 2223 } 2224 2225 DPRINTK ("EXIT\n"); 2226} 2227 2228#ifdef FBCON_HAS_CFB8 2229static void fbcon_clgen8_bmove (struct display *p, int sy, int sx, 2230 int dy, int dx, int height, int width) 2231{ 2232 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; 2233 2234 DPRINTK ("ENTER\n"); 2235 2236 sx *= fontwidth (p); 2237 sy *= fontheight (p); 2238 dx *= fontwidth (p); 2239 dy *= fontheight (p); 2240 width *= fontwidth (p); 2241 height *= fontheight (p); 2242 2243 clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy, 2244 (unsigned short) dx, (unsigned short) dy, 2245 (unsigned short) width, (unsigned short) height, 2246 fb_info->currentmode.line_length); 2247 2248 DPRINTK ("EXIT\n"); 2249} 2250 2251static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p, 2252 int sy, int sx, int height, int width) 2253{ 2254 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; 2255 unsigned short col; 2256 2257 DPRINTK ("ENTER\n"); 2258 2259 sx *= fontwidth (p); 2260 sy *= fontheight (p); 2261 width *= fontwidth (p); 2262 height *= fontheight (p); 2263 2264 col = attr_bgcol_ec (p, conp); 2265 col &= 0xff; 2266 2267 clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy, 2268 (unsigned short) width, (unsigned short) height, 2269 col, fb_info->currentmode.line_length); 2270 2271 DPRINTK ("EXIT\n"); 2272} 2273 2274#endif 2275 2276#ifdef FBCON_HAS_CFB16 2277static void fbcon_clgen16_bmove (struct display *p, int sy, int sx, 2278 int dy, int dx, int height, int width) 2279{ 2280 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; 2281 2282 DPRINTK ("ENTER\n"); 2283 2284 sx *= fontwidth (p) * 2; /* 2 bytes/pixel */ 2285 sy *= fontheight (p); 2286 dx *= fontwidth (p) * 2; /* 2 bytes/pixel */ 2287 dy *= fontheight (p); 2288 width *= fontwidth (p) * 2; /* 2 bytes/pixel */ 2289 height *= fontheight (p); 2290 2291 clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy, 2292 (unsigned short) dx, (unsigned short) dy, 2293 (unsigned short) width, (unsigned short) height, 2294 fb_info->currentmode.line_length); 2295 2296 DPRINTK ("EXIT\n"); 2297} 2298 2299static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p, 2300 int sy, int sx, int height, int width) 2301{ 2302 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; 2303 unsigned short col; 2304 2305 DPRINTK ("ENTER\n"); 2306 2307 sx *= fontwidth (p) * 2; /* 2 bytes/pixel */ 2308 sy *= fontheight (p); 2309 width *= fontwidth (p) * 2; /* 2 bytes/pixel? */ 2310 height *= fontheight (p); 2311 2312 col = attr_bgcol_ec (p, conp); 2313 col &= 0xff; 2314 2315 clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy, 2316 (unsigned short) width, (unsigned short) height, 2317 col, fb_info->currentmode.line_length); 2318 2319 DPRINTK ("EXIT\n"); 2320} 2321 2322#endif 2323 2324#ifdef FBCON_HAS_CFB32 2325static void fbcon_clgen32_bmove (struct display *p, int sy, int sx, 2326 int dy, int dx, int height, int width) 2327{ 2328 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; 2329 2330 DPRINTK ("ENTER\n"); 2331 2332 sx *= fontwidth (p) * 4; /* 4 bytes/pixel */ 2333 sy *= fontheight (p); 2334 dx *= fontwidth (p) * 4; /* 4 bytes/pixel */ 2335 dy *= fontheight (p); 2336 width *= fontwidth (p) * 4; /* 4 bytes/pixel */ 2337 height *= fontheight (p); 2338 2339 clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy, 2340 (unsigned short) dx, (unsigned short) dy, 2341 (unsigned short) width, (unsigned short) height, 2342 fb_info->currentmode.line_length); 2343 2344 DPRINTK ("EXIT\n"); 2345} 2346 2347static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p, 2348 int sy, int sx, int height, int width) 2349{ 2350 struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; 2351 2352 unsigned short col; 2353 2354 DPRINTK ("ENTER\n"); 2355 2356 sx *= fontwidth (p) * 4; /* 4 bytes/pixel */ 2357 sy *= fontheight (p); 2358 width *= fontwidth (p) * 4; /* 4 bytes/pixel? */ 2359 height *= fontheight (p); 2360 2361 col = attr_bgcol_ec (p, conp); 2362 col &= 0xff; 2363 2364 clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy, 2365 (unsigned short) width, (unsigned short) height, 2366 col, fb_info->currentmode.line_length); 2367 2368 DPRINTK ("EXIT\n"); 2369} 2370 2371#endif /* FBCON_HAS_CFB32 */ 2372 2373 2374 2375 2376#ifdef CONFIG_ALL_PPC 2377#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000) 2378#define PREP_IO_BASE ((volatile unsigned char *) 0x80000000) 2379static void __init get_prep_addrs (unsigned long *display, unsigned long *registers) 2380{ 2381 DPRINTK ("ENTER\n"); 2382 2383 *display = PREP_VIDEO_BASE; 2384 *registers = (unsigned long) PREP_IO_BASE; 2385 2386 DPRINTK ("EXIT\n"); 2387} 2388 2389#endif /* CONFIG_ALL_PPC */ 2390 2391 2392 2393 2394#ifdef CONFIG_PCI 2395static int release_io_ports = 0; 2396 2397/* Pulled the logic from XFree86 Cirrus driver to get the memory size, 2398 * based on the DRAM bandwidth bit and DRAM bank switching bit. This 2399 * works with 1MB, 2MB and 4MB configurations (which the Motorola boards 2400 * seem to have. */ 2401static unsigned int __init clgen_get_memsize (caddr_t regbase) 2402{ 2403 unsigned long mem; 2404 unsigned char SRF; 2405 2406 DPRINTK ("ENTER\n"); 2407 2408 SRF = vga_rseq (regbase, CL_SEQRF); 2409 switch ((SRF & 0x18)) { 2410 case 0x08: mem = 512 * 1024; break; 2411 case 0x10: mem = 1024 * 1024; break; 2412 /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory 2413 * on the 5430. */ 2414 case 0x18: mem = 2048 * 1024; break; 2415 default: printk ("CLgenfb: Unknown memory size!\n"); 2416 mem = 1024 * 1024; 2417 } 2418 if (SRF & 0x80) { 2419 /* If DRAM bank switching is enabled, there must be twice as much 2420 * memory installed. (4MB on the 5434) */ 2421 mem *= 2; 2422 } 2423 /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */ 2424 return mem; 2425 2426 DPRINTK ("EXIT\n"); 2427} 2428 2429 2430 2431static struct pci_dev * __init clgen_pci_dev_get (clgen_board_t *btype) 2432{ 2433 struct pci_dev *pdev; 2434 int i; 2435 2436 DPRINTK ("ENTER\n"); 2437 2438 for (i = 0; i < ARRAY_SIZE(clgen_pci_probe_list); i++) { 2439 pdev = NULL; 2440 while ((pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS, 2441 clgen_pci_probe_list[i].device, pdev)) != NULL) { 2442 if (pci_enable_device(pdev) == 0) { 2443 *btype = clgen_pci_probe_list[i].btype; 2444 DPRINTK ("EXIT, returning pdev=%p\n", pdev); 2445 return pdev; 2446 } 2447 } 2448 } 2449 2450 DPRINTK ("EXIT, returning NULL\n"); 2451 return NULL; 2452} 2453 2454 2455 2456 2457static void __init get_pci_addrs (const struct pci_dev *pdev, 2458 unsigned long *display, unsigned long *registers) 2459{ 2460 assert (pdev != NULL); 2461 assert (display != NULL); 2462 assert (registers != NULL); 2463 2464 DPRINTK ("ENTER\n"); 2465 2466 *display = 0; 2467 *registers = 0; 2468 2469 /* This is a best-guess for now */ 2470 2471 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { 2472 *display = pci_resource_start(pdev, 1); 2473 *registers = pci_resource_start(pdev, 0); 2474 } else { 2475 *display = pci_resource_start(pdev, 0); 2476 *registers = pci_resource_start(pdev, 1); 2477 } 2478 2479 assert (*display != 0); 2480 2481 DPRINTK ("EXIT\n"); 2482} 2483 2484 2485static void __exit clgen_pci_unmap (struct clgenfb_info *info) 2486{ 2487 iounmap (info->fbmem); 2488 release_mem_region(info->fbmem_phys, info->size); 2489 2490 2491 if (release_io_ports) 2492 release_region(0x3C0, 32); 2493} 2494 2495 2496static int __init clgen_pci_setup (struct clgenfb_info *info, 2497 clgen_board_t *btype) 2498{ 2499 struct pci_dev *pdev; 2500 unsigned long board_addr, board_size; 2501 2502 DPRINTK ("ENTER\n"); 2503 2504 pdev = clgen_pci_dev_get (btype); 2505 if (!pdev) { 2506 printk (KERN_ERR " Couldn't find PCI device\n"); 2507 DPRINTK ("EXIT, returning 1\n"); 2508 return 1; 2509 } 2510 DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n", 2511 pdev->resource[0].start, *btype); 2512 DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start); 2513 2514 info->pdev = pdev; 2515 2516 if(isPReP) { 2517 /* Xbh does this, though 0 seems to be the init value */ 2518 pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0, 2519 0x00000000); 2520 2521#ifdef CONFIG_ALL_PPC 2522 get_prep_addrs (&board_addr, &info->fbregs_phys); 2523#endif 2524 } else { 2525 DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n"); 2526 get_pci_addrs (pdev, &board_addr, &info->fbregs_phys); 2527 } 2528 2529 DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, info->fbregs_phys); 2530 2531 if(isPReP) { 2532 /* PReP dies if we ioremap the IO registers, but it works w/out... */ 2533 info->regs = (char *) info->fbregs_phys; 2534 } else 2535 info->regs = 0; 2536 2537 if (*btype == BT_GD5480) { 2538 board_size = 32 * MB_; 2539 } else { 2540 board_size = clgen_get_memsize (info->regs); 2541 } 2542 2543 if (!request_mem_region(board_addr, board_size, "clgenfb")) { 2544 printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n", 2545 board_addr); 2546 return -1; 2547 } 2548 if (request_region(0x3C0, 32, "clgenfb")) 2549 release_io_ports = 1; 2550 2551 info->fbmem = ioremap (board_addr, board_size); 2552 info->fbmem_phys = board_addr; 2553 info->size = board_size; 2554 2555 printk (" RAM (%lu kB) at 0x%lx, ", info->size / KB_, board_addr); 2556 2557 printk ("Cirrus Logic chipset on PCI bus\n"); 2558 2559 DPRINTK ("EXIT, returning 0\n"); 2560 return 0; 2561} 2562#endif /* CONFIG_PCI */ 2563 2564 2565 2566 2567#ifdef CONFIG_ZORRO 2568static int __init clgen_zorro_find (struct zorro_dev **z_o, 2569 struct zorro_dev **z2_o, 2570 clgen_board_t *btype, unsigned long *size) 2571{ 2572 struct zorro_dev *z = NULL; 2573 int i; 2574 2575 assert (z_o != NULL); 2576 assert (btype != NULL); 2577 2578 for (i = 0; i < ARRAY_SIZE(clgen_zorro_probe_list); i++) 2579 if ((z = zorro_find_device(clgen_zorro_probe_list[i].id, NULL))) 2580 break; 2581 2582 if (z) { 2583 *z_o = z; 2584 if (clgen_zorro_probe_list[i].id2) 2585 *z2_o = zorro_find_device(clgen_zorro_probe_list[i].id2, NULL); 2586 else 2587 *z2_o = NULL; 2588 2589 *btype = clgen_zorro_probe_list[i].btype; 2590 *size = clgen_zorro_probe_list[i].size; 2591 2592 printk (KERN_INFO "clgen: %s board detected; ", 2593 clgen_board_info[*btype].name); 2594 2595 return 0; 2596 } 2597 2598 printk (KERN_NOTICE "clgen: no supported board found.\n"); 2599 return -1; 2600} 2601 2602 2603static void __exit clgen_zorro_unmap (struct clgenfb_info *info) 2604{ 2605 release_mem_region(info->board_addr, info->board_size); 2606 2607 if (info->btype == BT_PICASSO4) { 2608 iounmap ((void *)info->board_addr); 2609 iounmap ((void *)info->fbmem_phys); 2610 } else { 2611 if (info->board_addr > 0x01000000) 2612 iounmap ((void *)info->board_addr); 2613 } 2614} 2615 2616 2617static int __init clgen_zorro_setup (struct clgenfb_info *info, 2618 clgen_board_t *btype) 2619{ 2620 struct zorro_dev *z = NULL, *z2 = NULL; 2621 unsigned long board_addr, board_size, size; 2622 2623 assert (info != NULL); 2624 assert (btype != NULL); 2625 2626 if (clgen_zorro_find (&z, &z2, btype, &size)) 2627 return -1; 2628 2629 assert (z > 0); 2630 assert (z2 >= 0); 2631 assert (*btype != BT_NONE); 2632 2633 info->board_addr = board_addr = z->resource.start; 2634 info->board_size = board_size = z->resource.end-z->resource.start+1; 2635 info->size = size; 2636 2637 if (!request_mem_region(board_addr, board_size, "clgenfb")) { 2638 printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n", 2639 board_addr); 2640 return -1; 2641 } 2642 2643 printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr); 2644 2645 if (*btype == BT_PICASSO4) { 2646 printk (" REG at $%lx\n", board_addr + 0x600000); 2647 2648 /* To be precise, for the P4 this is not the */ 2649 /* begin of the board, but the begin of RAM. */ 2650 /* for P4, map in its address space in 2 chunks (### TEST! ) */ 2651 /* (note the ugly hardcoded 16M number) */ 2652 info->regs = ioremap (board_addr, 16777216); 2653 DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs); 2654 info->regs += 0x600000; 2655 info->fbregs_phys = board_addr + 0x600000; 2656 2657 info->fbmem_phys = board_addr + 16777216; 2658 info->fbmem = ioremap (info->fbmem_phys, 16777216); 2659 } else { 2660 printk (" REG at $%lx\n", (unsigned long) z2->resource.start); 2661 2662 info->fbmem_phys = board_addr; 2663 if (board_addr > 0x01000000) 2664 info->fbmem = ioremap (board_addr, board_size); 2665 else 2666 info->fbmem = (caddr_t) ZTWO_VADDR (board_addr); 2667 2668 /* set address for REG area of board */ 2669 info->regs = (caddr_t) ZTWO_VADDR (z2->resource.start); 2670 info->fbregs_phys = z2->resource.start; 2671 2672 DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs); 2673 } 2674 2675 printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n"); 2676 2677 return 0; 2678} 2679#endif /* CONFIG_ZORRO */ 2680 2681 2682 2683/********************************************************************/ 2684/* clgenfb_init() - master initialization function */ 2685/********************************************************************/ 2686int __init clgenfb_init(void) 2687{ 2688 int err, j, k; 2689 2690 clgen_board_t btype = BT_NONE; 2691 struct clgenfb_info *fb_info = NULL; 2692 2693 DPRINTK ("ENTER\n"); 2694 2695 printk (KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n"); 2696 2697 fb_info = &boards[0]; 2698 2699#ifdef CONFIG_PCI 2700 if (clgen_pci_setup (fb_info, &btype)) { /* Also does OF setup */ 2701 DPRINTK ("EXIT, returning -ENXIO\n"); 2702 return -ENXIO; 2703 } 2704 2705#elif defined(CONFIG_ZORRO) 2706 if (clgen_zorro_setup (fb_info, &btype)) { 2707 DPRINTK ("EXIT, returning -ENXIO\n"); 2708 return -ENXIO; 2709 } 2710 2711#else 2712#error This driver requires Zorro or PCI bus. 2713#endif /* !CONFIG_PCI, !CONFIG_ZORRO */ 2714 2715 /* sanity checks */ 2716 assert (btype != BT_NONE); 2717 assert (btype == clgen_board_info[btype].btype); 2718 2719 fb_info->btype = btype; 2720 2721 DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem); 2722 2723 if (noaccel) 2724 { 2725 printk("clgen: disabling text acceleration support\n"); 2726#ifdef FBCON_HAS_CFB8 2727 fbcon_clgen_8.bmove = fbcon_cfb8_bmove; 2728 fbcon_clgen_8.clear = fbcon_cfb8_clear; 2729#endif 2730#ifdef FBCON_HAS_CFB16 2731 fbcon_clgen_16.bmove = fbcon_cfb16_bmove; 2732 fbcon_clgen_16.clear = fbcon_cfb16_clear; 2733#endif 2734#ifdef FBCON_HAS_CFB32 2735 fbcon_clgen_32.bmove = fbcon_cfb32_bmove; 2736 fbcon_clgen_32.clear = fbcon_cfb32_clear; 2737#endif 2738 } 2739 2740 init_vgachip (fb_info); 2741 2742 /* set up a few more things, register framebuffer driver etc */ 2743 fb_info->gen.parsize = sizeof (struct clgenfb_par); 2744 fb_info->gen.fbhw = &clgen_hwswitch; 2745 2746 strncpy (fb_info->gen.info.modename, clgen_board_info[btype].name, 2747 sizeof (fb_info->gen.info.modename)); 2748 fb_info->gen.info.modename [sizeof (fb_info->gen.info.modename) - 1] = 0; 2749 2750 fb_info->gen.info.node = -1; 2751 fb_info->gen.info.fbops = &clgenfb_ops; 2752 fb_info->gen.info.disp = &disp; 2753 fb_info->gen.info.changevar = NULL; 2754 fb_info->gen.info.switch_con = &fbgen_switch; 2755 fb_info->gen.info.updatevar = &fbgen_update_var; 2756 fb_info->gen.info.blank = &fbgen_blank; 2757 fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT; 2758 2759 for (j = 0; j < 256; j++) { 2760 if (j < 16) { 2761 k = color_table[j]; 2762 fb_info->palette[j].red = default_red[k]; 2763 fb_info->palette[j].green = default_grn[k]; 2764 fb_info->palette[j].blue = default_blu[k]; 2765 } else { 2766 fb_info->palette[j].red = 2767 fb_info->palette[j].green = 2768 fb_info->palette[j].blue = j; 2769 } 2770 } 2771 2772 /* now that we know the board has been registered n' stuff, we */ 2773 /* can finally initialize it to a default mode */ 2774 clgenfb_default = clgenfb_predefined[clgen_def_mode].var; 2775 clgenfb_default.activate = FB_ACTIVATE_NOW; 2776 clgenfb_default.yres_virtual = 480 * 3; /* for fast scrolling (YPAN-Mode) */ 2777 err = fbgen_do_set_var (&clgenfb_default, 1, &fb_info->gen); 2778 2779 if (err) { 2780 DPRINTK ("EXIT, returning -EINVAL\n"); 2781 return -EINVAL; 2782 } 2783 2784 disp.var = clgenfb_default; 2785 fbgen_set_disp (-1, &fb_info->gen); 2786 fbgen_install_cmap (0, &fb_info->gen); 2787 2788 err = register_framebuffer (&fb_info->gen.info); 2789 if (err) { 2790 printk (KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err); 2791 DPRINTK ("EXIT, returning -EINVAL\n"); 2792 return -EINVAL; 2793 } 2794 DPRINTK ("EXIT, returning 0\n"); 2795 return 0; 2796} 2797 2798 2799 2800 /* 2801 * Cleanup (only needed for module) 2802 */ 2803static void __exit clgenfb_cleanup (struct clgenfb_info *info) 2804{ 2805 DPRINTK ("ENTER\n"); 2806 2807#ifdef CONFIG_ZORRO 2808 switch_monitor (info, 0); 2809 2810 clgen_zorro_unmap (info); 2811#else 2812 clgen_pci_unmap (info); 2813#endif /* CONFIG_ZORRO */ 2814 2815 unregister_framebuffer ((struct fb_info *) info); 2816 printk ("Framebuffer unregistered\n"); 2817 2818 DPRINTK ("EXIT\n"); 2819} 2820 2821 2822#ifndef MODULE 2823int __init clgenfb_setup(char *options) { 2824 char *this_opt, s[32]; 2825 int i; 2826 2827 DPRINTK ("ENTER\n"); 2828 2829 if (!options || !*options) 2830 return 0; 2831 2832 for (this_opt = strtok (options, ","); this_opt != NULL; 2833 this_opt = strtok (NULL, ",")) { 2834 if (!*this_opt) continue; 2835 2836 DPRINTK("clgenfb_setup: option '%s'\n", this_opt); 2837 2838 for (i = 0; i < NUM_TOTAL_MODES; i++) { 2839 sprintf (s, "mode:%s", clgenfb_predefined[i].name); 2840 if (strcmp (this_opt, s) == 0) 2841 clgen_def_mode = i; 2842 } 2843 if (!strcmp(this_opt, "noaccel")) 2844 noaccel = 1; 2845 } 2846 return 0; 2847} 2848#endif 2849 2850 2851 /* 2852 * Modularization 2853 */ 2854 2855MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>"); 2856MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); 2857MODULE_LICENSE("GPL"); 2858 2859static void __exit clgenfb_exit (void) 2860{ 2861 DPRINTK ("ENTER\n"); 2862 2863 clgenfb_cleanup (&boards[0]); 2864 2865 DPRINTK ("EXIT\n"); 2866} 2867 2868#ifdef MODULE 2869module_init(clgenfb_init); 2870#endif 2871module_exit(clgenfb_exit); 2872 2873 2874/**********************************************************************/ 2875/* about the following functions - I have used the same names for the */ 2876/* functions as Markus Wild did in his Retina driver for NetBSD as */ 2877/* they just made sense for this purpose. Apart from that, I wrote */ 2878/* these functions myself. */ 2879/**********************************************************************/ 2880 2881/*** WGen() - write into one of the external/general registers ***/ 2882static void WGen (const struct clgenfb_info *fb_info, 2883 int regnum, unsigned char val) 2884{ 2885 unsigned long regofs = 0; 2886 2887 if (fb_info->btype == BT_PICASSO) { 2888 /* Picasso II specific hack */ 2889/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */ 2890 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) 2891 regofs = 0xfff; 2892 } 2893 2894 vga_w (fb_info->regs, regofs + regnum, val); 2895} 2896 2897/*** RGen() - read out one of the external/general registers ***/ 2898static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum) 2899{ 2900 unsigned long regofs = 0; 2901 2902 if (fb_info->btype == BT_PICASSO) { 2903 /* Picasso II specific hack */ 2904/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */ 2905 if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) 2906 regofs = 0xfff; 2907 } 2908 2909 return vga_r (fb_info->regs, regofs + regnum); 2910} 2911 2912/*** AttrOn() - turn on VideoEnable for Attribute controller ***/ 2913static void AttrOn (const struct clgenfb_info *fb_info) 2914{ 2915 assert (fb_info != NULL); 2916 2917 DPRINTK ("ENTER\n"); 2918 2919 if (vga_rcrt (fb_info->regs, CL_CRT24) & 0x80) { 2920 /* if we're just in "write value" mode, write back the */ 2921 /* same value as before to not modify anything */ 2922 vga_w (fb_info->regs, VGA_ATT_IW, 2923 vga_r (fb_info->regs, VGA_ATT_R)); 2924 } 2925 /* turn on video bit */ 2926/* vga_w (fb_info->regs, VGA_ATT_IW, 0x20); */ 2927 vga_w (fb_info->regs, VGA_ATT_IW, 0x33); 2928 2929 /* dummy write on Reg0 to be on "write index" mode next time */ 2930 vga_w (fb_info->regs, VGA_ATT_IW, 0x00); 2931 2932 DPRINTK ("EXIT\n"); 2933} 2934 2935/*** WHDR() - write into the Hidden DAC register ***/ 2936/* as the HDR is the only extension register that requires special treatment 2937 * (the other extension registers are accessible just like the "ordinary" 2938 * registers of their functional group) here is a specialized routine for 2939 * accessing the HDR 2940 */ 2941static void WHDR (const struct clgenfb_info *fb_info, unsigned char val) 2942{ 2943 unsigned char dummy; 2944 2945 if (fb_info->btype == BT_PICASSO) { 2946 /* Klaus' hint for correct access to HDR on some boards */ 2947 /* first write 0 to pixel mask (3c6) */ 2948 WGen (fb_info, VGA_PEL_MSK, 0x00); 2949 udelay (200); 2950 /* next read dummy from pixel address (3c8) */ 2951 dummy = RGen (fb_info, VGA_PEL_IW); 2952 udelay (200); 2953 } 2954 /* now do the usual stuff to access the HDR */ 2955 2956 dummy = RGen (fb_info, VGA_PEL_MSK); 2957 udelay (200); 2958 dummy = RGen (fb_info, VGA_PEL_MSK); 2959 udelay (200); 2960 dummy = RGen (fb_info, VGA_PEL_MSK); 2961 udelay (200); 2962 dummy = RGen (fb_info, VGA_PEL_MSK); 2963 udelay (200); 2964 2965 WGen (fb_info, VGA_PEL_MSK, val); 2966 udelay (200); 2967 2968 if (fb_info->btype == BT_PICASSO) { 2969 /* now first reset HDR access counter */ 2970 dummy = RGen (fb_info, VGA_PEL_IW); 2971 udelay (200); 2972 2973 /* and at the end, restore the mask value */ 2974 /* ## is this mask always 0xff? */ 2975 WGen (fb_info, VGA_PEL_MSK, 0xff); 2976 udelay (200); 2977 } 2978} 2979 2980 2981/*** WSFR() - write to the "special function register" (SFR) ***/ 2982static void WSFR (struct clgenfb_info *fb_info, unsigned char val) 2983{ 2984#ifdef CONFIG_ZORRO 2985 assert (fb_info->regs != NULL); 2986 fb_info->SFR = val; 2987 z_writeb (val, fb_info->regs + 0x8000); 2988#endif 2989} 2990 2991/* The Picasso has a second register for switching the monitor bit */ 2992static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val) 2993{ 2994#ifdef CONFIG_ZORRO 2995 /* writing an arbitrary value to this one causes the monitor switcher */ 2996 /* to flip to Amiga display */ 2997 assert (fb_info->regs != NULL); 2998 fb_info->SFR = val; 2999 z_writeb (val, fb_info->regs + 0x9000); 3000#endif 3001} 3002 3003 3004/*** WClut - set CLUT entry (range: 0..63) ***/ 3005static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red, 3006 unsigned char green, unsigned char blue) 3007{ 3008 unsigned int data = VGA_PEL_D; 3009 3010 /* address write mode register is not translated.. */ 3011 vga_w (fb_info->regs, VGA_PEL_IW, regnum); 3012 3013 if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 || 3014 fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) { 3015 /* but DAC data register IS, at least for Picasso II */ 3016 if (fb_info->btype == BT_PICASSO) 3017 data += 0xfff; 3018 vga_w (fb_info->regs, data, red); 3019 vga_w (fb_info->regs, data, green); 3020 vga_w (fb_info->regs, data, blue); 3021 } else { 3022 vga_w (fb_info->regs, data, blue); 3023 vga_w (fb_info->regs, data, green); 3024 vga_w (fb_info->regs, data, red); 3025 } 3026} 3027 3028 3029 3030 3031/******************************************************************* 3032 clgen_WaitBLT() 3033 3034 Wait for the BitBLT engine to complete a possible earlier job 3035*********************************************************************/ 3036 3037static inline void clgen_WaitBLT (caddr_t regbase) 3038{ 3039 /* now busy-wait until we're done */ 3040 while (vga_rgfx (regbase, CL_GR31) & 0x08) 3041 /* do nothing */ ; 3042} 3043 3044/******************************************************************* 3045 clgen_BitBLT() 3046 3047 perform accelerated "scrolling" 3048********************************************************************/ 3049 3050static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, u_short destx, u_short desty, 3051 u_short width, u_short height, u_short line_length) 3052{ 3053 u_short nwidth, nheight; 3054 u_long nsrc, ndest; 3055 u_char bltmode; 3056 3057 DPRINTK ("ENTER\n"); 3058 3059 nwidth = width - 1; 3060 nheight = height - 1; 3061 3062 bltmode = 0x00; 3063 /* if source adr < dest addr, do the Blt backwards */ 3064 if (cury <= desty) { 3065 if (cury == desty) { 3066 /* if src and dest are on the same line, check x */ 3067 if (curx < destx) 3068 bltmode |= 0x01; 3069 } else 3070 bltmode |= 0x01; 3071 } 3072 if (!bltmode) { 3073 /* standard case: forward blitting */ 3074 nsrc = (cury * line_length) + curx; 3075 ndest = (desty * line_length) + destx; 3076 } else { 3077 /* this means start addresses are at the end, counting backwards */ 3078 nsrc = cury * line_length + curx + nheight * line_length + nwidth; 3079 ndest = desty * line_length + destx + nheight * line_length + nwidth; 3080 } 3081 3082 clgen_WaitBLT(regbase); 3083 3084 /* 3085 run-down of registers to be programmed: 3086 destination pitch 3087 source pitch 3088 BLT width/height 3089 source start 3090 destination start 3091 BLT mode 3092 BLT ROP 3093 VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color" 3094 start/stop 3095 */ 3096 3097 /* pitch: set to line_length */ 3098 vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */ 3099 vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */ 3100 vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */ 3101 vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */ 3102 3103 /* BLT width: actual number of pixels - 1 */ 3104 vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */ 3105 vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */ 3106 3107 /* BLT height: actual number of lines -1 */ 3108 vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */ 3109 vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */ 3110 3111 /* BLT destination */ 3112 vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */ 3113 vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */ 3114 vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */ 3115 3116 /* BLT source */ 3117 vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff)); /* BLT src low */ 3118 vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8)); /* BLT src mid */ 3119 vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16)); /* BLT src hi */ 3120 3121 /* BLT mode */ 3122 vga_wgfx (regbase, CL_GR30, bltmode); /* BLT mode */ 3123 3124 /* BLT ROP: SrcCopy */ 3125 vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */ 3126 3127 /* and finally: GO! */ 3128 vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */ 3129 3130 DPRINTK ("EXIT\n"); 3131} 3132 3133 3134/******************************************************************* 3135 clgen_RectFill() 3136 3137 perform accelerated rectangle fill 3138********************************************************************/ 3139 3140static void clgen_RectFill (struct clgenfb_info *fb_info, 3141 u_short x, u_short y, u_short width, u_short height, 3142 u_char color, u_short line_length) 3143{ 3144 u_short nwidth, nheight; 3145 u_long ndest; 3146 u_char op; 3147 3148 DPRINTK ("ENTER\n"); 3149 3150 nwidth = width - 1; 3151 nheight = height - 1; 3152 3153 ndest = (y * line_length) + x; 3154 3155 clgen_WaitBLT(fb_info->regs); 3156 3157 /* pitch: set to line_length */ 3158 vga_wgfx (fb_info->regs, CL_GR24, line_length & 0xff); /* dest pitch low */ 3159 vga_wgfx (fb_info->regs, CL_GR25, (line_length >> 8)); /* dest pitch hi */ 3160 vga_wgfx (fb_info->regs, CL_GR26, line_length & 0xff); /* source pitch low */ 3161 vga_wgfx (fb_info->regs, CL_GR27, (line_length >> 8)); /* source pitch hi */ 3162 3163 /* BLT width: actual number of pixels - 1 */ 3164 vga_wgfx (fb_info->regs, CL_GR20, nwidth & 0xff); /* BLT width low */ 3165 vga_wgfx (fb_info->regs, CL_GR21, (nwidth >> 8)); /* BLT width hi */ 3166 3167 /* BLT height: actual number of lines -1 */ 3168 vga_wgfx (fb_info->regs, CL_GR22, nheight & 0xff); /* BLT height low */ 3169 vga_wgfx (fb_info->regs, CL_GR23, (nheight >> 8)); /* BLT width hi */ 3170 3171 /* BLT destination */ 3172 vga_wgfx (fb_info->regs, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */ 3173 vga_wgfx (fb_info->regs, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */ 3174 vga_wgfx (fb_info->regs, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */ 3175 3176 /* BLT source: set to 0 (is a dummy here anyway) */ 3177 vga_wgfx (fb_info->regs, CL_GR2C, 0x00); /* BLT src low */ 3178 vga_wgfx (fb_info->regs, CL_GR2D, 0x00); /* BLT src mid */ 3179 vga_wgfx (fb_info->regs, CL_GR2E, 0x00); /* BLT src hi */ 3180 3181 /* This is a ColorExpand Blt, using the */ 3182 /* same color for foreground and background */ 3183 vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, color); /* foreground color */ 3184 vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, color); /* background color */ 3185 3186 op = 0xc0; 3187 if (fb_info->currentmode.var.bits_per_pixel == 16) { 3188 vga_wgfx (fb_info->regs, CL_GR10, color); /* foreground color */ 3189 vga_wgfx (fb_info->regs, CL_GR11, color); /* background color */ 3190 op = 0x50; 3191 op = 0xd0; 3192 } else if (fb_info->currentmode.var.bits_per_pixel == 32) { 3193 vga_wgfx (fb_info->regs, CL_GR10, color); /* foreground color */ 3194 vga_wgfx (fb_info->regs, CL_GR11, color); /* background color */ 3195 vga_wgfx (fb_info->regs, CL_GR12, color); /* foreground color */ 3196 vga_wgfx (fb_info->regs, CL_GR13, color); /* background color */ 3197 vga_wgfx (fb_info->regs, CL_GR14, 0); /* foreground color */ 3198 vga_wgfx (fb_info->regs, CL_GR15, 0); /* background color */ 3199 op = 0x50; 3200 op = 0xf0; 3201 } 3202 /* BLT mode: color expand, Enable 8x8 copy (faster?) */ 3203 vga_wgfx (fb_info->regs, CL_GR30, op); /* BLT mode */ 3204 3205 /* BLT ROP: SrcCopy */ 3206 vga_wgfx (fb_info->regs, CL_GR32, 0x0d); /* BLT ROP */ 3207 3208 /* and finally: GO! */ 3209 vga_wgfx (fb_info->regs, CL_GR31, 0x02); /* BLT Start/status */ 3210 3211 DPRINTK ("EXIT\n"); 3212} 3213 3214 3215/************************************************************************** 3216 * bestclock() - determine closest possible clock lower(?) than the 3217 * desired pixel clock 3218 **************************************************************************/ 3219static void bestclock (long freq, long *best, long *nom, 3220 long *den, long *div, long maxfreq) 3221{ 3222 long n, h, d, f; 3223 3224 assert (best != NULL); 3225 assert (nom != NULL); 3226 assert (den != NULL); 3227 assert (div != NULL); 3228 assert (maxfreq > 0); 3229 3230 *nom = 0; 3231 *den = 0; 3232 *div = 0; 3233 3234 DPRINTK ("ENTER\n"); 3235 3236 if (freq < 8000) 3237 freq = 8000; 3238 3239 if (freq > maxfreq) 3240 freq = maxfreq; 3241 3242 *best = 0; 3243 f = freq * 10; 3244 3245 for (n = 32; n < 128; n++) { 3246 d = (143181 * n) / f; 3247 if ((d >= 7) && (d <= 63)) { 3248 if (d > 31) 3249 d = (d / 2) * 2; 3250 h = (14318 * n) / d; 3251 if (abs (h - freq) < abs (*best - freq)) { 3252 *best = h; 3253 *nom = n; 3254 if (d < 32) { 3255 *den = d; 3256 *div = 0; 3257 } else { 3258 *den = d / 2; 3259 *div = 1; 3260 } 3261 } 3262 } 3263 d = ((143181 * n) + f - 1) / f; 3264 if ((d >= 7) && (d <= 63)) { 3265 if (d > 31) 3266 d = (d / 2) * 2; 3267 h = (14318 * n) / d; 3268 if (abs (h - freq) < abs (*best - freq)) { 3269 *best = h; 3270 *nom = n; 3271 if (d < 32) { 3272 *den = d; 3273 *div = 0; 3274 } else { 3275 *den = d / 2; 3276 *div = 1; 3277 } 3278 } 3279 } 3280 } 3281 3282 DPRINTK ("Best possible values for given frequency:\n"); 3283 DPRINTK (" best: %ld kHz nom: %ld den: %ld div: %ld\n", 3284 freq, *nom, *den, *div); 3285 3286 DPRINTK ("EXIT\n"); 3287} 3288 3289 3290/* ------------------------------------------------------------------------- 3291 * 3292 * debugging functions 3293 * 3294 * ------------------------------------------------------------------------- 3295 */ 3296 3297#ifdef CLGEN_DEBUG 3298 3299/** 3300 * clgen_dbg_print_byte 3301 * @name: name associated with byte value to be displayed 3302 * @val: byte value to be displayed 3303 * 3304 * DESCRIPTION: 3305 * Display an indented string, along with a hexidecimal byte value, and 3306 * its decoded bits. Bits 7 through 0 are listed in left-to-right 3307 * order. 3308 */ 3309 3310static 3311void clgen_dbg_print_byte (const char *name, unsigned char val) 3312{ 3313 DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n", 3314 name, val, 3315 val & 0x80 ? '1' : '0', 3316 val & 0x40 ? '1' : '0', 3317 val & 0x20 ? '1' : '0', 3318 val & 0x10 ? '1' : '0', 3319 val & 0x08 ? '1' : '0', 3320 val & 0x04 ? '1' : '0', 3321 val & 0x02 ? '1' : '0', 3322 val & 0x01 ? '1' : '0'); 3323} 3324 3325 3326/** 3327 * clgen_dbg_print_regs 3328 * @base: If using newmmio, the newmmio base address, otherwise %NULL 3329 * @reg_class: type of registers to read: %CRT, or %SEQ 3330 * 3331 * DESCRIPTION: 3332 * Dumps the given list of VGA CRTC registers. If @base is %NULL, 3333 * old-style I/O ports are queried for information, otherwise MMIO is 3334 * used at the given @base address to query the information. 3335 */ 3336 3337static 3338void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...) 3339{ 3340 va_list list; 3341 unsigned char val = 0; 3342 unsigned reg; 3343 char *name; 3344 3345 va_start (list, reg_class); 3346 3347 name = va_arg (list, char *); 3348 while (name != NULL) { 3349 reg = va_arg (list, int); 3350 3351 switch (reg_class) { 3352 case CRT: 3353 val = vga_rcrt (regbase, (unsigned char) reg); 3354 break; 3355 case SEQ: 3356 val = vga_rseq (regbase, (unsigned char) reg); 3357 break; 3358 default: 3359 /* should never occur */ 3360 assert (FALSE); 3361 break; 3362 } 3363 3364 clgen_dbg_print_byte (name, val); 3365 3366 name = va_arg (list, char *); 3367 } 3368 3369 va_end (list); 3370} 3371 3372 3373/** 3374 * clgen_dump 3375 * @clgeninfo: 3376 * 3377 * DESCRIPTION: 3378 */ 3379 3380static 3381void clgen_dump (void) 3382{ 3383 clgen_dbg_reg_dump (NULL); 3384} 3385 3386 3387/** 3388 * clgen_dbg_reg_dump 3389 * @base: If using newmmio, the newmmio base address, otherwise %NULL 3390 * 3391 * DESCRIPTION: 3392 * Dumps a list of interesting VGA and CLGEN registers. If @base is %NULL, 3393 * old-style I/O ports are queried for information, otherwise MMIO is 3394 * used at the given @base address to query the information. 3395 */ 3396 3397static 3398void clgen_dbg_reg_dump (caddr_t regbase) 3399{ 3400 DPRINTK ("CLGEN VGA CRTC register dump:\n"); 3401 3402 clgen_dbg_print_regs (regbase, CRT, 3403 "CR00", 0x00, 3404 "CR01", 0x01, 3405 "CR02", 0x02, 3406 "CR03", 0x03, 3407 "CR04", 0x04, 3408 "CR05", 0x05, 3409 "CR06", 0x06, 3410 "CR07", 0x07, 3411 "CR08", 0x08, 3412 "CR09", 0x09, 3413 "CR0A", 0x0A, 3414 "CR0B", 0x0B, 3415 "CR0C", 0x0C, 3416 "CR0D", 0x0D, 3417 "CR0E", 0x0E, 3418 "CR0F", 0x0F, 3419 "CR10", 0x10, 3420 "CR11", 0x11, 3421 "CR12", 0x12, 3422 "CR13", 0x13, 3423 "CR14", 0x14, 3424 "CR15", 0x15, 3425 "CR16", 0x16, 3426 "CR17", 0x17, 3427 "CR18", 0x18, 3428 "CR22", 0x22, 3429 "CR24", 0x24, 3430 "CR26", 0x26, 3431 "CR2D", 0x2D, 3432 "CR2E", 0x2E, 3433 "CR2F", 0x2F, 3434 "CR30", 0x30, 3435 "CR31", 0x31, 3436 "CR32", 0x32, 3437 "CR33", 0x33, 3438 "CR34", 0x34, 3439 "CR35", 0x35, 3440 "CR36", 0x36, 3441 "CR37", 0x37, 3442 "CR38", 0x38, 3443 "CR39", 0x39, 3444 "CR3A", 0x3A, 3445 "CR3B", 0x3B, 3446 "CR3C", 0x3C, 3447 "CR3D", 0x3D, 3448 "CR3E", 0x3E, 3449 "CR3F", 0x3F, 3450 NULL); 3451 3452 DPRINTK ("\n"); 3453 3454 DPRINTK ("CLGEN VGA SEQ register dump:\n"); 3455 3456 clgen_dbg_print_regs (regbase, SEQ, 3457 "SR00", 0x00, 3458 "SR01", 0x01, 3459 "SR02", 0x02, 3460 "SR03", 0x03, 3461 "SR04", 0x04, 3462 "SR08", 0x08, 3463 "SR09", 0x09, 3464 "SR0A", 0x0A, 3465 "SR0B", 0x0B, 3466 "SR0D", 0x0D, 3467 "SR10", 0x10, 3468 "SR11", 0x11, 3469 "SR12", 0x12, 3470 "SR13", 0x13, 3471 "SR14", 0x14, 3472 "SR15", 0x15, 3473 "SR16", 0x16, 3474 "SR17", 0x17, 3475 "SR18", 0x18, 3476 "SR19", 0x19, 3477 "SR1A", 0x1A, 3478 "SR1B", 0x1B, 3479 "SR1C", 0x1C, 3480 "SR1D", 0x1D, 3481 "SR1E", 0x1E, 3482 "SR1F", 0x1F, 3483 NULL); 3484 3485 DPRINTK ("\n"); 3486} 3487 3488#endif /* CLGEN_DEBUG */ 3489 3490