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