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