linux/drivers/video/fbdev/cyber2000fb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  linux/drivers/video/cyber2000fb.c
   4 *
   5 *  Copyright (C) 1998-2002 Russell King
   6 *
   7 *  MIPS and 50xx clock support
   8 *  Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
   9 *
  10 *  32 bit support, text color and panning fixes for modes != 8 bit
  11 *  Copyright (C) 2002 Denis Oliver Kropp <dok@directfb.org>
  12 *
  13 * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device
  14 *
  15 * Based on cyberfb.c.
  16 *
  17 * Note that we now use the new fbcon fix, var and cmap scheme.  We do
  18 * still have to check which console is the currently displayed one
  19 * however, especially for the colourmap stuff.
  20 *
  21 * We also use the new hotplug PCI subsystem.  I'm not sure if there
  22 * are any such cards, but I'm erring on the side of caution.  We don't
  23 * want to go pop just because someone does have one.
  24 *
  25 * Note that this doesn't work fully in the case of multiple CyberPro
  26 * cards with grabbers.  We currently can only attach to the first
  27 * CyberPro card found.
  28 *
  29 * When we're in truecolour mode, we power down the LUT RAM as a power
  30 * saving feature.  Also, when we enter any of the powersaving modes
  31 * (except soft blanking) we power down the RAMDACs.  This saves about
  32 * 1W, which is roughly 8% of the power consumption of a NetWinder
  33 * (which, incidentally, is about the same saving as a 2.5in hard disk
  34 * entering standby mode.)
  35 */
  36#include <linux/module.h>
  37#include <linux/kernel.h>
  38#include <linux/errno.h>
  39#include <linux/string.h>
  40#include <linux/mm.h>
  41#include <linux/slab.h>
  42#include <linux/delay.h>
  43#include <linux/fb.h>
  44#include <linux/pci.h>
  45#include <linux/init.h>
  46#include <linux/io.h>
  47#include <linux/i2c.h>
  48#include <linux/i2c-algo-bit.h>
  49
  50#include <asm/pgtable.h>
  51
  52#ifdef __arm__
  53#include <asm/mach-types.h>
  54#endif
  55
  56#include "cyber2000fb.h"
  57
  58struct cfb_info {
  59        struct fb_info          fb;
  60        struct display_switch   *dispsw;
  61        unsigned char           __iomem *region;
  62        unsigned char           __iomem *regs;
  63        u_int                   id;
  64        u_int                   irq;
  65        int                     func_use_count;
  66        u_long                  ref_ps;
  67
  68        /*
  69         * Clock divisors
  70         */
  71        u_int                   divisors[4];
  72
  73        struct {
  74                u8 red, green, blue;
  75        } palette[NR_PALETTE];
  76
  77        u_char                  mem_ctl1;
  78        u_char                  mem_ctl2;
  79        u_char                  mclk_mult;
  80        u_char                  mclk_div;
  81        /*
  82         * RAMDAC control register is both of these or'ed together
  83         */
  84        u_char                  ramdac_ctrl;
  85        u_char                  ramdac_powerdown;
  86
  87        u32                     pseudo_palette[16];
  88
  89        spinlock_t              reg_b0_lock;
  90
  91#ifdef CONFIG_FB_CYBER2000_DDC
  92        bool                    ddc_registered;
  93        struct i2c_adapter      ddc_adapter;
  94        struct i2c_algo_bit_data        ddc_algo;
  95#endif
  96
  97#ifdef CONFIG_FB_CYBER2000_I2C
  98        struct i2c_adapter      i2c_adapter;
  99        struct i2c_algo_bit_data i2c_algo;
 100#endif
 101};
 102
 103static char *default_font = "Acorn8x8";
 104module_param(default_font, charp, 0);
 105MODULE_PARM_DESC(default_font, "Default font name");
 106
 107/*
 108 * Our access methods.
 109 */
 110#define cyber2000fb_writel(val, reg, cfb)       writel(val, (cfb)->regs + (reg))
 111#define cyber2000fb_writew(val, reg, cfb)       writew(val, (cfb)->regs + (reg))
 112#define cyber2000fb_writeb(val, reg, cfb)       writeb(val, (cfb)->regs + (reg))
 113
 114#define cyber2000fb_readb(reg, cfb)             readb((cfb)->regs + (reg))
 115
 116static inline void
 117cyber2000_crtcw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
 118{
 119        cyber2000fb_writew((reg & 255) | val << 8, 0x3d4, cfb);
 120}
 121
 122static inline void
 123cyber2000_grphw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
 124{
 125        cyber2000fb_writew((reg & 255) | val << 8, 0x3ce, cfb);
 126}
 127
 128static inline unsigned int
 129cyber2000_grphr(unsigned int reg, struct cfb_info *cfb)
 130{
 131        cyber2000fb_writeb(reg, 0x3ce, cfb);
 132        return cyber2000fb_readb(0x3cf, cfb);
 133}
 134
 135static inline void
 136cyber2000_attrw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
 137{
 138        cyber2000fb_readb(0x3da, cfb);
 139        cyber2000fb_writeb(reg, 0x3c0, cfb);
 140        cyber2000fb_readb(0x3c1, cfb);
 141        cyber2000fb_writeb(val, 0x3c0, cfb);
 142}
 143
 144static inline void
 145cyber2000_seqw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
 146{
 147        cyber2000fb_writew((reg & 255) | val << 8, 0x3c4, cfb);
 148}
 149
 150/* -------------------- Hardware specific routines ------------------------- */
 151
 152/*
 153 * Hardware Cyber2000 Acceleration
 154 */
 155static void
 156cyber2000fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 157{
 158        struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
 159        unsigned long dst, col;
 160
 161        if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
 162                cfb_fillrect(info, rect);
 163                return;
 164        }
 165
 166        cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
 167        cyber2000fb_writew(rect->width - 1, CO_REG_PIXWIDTH, cfb);
 168        cyber2000fb_writew(rect->height - 1, CO_REG_PIXHEIGHT, cfb);
 169
 170        col = rect->color;
 171        if (cfb->fb.var.bits_per_pixel > 8)
 172                col = ((u32 *)cfb->fb.pseudo_palette)[col];
 173        cyber2000fb_writel(col, CO_REG_FGCOLOUR, cfb);
 174
 175        dst = rect->dx + rect->dy * cfb->fb.var.xres_virtual;
 176        if (cfb->fb.var.bits_per_pixel == 24) {
 177                cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
 178                dst *= 3;
 179        }
 180
 181        cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
 182        cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
 183        cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
 184        cyber2000fb_writew(CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
 185}
 186
 187static void
 188cyber2000fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
 189{
 190        struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
 191        unsigned int cmd = CO_CMD_L_PATTERN_FGCOL;
 192        unsigned long src, dst;
 193
 194        if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT)) {
 195                cfb_copyarea(info, region);
 196                return;
 197        }
 198
 199        cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
 200        cyber2000fb_writew(region->width - 1, CO_REG_PIXWIDTH, cfb);
 201        cyber2000fb_writew(region->height - 1, CO_REG_PIXHEIGHT, cfb);
 202
 203        src = region->sx + region->sy * cfb->fb.var.xres_virtual;
 204        dst = region->dx + region->dy * cfb->fb.var.xres_virtual;
 205
 206        if (region->sx < region->dx) {
 207                src += region->width - 1;
 208                dst += region->width - 1;
 209                cmd |= CO_CMD_L_INC_LEFT;
 210        }
 211
 212        if (region->sy < region->dy) {
 213                src += (region->height - 1) * cfb->fb.var.xres_virtual;
 214                dst += (region->height - 1) * cfb->fb.var.xres_virtual;
 215                cmd |= CO_CMD_L_INC_UP;
 216        }
 217
 218        if (cfb->fb.var.bits_per_pixel == 24) {
 219                cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
 220                src *= 3;
 221                dst *= 3;
 222        }
 223        cyber2000fb_writel(src, CO_REG_SRC1_PTR, cfb);
 224        cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
 225        cyber2000fb_writew(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
 226        cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
 227        cyber2000fb_writew(CO_CMD_H_FGSRCMAP | CO_CMD_H_BLITTER,
 228                           CO_REG_CMD_H, cfb);
 229}
 230
 231static void
 232cyber2000fb_imageblit(struct fb_info *info, const struct fb_image *image)
 233{
 234        cfb_imageblit(info, image);
 235        return;
 236}
 237
 238static int cyber2000fb_sync(struct fb_info *info)
 239{
 240        struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
 241        int count = 100000;
 242
 243        if (!(cfb->fb.var.accel_flags & FB_ACCELF_TEXT))
 244                return 0;
 245
 246        while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & CO_CTRL_BUSY) {
 247                if (!count--) {
 248                        debug_printf("accel_wait timed out\n");
 249                        cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
 250                        break;
 251                }
 252                udelay(1);
 253        }
 254        return 0;
 255}
 256
 257/*
 258 * ===========================================================================
 259 */
 260
 261static inline u32 convert_bitfield(u_int val, struct fb_bitfield *bf)
 262{
 263        u_int mask = (1 << bf->length) - 1;
 264
 265        return (val >> (16 - bf->length) & mask) << bf->offset;
 266}
 267
 268/*
 269 *    Set a single color register. Return != 0 for invalid regno.
 270 */
 271static int
 272cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 273                      u_int transp, struct fb_info *info)
 274{
 275        struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
 276        struct fb_var_screeninfo *var = &cfb->fb.var;
 277        u32 pseudo_val;
 278        int ret = 1;
 279
 280        switch (cfb->fb.fix.visual) {
 281        default:
 282                return 1;
 283
 284        /*
 285         * Pseudocolour:
 286         *         8     8
 287         * pixel --/--+--/-->  red lut  --> red dac
 288         *            |  8
 289         *            +--/--> green lut --> green dac
 290         *            |  8
 291         *            +--/-->  blue lut --> blue dac
 292         */
 293        case FB_VISUAL_PSEUDOCOLOR:
 294                if (regno >= NR_PALETTE)
 295                        return 1;
 296
 297                red >>= 8;
 298                green >>= 8;
 299                blue >>= 8;
 300
 301                cfb->palette[regno].red = red;
 302                cfb->palette[regno].green = green;
 303                cfb->palette[regno].blue = blue;
 304
 305                cyber2000fb_writeb(regno, 0x3c8, cfb);
 306                cyber2000fb_writeb(red, 0x3c9, cfb);
 307                cyber2000fb_writeb(green, 0x3c9, cfb);
 308                cyber2000fb_writeb(blue, 0x3c9, cfb);
 309                return 0;
 310
 311        /*
 312         * Direct colour:
 313         *         n     rl
 314         * pixel --/--+--/-->  red lut  --> red dac
 315         *            |  gl
 316         *            +--/--> green lut --> green dac
 317         *            |  bl
 318         *            +--/-->  blue lut --> blue dac
 319         * n = bpp, rl = red length, gl = green length, bl = blue length
 320         */
 321        case FB_VISUAL_DIRECTCOLOR:
 322                red >>= 8;
 323                green >>= 8;
 324                blue >>= 8;
 325
 326                if (var->green.length == 6 && regno < 64) {
 327                        cfb->palette[regno << 2].green = green;
 328
 329                        /*
 330                         * The 6 bits of the green component are applied
 331                         * to the high 6 bits of the LUT.
 332                         */
 333                        cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
 334                        cyber2000fb_writeb(cfb->palette[regno >> 1].red,
 335                                           0x3c9, cfb);
 336                        cyber2000fb_writeb(green, 0x3c9, cfb);
 337                        cyber2000fb_writeb(cfb->palette[regno >> 1].blue,
 338                                           0x3c9, cfb);
 339
 340                        green = cfb->palette[regno << 3].green;
 341
 342                        ret = 0;
 343                }
 344
 345                if (var->green.length >= 5 && regno < 32) {
 346                        cfb->palette[regno << 3].red = red;
 347                        cfb->palette[regno << 3].green = green;
 348                        cfb->palette[regno << 3].blue = blue;
 349
 350                        /*
 351                         * The 5 bits of each colour component are
 352                         * applied to the high 5 bits of the LUT.
 353                         */
 354                        cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
 355                        cyber2000fb_writeb(red, 0x3c9, cfb);
 356                        cyber2000fb_writeb(green, 0x3c9, cfb);
 357                        cyber2000fb_writeb(blue, 0x3c9, cfb);
 358                        ret = 0;
 359                }
 360
 361                if (var->green.length == 4 && regno < 16) {
 362                        cfb->palette[regno << 4].red = red;
 363                        cfb->palette[regno << 4].green = green;
 364                        cfb->palette[regno << 4].blue = blue;
 365
 366                        /*
 367                         * The 5 bits of each colour component are
 368                         * applied to the high 5 bits of the LUT.
 369                         */
 370                        cyber2000fb_writeb(regno << 4, 0x3c8, cfb);
 371                        cyber2000fb_writeb(red, 0x3c9, cfb);
 372                        cyber2000fb_writeb(green, 0x3c9, cfb);
 373                        cyber2000fb_writeb(blue, 0x3c9, cfb);
 374                        ret = 0;
 375                }
 376
 377                /*
 378                 * Since this is only used for the first 16 colours, we
 379                 * don't have to care about overflowing for regno >= 32
 380                 */
 381                pseudo_val = regno << var->red.offset |
 382                             regno << var->green.offset |
 383                             regno << var->blue.offset;
 384                break;
 385
 386        /*
 387         * True colour:
 388         *         n     rl
 389         * pixel --/--+--/--> red dac
 390         *            |  gl
 391         *            +--/--> green dac
 392         *            |  bl
 393         *            +--/--> blue dac
 394         * n = bpp, rl = red length, gl = green length, bl = blue length
 395         */
 396        case FB_VISUAL_TRUECOLOR:
 397                pseudo_val = convert_bitfield(transp ^ 0xffff, &var->transp);
 398                pseudo_val |= convert_bitfield(red, &var->red);
 399                pseudo_val |= convert_bitfield(green, &var->green);
 400                pseudo_val |= convert_bitfield(blue, &var->blue);
 401                ret = 0;
 402                break;
 403        }
 404
 405        /*
 406         * Now set our pseudo palette for the CFB16/24/32 drivers.
 407         */
 408        if (regno < 16)
 409                ((u32 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
 410
 411        return ret;
 412}
 413
 414struct par_info {
 415        /*
 416         * Hardware
 417         */
 418        u_char  clock_mult;
 419        u_char  clock_div;
 420        u_char  extseqmisc;
 421        u_char  co_pixfmt;
 422        u_char  crtc_ofl;
 423        u_char  crtc[19];
 424        u_int   width;
 425        u_int   pitch;
 426        u_int   fetch;
 427
 428        /*
 429         * Other
 430         */
 431        u_char  ramdac;
 432};
 433
 434static const u_char crtc_idx[] = {
 435        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
 436        0x08, 0x09,
 437        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
 438};
 439
 440static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
 441{
 442        unsigned int i;
 443        unsigned int val = cfb->ramdac_ctrl | cfb->ramdac_powerdown;
 444
 445        cyber2000fb_writeb(0x56, 0x3ce, cfb);
 446        i = cyber2000fb_readb(0x3cf, cfb);
 447        cyber2000fb_writeb(i | 4, 0x3cf, cfb);
 448        cyber2000fb_writeb(val, 0x3c6, cfb);
 449        cyber2000fb_writeb(i, 0x3cf, cfb);
 450        /* prevent card lock-up observed on x86 with CyberPro 2000 */
 451        cyber2000fb_readb(0x3cf, cfb);
 452}
 453
 454static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
 455{
 456        u_int i;
 457
 458        /*
 459         * Blank palette
 460         */
 461        for (i = 0; i < NR_PALETTE; i++) {
 462                cyber2000fb_writeb(i, 0x3c8, cfb);
 463                cyber2000fb_writeb(0, 0x3c9, cfb);
 464                cyber2000fb_writeb(0, 0x3c9, cfb);
 465                cyber2000fb_writeb(0, 0x3c9, cfb);
 466        }
 467
 468        cyber2000fb_writeb(0xef, 0x3c2, cfb);
 469        cyber2000_crtcw(0x11, 0x0b, cfb);
 470        cyber2000_attrw(0x11, 0x00, cfb);
 471
 472        cyber2000_seqw(0x00, 0x01, cfb);
 473        cyber2000_seqw(0x01, 0x01, cfb);
 474        cyber2000_seqw(0x02, 0x0f, cfb);
 475        cyber2000_seqw(0x03, 0x00, cfb);
 476        cyber2000_seqw(0x04, 0x0e, cfb);
 477        cyber2000_seqw(0x00, 0x03, cfb);
 478
 479        for (i = 0; i < sizeof(crtc_idx); i++)
 480                cyber2000_crtcw(crtc_idx[i], hw->crtc[i], cfb);
 481
 482        for (i = 0x0a; i < 0x10; i++)
 483                cyber2000_crtcw(i, 0, cfb);
 484
 485        cyber2000_grphw(EXT_CRT_VRTOFL, hw->crtc_ofl, cfb);
 486        cyber2000_grphw(0x00, 0x00, cfb);
 487        cyber2000_grphw(0x01, 0x00, cfb);
 488        cyber2000_grphw(0x02, 0x00, cfb);
 489        cyber2000_grphw(0x03, 0x00, cfb);
 490        cyber2000_grphw(0x04, 0x00, cfb);
 491        cyber2000_grphw(0x05, 0x60, cfb);
 492        cyber2000_grphw(0x06, 0x05, cfb);
 493        cyber2000_grphw(0x07, 0x0f, cfb);
 494        cyber2000_grphw(0x08, 0xff, cfb);
 495
 496        /* Attribute controller registers */
 497        for (i = 0; i < 16; i++)
 498                cyber2000_attrw(i, i, cfb);
 499
 500        cyber2000_attrw(0x10, 0x01, cfb);
 501        cyber2000_attrw(0x11, 0x00, cfb);
 502        cyber2000_attrw(0x12, 0x0f, cfb);
 503        cyber2000_attrw(0x13, 0x00, cfb);
 504        cyber2000_attrw(0x14, 0x00, cfb);
 505
 506        /* PLL registers */
 507        spin_lock(&cfb->reg_b0_lock);
 508        cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
 509        cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
 510        cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
 511        cyber2000_grphw(EXT_MCLK_DIV, cfb->mclk_div, cfb);
 512        cyber2000_grphw(0x90, 0x01, cfb);
 513        cyber2000_grphw(0xb9, 0x80, cfb);
 514        cyber2000_grphw(0xb9, 0x00, cfb);
 515        spin_unlock(&cfb->reg_b0_lock);
 516
 517        cfb->ramdac_ctrl = hw->ramdac;
 518        cyber2000fb_write_ramdac_ctrl(cfb);
 519
 520        cyber2000fb_writeb(0x20, 0x3c0, cfb);
 521        cyber2000fb_writeb(0xff, 0x3c6, cfb);
 522
 523        cyber2000_grphw(0x14, hw->fetch, cfb);
 524        cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
 525                              ((hw->pitch >> 4) & 0x30), cfb);
 526        cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
 527
 528        /*
 529         * Set up accelerator registers
 530         */
 531        cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
 532        cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
 533        cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
 534}
 535
 536static inline int
 537cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
 538{
 539        u_int base = var->yoffset * var->xres_virtual + var->xoffset;
 540
 541        base *= var->bits_per_pixel;
 542
 543        /*
 544         * Convert to bytes and shift two extra bits because DAC
 545         * can only start on 4 byte aligned data.
 546         */
 547        base >>= 5;
 548
 549        if (base >= 1 << 20)
 550                return -EINVAL;
 551
 552        cyber2000_grphw(0x10, base >> 16 | 0x10, cfb);
 553        cyber2000_crtcw(0x0c, base >> 8, cfb);
 554        cyber2000_crtcw(0x0d, base, cfb);
 555
 556        return 0;
 557}
 558
 559static int
 560cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
 561                        struct fb_var_screeninfo *var)
 562{
 563        u_int Htotal, Hblankend, Hsyncend;
 564        u_int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
 565#define ENCODE_BIT(v, b1, m, b2) ((((v) >> (b1)) & (m)) << (b2))
 566
 567        hw->crtc[13] = hw->pitch;
 568        hw->crtc[17] = 0xe3;
 569        hw->crtc[14] = 0;
 570        hw->crtc[8]  = 0;
 571
 572        Htotal     = var->xres + var->right_margin +
 573                     var->hsync_len + var->left_margin;
 574
 575        if (Htotal > 2080)
 576                return -EINVAL;
 577
 578        hw->crtc[0] = (Htotal >> 3) - 5;
 579        hw->crtc[1] = (var->xres >> 3) - 1;
 580        hw->crtc[2] = var->xres >> 3;
 581        hw->crtc[4] = (var->xres + var->right_margin) >> 3;
 582
 583        Hblankend   = (Htotal - 4 * 8) >> 3;
 584
 585        hw->crtc[3] = ENCODE_BIT(Hblankend,  0, 0x1f,  0) |
 586                      ENCODE_BIT(1,          0, 0x01,  7);
 587
 588        Hsyncend    = (var->xres + var->right_margin + var->hsync_len) >> 3;
 589
 590        hw->crtc[5] = ENCODE_BIT(Hsyncend,   0, 0x1f,  0) |
 591                      ENCODE_BIT(Hblankend,  5, 0x01,  7);
 592
 593        Vdispend    = var->yres - 1;
 594        Vsyncstart  = var->yres + var->lower_margin;
 595        Vsyncend    = var->yres + var->lower_margin + var->vsync_len;
 596        Vtotal      = var->yres + var->lower_margin + var->vsync_len +
 597                      var->upper_margin - 2;
 598
 599        if (Vtotal > 2047)
 600                return -EINVAL;
 601
 602        Vblankstart = var->yres + 6;
 603        Vblankend   = Vtotal - 10;
 604
 605        hw->crtc[6]  = Vtotal;
 606        hw->crtc[7]  = ENCODE_BIT(Vtotal,     8, 0x01,  0) |
 607                        ENCODE_BIT(Vdispend,   8, 0x01,  1) |
 608                        ENCODE_BIT(Vsyncstart, 8, 0x01,  2) |
 609                        ENCODE_BIT(Vblankstart, 8, 0x01,  3) |
 610                        ENCODE_BIT(1,          0, 0x01,  4) |
 611                        ENCODE_BIT(Vtotal,     9, 0x01,  5) |
 612                        ENCODE_BIT(Vdispend,   9, 0x01,  6) |
 613                        ENCODE_BIT(Vsyncstart, 9, 0x01,  7);
 614        hw->crtc[9]  = ENCODE_BIT(0,          0, 0x1f,  0) |
 615                        ENCODE_BIT(Vblankstart, 9, 0x01,  5) |
 616                        ENCODE_BIT(1,          0, 0x01,  6);
 617        hw->crtc[10] = Vsyncstart;
 618        hw->crtc[11] = ENCODE_BIT(Vsyncend,   0, 0x0f,  0) |
 619                       ENCODE_BIT(1,          0, 0x01,  7);
 620        hw->crtc[12] = Vdispend;
 621        hw->crtc[15] = Vblankstart;
 622        hw->crtc[16] = Vblankend;
 623        hw->crtc[18] = 0xff;
 624
 625        /*
 626         * overflow - graphics reg 0x11
 627         * 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
 628         * 4=LINECOMP:10 5-IVIDEO 6=FIXCNT
 629         */
 630        hw->crtc_ofl =
 631                ENCODE_BIT(Vtotal, 10, 0x01, 0) |
 632                ENCODE_BIT(Vdispend, 10, 0x01, 1) |
 633                ENCODE_BIT(Vsyncstart, 10, 0x01, 2) |
 634                ENCODE_BIT(Vblankstart, 10, 0x01, 3) |
 635                EXT_CRT_VRTOFL_LINECOMP10;
 636
 637        /* woody: set the interlaced bit... */
 638        /* FIXME: what about doublescan? */
 639        if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
 640                hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;
 641
 642        return 0;
 643}
 644
 645/*
 646 * The following was discovered by a good monitor, bit twiddling, theorising
 647 * and but mostly luck.  Strangely, it looks like everyone elses' PLL!
 648 *
 649 * Clock registers:
 650 *   fclock = fpll / div2
 651 *   fpll   = fref * mult / div1
 652 * where:
 653 *   fref = 14.318MHz (69842ps)
 654 *   mult = reg0xb0.7:0
 655 *   div1 = (reg0xb1.5:0 + 1)
 656 *   div2 =  2^(reg0xb1.7:6)
 657 *   fpll should be between 115 and 260 MHz
 658 *  (8696ps and 3846ps)
 659 */
 660static int
 661cyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb,
 662                         struct fb_var_screeninfo *var)
 663{
 664        u_long pll_ps = var->pixclock;
 665        const u_long ref_ps = cfb->ref_ps;
 666        u_int div2, t_div1, best_div1, best_mult;
 667        int best_diff;
 668        int vco;
 669
 670        /*
 671         * Step 1:
 672         *   find div2 such that 115MHz < fpll < 260MHz
 673         *   and 0 <= div2 < 4
 674         */
 675        for (div2 = 0; div2 < 4; div2++) {
 676                u_long new_pll;
 677
 678                new_pll = pll_ps / cfb->divisors[div2];
 679                if (8696 > new_pll && new_pll > 3846) {
 680                        pll_ps = new_pll;
 681                        break;
 682                }
 683        }
 684
 685        if (div2 == 4)
 686                return -EINVAL;
 687
 688        /*
 689         * Step 2:
 690         *  Given pll_ps and ref_ps, find:
 691         *    pll_ps * 0.995 < pll_ps_calc < pll_ps * 1.005
 692         *  where { 1 < best_div1 < 32, 1 < best_mult < 256 }
 693         *    pll_ps_calc = best_div1 / (ref_ps * best_mult)
 694         */
 695        best_diff = 0x7fffffff;
 696        best_mult = 2;
 697        best_div1 = 32;
 698        for (t_div1 = 2; t_div1 < 32; t_div1 += 1) {
 699                u_int rr, t_mult, t_pll_ps;
 700                int diff;
 701
 702                /*
 703                 * Find the multiplier for this divisor
 704                 */
 705                rr = ref_ps * t_div1;
 706                t_mult = (rr + pll_ps / 2) / pll_ps;
 707
 708                /*
 709                 * Is the multiplier within the correct range?
 710                 */
 711                if (t_mult > 256 || t_mult < 2)
 712                        continue;
 713
 714                /*
 715                 * Calculate the actual clock period from this multiplier
 716                 * and divisor, and estimate the error.
 717                 */
 718                t_pll_ps = (rr + t_mult / 2) / t_mult;
 719                diff = pll_ps - t_pll_ps;
 720                if (diff < 0)
 721                        diff = -diff;
 722
 723                if (diff < best_diff) {
 724                        best_diff = diff;
 725                        best_mult = t_mult;
 726                        best_div1 = t_div1;
 727                }
 728
 729                /*
 730                 * If we hit an exact value, there is no point in continuing.
 731                 */
 732                if (diff == 0)
 733                        break;
 734        }
 735
 736        /*
 737         * Step 3:
 738         *  combine values
 739         */
 740        hw->clock_mult = best_mult - 1;
 741        hw->clock_div  = div2 << 6 | (best_div1 - 1);
 742
 743        vco = ref_ps * best_div1 / best_mult;
 744        if ((ref_ps == 40690) && (vco < 5556))
 745                /* Set VFSEL when VCO > 180MHz (5.556 ps). */
 746                hw->clock_div |= EXT_DCLK_DIV_VFSEL;
 747
 748        return 0;
 749}
 750
 751/*
 752 *    Set the User Defined Part of the Display
 753 */
 754static int
 755cyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 756{
 757        struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
 758        struct par_info hw;
 759        unsigned int mem;
 760        int err;
 761
 762        var->transp.msb_right   = 0;
 763        var->red.msb_right      = 0;
 764        var->green.msb_right    = 0;
 765        var->blue.msb_right     = 0;
 766        var->transp.offset      = 0;
 767        var->transp.length      = 0;
 768
 769        switch (var->bits_per_pixel) {
 770        case 8: /* PSEUDOCOLOUR, 256 */
 771                var->red.offset         = 0;
 772                var->red.length         = 8;
 773                var->green.offset       = 0;
 774                var->green.length       = 8;
 775                var->blue.offset        = 0;
 776                var->blue.length        = 8;
 777                break;
 778
 779        case 16:/* DIRECTCOLOUR, 64k or 32k */
 780                switch (var->green.length) {
 781                case 6: /* RGB565, 64k */
 782                        var->red.offset         = 11;
 783                        var->red.length         = 5;
 784                        var->green.offset       = 5;
 785                        var->green.length       = 6;
 786                        var->blue.offset        = 0;
 787                        var->blue.length        = 5;
 788                        break;
 789
 790                default:
 791                case 5: /* RGB555, 32k */
 792                        var->red.offset         = 10;
 793                        var->red.length         = 5;
 794                        var->green.offset       = 5;
 795                        var->green.length       = 5;
 796                        var->blue.offset        = 0;
 797                        var->blue.length        = 5;
 798                        break;
 799
 800                case 4: /* RGB444, 4k + transparency? */
 801                        var->transp.offset      = 12;
 802                        var->transp.length      = 4;
 803                        var->red.offset         = 8;
 804                        var->red.length         = 4;
 805                        var->green.offset       = 4;
 806                        var->green.length       = 4;
 807                        var->blue.offset        = 0;
 808                        var->blue.length        = 4;
 809                        break;
 810                }
 811                break;
 812
 813        case 24:/* TRUECOLOUR, 16m */
 814                var->red.offset         = 16;
 815                var->red.length         = 8;
 816                var->green.offset       = 8;
 817                var->green.length       = 8;
 818                var->blue.offset        = 0;
 819                var->blue.length        = 8;
 820                break;
 821
 822        case 32:/* TRUECOLOUR, 16m */
 823                var->transp.offset      = 24;
 824                var->transp.length      = 8;
 825                var->red.offset         = 16;
 826                var->red.length         = 8;
 827                var->green.offset       = 8;
 828                var->green.length       = 8;
 829                var->blue.offset        = 0;
 830                var->blue.length        = 8;
 831                break;
 832
 833        default:
 834                return -EINVAL;
 835        }
 836
 837        mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
 838        if (mem > cfb->fb.fix.smem_len)
 839                var->yres_virtual = cfb->fb.fix.smem_len * 8 /
 840                                    (var->bits_per_pixel * var->xres_virtual);
 841
 842        if (var->yres > var->yres_virtual)
 843                var->yres = var->yres_virtual;
 844        if (var->xres > var->xres_virtual)
 845                var->xres = var->xres_virtual;
 846
 847        err = cyber2000fb_decode_clock(&hw, cfb, var);
 848        if (err)
 849                return err;
 850
 851        err = cyber2000fb_decode_crtc(&hw, cfb, var);
 852        if (err)
 853                return err;
 854
 855        return 0;
 856}
 857
 858static int cyber2000fb_set_par(struct fb_info *info)
 859{
 860        struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
 861        struct fb_var_screeninfo *var = &cfb->fb.var;
 862        struct par_info hw;
 863        unsigned int mem;
 864
 865        hw.width = var->xres_virtual;
 866        hw.ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;
 867
 868        switch (var->bits_per_pixel) {
 869        case 8:
 870                hw.co_pixfmt            = CO_PIXFMT_8BPP;
 871                hw.pitch                = hw.width >> 3;
 872                hw.extseqmisc           = EXT_SEQ_MISC_8;
 873                break;
 874
 875        case 16:
 876                hw.co_pixfmt            = CO_PIXFMT_16BPP;
 877                hw.pitch                = hw.width >> 2;
 878
 879                switch (var->green.length) {
 880                case 6: /* RGB565, 64k */
 881                        hw.extseqmisc   = EXT_SEQ_MISC_16_RGB565;
 882                        break;
 883                case 5: /* RGB555, 32k */
 884                        hw.extseqmisc   = EXT_SEQ_MISC_16_RGB555;
 885                        break;
 886                case 4: /* RGB444, 4k + transparency? */
 887                        hw.extseqmisc   = EXT_SEQ_MISC_16_RGB444;
 888                        break;
 889                default:
 890                        BUG();
 891                }
 892                break;
 893
 894        case 24:/* TRUECOLOUR, 16m */
 895                hw.co_pixfmt            = CO_PIXFMT_24BPP;
 896                hw.width                *= 3;
 897                hw.pitch                = hw.width >> 3;
 898                hw.ramdac               |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
 899                hw.extseqmisc           = EXT_SEQ_MISC_24_RGB888;
 900                break;
 901
 902        case 32:/* TRUECOLOUR, 16m */
 903                hw.co_pixfmt            = CO_PIXFMT_32BPP;
 904                hw.pitch                = hw.width >> 1;
 905                hw.ramdac               |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
 906                hw.extseqmisc           = EXT_SEQ_MISC_32;
 907                break;
 908
 909        default:
 910                BUG();
 911        }
 912
 913        /*
 914         * Sigh, this is absolutely disgusting, but caused by
 915         * the way the fbcon developers want to separate out
 916         * the "checking" and the "setting" of the video mode.
 917         *
 918         * If the mode is not suitable for the hardware here,
 919         * we can't prevent it being set by returning an error.
 920         *
 921         * In theory, since NetWinders contain just one VGA card,
 922         * we should never end up hitting this problem.
 923         */
 924        BUG_ON(cyber2000fb_decode_clock(&hw, cfb, var) != 0);
 925        BUG_ON(cyber2000fb_decode_crtc(&hw, cfb, var) != 0);
 926
 927        hw.width -= 1;
 928        hw.fetch = hw.pitch;
 929        if (!(cfb->mem_ctl2 & MEM_CTL2_64BIT))
 930                hw.fetch <<= 1;
 931        hw.fetch += 1;
 932
 933        cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
 934
 935        /*
 936         * Same here - if the size of the video mode exceeds the
 937         * available RAM, we can't prevent this mode being set.
 938         *
 939         * In theory, since NetWinders contain just one VGA card,
 940         * we should never end up hitting this problem.
 941         */
 942        mem = cfb->fb.fix.line_length * var->yres_virtual;
 943        BUG_ON(mem > cfb->fb.fix.smem_len);
 944
 945        /*
 946         * 8bpp displays are always pseudo colour.  16bpp and above
 947         * are direct colour or true colour, depending on whether
 948         * the RAMDAC palettes are bypassed.  (Direct colour has
 949         * palettes, true colour does not.)
 950         */
 951        if (var->bits_per_pixel == 8)
 952                cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
 953        else if (hw.ramdac & RAMDAC_BYPASS)
 954                cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
 955        else
 956                cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
 957
 958        cyber2000fb_set_timing(cfb, &hw);
 959        cyber2000fb_update_start(cfb, var);
 960
 961        return 0;
 962}
 963
 964/*
 965 *    Pan or Wrap the Display
 966 */
 967static int
 968cyber2000fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 969{
 970        struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
 971
 972        if (cyber2000fb_update_start(cfb, var))
 973                return -EINVAL;
 974
 975        cfb->fb.var.xoffset = var->xoffset;
 976        cfb->fb.var.yoffset = var->yoffset;
 977
 978        if (var->vmode & FB_VMODE_YWRAP) {
 979                cfb->fb.var.vmode |= FB_VMODE_YWRAP;
 980        } else {
 981                cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;
 982        }
 983
 984        return 0;
 985}
 986
 987/*
 988 *    (Un)Blank the display.
 989 *
 990 *  Blank the screen if blank_mode != 0, else unblank. If
 991 *  blank == NULL then the caller blanks by setting the CLUT
 992 *  (Color Look Up Table) to all black. Return 0 if blanking
 993 *  succeeded, != 0 if un-/blanking failed due to e.g. a
 994 *  video mode which doesn't support it. Implements VESA
 995 *  suspend and powerdown modes on hardware that supports
 996 *  disabling hsync/vsync:
 997 *    blank_mode == 2: suspend vsync
 998 *    blank_mode == 3: suspend hsync
 999 *    blank_mode == 4: powerdown
1000 *
1001 *  wms...Enable VESA DMPS compatible powerdown mode
1002 *  run "setterm -powersave powerdown" to take advantage
1003 */
1004static int cyber2000fb_blank(int blank, struct fb_info *info)
1005{
1006        struct cfb_info *cfb = container_of(info, struct cfb_info, fb);
1007        unsigned int sync = 0;
1008        int i;
1009
1010        switch (blank) {
1011        case FB_BLANK_POWERDOWN:        /* powerdown - both sync lines down */
1012                sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
1013                break;
1014        case FB_BLANK_HSYNC_SUSPEND:    /* hsync off */
1015                sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;
1016                break;
1017        case FB_BLANK_VSYNC_SUSPEND:    /* vsync off */
1018                sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
1019                break;
1020        case FB_BLANK_NORMAL:           /* soft blank */
1021        default:                        /* unblank */
1022                break;
1023        }
1024
1025        cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
1026
1027        if (blank <= 1) {
1028                /* turn on ramdacs */
1029                cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS |
1030                                           RAMDAC_RAMPWRDN);
1031                cyber2000fb_write_ramdac_ctrl(cfb);
1032        }
1033
1034        /*
1035         * Soft blank/unblank the display.
1036         */
1037        if (blank) {    /* soft blank */
1038                for (i = 0; i < NR_PALETTE; i++) {
1039                        cyber2000fb_writeb(i, 0x3c8, cfb);
1040                        cyber2000fb_writeb(0, 0x3c9, cfb);
1041                        cyber2000fb_writeb(0, 0x3c9, cfb);
1042                        cyber2000fb_writeb(0, 0x3c9, cfb);
1043                }
1044        } else {        /* unblank */
1045                for (i = 0; i < NR_PALETTE; i++) {
1046                        cyber2000fb_writeb(i, 0x3c8, cfb);
1047                        cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
1048                        cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
1049                        cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
1050                }
1051        }
1052
1053        if (blank >= 2) {
1054                /* turn off ramdacs */
1055                cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS |
1056                                         RAMDAC_RAMPWRDN;
1057                cyber2000fb_write_ramdac_ctrl(cfb);
1058        }
1059
1060        return 0;
1061}
1062
1063static struct fb_ops cyber2000fb_ops = {
1064        .owner          = THIS_MODULE,
1065        .fb_check_var   = cyber2000fb_check_var,
1066        .fb_set_par     = cyber2000fb_set_par,
1067        .fb_setcolreg   = cyber2000fb_setcolreg,
1068        .fb_blank       = cyber2000fb_blank,
1069        .fb_pan_display = cyber2000fb_pan_display,
1070        .fb_fillrect    = cyber2000fb_fillrect,
1071        .fb_copyarea    = cyber2000fb_copyarea,
1072        .fb_imageblit   = cyber2000fb_imageblit,
1073        .fb_sync        = cyber2000fb_sync,
1074};
1075
1076/*
1077 * This is the only "static" reference to the internal data structures
1078 * of this driver.  It is here solely at the moment to support the other
1079 * CyberPro modules external to this driver.
1080 */
1081static struct cfb_info *int_cfb_info;
1082
1083/*
1084 * Enable access to the extended registers
1085 */
1086void cyber2000fb_enable_extregs(struct cfb_info *cfb)
1087{
1088        cfb->func_use_count += 1;
1089
1090        if (cfb->func_use_count == 1) {
1091                int old;
1092
1093                old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
1094                old |= EXT_FUNC_CTL_EXTREGENBL;
1095                cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
1096        }
1097}
1098EXPORT_SYMBOL(cyber2000fb_enable_extregs);
1099
1100/*
1101 * Disable access to the extended registers
1102 */
1103void cyber2000fb_disable_extregs(struct cfb_info *cfb)
1104{
1105        if (cfb->func_use_count == 1) {
1106                int old;
1107
1108                old = cyber2000_grphr(EXT_FUNC_CTL, cfb);
1109                old &= ~EXT_FUNC_CTL_EXTREGENBL;
1110                cyber2000_grphw(EXT_FUNC_CTL, old, cfb);
1111        }
1112
1113        if (cfb->func_use_count == 0)
1114                printk(KERN_ERR "disable_extregs: count = 0\n");
1115        else
1116                cfb->func_use_count -= 1;
1117}
1118EXPORT_SYMBOL(cyber2000fb_disable_extregs);
1119
1120/*
1121 * Attach a capture/tv driver to the core CyberX0X0 driver.
1122 */
1123int cyber2000fb_attach(struct cyberpro_info *info, int idx)
1124{
1125        if (int_cfb_info != NULL) {
1126                info->dev             = int_cfb_info->fb.device;
1127#ifdef CONFIG_FB_CYBER2000_I2C
1128                info->i2c             = &int_cfb_info->i2c_adapter;
1129#else
1130                info->i2c             = NULL;
1131#endif
1132                info->regs            = int_cfb_info->regs;
1133                info->irq             = int_cfb_info->irq;
1134                info->fb              = int_cfb_info->fb.screen_base;
1135                info->fb_size         = int_cfb_info->fb.fix.smem_len;
1136                info->info            = int_cfb_info;
1137
1138                strlcpy(info->dev_name, int_cfb_info->fb.fix.id,
1139                        sizeof(info->dev_name));
1140        }
1141
1142        return int_cfb_info != NULL;
1143}
1144EXPORT_SYMBOL(cyber2000fb_attach);
1145
1146/*
1147 * Detach a capture/tv driver from the core CyberX0X0 driver.
1148 */
1149void cyber2000fb_detach(int idx)
1150{
1151}
1152EXPORT_SYMBOL(cyber2000fb_detach);
1153
1154#ifdef CONFIG_FB_CYBER2000_DDC
1155
1156#define DDC_REG         0xb0
1157#define DDC_SCL_OUT     (1 << 0)
1158#define DDC_SDA_OUT     (1 << 4)
1159#define DDC_SCL_IN      (1 << 2)
1160#define DDC_SDA_IN      (1 << 6)
1161
1162static void cyber2000fb_enable_ddc(struct cfb_info *cfb)
1163{
1164        spin_lock(&cfb->reg_b0_lock);
1165        cyber2000fb_writew(0x1bf, 0x3ce, cfb);
1166}
1167
1168static void cyber2000fb_disable_ddc(struct cfb_info *cfb)
1169{
1170        cyber2000fb_writew(0x0bf, 0x3ce, cfb);
1171        spin_unlock(&cfb->reg_b0_lock);
1172}
1173
1174
1175static void cyber2000fb_ddc_setscl(void *data, int val)
1176{
1177        struct cfb_info *cfb = data;
1178        unsigned char reg;
1179
1180        cyber2000fb_enable_ddc(cfb);
1181        reg = cyber2000_grphr(DDC_REG, cfb);
1182        if (!val)       /* bit is inverted */
1183                reg |= DDC_SCL_OUT;
1184        else
1185                reg &= ~DDC_SCL_OUT;
1186        cyber2000_grphw(DDC_REG, reg, cfb);
1187        cyber2000fb_disable_ddc(cfb);
1188}
1189
1190static void cyber2000fb_ddc_setsda(void *data, int val)
1191{
1192        struct cfb_info *cfb = data;
1193        unsigned char reg;
1194
1195        cyber2000fb_enable_ddc(cfb);
1196        reg = cyber2000_grphr(DDC_REG, cfb);
1197        if (!val)       /* bit is inverted */
1198                reg |= DDC_SDA_OUT;
1199        else
1200                reg &= ~DDC_SDA_OUT;
1201        cyber2000_grphw(DDC_REG, reg, cfb);
1202        cyber2000fb_disable_ddc(cfb);
1203}
1204
1205static int cyber2000fb_ddc_getscl(void *data)
1206{
1207        struct cfb_info *cfb = data;
1208        int retval;
1209
1210        cyber2000fb_enable_ddc(cfb);
1211        retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SCL_IN);
1212        cyber2000fb_disable_ddc(cfb);
1213
1214        return retval;
1215}
1216
1217static int cyber2000fb_ddc_getsda(void *data)
1218{
1219        struct cfb_info *cfb = data;
1220        int retval;
1221
1222        cyber2000fb_enable_ddc(cfb);
1223        retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SDA_IN);
1224        cyber2000fb_disable_ddc(cfb);
1225
1226        return retval;
1227}
1228
1229static int cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
1230{
1231        strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
1232                sizeof(cfb->ddc_adapter.name));
1233        cfb->ddc_adapter.owner          = THIS_MODULE;
1234        cfb->ddc_adapter.class          = I2C_CLASS_DDC;
1235        cfb->ddc_adapter.algo_data      = &cfb->ddc_algo;
1236        cfb->ddc_adapter.dev.parent     = cfb->fb.device;
1237        cfb->ddc_algo.setsda            = cyber2000fb_ddc_setsda;
1238        cfb->ddc_algo.setscl            = cyber2000fb_ddc_setscl;
1239        cfb->ddc_algo.getsda            = cyber2000fb_ddc_getsda;
1240        cfb->ddc_algo.getscl            = cyber2000fb_ddc_getscl;
1241        cfb->ddc_algo.udelay            = 10;
1242        cfb->ddc_algo.timeout           = 20;
1243        cfb->ddc_algo.data              = cfb;
1244
1245        i2c_set_adapdata(&cfb->ddc_adapter, cfb);
1246
1247        return i2c_bit_add_bus(&cfb->ddc_adapter);
1248}
1249#endif /* CONFIG_FB_CYBER2000_DDC */
1250
1251#ifdef CONFIG_FB_CYBER2000_I2C
1252static void cyber2000fb_i2c_setsda(void *data, int state)
1253{
1254        struct cfb_info *cfb = data;
1255        unsigned int latch2;
1256
1257        spin_lock(&cfb->reg_b0_lock);
1258        latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
1259        latch2 &= EXT_LATCH2_I2C_CLKEN;
1260        if (state)
1261                latch2 |= EXT_LATCH2_I2C_DATEN;
1262        cyber2000_grphw(EXT_LATCH2, latch2, cfb);
1263        spin_unlock(&cfb->reg_b0_lock);
1264}
1265
1266static void cyber2000fb_i2c_setscl(void *data, int state)
1267{
1268        struct cfb_info *cfb = data;
1269        unsigned int latch2;
1270
1271        spin_lock(&cfb->reg_b0_lock);
1272        latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
1273        latch2 &= EXT_LATCH2_I2C_DATEN;
1274        if (state)
1275                latch2 |= EXT_LATCH2_I2C_CLKEN;
1276        cyber2000_grphw(EXT_LATCH2, latch2, cfb);
1277        spin_unlock(&cfb->reg_b0_lock);
1278}
1279
1280static int cyber2000fb_i2c_getsda(void *data)
1281{
1282        struct cfb_info *cfb = data;
1283        int ret;
1284
1285        spin_lock(&cfb->reg_b0_lock);
1286        ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_DAT);
1287        spin_unlock(&cfb->reg_b0_lock);
1288
1289        return ret;
1290}
1291
1292static int cyber2000fb_i2c_getscl(void *data)
1293{
1294        struct cfb_info *cfb = data;
1295        int ret;
1296
1297        spin_lock(&cfb->reg_b0_lock);
1298        ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_CLK);
1299        spin_unlock(&cfb->reg_b0_lock);
1300
1301        return ret;
1302}
1303
1304static int cyber2000fb_i2c_register(struct cfb_info *cfb)
1305{
1306        strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
1307                sizeof(cfb->i2c_adapter.name));
1308        cfb->i2c_adapter.owner = THIS_MODULE;
1309        cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
1310        cfb->i2c_adapter.dev.parent = cfb->fb.device;
1311        cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda;
1312        cfb->i2c_algo.setscl = cyber2000fb_i2c_setscl;
1313        cfb->i2c_algo.getsda = cyber2000fb_i2c_getsda;
1314        cfb->i2c_algo.getscl = cyber2000fb_i2c_getscl;
1315        cfb->i2c_algo.udelay = 5;
1316        cfb->i2c_algo.timeout = msecs_to_jiffies(100);
1317        cfb->i2c_algo.data = cfb;
1318
1319        return i2c_bit_add_bus(&cfb->i2c_adapter);
1320}
1321
1322static void cyber2000fb_i2c_unregister(struct cfb_info *cfb)
1323{
1324        i2c_del_adapter(&cfb->i2c_adapter);
1325}
1326#else
1327#define cyber2000fb_i2c_register(cfb)   (0)
1328#define cyber2000fb_i2c_unregister(cfb) do { } while (0)
1329#endif
1330
1331/*
1332 * These parameters give
1333 * 640x480, hsync 31.5kHz, vsync 60Hz
1334 */
1335static const struct fb_videomode cyber2000fb_default_mode = {
1336        .refresh        = 60,
1337        .xres           = 640,
1338        .yres           = 480,
1339        .pixclock       = 39722,
1340        .left_margin    = 56,
1341        .right_margin   = 16,
1342        .upper_margin   = 34,
1343        .lower_margin   = 9,
1344        .hsync_len      = 88,
1345        .vsync_len      = 2,
1346        .sync           = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1347        .vmode          = FB_VMODE_NONINTERLACED
1348};
1349
1350static char igs_regs[] = {
1351        EXT_CRT_IRQ,            0,
1352        EXT_CRT_TEST,           0,
1353        EXT_SYNC_CTL,           0,
1354        EXT_SEG_WRITE_PTR,      0,
1355        EXT_SEG_READ_PTR,       0,
1356        EXT_BIU_MISC,           EXT_BIU_MISC_LIN_ENABLE |
1357                                EXT_BIU_MISC_COP_ENABLE |
1358                                EXT_BIU_MISC_COP_BFC,
1359        EXT_FUNC_CTL,           0,
1360        CURS_H_START,           0,
1361        CURS_H_START + 1,       0,
1362        CURS_H_PRESET,          0,
1363        CURS_V_START,           0,
1364        CURS_V_START + 1,       0,
1365        CURS_V_PRESET,          0,
1366        CURS_CTL,               0,
1367        EXT_ATTRIB_CTL,         EXT_ATTRIB_CTL_EXT,
1368        EXT_OVERSCAN_RED,       0,
1369        EXT_OVERSCAN_GREEN,     0,
1370        EXT_OVERSCAN_BLUE,      0,
1371
1372        /* some of these are questionable when we have a BIOS */
1373        EXT_MEM_CTL0,           EXT_MEM_CTL0_7CLK |
1374                                EXT_MEM_CTL0_RAS_1 |
1375                                EXT_MEM_CTL0_MULTCAS,
1376        EXT_HIDDEN_CTL1,        0x30,
1377        EXT_FIFO_CTL,           0x0b,
1378        EXT_FIFO_CTL + 1,       0x17,
1379        0x76,                   0x00,
1380        EXT_HIDDEN_CTL4,        0xc8
1381};
1382
1383/*
1384 * Initialise the CyberPro hardware.  On the CyberPro5XXXX,
1385 * ensure that we're using the correct PLL (5XXX's may be
1386 * programmed to use an additional set of PLLs.)
1387 */
1388static void cyberpro_init_hw(struct cfb_info *cfb)
1389{
1390        int i;
1391
1392        for (i = 0; i < sizeof(igs_regs); i += 2)
1393                cyber2000_grphw(igs_regs[i], igs_regs[i + 1], cfb);
1394
1395        if (cfb->id == ID_CYBERPRO_5000) {
1396                unsigned char val;
1397                cyber2000fb_writeb(0xba, 0x3ce, cfb);
1398                val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
1399                cyber2000fb_writeb(val, 0x3cf, cfb);
1400        }
1401}
1402
1403static struct cfb_info *cyberpro_alloc_fb_info(unsigned int id, char *name)
1404{
1405        struct cfb_info *cfb;
1406
1407        cfb = kzalloc(sizeof(struct cfb_info), GFP_KERNEL);
1408        if (!cfb)
1409                return NULL;
1410
1411
1412        cfb->id                 = id;
1413
1414        if (id == ID_CYBERPRO_5000)
1415                cfb->ref_ps     = 40690; /* 24.576 MHz */
1416        else
1417                cfb->ref_ps     = 69842; /* 14.31818 MHz (69841?) */
1418
1419        cfb->divisors[0]        = 1;
1420        cfb->divisors[1]        = 2;
1421        cfb->divisors[2]        = 4;
1422
1423        if (id == ID_CYBERPRO_2000)
1424                cfb->divisors[3] = 8;
1425        else
1426                cfb->divisors[3] = 6;
1427
1428        strcpy(cfb->fb.fix.id, name);
1429
1430        cfb->fb.fix.type        = FB_TYPE_PACKED_PIXELS;
1431        cfb->fb.fix.type_aux    = 0;
1432        cfb->fb.fix.xpanstep    = 0;
1433        cfb->fb.fix.ypanstep    = 1;
1434        cfb->fb.fix.ywrapstep   = 0;
1435
1436        switch (id) {
1437        case ID_IGA_1682:
1438                cfb->fb.fix.accel = 0;
1439                break;
1440
1441        case ID_CYBERPRO_2000:
1442                cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2000;
1443                break;
1444
1445        case ID_CYBERPRO_2010:
1446                cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER2010;
1447                break;
1448
1449        case ID_CYBERPRO_5000:
1450                cfb->fb.fix.accel = FB_ACCEL_IGS_CYBER5000;
1451                break;
1452        }
1453
1454        cfb->fb.var.nonstd      = 0;
1455        cfb->fb.var.activate    = FB_ACTIVATE_NOW;
1456        cfb->fb.var.height      = -1;
1457        cfb->fb.var.width       = -1;
1458        cfb->fb.var.accel_flags = FB_ACCELF_TEXT;
1459
1460        cfb->fb.fbops           = &cyber2000fb_ops;
1461        cfb->fb.flags           = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1462        cfb->fb.pseudo_palette  = cfb->pseudo_palette;
1463
1464        spin_lock_init(&cfb->reg_b0_lock);
1465
1466        fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);
1467
1468        return cfb;
1469}
1470
1471static void cyberpro_free_fb_info(struct cfb_info *cfb)
1472{
1473        if (cfb) {
1474                /*
1475                 * Free the colourmap
1476                 */
1477                fb_alloc_cmap(&cfb->fb.cmap, 0, 0);
1478
1479                kfree(cfb);
1480        }
1481}
1482
1483/*
1484 * Parse Cyber2000fb options.  Usage:
1485 *  video=cyber2000:font:fontname
1486 */
1487#ifndef MODULE
1488static int cyber2000fb_setup(char *options)
1489{
1490        char *opt;
1491
1492        if (!options || !*options)
1493                return 0;
1494
1495        while ((opt = strsep(&options, ",")) != NULL) {
1496                if (!*opt)
1497                        continue;
1498
1499                if (strncmp(opt, "font:", 5) == 0) {
1500                        static char default_font_storage[40];
1501
1502                        strlcpy(default_font_storage, opt + 5,
1503                                sizeof(default_font_storage));
1504                        default_font = default_font_storage;
1505                        continue;
1506                }
1507
1508                printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n", opt);
1509        }
1510        return 0;
1511}
1512#endif  /*  MODULE  */
1513
1514/*
1515 * The CyberPro chips can be placed on many different bus types.
1516 * This probe function is common to all bus types.  The bus-specific
1517 * probe function is expected to have:
1518 *  - enabled access to the linear memory region
1519 *  - memory mapped access to the registers
1520 *  - initialised mem_ctl1 and mem_ctl2 appropriately.
1521 */
1522static int cyberpro_common_probe(struct cfb_info *cfb)
1523{
1524        u_long smem_size;
1525        u_int h_sync, v_sync;
1526        int err;
1527
1528        cyberpro_init_hw(cfb);
1529
1530        /*
1531         * Get the video RAM size and width from the VGA register.
1532         * This should have been already initialised by the BIOS,
1533         * but if it's garbage, claim default 1MB VRAM (woody)
1534         */
1535        cfb->mem_ctl1 = cyber2000_grphr(EXT_MEM_CTL1, cfb);
1536        cfb->mem_ctl2 = cyber2000_grphr(EXT_MEM_CTL2, cfb);
1537
1538        /*
1539         * Determine the size of the memory.
1540         */
1541        switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) {
1542        case MEM_CTL2_SIZE_4MB:
1543                smem_size = 0x00400000;
1544                break;
1545        case MEM_CTL2_SIZE_2MB:
1546                smem_size = 0x00200000;
1547                break;
1548        case MEM_CTL2_SIZE_1MB:
1549                smem_size = 0x00100000;
1550                break;
1551        default:
1552                smem_size = 0x00100000;
1553                break;
1554        }
1555
1556        cfb->fb.fix.smem_len   = smem_size;
1557        cfb->fb.fix.mmio_len   = MMIO_SIZE;
1558        cfb->fb.screen_base    = cfb->region;
1559
1560#ifdef CONFIG_FB_CYBER2000_DDC
1561        if (cyber2000fb_setup_ddc_bus(cfb) == 0)
1562                cfb->ddc_registered = true;
1563#endif
1564
1565        err = -EINVAL;
1566        if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
1567                          &cyber2000fb_default_mode, 8)) {
1568                printk(KERN_ERR "%s: no valid mode found\n", cfb->fb.fix.id);
1569                goto failed;
1570        }
1571
1572        cfb->fb.var.yres_virtual = cfb->fb.fix.smem_len * 8 /
1573                        (cfb->fb.var.bits_per_pixel * cfb->fb.var.xres_virtual);
1574
1575        if (cfb->fb.var.yres_virtual < cfb->fb.var.yres)
1576                cfb->fb.var.yres_virtual = cfb->fb.var.yres;
1577
1578/*      fb_set_var(&cfb->fb.var, -1, &cfb->fb); */
1579
1580        /*
1581         * Calculate the hsync and vsync frequencies.  Note that
1582         * we split the 1e12 constant up so that we can preserve
1583         * the precision and fit the results into 32-bit registers.
1584         *  (1953125000 * 512 = 1e12)
1585         */
1586        h_sync = 1953125000 / cfb->fb.var.pixclock;
1587        h_sync = h_sync * 512 / (cfb->fb.var.xres + cfb->fb.var.left_margin +
1588                 cfb->fb.var.right_margin + cfb->fb.var.hsync_len);
1589        v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin +
1590                 cfb->fb.var.lower_margin + cfb->fb.var.vsync_len);
1591
1592        printk(KERN_INFO "%s: %dKiB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
1593                cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10,
1594                cfb->fb.var.xres, cfb->fb.var.yres,
1595                h_sync / 1000, h_sync % 1000, v_sync);
1596
1597        err = cyber2000fb_i2c_register(cfb);
1598        if (err)
1599                goto failed;
1600
1601        err = register_framebuffer(&cfb->fb);
1602        if (err)
1603                cyber2000fb_i2c_unregister(cfb);
1604
1605failed:
1606#ifdef CONFIG_FB_CYBER2000_DDC
1607        if (err && cfb->ddc_registered)
1608                i2c_del_adapter(&cfb->ddc_adapter);
1609#endif
1610        return err;
1611}
1612
1613static void cyberpro_common_remove(struct cfb_info *cfb)
1614{
1615        unregister_framebuffer(&cfb->fb);
1616#ifdef CONFIG_FB_CYBER2000_DDC
1617        if (cfb->ddc_registered)
1618                i2c_del_adapter(&cfb->ddc_adapter);
1619#endif
1620        cyber2000fb_i2c_unregister(cfb);
1621}
1622
1623static void cyberpro_common_resume(struct cfb_info *cfb)
1624{
1625        cyberpro_init_hw(cfb);
1626
1627        /*
1628         * Reprogram the MEM_CTL1 and MEM_CTL2 registers
1629         */
1630        cyber2000_grphw(EXT_MEM_CTL1, cfb->mem_ctl1, cfb);
1631        cyber2000_grphw(EXT_MEM_CTL2, cfb->mem_ctl2, cfb);
1632
1633        /*
1634         * Restore the old video mode and the palette.
1635         * We also need to tell fbcon to redraw the console.
1636         */
1637        cyber2000fb_set_par(&cfb->fb);
1638}
1639
1640/*
1641 * We need to wake up the CyberPro, and make sure its in linear memory
1642 * mode.  Unfortunately, this is specific to the platform and card that
1643 * we are running on.
1644 *
1645 * On x86 and ARM, should we be initialising the CyberPro first via the
1646 * IO registers, and then the MMIO registers to catch all cases?  Can we
1647 * end up in the situation where the chip is in MMIO mode, but not awake
1648 * on an x86 system?
1649 */
1650static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
1651{
1652        unsigned char val;
1653
1654#if defined(__sparc_v9__)
1655#error "You lose, consult DaveM."
1656#elif defined(__sparc__)
1657        /*
1658         * SPARC does not have an "outb" instruction, so we generate
1659         * I/O cycles storing into a reserved memory space at
1660         * physical address 0x3000000
1661         */
1662        unsigned char __iomem *iop;
1663
1664        iop = ioremap(0x3000000, 0x5000);
1665        if (iop == NULL) {
1666                printk(KERN_ERR "iga5000: cannot map I/O\n");
1667                return -ENOMEM;
1668        }
1669
1670        writeb(0x18, iop + 0x46e8);
1671        writeb(0x01, iop + 0x102);
1672        writeb(0x08, iop + 0x46e8);
1673        writeb(EXT_BIU_MISC, iop + 0x3ce);
1674        writeb(EXT_BIU_MISC_LIN_ENABLE, iop + 0x3cf);
1675
1676        iounmap(iop);
1677#else
1678        /*
1679         * Most other machine types are "normal", so
1680         * we use the standard IO-based wakeup.
1681         */
1682        outb(0x18, 0x46e8);
1683        outb(0x01, 0x102);
1684        outb(0x08, 0x46e8);
1685        outb(EXT_BIU_MISC, 0x3ce);
1686        outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
1687#endif
1688
1689        /*
1690         * Allow the CyberPro to accept PCI burst accesses
1691         */
1692        if (cfb->id == ID_CYBERPRO_2010) {
1693                printk(KERN_INFO "%s: NOT enabling PCI bursts\n",
1694                       cfb->fb.fix.id);
1695        } else {
1696                val = cyber2000_grphr(EXT_BUS_CTL, cfb);
1697                if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
1698                        printk(KERN_INFO "%s: enabling PCI bursts\n",
1699                                cfb->fb.fix.id);
1700
1701                        val |= EXT_BUS_CTL_PCIBURST_WRITE;
1702
1703                        if (cfb->id == ID_CYBERPRO_5000)
1704                                val |= EXT_BUS_CTL_PCIBURST_READ;
1705
1706                        cyber2000_grphw(EXT_BUS_CTL, val, cfb);
1707                }
1708        }
1709
1710        return 0;
1711}
1712
1713static int cyberpro_pci_probe(struct pci_dev *dev,
1714                              const struct pci_device_id *id)
1715{
1716        struct cfb_info *cfb;
1717        char name[16];
1718        int err;
1719
1720        sprintf(name, "CyberPro%4X", id->device);
1721
1722        err = pci_enable_device(dev);
1723        if (err)
1724                return err;
1725
1726        err = -ENOMEM;
1727        cfb = cyberpro_alloc_fb_info(id->driver_data, name);
1728        if (!cfb)
1729                goto failed_release;
1730
1731        err = pci_request_regions(dev, cfb->fb.fix.id);
1732        if (err)
1733                goto failed_regions;
1734
1735        cfb->irq = dev->irq;
1736        cfb->region = pci_ioremap_bar(dev, 0);
1737        if (!cfb->region) {
1738                err = -ENOMEM;
1739                goto failed_ioremap;
1740        }
1741
1742        cfb->regs = cfb->region + MMIO_OFFSET;
1743        cfb->fb.device = &dev->dev;
1744        cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
1745        cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
1746
1747        /*
1748         * Bring up the hardware.  This is expected to enable access
1749         * to the linear memory region, and allow access to the memory
1750         * mapped registers.  Also, mem_ctl1 and mem_ctl2 must be
1751         * initialised.
1752         */
1753        err = cyberpro_pci_enable_mmio(cfb);
1754        if (err)
1755                goto failed;
1756
1757        /*
1758         * Use MCLK from BIOS. FIXME: what about hotplug?
1759         */
1760        cfb->mclk_mult = cyber2000_grphr(EXT_MCLK_MULT, cfb);
1761        cfb->mclk_div  = cyber2000_grphr(EXT_MCLK_DIV, cfb);
1762
1763#ifdef __arm__
1764        /*
1765         * MCLK on the NetWinder and the Shark is fixed at 75MHz
1766         */
1767        if (machine_is_netwinder()) {
1768                cfb->mclk_mult = 0xdb;
1769                cfb->mclk_div  = 0x54;
1770        }
1771#endif
1772
1773        err = cyberpro_common_probe(cfb);
1774        if (err)
1775                goto failed;
1776
1777        /*
1778         * Our driver data
1779         */
1780        pci_set_drvdata(dev, cfb);
1781        if (int_cfb_info == NULL)
1782                int_cfb_info = cfb;
1783
1784        return 0;
1785
1786failed:
1787        iounmap(cfb->region);
1788failed_ioremap:
1789        pci_release_regions(dev);
1790failed_regions:
1791        cyberpro_free_fb_info(cfb);
1792failed_release:
1793        return err;
1794}
1795
1796static void cyberpro_pci_remove(struct pci_dev *dev)
1797{
1798        struct cfb_info *cfb = pci_get_drvdata(dev);
1799
1800        if (cfb) {
1801                cyberpro_common_remove(cfb);
1802                iounmap(cfb->region);
1803                cyberpro_free_fb_info(cfb);
1804
1805                if (cfb == int_cfb_info)
1806                        int_cfb_info = NULL;
1807
1808                pci_release_regions(dev);
1809        }
1810}
1811
1812static int cyberpro_pci_suspend(struct pci_dev *dev, pm_message_t state)
1813{
1814        return 0;
1815}
1816
1817/*
1818 * Re-initialise the CyberPro hardware
1819 */
1820static int cyberpro_pci_resume(struct pci_dev *dev)
1821{
1822        struct cfb_info *cfb = pci_get_drvdata(dev);
1823
1824        if (cfb) {
1825                cyberpro_pci_enable_mmio(cfb);
1826                cyberpro_common_resume(cfb);
1827        }
1828
1829        return 0;
1830}
1831
1832static struct pci_device_id cyberpro_pci_table[] = {
1833/*      Not yet
1834 *      { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
1835 *              PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
1836 */
1837        { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
1838                PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
1839        { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
1840                PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2010 },
1841        { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000,
1842                PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_5000 },
1843        { 0, }
1844};
1845
1846MODULE_DEVICE_TABLE(pci, cyberpro_pci_table);
1847
1848static struct pci_driver cyberpro_driver = {
1849        .name           = "CyberPro",
1850        .probe          = cyberpro_pci_probe,
1851        .remove         = cyberpro_pci_remove,
1852        .suspend        = cyberpro_pci_suspend,
1853        .resume         = cyberpro_pci_resume,
1854        .id_table       = cyberpro_pci_table
1855};
1856
1857/*
1858 * I don't think we can use the "module_init" stuff here because
1859 * the fbcon stuff may not be initialised yet.  Hence the #ifdef
1860 * around module_init.
1861 *
1862 * Tony: "module_init" is now required
1863 */
1864static int __init cyber2000fb_init(void)
1865{
1866        int ret = -1, err;
1867
1868#ifndef MODULE
1869        char *option = NULL;
1870
1871        if (fb_get_options("cyber2000fb", &option))
1872                return -ENODEV;
1873        cyber2000fb_setup(option);
1874#endif
1875
1876        err = pci_register_driver(&cyberpro_driver);
1877        if (!err)
1878                ret = 0;
1879
1880        return ret ? err : 0;
1881}
1882module_init(cyber2000fb_init);
1883
1884static void __exit cyberpro_exit(void)
1885{
1886        pci_unregister_driver(&cyberpro_driver);
1887}
1888module_exit(cyberpro_exit);
1889
1890MODULE_AUTHOR("Russell King");
1891MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
1892MODULE_LICENSE("GPL");
1893