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

Configure Feed

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

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