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