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

Configure Feed

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

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