linux/drivers/video/aty/atyfb_base.c
<<
>>
Prefs
   1/*
   2 *  ATI Frame Buffer Device Driver Core
   3 *
   4 *      Copyright (C) 2004  Alex Kern <alex.kern@gmx.de>
   5 *      Copyright (C) 1997-2001  Geert Uytterhoeven
   6 *      Copyright (C) 1998  Bernd Harries
   7 *      Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
   8 *
   9 *  This driver supports the following ATI graphics chips:
  10 *    - ATI Mach64
  11 *
  12 *  To do: add support for
  13 *    - ATI Rage128 (from aty128fb.c)
  14 *    - ATI Radeon (from radeonfb.c)
  15 *
  16 *  This driver is partly based on the PowerMac console driver:
  17 *
  18 *      Copyright (C) 1996 Paul Mackerras
  19 *
  20 *  and on the PowerMac ATI/mach64 display driver:
  21 *
  22 *      Copyright (C) 1997 Michael AK Tesch
  23 *
  24 *            with work by Jon Howell
  25 *                         Harry AC Eaton
  26 *                         Anthony Tong <atong@uiuc.edu>
  27 *
  28 *  Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
  29 *  Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
  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 for
  33 *  more details.
  34 *
  35 *  Many thanks to Nitya from ATI devrel for support and patience !
  36 */
  37
  38/******************************************************************************
  39
  40  TODO:
  41
  42    - cursor support on all cards and all ramdacs.
  43    - cursor parameters controlable via ioctl()s.
  44    - guess PLL and MCLK based on the original PLL register values initialized
  45      by Open Firmware (if they are initialized). BIOS is done
  46
  47    (Anyone with Mac to help with this?)
  48
  49******************************************************************************/
  50
  51
  52#include <linux/module.h>
  53#include <linux/moduleparam.h>
  54#include <linux/kernel.h>
  55#include <linux/errno.h>
  56#include <linux/string.h>
  57#include <linux/mm.h>
  58#include <linux/slab.h>
  59#include <linux/vmalloc.h>
  60#include <linux/delay.h>
  61#include <linux/console.h>
  62#include <linux/fb.h>
  63#include <linux/init.h>
  64#include <linux/pci.h>
  65#include <linux/interrupt.h>
  66#include <linux/spinlock.h>
  67#include <linux/wait.h>
  68#include <linux/backlight.h>
  69
  70#include <asm/io.h>
  71#include <linux/uaccess.h>
  72
  73#include <video/mach64.h>
  74#include "atyfb.h"
  75#include "ati_ids.h"
  76
  77#ifdef __powerpc__
  78#include <asm/machdep.h>
  79#include <asm/prom.h>
  80#include "../macmodes.h"
  81#endif
  82#ifdef __sparc__
  83#include <asm/fbio.h>
  84#include <asm/oplib.h>
  85#include <asm/prom.h>
  86#endif
  87
  88#ifdef CONFIG_ADB_PMU
  89#include <linux/adb.h>
  90#include <linux/pmu.h>
  91#endif
  92#ifdef CONFIG_BOOTX_TEXT
  93#include <asm/btext.h>
  94#endif
  95#ifdef CONFIG_PMAC_BACKLIGHT
  96#include <asm/backlight.h>
  97#endif
  98#ifdef CONFIG_MTRR
  99#include <asm/mtrr.h>
 100#endif
 101
 102/*
 103 * Debug flags.
 104 */
 105#undef DEBUG
 106/*#define DEBUG*/
 107
 108/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
 109/*  - must be large enough to catch all GUI-Regs   */
 110/*  - must be aligned to a PAGE boundary           */
 111#define GUI_RESERVE     (1 * PAGE_SIZE)
 112
 113/* FIXME: remove the FAIL definition */
 114#define FAIL(msg) do { \
 115        if (!(var->activate & FB_ACTIVATE_TEST)) \
 116                printk(KERN_CRIT "atyfb: " msg "\n"); \
 117        return -EINVAL; \
 118} while (0)
 119#define FAIL_MAX(msg, x, _max_) do { \
 120        if (x > _max_) { \
 121                if (!(var->activate & FB_ACTIVATE_TEST)) \
 122                        printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
 123                return -EINVAL; \
 124        } \
 125} while (0)
 126#ifdef DEBUG
 127#define DPRINTK(fmt, args...)   printk(KERN_DEBUG "atyfb: " fmt, ## args)
 128#else
 129#define DPRINTK(fmt, args...)
 130#endif
 131
 132#define PRINTKI(fmt, args...)   printk(KERN_INFO "atyfb: " fmt, ## args)
 133#define PRINTKE(fmt, args...)    printk(KERN_ERR "atyfb: " fmt, ## args)
 134
 135#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \
 136defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)
 137static const u32 lt_lcd_regs[] = {
 138        CONFIG_PANEL_LG,
 139        LCD_GEN_CNTL_LG,
 140        DSTN_CONTROL_LG,
 141        HFB_PITCH_ADDR_LG,
 142        HORZ_STRETCHING_LG,
 143        VERT_STRETCHING_LG,
 144        0, /* EXT_VERT_STRETCH */
 145        LT_GIO_LG,
 146        POWER_MANAGEMENT_LG
 147};
 148
 149void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
 150{
 151        if (M64_HAS(LT_LCD_REGS)) {
 152                aty_st_le32(lt_lcd_regs[index], val, par);
 153        } else {
 154                unsigned long temp;
 155
 156                /* write addr byte */
 157                temp = aty_ld_le32(LCD_INDEX, par);
 158                aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
 159                /* write the register value */
 160                aty_st_le32(LCD_DATA, val, par);
 161        }
 162}
 163
 164u32 aty_ld_lcd(int index, const struct atyfb_par *par)
 165{
 166        if (M64_HAS(LT_LCD_REGS)) {
 167                return aty_ld_le32(lt_lcd_regs[index], par);
 168        } else {
 169                unsigned long temp;
 170
 171                /* write addr byte */
 172                temp = aty_ld_le32(LCD_INDEX, par);
 173                aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
 174                /* read the register value */
 175                return aty_ld_le32(LCD_DATA, par);
 176        }
 177}
 178#endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */
 179
 180#ifdef CONFIG_FB_ATY_GENERIC_LCD
 181/*
 182 * ATIReduceRatio --
 183 *
 184 * Reduce a fraction by factoring out the largest common divider of the
 185 * fraction's numerator and denominator.
 186 */
 187static void ATIReduceRatio(int *Numerator, int *Denominator)
 188{
 189    int Multiplier, Divider, Remainder;
 190
 191    Multiplier = *Numerator;
 192    Divider = *Denominator;
 193
 194    while ((Remainder = Multiplier % Divider))
 195    {
 196        Multiplier = Divider;
 197        Divider = Remainder;
 198    }
 199
 200    *Numerator /= Divider;
 201    *Denominator /= Divider;
 202}
 203#endif
 204    /*
 205     *  The Hardware parameters for each card
 206     */
 207
 208struct pci_mmap_map {
 209        unsigned long voff;
 210        unsigned long poff;
 211        unsigned long size;
 212        unsigned long prot_flag;
 213        unsigned long prot_mask;
 214};
 215
 216static struct fb_fix_screeninfo atyfb_fix __devinitdata = {
 217        .id             = "ATY Mach64",
 218        .type           = FB_TYPE_PACKED_PIXELS,
 219        .visual         = FB_VISUAL_PSEUDOCOLOR,
 220        .xpanstep       = 8,
 221        .ypanstep       = 1,
 222};
 223
 224    /*
 225     *  Frame buffer device API
 226     */
 227
 228static int atyfb_open(struct fb_info *info, int user);
 229static int atyfb_release(struct fb_info *info, int user);
 230static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
 231static int atyfb_set_par(struct fb_info *info);
 232static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 233        u_int transp, struct fb_info *info);
 234static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
 235static int atyfb_blank(int blank, struct fb_info *info);
 236static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
 237#ifdef __sparc__
 238static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
 239#endif
 240static int atyfb_sync(struct fb_info *info);
 241
 242    /*
 243     *  Internal routines
 244     */
 245
 246static int aty_init(struct fb_info *info);
 247static void aty_resume_chip(struct fb_info *info);
 248#ifdef CONFIG_ATARI
 249static int store_video_par(char *videopar, unsigned char m64_num);
 250#endif
 251
 252static struct crtc saved_crtc;
 253static union aty_pll saved_pll;
 254static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
 255
 256static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
 257static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc);
 258static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var);
 259static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);
 260#ifdef CONFIG_PPC
 261static int read_aty_sense(const struct atyfb_par *par);
 262#endif
 263
 264
 265    /*
 266     *  Interface used by the world
 267     */
 268
 269static struct fb_var_screeninfo default_var = {
 270        /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
 271        640, 480, 640, 480, 0, 0, 8, 0,
 272        {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
 273        0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
 274        0, FB_VMODE_NONINTERLACED
 275};
 276
 277static struct fb_videomode defmode = {
 278        /* 640x480 @ 60 Hz, 31.5 kHz hsync */
 279        NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
 280        0, FB_VMODE_NONINTERLACED
 281};
 282
 283static struct fb_ops atyfb_ops = {
 284        .owner          = THIS_MODULE,
 285        .fb_open        = atyfb_open,
 286        .fb_release     = atyfb_release,
 287        .fb_check_var   = atyfb_check_var,
 288        .fb_set_par     = atyfb_set_par,
 289        .fb_setcolreg   = atyfb_setcolreg,
 290        .fb_pan_display = atyfb_pan_display,
 291        .fb_blank       = atyfb_blank,
 292        .fb_ioctl       = atyfb_ioctl,
 293        .fb_fillrect    = atyfb_fillrect,
 294        .fb_copyarea    = atyfb_copyarea,
 295        .fb_imageblit   = atyfb_imageblit,
 296#ifdef __sparc__
 297        .fb_mmap        = atyfb_mmap,
 298#endif
 299        .fb_sync        = atyfb_sync,
 300};
 301
 302static int noaccel;
 303#ifdef CONFIG_MTRR
 304static int nomtrr;
 305#endif
 306static int vram;
 307static int pll;
 308static int mclk;
 309static int xclk;
 310static int comp_sync __devinitdata = -1;
 311static char *mode;
 312
 313#ifdef CONFIG_PMAC_BACKLIGHT
 314static int backlight __devinitdata = 1;
 315#else
 316static int backlight __devinitdata = 0;
 317#endif
 318
 319#ifdef CONFIG_PPC
 320static int default_vmode __devinitdata = VMODE_CHOOSE;
 321static int default_cmode __devinitdata = CMODE_CHOOSE;
 322
 323module_param_named(vmode, default_vmode, int, 0);
 324MODULE_PARM_DESC(vmode, "int: video mode for mac");
 325module_param_named(cmode, default_cmode, int, 0);
 326MODULE_PARM_DESC(cmode, "int: color mode for mac");
 327#endif
 328
 329#ifdef CONFIG_ATARI
 330static unsigned int mach64_count __devinitdata = 0;
 331static unsigned long phys_vmembase[FB_MAX] __devinitdata = { 0, };
 332static unsigned long phys_size[FB_MAX] __devinitdata = { 0, };
 333static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, };
 334#endif
 335
 336/* top -> down is an evolution of mach64 chipset, any corrections? */
 337#define ATI_CHIP_88800GX   (M64F_GX)
 338#define ATI_CHIP_88800CX   (M64F_GX)
 339
 340#define ATI_CHIP_264CT     (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
 341#define ATI_CHIP_264ET     (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
 342
 343#define ATI_CHIP_264VT     (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO)
 344#define ATI_CHIP_264GT     (M64F_GT | M64F_INTEGRATED               | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)
 345
 346#define ATI_CHIP_264VTB    (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
 347#define ATI_CHIP_264VT3    (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
 348#define ATI_CHIP_264VT4    (M64F_VT | M64F_INTEGRATED               | M64F_GTB_DSP)
 349
 350/* FIXME what is this chip? */
 351#define ATI_CHIP_264LT     (M64F_GT | M64F_INTEGRATED               | M64F_GTB_DSP)
 352
 353/* make sets shorter */
 354#define ATI_MODERN_SET     (M64F_GT | M64F_INTEGRATED               | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)
 355
 356#define ATI_CHIP_264GTB    (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
 357/*#define ATI_CHIP_264GTDVD  ?*/
 358#define ATI_CHIP_264LTG    (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
 359
 360#define ATI_CHIP_264GT2C   (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)
 361#define ATI_CHIP_264GTPRO  (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
 362#define ATI_CHIP_264LTPRO  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
 363
 364#define ATI_CHIP_264XL     (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4)
 365#define ATI_CHIP_MOBILITY  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS)
 366
 367static struct {
 368        u16 pci_id;
 369        const char *name;
 370        int pll, mclk, xclk, ecp_max;
 371        u32 features;
 372} aty_chips[] __devinitdata = {
 373#ifdef CONFIG_FB_ATY_GX
 374        /* Mach64 GX */
 375        { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX },
 376        { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX },
 377#endif /* CONFIG_FB_ATY_GX */
 378
 379#ifdef CONFIG_FB_ATY_CT
 380        { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT },
 381        { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET },
 382
 383        /* FIXME what is this chip? */
 384        { PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT },
 385
 386        { PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT },
 387        { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT },
 388
 389        { PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 },
 390        { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB },
 391
 392        { PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
 393
 394        { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 },
 395
 396        { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
 397        { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
 398        { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
 399        { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
 400
 401        { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
 402        { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
 403        { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
 404        { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
 405        { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
 406
 407        { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO },
 408        { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
 409        { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
 410        { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1024x768 },
 411        { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
 412
 413        { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
 414        { PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
 415        { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
 416        { PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
 417        { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
 418        { PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL },
 419
 420        { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
 421        { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
 422        { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
 423        { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
 424#endif /* CONFIG_FB_ATY_CT */
 425};
 426
 427/* can not fail */
 428static int __devinit correct_chipset(struct atyfb_par *par)
 429{
 430        u8 rev;
 431        u16 type;
 432        u32 chip_id;
 433        const char *name;
 434        int i;
 435
 436        for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
 437                if (par->pci_id == aty_chips[i].pci_id)
 438                        break;
 439
 440        name = aty_chips[i].name;
 441        par->pll_limits.pll_max = aty_chips[i].pll;
 442        par->pll_limits.mclk = aty_chips[i].mclk;
 443        par->pll_limits.xclk = aty_chips[i].xclk;
 444        par->pll_limits.ecp_max = aty_chips[i].ecp_max;
 445        par->features = aty_chips[i].features;
 446
 447        chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
 448        type = chip_id & CFG_CHIP_TYPE;
 449        rev = (chip_id & CFG_CHIP_REV) >> 24;
 450
 451        switch(par->pci_id) {
 452#ifdef CONFIG_FB_ATY_GX
 453        case PCI_CHIP_MACH64GX:
 454                if(type != 0x00d7)
 455                        return -ENODEV;
 456                break;
 457        case PCI_CHIP_MACH64CX:
 458                if(type != 0x0057)
 459                        return -ENODEV;
 460                break;
 461#endif
 462#ifdef CONFIG_FB_ATY_CT
 463        case PCI_CHIP_MACH64VT:
 464                switch (rev & 0x07) {
 465                case 0x00:
 466                        switch (rev & 0xc0) {
 467                        case 0x00:
 468                                name = "ATI264VT (A3) (Mach64 VT)";
 469                                par->pll_limits.pll_max = 170;
 470                                par->pll_limits.mclk = 67;
 471                                par->pll_limits.xclk = 67;
 472                                par->pll_limits.ecp_max = 80;
 473                                par->features = ATI_CHIP_264VT;
 474                                break;
 475                        case 0x40:
 476                                name = "ATI264VT2 (A4) (Mach64 VT)";
 477                                par->pll_limits.pll_max = 200;
 478                                par->pll_limits.mclk = 67;
 479                                par->pll_limits.xclk = 67;
 480                                par->pll_limits.ecp_max = 80;
 481                                par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
 482                                break;
 483                        }
 484                        break;
 485                case 0x01:
 486                        name = "ATI264VT3 (B1) (Mach64 VT)";
 487                        par->pll_limits.pll_max = 200;
 488                        par->pll_limits.mclk = 67;
 489                        par->pll_limits.xclk = 67;
 490                        par->pll_limits.ecp_max = 80;
 491                        par->features = ATI_CHIP_264VTB;
 492                        break;
 493                case 0x02:
 494                        name = "ATI264VT3 (B2) (Mach64 VT)";
 495                        par->pll_limits.pll_max = 200;
 496                        par->pll_limits.mclk = 67;
 497                        par->pll_limits.xclk = 67;
 498                        par->pll_limits.ecp_max = 80;
 499                        par->features = ATI_CHIP_264VT3;
 500                        break;
 501                }
 502                break;
 503        case PCI_CHIP_MACH64GT:
 504                switch (rev & 0x07) {
 505                case 0x01:
 506                        name = "3D RAGE II (Mach64 GT)";
 507                        par->pll_limits.pll_max = 170;
 508                        par->pll_limits.mclk = 67;
 509                        par->pll_limits.xclk = 67;
 510                        par->pll_limits.ecp_max = 80;
 511                        par->features = ATI_CHIP_264GTB;
 512                        break;
 513                case 0x02:
 514                        name = "3D RAGE II+ (Mach64 GT)";
 515                        par->pll_limits.pll_max = 200;
 516                        par->pll_limits.mclk = 67;
 517                        par->pll_limits.xclk = 67;
 518                        par->pll_limits.ecp_max = 100;
 519                        par->features = ATI_CHIP_264GTB;
 520                        break;
 521                }
 522                break;
 523#endif
 524        }
 525
 526        PRINTKI("%s [0x%04x rev 0x%02x]\n", name, type, rev);
 527        return 0;
 528}
 529
 530static char ram_dram[] __devinitdata = "DRAM";
 531static char ram_resv[] __devinitdata = "RESV";
 532#ifdef CONFIG_FB_ATY_GX
 533static char ram_vram[] __devinitdata = "VRAM";
 534#endif /* CONFIG_FB_ATY_GX */
 535#ifdef CONFIG_FB_ATY_CT
 536static char ram_edo[] __devinitdata = "EDO";
 537static char ram_sdram[] __devinitdata = "SDRAM (1:1)";
 538static char ram_sgram[] __devinitdata = "SGRAM (1:1)";
 539static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)";
 540static char ram_off[] __devinitdata = "OFF";
 541#endif /* CONFIG_FB_ATY_CT */
 542
 543
 544#ifdef CONFIG_FB_ATY_GX
 545static char *aty_gx_ram[8] __devinitdata = {
 546        ram_dram, ram_vram, ram_vram, ram_dram,
 547        ram_dram, ram_vram, ram_vram, ram_resv
 548};
 549#endif /* CONFIG_FB_ATY_GX */
 550
 551#ifdef CONFIG_FB_ATY_CT
 552static char *aty_ct_ram[8] __devinitdata = {
 553        ram_off, ram_dram, ram_edo, ram_edo,
 554        ram_sdram, ram_sgram, ram_sdram32, ram_resv
 555};
 556#endif /* CONFIG_FB_ATY_CT */
 557
 558static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *par)
 559{
 560        u32 pixclock = var->pixclock;
 561#ifdef CONFIG_FB_ATY_GENERIC_LCD
 562        u32 lcd_on_off;
 563        par->pll.ct.xres = 0;
 564        if (par->lcd_table != 0) {
 565                lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);
 566                if(lcd_on_off & LCD_ON) {
 567                        par->pll.ct.xres = var->xres;
 568                        pixclock = par->lcd_pixclock;
 569                }
 570        }
 571#endif
 572        return pixclock;
 573}
 574
 575#if defined(CONFIG_PPC)
 576
 577/*
 578 *  Apple monitor sense
 579 */
 580
 581static int __devinit read_aty_sense(const struct atyfb_par *par)
 582{
 583        int sense, i;
 584
 585        aty_st_le32(GP_IO, 0x31003100, par); /* drive outputs high */
 586        __delay(200);
 587        aty_st_le32(GP_IO, 0, par); /* turn off outputs */
 588        __delay(2000);
 589        i = aty_ld_le32(GP_IO, par); /* get primary sense value */
 590        sense = ((i & 0x3000) >> 3) | (i & 0x100);
 591
 592        /* drive each sense line low in turn and collect the other 2 */
 593        aty_st_le32(GP_IO, 0x20000000, par); /* drive A low */
 594        __delay(2000);
 595        i = aty_ld_le32(GP_IO, par);
 596        sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
 597        aty_st_le32(GP_IO, 0x20002000, par); /* drive A high again */
 598        __delay(200);
 599
 600        aty_st_le32(GP_IO, 0x10000000, par); /* drive B low */
 601        __delay(2000);
 602        i = aty_ld_le32(GP_IO, par);
 603        sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
 604        aty_st_le32(GP_IO, 0x10001000, par); /* drive B high again */
 605        __delay(200);
 606
 607        aty_st_le32(GP_IO, 0x01000000, par); /* drive C low */
 608        __delay(2000);
 609        sense |= (aty_ld_le32(GP_IO, par) & 0x3000) >> 12;
 610        aty_st_le32(GP_IO, 0, par); /* turn off outputs */
 611        return sense;
 612}
 613
 614#endif /* defined(CONFIG_PPC) */
 615
 616/* ------------------------------------------------------------------------- */
 617
 618/*
 619 *  CRTC programming
 620 */
 621
 622static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
 623{
 624#ifdef CONFIG_FB_ATY_GENERIC_LCD
 625        if (par->lcd_table != 0) {
 626                if(!M64_HAS(LT_LCD_REGS)) {
 627                    crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
 628                    aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
 629                }
 630                crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par);
 631                crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
 632
 633
 634                /* switch to non shadow registers */
 635                aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
 636                    ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
 637
 638                /* save stretching */
 639                crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
 640                crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);
 641                if (!M64_HAS(LT_LCD_REGS))
 642                        crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);
 643        }
 644#endif
 645        crtc->h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
 646        crtc->h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
 647        crtc->v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
 648        crtc->v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
 649        crtc->vline_crnt_vline = aty_ld_le32(CRTC_VLINE_CRNT_VLINE, par);
 650        crtc->off_pitch = aty_ld_le32(CRTC_OFF_PITCH, par);
 651        crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
 652
 653#ifdef CONFIG_FB_ATY_GENERIC_LCD
 654        if (par->lcd_table != 0) {
 655                /* switch to shadow registers */
 656                aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
 657                        SHADOW_EN | SHADOW_RW_EN, par);
 658
 659                crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
 660                crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
 661                crtc->shadow_v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
 662                crtc->shadow_v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
 663
 664                aty_st_le32(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
 665        }
 666#endif /* CONFIG_FB_ATY_GENERIC_LCD */
 667}
 668
 669static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
 670{
 671#ifdef CONFIG_FB_ATY_GENERIC_LCD
 672        if (par->lcd_table != 0) {
 673                /* stop CRTC */
 674                aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
 675
 676                /* update non-shadow registers first */
 677                aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par);
 678                aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
 679                        ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
 680
 681                /* temporarily disable stretching */
 682                aty_st_lcd(HORZ_STRETCHING,
 683                        crtc->horz_stretching &
 684                        ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);
 685                aty_st_lcd(VERT_STRETCHING,
 686                        crtc->vert_stretching &
 687                        ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
 688                        VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
 689        }
 690#endif
 691        /* turn off CRT */
 692        aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~CRTC_EN, par);
 693
 694        DPRINTK("setting up CRTC\n");
 695        DPRINTK("set primary CRT to %ix%i %c%c composite %c\n",
 696            ((((crtc->h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->v_tot_disp>>16) & 0x7ff) + 1),
 697            (crtc->h_sync_strt_wid & 0x200000)?'N':'P', (crtc->v_sync_strt_wid & 0x200000)?'N':'P',
 698            (crtc->gen_cntl & CRTC_CSYNC_EN)?'P':'N');
 699
 700        DPRINTK("CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp);
 701        DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid);
 702        DPRINTK("CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp);
 703        DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid);
 704        DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);
 705        DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);
 706        DPRINTK("CRTC_GEN_CNTL: %x\n",crtc->gen_cntl);
 707
 708        aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);
 709        aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);
 710        aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);
 711        aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);
 712        aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);
 713        aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);
 714
 715        aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);
 716#if 0
 717        FIXME
 718        if (par->accel_flags & FB_ACCELF_TEXT)
 719                aty_init_engine(par, info);
 720#endif
 721#ifdef CONFIG_FB_ATY_GENERIC_LCD
 722        /* after setting the CRTC registers we should set the LCD registers. */
 723        if (par->lcd_table != 0) {
 724                /* switch to shadow registers */
 725                aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
 726                        (SHADOW_EN | SHADOW_RW_EN), par);
 727
 728                DPRINTK("set shadow CRT to %ix%i %c%c\n",
 729                    ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1),
 730                    (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P');
 731
 732                DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", crtc->shadow_h_tot_disp);
 733                DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", crtc->shadow_h_sync_strt_wid);
 734                DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", crtc->shadow_v_tot_disp);
 735                DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", crtc->shadow_v_sync_strt_wid);
 736
 737                aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);
 738                aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);
 739                aty_st_le32(CRTC_V_TOTAL_DISP, crtc->shadow_v_tot_disp, par);
 740                aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->shadow_v_sync_strt_wid, par);
 741
 742                /* restore CRTC selection & shadow state and enable stretching */
 743                DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);
 744                DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);
 745                DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);
 746                if(!M64_HAS(LT_LCD_REGS))
 747                    DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
 748
 749                aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
 750                aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);
 751                aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);
 752                if(!M64_HAS(LT_LCD_REGS)) {
 753                    aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
 754                    aty_ld_le32(LCD_INDEX, par);
 755                    aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
 756                }
 757        }
 758#endif /* CONFIG_FB_ATY_GENERIC_LCD */
 759}
 760
 761static int aty_var_to_crtc(const struct fb_info *info,
 762        const struct fb_var_screeninfo *var, struct crtc *crtc)
 763{
 764        struct atyfb_par *par = (struct atyfb_par *) info->par;
 765        u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
 766        u32 sync, vmode, vdisplay;
 767        u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
 768        u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
 769        u32 pix_width, dp_pix_width, dp_chain_mask;
 770
 771        /* input */
 772        xres = var->xres;
 773        yres = var->yres;
 774        vxres = var->xres_virtual;
 775        vyres = var->yres_virtual;
 776        xoffset = var->xoffset;
 777        yoffset = var->yoffset;
 778        bpp = var->bits_per_pixel;
 779        if (bpp == 16)
 780                bpp = (var->green.length == 5) ? 15 : 16;
 781        sync = var->sync;
 782        vmode = var->vmode;
 783
 784        /* convert (and round up) and validate */
 785        if (vxres < xres + xoffset)
 786                vxres = xres + xoffset;
 787        h_disp = xres;
 788
 789        if (vyres < yres + yoffset)
 790                vyres = yres + yoffset;
 791        v_disp = yres;
 792
 793        if (bpp <= 8) {
 794                bpp = 8;
 795                pix_width = CRTC_PIX_WIDTH_8BPP;
 796                dp_pix_width =
 797                    HOST_8BPP | SRC_8BPP | DST_8BPP |
 798                    BYTE_ORDER_LSB_TO_MSB;
 799                dp_chain_mask = DP_CHAIN_8BPP;
 800        } else if (bpp <= 15) {
 801                bpp = 16;
 802                pix_width = CRTC_PIX_WIDTH_15BPP;
 803                dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
 804                    BYTE_ORDER_LSB_TO_MSB;
 805                dp_chain_mask = DP_CHAIN_15BPP;
 806        } else if (bpp <= 16) {
 807                bpp = 16;
 808                pix_width = CRTC_PIX_WIDTH_16BPP;
 809                dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
 810                    BYTE_ORDER_LSB_TO_MSB;
 811                dp_chain_mask = DP_CHAIN_16BPP;
 812        } else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
 813                bpp = 24;
 814                pix_width = CRTC_PIX_WIDTH_24BPP;
 815                dp_pix_width =
 816                    HOST_8BPP | SRC_8BPP | DST_8BPP |
 817                    BYTE_ORDER_LSB_TO_MSB;
 818                dp_chain_mask = DP_CHAIN_24BPP;
 819        } else if (bpp <= 32) {
 820                bpp = 32;
 821                pix_width = CRTC_PIX_WIDTH_32BPP;
 822                dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
 823                    BYTE_ORDER_LSB_TO_MSB;
 824                dp_chain_mask = DP_CHAIN_32BPP;
 825        } else
 826                FAIL("invalid bpp");
 827
 828        if (vxres * vyres * bpp / 8 > info->fix.smem_len)
 829                FAIL("not enough video RAM");
 830
 831        h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
 832        v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
 833
 834        if((xres > 1600) || (yres > 1200)) {
 835                FAIL("MACH64 chips are designed for max 1600x1200\n"
 836                "select anoter resolution.");
 837        }
 838        h_sync_strt = h_disp + var->right_margin;
 839        h_sync_end = h_sync_strt + var->hsync_len;
 840        h_sync_dly  = var->right_margin & 7;
 841        h_total = h_sync_end + h_sync_dly + var->left_margin;
 842
 843        v_sync_strt = v_disp + var->lower_margin;
 844        v_sync_end = v_sync_strt + var->vsync_len;
 845        v_total = v_sync_end + var->upper_margin;
 846
 847#ifdef CONFIG_FB_ATY_GENERIC_LCD
 848        if (par->lcd_table != 0) {
 849                if(!M64_HAS(LT_LCD_REGS)) {
 850                    u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
 851                    crtc->lcd_index = lcd_index &
 852                        ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS);
 853                    aty_st_le32(LCD_INDEX, lcd_index, par);
 854                }
 855
 856                if (!M64_HAS(MOBIL_BUS))
 857                        crtc->lcd_index |= CRTC2_DISPLAY_DIS;
 858
 859                crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000;
 860                crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
 861
 862                crtc->lcd_gen_cntl &=
 863                        ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |
 864                        /*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/
 865                        USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
 866                crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;
 867
 868                if((crtc->lcd_gen_cntl & LCD_ON) &&
 869                        ((xres > par->lcd_width) || (yres > par->lcd_height))) {
 870                        /* We cannot display the mode on the LCD. If the CRT is enabled
 871                           we can turn off the LCD.
 872                           If the CRT is off, it isn't a good idea to switch it on; we don't
 873                           know if one is connected. So it's better to fail then.
 874                         */
 875                        if (crtc->lcd_gen_cntl & CRT_ON) {
 876                                if (!(var->activate & FB_ACTIVATE_TEST))
 877                                        PRINTKI("Disable LCD panel, because video mode does not fit.\n");
 878                                crtc->lcd_gen_cntl &= ~LCD_ON;
 879                                /*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
 880                        } else {
 881                                if (!(var->activate & FB_ACTIVATE_TEST))
 882                                        PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
 883                                return -EINVAL;
 884                        }
 885                }
 886        }
 887
 888        if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {
 889                int VScan = 1;
 890                /* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5
 891                const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };
 892                const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 };  */
 893
 894                vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
 895
 896                /* This is horror! When we simulate, say 640x480 on an 800x600
 897                   LCD monitor, the CRTC should be programmed 800x600 values for
 898                   the non visible part, but 640x480 for the visible part.
 899                   This code has been tested on a laptop with it's 1400x1050 LCD
 900                   monitor and a conventional monitor both switched on.
 901                   Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
 902                    works with little glitches also with DOUBLESCAN modes
 903                 */
 904                if (yres < par->lcd_height) {
 905                        VScan = par->lcd_height / yres;
 906                        if(VScan > 1) {
 907                                VScan = 2;
 908                                vmode |= FB_VMODE_DOUBLE;
 909                        }
 910                }
 911
 912                h_sync_strt = h_disp + par->lcd_right_margin;
 913                h_sync_end = h_sync_strt + par->lcd_hsync_len;
 914                h_sync_dly = /*DFP_h_sync_dly[ ( bpp + 1 ) / 3 ]; */par->lcd_hsync_dly;
 915                h_total = h_disp + par->lcd_hblank_len;
 916
 917                v_sync_strt = v_disp + par->lcd_lower_margin / VScan;
 918                v_sync_end = v_sync_strt + par->lcd_vsync_len / VScan;
 919                v_total = v_disp + par->lcd_vblank_len / VScan;
 920        }
 921#endif /* CONFIG_FB_ATY_GENERIC_LCD */
 922
 923        h_disp = (h_disp >> 3) - 1;
 924        h_sync_strt = (h_sync_strt >> 3) - 1;
 925        h_sync_end = (h_sync_end >> 3) - 1;
 926        h_total = (h_total >> 3) - 1;
 927        h_sync_wid = h_sync_end - h_sync_strt;
 928
 929        FAIL_MAX("h_disp too large", h_disp, 0xff);
 930        FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);
 931        /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
 932        if(h_sync_wid > 0x1f)
 933                h_sync_wid = 0x1f;
 934        FAIL_MAX("h_total too large", h_total, 0x1ff);
 935
 936        if (vmode & FB_VMODE_DOUBLE) {
 937                v_disp <<= 1;
 938                v_sync_strt <<= 1;
 939                v_sync_end <<= 1;
 940                v_total <<= 1;
 941        }
 942
 943        vdisplay = yres;
 944#ifdef CONFIG_FB_ATY_GENERIC_LCD
 945        if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON))
 946                vdisplay  = par->lcd_height;
 947#endif
 948
 949        v_disp--;
 950        v_sync_strt--;
 951        v_sync_end--;
 952        v_total--;
 953        v_sync_wid = v_sync_end - v_sync_strt;
 954
 955        FAIL_MAX("v_disp too large", v_disp, 0x7ff);
 956        FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);
 957        /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
 958        if(v_sync_wid > 0x1f)
 959                v_sync_wid = 0x1f;
 960        FAIL_MAX("v_total too large", v_total, 0x7ff);
 961
 962        c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
 963
 964        /* output */
 965        crtc->vxres = vxres;
 966        crtc->vyres = vyres;
 967        crtc->xoffset = xoffset;
 968        crtc->yoffset = yoffset;
 969        crtc->bpp = bpp;
 970        crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
 971        crtc->vline_crnt_vline = 0;
 972
 973        crtc->h_tot_disp = h_total | (h_disp<<16);
 974        crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
 975                ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21);
 976        crtc->v_tot_disp = v_total | (v_disp<<16);
 977        crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
 978
 979        /* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */
 980        crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync;
 981        crtc->gen_cntl |= CRTC_VGA_LINEAR;
 982
 983        /* Enable doublescan mode if requested */
 984        if (vmode & FB_VMODE_DOUBLE)
 985                crtc->gen_cntl |= CRTC_DBL_SCAN_EN;
 986        /* Enable interlaced mode if requested */
 987        if (vmode & FB_VMODE_INTERLACED)
 988                crtc->gen_cntl |= CRTC_INTERLACE_EN;
 989#ifdef CONFIG_FB_ATY_GENERIC_LCD
 990        if (par->lcd_table != 0) {
 991                vdisplay = yres;
 992                if(vmode & FB_VMODE_DOUBLE)
 993                        vdisplay <<= 1;
 994                crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
 995                crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
 996                        /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
 997                        USE_SHADOWED_VEND | USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
 998                crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR/* | LOCK_8DOT*/);
 999
1000                /* MOBILITY M1 tested, FIXME: LT */
1001                crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
1002                if (!M64_HAS(LT_LCD_REGS))
1003                        crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
1004                                ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
1005
1006                crtc->horz_stretching &=
1007                        ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
1008                        HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
1009                if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) {
1010                        do {
1011                                /*
1012                                * The horizontal blender misbehaves when HDisplay is less than a
1013                                * a certain threshold (440 for a 1024-wide panel).  It doesn't
1014                                * stretch such modes enough.  Use pixel replication instead of
1015                                * blending to stretch modes that can be made to exactly fit the
1016                                * panel width.  The undocumented "NoLCDBlend" option allows the
1017                                * pixel-replicated mode to be slightly wider or narrower than the
1018                                * panel width.  It also causes a mode that is exactly half as wide
1019                                * as the panel to be pixel-replicated, rather than blended.
1020                                */
1021                                int HDisplay  = xres & ~7;
1022                                int nStretch  = par->lcd_width / HDisplay;
1023                                int Remainder = par->lcd_width % HDisplay;
1024
1025                                if ((!Remainder && ((nStretch > 2))) ||
1026                                        (((HDisplay * 16) / par->lcd_width) < 7)) {
1027                                        static const char StretchLoops[] = {10, 12, 13, 15, 16};
1028                                        int horz_stretch_loop = -1, BestRemainder;
1029                                        int Numerator = HDisplay, Denominator = par->lcd_width;
1030                                        int Index = 5;
1031                                        ATIReduceRatio(&Numerator, &Denominator);
1032
1033                                        BestRemainder = (Numerator * 16) / Denominator;
1034                                        while (--Index >= 0) {
1035                                                Remainder = ((Denominator - Numerator) * StretchLoops[Index]) %
1036                                                        Denominator;
1037                                                if (Remainder < BestRemainder) {
1038                                                        horz_stretch_loop = Index;
1039                                                        if (!(BestRemainder = Remainder))
1040                                                                break;
1041                                                }
1042                                        }
1043
1044                                        if ((horz_stretch_loop >= 0) && !BestRemainder) {
1045                                                int horz_stretch_ratio = 0, Accumulator = 0;
1046                                                int reuse_previous = 1;
1047
1048                                                Index = StretchLoops[horz_stretch_loop];
1049
1050                                                while (--Index >= 0) {
1051                                                        if (Accumulator > 0)
1052                                                                horz_stretch_ratio |= reuse_previous;
1053                                                        else
1054                                                                Accumulator += Denominator;
1055                                                        Accumulator -= Numerator;
1056                                                        reuse_previous <<= 1;
1057                                                }
1058
1059                                                crtc->horz_stretching |= (HORZ_STRETCH_EN |
1060                                                        ((horz_stretch_loop & HORZ_STRETCH_LOOP) << 16) |
1061                                                        (horz_stretch_ratio & HORZ_STRETCH_RATIO));
1062                                                break;      /* Out of the do { ... } while (0) */
1063                                        }
1064                                }
1065
1066                                crtc->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN |
1067                                        (((HDisplay * (HORZ_STRETCH_BLEND + 1)) / par->lcd_width) & HORZ_STRETCH_BLEND));
1068                        } while (0);
1069                }
1070
1071                if (vdisplay < par->lcd_height && crtc->lcd_gen_cntl & LCD_ON) {
1072                        crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
1073                                (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
1074
1075                        if (!M64_HAS(LT_LCD_REGS) &&
1076                            xres <= (M64_HAS(MOBIL_BUS)?1024:800))
1077                                crtc->ext_vert_stretch |= VERT_STRETCH_MODE;
1078                } else {
1079                        /*
1080                         * Don't use vertical blending if the mode is too wide or not
1081                         * vertically stretched.
1082                         */
1083                        crtc->vert_stretching = 0;
1084                }
1085                /* copy to shadow crtc */
1086                crtc->shadow_h_tot_disp = crtc->h_tot_disp;
1087                crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;
1088                crtc->shadow_v_tot_disp = crtc->v_tot_disp;
1089                crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;
1090        }
1091#endif /* CONFIG_FB_ATY_GENERIC_LCD */
1092
1093        if (M64_HAS(MAGIC_FIFO)) {
1094                /* FIXME: display FIFO low watermark values */
1095                crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_FIFO_LWM);
1096        }
1097        crtc->dp_pix_width = dp_pix_width;
1098        crtc->dp_chain_mask = dp_chain_mask;
1099
1100        return 0;
1101}
1102
1103static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var)
1104{
1105        u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
1106        u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid,
1107            h_sync_pol;
1108        u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
1109        u32 pix_width;
1110        u32 double_scan, interlace;
1111
1112        /* input */
1113        h_total = crtc->h_tot_disp & 0x1ff;
1114        h_disp = (crtc->h_tot_disp >> 16) & 0xff;
1115        h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | ((crtc->h_sync_strt_wid >> 4) & 0x100);
1116        h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7;
1117        h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f;
1118        h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1;
1119        v_total = crtc->v_tot_disp & 0x7ff;
1120        v_disp = (crtc->v_tot_disp >> 16) & 0x7ff;
1121        v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
1122        v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f;
1123        v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1;
1124        c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
1125        pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
1126        double_scan = crtc->gen_cntl & CRTC_DBL_SCAN_EN;
1127        interlace = crtc->gen_cntl & CRTC_INTERLACE_EN;
1128
1129        /* convert */
1130        xres = (h_disp + 1) * 8;
1131        yres = v_disp + 1;
1132        left = (h_total - h_sync_strt - h_sync_wid) * 8 - h_sync_dly;
1133        right = (h_sync_strt - h_disp) * 8 + h_sync_dly;
1134        hslen = h_sync_wid * 8;
1135        upper = v_total - v_sync_strt - v_sync_wid;
1136        lower = v_sync_strt - v_disp;
1137        vslen = v_sync_wid;
1138        sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
1139            (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
1140            (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
1141
1142        switch (pix_width) {
1143#if 0
1144        case CRTC_PIX_WIDTH_4BPP:
1145                bpp = 4;
1146                var->red.offset = 0;
1147                var->red.length = 8;
1148                var->green.offset = 0;
1149                var->green.length = 8;
1150                var->blue.offset = 0;
1151                var->blue.length = 8;
1152                var->transp.offset = 0;
1153                var->transp.length = 0;
1154                break;
1155#endif
1156        case CRTC_PIX_WIDTH_8BPP:
1157                bpp = 8;
1158                var->red.offset = 0;
1159                var->red.length = 8;
1160                var->green.offset = 0;
1161                var->green.length = 8;
1162                var->blue.offset = 0;
1163                var->blue.length = 8;
1164                var->transp.offset = 0;
1165                var->transp.length = 0;
1166                break;
1167        case CRTC_PIX_WIDTH_15BPP:      /* RGB 555 */
1168                bpp = 16;
1169                var->red.offset = 10;
1170                var->red.length = 5;
1171                var->green.offset = 5;
1172                var->green.length = 5;
1173                var->blue.offset = 0;
1174                var->blue.length = 5;
1175                var->transp.offset = 0;
1176                var->transp.length = 0;
1177                break;
1178        case CRTC_PIX_WIDTH_16BPP:      /* RGB 565 */
1179                bpp = 16;
1180                var->red.offset = 11;
1181                var->red.length = 5;
1182                var->green.offset = 5;
1183                var->green.length = 6;
1184                var->blue.offset = 0;
1185                var->blue.length = 5;
1186                var->transp.offset = 0;
1187                var->transp.length = 0;
1188                break;
1189        case CRTC_PIX_WIDTH_24BPP:      /* RGB 888 */
1190                bpp = 24;
1191                var->red.offset = 16;
1192                var->red.length = 8;
1193                var->green.offset = 8;
1194                var->green.length = 8;
1195                var->blue.offset = 0;
1196                var->blue.length = 8;
1197                var->transp.offset = 0;
1198                var->transp.length = 0;
1199                break;
1200        case CRTC_PIX_WIDTH_32BPP:      /* ARGB 8888 */
1201                bpp = 32;
1202                var->red.offset = 16;
1203                var->red.length = 8;
1204                var->green.offset = 8;
1205                var->green.length = 8;
1206                var->blue.offset = 0;
1207                var->blue.length = 8;
1208                var->transp.offset = 24;
1209                var->transp.length = 8;
1210                break;
1211        default:
1212                PRINTKE("Invalid pixel width\n");
1213                return -EINVAL;
1214        }
1215
1216        /* output */
1217        var->xres = xres;
1218        var->yres = yres;
1219        var->xres_virtual = crtc->vxres;
1220        var->yres_virtual = crtc->vyres;
1221        var->bits_per_pixel = bpp;
1222        var->left_margin = left;
1223        var->right_margin = right;
1224        var->upper_margin = upper;
1225        var->lower_margin = lower;
1226        var->hsync_len = hslen;
1227        var->vsync_len = vslen;
1228        var->sync = sync;
1229        var->vmode = FB_VMODE_NONINTERLACED;
1230        /* In double scan mode, the vertical parameters are doubled, so we need to
1231           half them to get the right values.
1232           In interlaced mode the values are already correct, so no correction is
1233           necessary.
1234         */
1235        if (interlace)
1236                var->vmode = FB_VMODE_INTERLACED;
1237
1238        if (double_scan) {
1239                var->vmode = FB_VMODE_DOUBLE;
1240                var->yres>>=1;
1241                var->upper_margin>>=1;
1242                var->lower_margin>>=1;
1243                var->vsync_len>>=1;
1244        }
1245
1246        return 0;
1247}
1248
1249/* ------------------------------------------------------------------------- */
1250
1251static int atyfb_set_par(struct fb_info *info)
1252{
1253        struct atyfb_par *par = (struct atyfb_par *) info->par;
1254        struct fb_var_screeninfo *var = &info->var;
1255        u32 tmp, pixclock;
1256        int err;
1257#ifdef DEBUG
1258        struct fb_var_screeninfo debug;
1259        u32 pixclock_in_ps;
1260#endif
1261        if (par->asleep)
1262                return 0;
1263
1264        if ((err = aty_var_to_crtc(info, var, &par->crtc)))
1265                return err;
1266
1267        pixclock = atyfb_get_pixclock(var, par);
1268
1269        if (pixclock == 0) {
1270                PRINTKE("Invalid pixclock\n");
1271                return -EINVAL;
1272        } else {
1273                if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll)))
1274                        return err;
1275        }
1276
1277        par->accel_flags = var->accel_flags; /* hack */
1278
1279        if (var->accel_flags) {
1280                info->fbops->fb_sync = atyfb_sync;
1281                info->flags &= ~FBINFO_HWACCEL_DISABLED;
1282        } else {
1283                info->fbops->fb_sync = NULL;
1284                info->flags |= FBINFO_HWACCEL_DISABLED;
1285        }
1286
1287        if (par->blitter_may_be_busy)
1288                wait_for_idle(par);
1289
1290        aty_set_crtc(par, &par->crtc);
1291        par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel, par->accel_flags);
1292        par->pll_ops->set_pll(info, &par->pll);
1293
1294#ifdef DEBUG
1295        if(par->pll_ops && par->pll_ops->pll_to_var)
1296                pixclock_in_ps = par->pll_ops->pll_to_var(info, &(par->pll));
1297        else
1298                pixclock_in_ps = 0;
1299
1300        if(0 == pixclock_in_ps) {
1301                PRINTKE("ALERT ops->pll_to_var get 0\n");
1302                pixclock_in_ps = pixclock;
1303        }
1304
1305        memset(&debug, 0, sizeof(debug));
1306        if(!aty_crtc_to_var(&(par->crtc), &debug)) {
1307                u32 hSync, vRefresh;
1308                u32 h_disp, h_sync_strt, h_sync_end, h_total;
1309                u32 v_disp, v_sync_strt, v_sync_end, v_total;
1310
1311                h_disp = debug.xres;
1312                h_sync_strt = h_disp + debug.right_margin;
1313                h_sync_end = h_sync_strt + debug.hsync_len;
1314                h_total = h_sync_end + debug.left_margin;
1315                v_disp = debug.yres;
1316                v_sync_strt = v_disp + debug.lower_margin;
1317                v_sync_end = v_sync_strt + debug.vsync_len;
1318                v_total = v_sync_end + debug.upper_margin;
1319
1320                hSync = 1000000000 / (pixclock_in_ps * h_total);
1321                vRefresh = (hSync * 1000) / v_total;
1322                if (par->crtc.gen_cntl & CRTC_INTERLACE_EN)
1323                vRefresh *= 2;
1324                if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
1325                vRefresh /= 2;
1326
1327                DPRINTK("atyfb_set_par\n");
1328                DPRINTK(" Set Visible Mode to %ix%i-%i\n", var->xres, var->yres, var->bits_per_pixel);
1329                DPRINTK(" Virtual resolution %ix%i, pixclock_in_ps %i (calculated %i)\n",
1330                        var->xres_virtual, var->yres_virtual, pixclock, pixclock_in_ps);
1331                DPRINTK(" Dot clock:           %i MHz\n", 1000000 / pixclock_in_ps);
1332                DPRINTK(" Horizontal sync:     %i kHz\n", hSync);
1333                DPRINTK(" Vertical refresh:    %i Hz\n", vRefresh);
1334                DPRINTK(" x  style: %i.%03i %i %i %i %i   %i %i %i %i\n",
1335                        1000000 / pixclock_in_ps, 1000000 % pixclock_in_ps,
1336                        h_disp, h_sync_strt, h_sync_end, h_total,
1337                        v_disp, v_sync_strt, v_sync_end, v_total);
1338                DPRINTK(" fb style: %i  %i %i %i %i %i %i %i %i\n",
1339                        pixclock_in_ps,
1340                        debug.left_margin, h_disp, debug.right_margin, debug.hsync_len,
1341                        debug.upper_margin, v_disp, debug.lower_margin, debug.vsync_len);
1342        }
1343#endif /* DEBUG */
1344
1345        if (!M64_HAS(INTEGRATED)) {
1346                /* Don't forget MEM_CNTL */
1347                tmp = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
1348                switch (var->bits_per_pixel) {
1349                case 8:
1350                        tmp |= 0x02000000;
1351                        break;
1352                case 16:
1353                        tmp |= 0x03000000;
1354                        break;
1355                case 32:
1356                        tmp |= 0x06000000;
1357                        break;
1358                }
1359                aty_st_le32(MEM_CNTL, tmp, par);
1360        } else {
1361                tmp = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
1362                if (!M64_HAS(MAGIC_POSTDIV))
1363                        tmp |= par->mem_refresh_rate << 20;
1364                switch (var->bits_per_pixel) {
1365                case 8:
1366                case 24:
1367                        tmp |= 0x00000000;
1368                        break;
1369                case 16:
1370                        tmp |= 0x04000000;
1371                        break;
1372                case 32:
1373                        tmp |= 0x08000000;
1374                        break;
1375                }
1376                if (M64_HAS(CT_BUS)) {
1377                        aty_st_le32(DAC_CNTL, 0x87010184, par);
1378                        aty_st_le32(BUS_CNTL, 0x680000f9, par);
1379                } else if (M64_HAS(VT_BUS)) {
1380                        aty_st_le32(DAC_CNTL, 0x87010184, par);
1381                        aty_st_le32(BUS_CNTL, 0x680000f9, par);
1382                } else if (M64_HAS(MOBIL_BUS)) {
1383                        aty_st_le32(DAC_CNTL, 0x80010102, par);
1384                        aty_st_le32(BUS_CNTL, 0x7b33a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
1385                } else {
1386                        /* GT */
1387                        aty_st_le32(DAC_CNTL, 0x86010102, par);
1388                        aty_st_le32(BUS_CNTL, 0x7b23a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
1389                        aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par);
1390                }
1391                aty_st_le32(MEM_CNTL, tmp, par);
1392        }
1393        aty_st_8(DAC_MASK, 0xff, par);
1394
1395        info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8;
1396        info->fix.visual = var->bits_per_pixel <= 8 ?
1397                FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1398
1399        /* Initialize the graphics engine */
1400        if (par->accel_flags & FB_ACCELF_TEXT)
1401                aty_init_engine(par, info);
1402
1403#ifdef CONFIG_BOOTX_TEXT
1404        btext_update_display(info->fix.smem_start,
1405                (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
1406                ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
1407                var->bits_per_pixel,
1408                par->crtc.vxres * var->bits_per_pixel / 8);
1409#endif /* CONFIG_BOOTX_TEXT */
1410#if 0
1411        /* switch to accelerator mode */
1412        if (!(par->crtc.gen_cntl & CRTC_EXT_DISP_EN))
1413                aty_st_le32(CRTC_GEN_CNTL, par->crtc.gen_cntl | CRTC_EXT_DISP_EN, par);
1414#endif
1415#ifdef DEBUG
1416{
1417        /* dump non shadow CRTC, pll, LCD registers */
1418        int i; u32 base;
1419
1420        /* CRTC registers */
1421        base = 0x2000;
1422        printk("debug atyfb: Mach64 non-shadow register values:");
1423        for (i = 0; i < 256; i = i+4) {
1424                if(i%16 == 0) printk("\ndebug atyfb: 0x%04X: ", base + i);
1425                printk(" %08X", aty_ld_le32(i, par));
1426        }
1427        printk("\n\n");
1428
1429#ifdef CONFIG_FB_ATY_CT
1430        /* PLL registers */
1431        base = 0x00;
1432        printk("debug atyfb: Mach64 PLL register values:");
1433        for (i = 0; i < 64; i++) {
1434                if(i%16 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
1435                if(i%4 == 0)  printk(" ");
1436                printk("%02X", aty_ld_pll_ct(i, par));
1437        }
1438        printk("\n\n");
1439#endif  /* CONFIG_FB_ATY_CT */
1440
1441#ifdef CONFIG_FB_ATY_GENERIC_LCD
1442        if (par->lcd_table != 0) {
1443                /* LCD registers */
1444                base = 0x00;
1445                printk("debug atyfb: LCD register values:");
1446                if(M64_HAS(LT_LCD_REGS)) {
1447                    for(i = 0; i <= POWER_MANAGEMENT; i++) {
1448                        if(i == EXT_VERT_STRETCH)
1449                            continue;
1450                        printk("\ndebug atyfb: 0x%04X: ", lt_lcd_regs[i]);
1451                        printk(" %08X", aty_ld_lcd(i, par));
1452                    }
1453
1454                } else {
1455                    for (i = 0; i < 64; i++) {
1456                        if(i%4 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
1457                        printk(" %08X", aty_ld_lcd(i, par));
1458                    }
1459                }
1460                printk("\n\n");
1461        }
1462#endif /* CONFIG_FB_ATY_GENERIC_LCD */
1463}
1464#endif /* DEBUG */
1465        return 0;
1466}
1467
1468static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1469{
1470        struct atyfb_par *par = (struct atyfb_par *) info->par;
1471        int err;
1472        struct crtc crtc;
1473        union aty_pll pll;
1474        u32 pixclock;
1475
1476        memcpy(&pll, &(par->pll), sizeof(pll));
1477
1478        if((err = aty_var_to_crtc(info, var, &crtc)))
1479                return err;
1480
1481        pixclock = atyfb_get_pixclock(var, par);
1482
1483        if (pixclock == 0) {
1484                if (!(var->activate & FB_ACTIVATE_TEST))
1485                        PRINTKE("Invalid pixclock\n");
1486                return -EINVAL;
1487        } else {
1488                if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll)))
1489                        return err;
1490        }
1491
1492        if (var->accel_flags & FB_ACCELF_TEXT)
1493                info->var.accel_flags = FB_ACCELF_TEXT;
1494        else
1495                info->var.accel_flags = 0;
1496
1497        aty_crtc_to_var(&crtc, var);
1498        var->pixclock = par->pll_ops->pll_to_var(info, &pll);
1499        return 0;
1500}
1501
1502static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
1503{
1504        u32 xoffset = info->var.xoffset;
1505        u32 yoffset = info->var.yoffset;
1506        u32 vxres = par->crtc.vxres;
1507        u32 bpp = info->var.bits_per_pixel;
1508
1509        par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
1510}
1511
1512
1513    /*
1514     *  Open/Release the frame buffer device
1515     */
1516
1517static int atyfb_open(struct fb_info *info, int user)
1518{
1519        struct atyfb_par *par = (struct atyfb_par *) info->par;
1520
1521        if (user) {
1522                par->open++;
1523#ifdef __sparc__
1524                par->mmaped = 0;
1525#endif
1526        }
1527        return (0);
1528}
1529
1530static irqreturn_t aty_irq(int irq, void *dev_id)
1531{
1532        struct atyfb_par *par = dev_id;
1533        int handled = 0;
1534        u32 int_cntl;
1535
1536        spin_lock(&par->int_lock);
1537
1538        int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);
1539
1540        if (int_cntl & CRTC_VBLANK_INT) {
1541                /* clear interrupt */
1542                aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par);
1543                par->vblank.count++;
1544                if (par->vblank.pan_display) {
1545                        par->vblank.pan_display = 0;
1546                        aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1547                }
1548                wake_up_interruptible(&par->vblank.wait);
1549                handled = 1;
1550        }
1551
1552        spin_unlock(&par->int_lock);
1553
1554        return IRQ_RETVAL(handled);
1555}
1556
1557static int aty_enable_irq(struct atyfb_par *par, int reenable)
1558{
1559        u32 int_cntl;
1560
1561        if (!test_and_set_bit(0, &par->irq_flags)) {
1562                if (request_irq(par->irq, aty_irq, IRQF_SHARED, "atyfb", par)) {
1563                        clear_bit(0, &par->irq_flags);
1564                        return -EINVAL;
1565                }
1566                spin_lock_irq(&par->int_lock);
1567                int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1568                /* clear interrupt */
1569                aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);
1570                /* enable interrupt */
1571                aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);
1572                spin_unlock_irq(&par->int_lock);
1573        } else if (reenable) {
1574                spin_lock_irq(&par->int_lock);
1575                int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1576                if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
1577                        printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl);
1578                        /* re-enable interrupt */
1579                        aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par );
1580                }
1581                spin_unlock_irq(&par->int_lock);
1582        }
1583
1584        return 0;
1585}
1586
1587static int aty_disable_irq(struct atyfb_par *par)
1588{
1589        u32 int_cntl;
1590
1591        if (test_and_clear_bit(0, &par->irq_flags)) {
1592                if (par->vblank.pan_display) {
1593                        par->vblank.pan_display = 0;
1594                        aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1595                }
1596                spin_lock_irq(&par->int_lock);
1597                int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
1598                /* disable interrupt */
1599                aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par );
1600                spin_unlock_irq(&par->int_lock);
1601                free_irq(par->irq, par);
1602        }
1603
1604        return 0;
1605}
1606
1607static int atyfb_release(struct fb_info *info, int user)
1608{
1609        struct atyfb_par *par = (struct atyfb_par *) info->par;
1610        if (user) {
1611                par->open--;
1612                mdelay(1);
1613                wait_for_idle(par);
1614                if (!par->open) {
1615#ifdef __sparc__
1616                        int was_mmaped = par->mmaped;
1617
1618                        par->mmaped = 0;
1619
1620                        if (was_mmaped) {
1621                                struct fb_var_screeninfo var;
1622
1623                                /* Now reset the default display config, we have no
1624                                 * idea what the program(s) which mmap'd the chip did
1625                                 * to the configuration, nor whether it restored it
1626                                 * correctly.
1627                                 */
1628                                var = default_var;
1629                                if (noaccel)
1630                                        var.accel_flags &= ~FB_ACCELF_TEXT;
1631                                else
1632                                        var.accel_flags |= FB_ACCELF_TEXT;
1633                                if (var.yres == var.yres_virtual) {
1634                                        u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
1635                                        var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
1636                                        if (var.yres_virtual < var.yres)
1637                                                var.yres_virtual = var.yres;
1638                                }
1639                        }
1640#endif
1641                        aty_disable_irq(par);
1642                }
1643        }
1644        return (0);
1645}
1646
1647    /*
1648     *  Pan or Wrap the Display
1649     *
1650     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1651     */
1652
1653static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1654{
1655        struct atyfb_par *par = (struct atyfb_par *) info->par;
1656        u32 xres, yres, xoffset, yoffset;
1657
1658        xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
1659        yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
1660        if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
1661                yres >>= 1;
1662        xoffset = (var->xoffset + 7) & ~7;
1663        yoffset = var->yoffset;
1664        if (xoffset + xres > par->crtc.vxres || yoffset + yres > par->crtc.vyres)
1665                return -EINVAL;
1666        info->var.xoffset = xoffset;
1667        info->var.yoffset = yoffset;
1668        if (par->asleep)
1669                return 0;
1670
1671        set_off_pitch(par, info);
1672        if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {
1673                par->vblank.pan_display = 1;
1674        } else {
1675                par->vblank.pan_display = 0;
1676                aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1677        }
1678
1679        return 0;
1680}
1681
1682static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
1683{
1684        struct aty_interrupt *vbl;
1685        unsigned int count;
1686        int ret;
1687
1688        switch (crtc) {
1689        case 0:
1690                vbl = &par->vblank;
1691                break;
1692        default:
1693                return -ENODEV;
1694        }
1695
1696        ret = aty_enable_irq(par, 0);
1697        if (ret)
1698                return ret;
1699
1700        count = vbl->count;
1701        ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10);
1702        if (ret < 0) {
1703                return ret;
1704        }
1705        if (ret == 0) {
1706                aty_enable_irq(par, 1);
1707                return -ETIMEDOUT;
1708        }
1709
1710        return 0;
1711}
1712
1713
1714#ifdef DEBUG
1715#define ATYIO_CLKR              0x41545900      /* ATY\00 */
1716#define ATYIO_CLKW              0x41545901      /* ATY\01 */
1717
1718struct atyclk {
1719        u32 ref_clk_per;
1720        u8 pll_ref_div;
1721        u8 mclk_fb_div;
1722        u8 mclk_post_div;       /* 1,2,3,4,8 */
1723        u8 mclk_fb_mult;        /* 2 or 4 */
1724        u8 xclk_post_div;       /* 1,2,3,4,8 */
1725        u8 vclk_fb_div;
1726        u8 vclk_post_div;       /* 1,2,3,4,6,8,12 */
1727        u32 dsp_xclks_per_row;  /* 0-16383 */
1728        u32 dsp_loop_latency;   /* 0-15 */
1729        u32 dsp_precision;      /* 0-7 */
1730        u32 dsp_on;             /* 0-2047 */
1731        u32 dsp_off;            /* 0-2047 */
1732};
1733
1734#define ATYIO_FEATR             0x41545902      /* ATY\02 */
1735#define ATYIO_FEATW             0x41545903      /* ATY\03 */
1736#endif
1737
1738#ifndef FBIO_WAITFORVSYNC
1739#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
1740#endif
1741
1742static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
1743{
1744        struct atyfb_par *par = (struct atyfb_par *) info->par;
1745#ifdef __sparc__
1746        struct fbtype fbtyp;
1747#endif
1748
1749        switch (cmd) {
1750#ifdef __sparc__
1751        case FBIOGTYPE:
1752                fbtyp.fb_type = FBTYPE_PCI_GENERIC;
1753                fbtyp.fb_width = par->crtc.vxres;
1754                fbtyp.fb_height = par->crtc.vyres;
1755                fbtyp.fb_depth = info->var.bits_per_pixel;
1756                fbtyp.fb_cmsize = info->cmap.len;
1757                fbtyp.fb_size = info->fix.smem_len;
1758                if (copy_to_user((struct fbtype __user *) arg, &fbtyp, sizeof(fbtyp)))
1759                        return -EFAULT;
1760                break;
1761#endif /* __sparc__ */
1762
1763        case FBIO_WAITFORVSYNC:
1764                {
1765                        u32 crtc;
1766
1767                        if (get_user(crtc, (__u32 __user *) arg))
1768                                return -EFAULT;
1769
1770                        return aty_waitforvblank(par, crtc);
1771                }
1772                break;
1773
1774#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
1775        case ATYIO_CLKR:
1776                if (M64_HAS(INTEGRATED)) {
1777                        struct atyclk clk;
1778                        union aty_pll *pll = &(par->pll);
1779                        u32 dsp_config = pll->ct.dsp_config;
1780                        u32 dsp_on_off = pll->ct.dsp_on_off;
1781                        clk.ref_clk_per = par->ref_clk_per;
1782                        clk.pll_ref_div = pll->ct.pll_ref_div;
1783                        clk.mclk_fb_div = pll->ct.mclk_fb_div;
1784                        clk.mclk_post_div = pll->ct.mclk_post_div_real;
1785                        clk.mclk_fb_mult = pll->ct.mclk_fb_mult;
1786                        clk.xclk_post_div = pll->ct.xclk_post_div_real;
1787                        clk.vclk_fb_div = pll->ct.vclk_fb_div;
1788                        clk.vclk_post_div = pll->ct.vclk_post_div_real;
1789                        clk.dsp_xclks_per_row = dsp_config & 0x3fff;
1790                        clk.dsp_loop_latency = (dsp_config >> 16) & 0xf;
1791                        clk.dsp_precision = (dsp_config >> 20) & 7;
1792                        clk.dsp_off = dsp_on_off & 0x7ff;
1793                        clk.dsp_on = (dsp_on_off >> 16) & 0x7ff;
1794                        if (copy_to_user((struct atyclk __user *) arg, &clk,
1795                                         sizeof(clk)))
1796                                return -EFAULT;
1797                } else
1798                        return -EINVAL;
1799                break;
1800        case ATYIO_CLKW:
1801                if (M64_HAS(INTEGRATED)) {
1802                        struct atyclk clk;
1803                        union aty_pll *pll = &(par->pll);
1804                        if (copy_from_user(&clk, (struct atyclk __user *) arg, sizeof(clk)))
1805                                return -EFAULT;
1806                        par->ref_clk_per = clk.ref_clk_per;
1807                        pll->ct.pll_ref_div = clk.pll_ref_div;
1808                        pll->ct.mclk_fb_div = clk.mclk_fb_div;
1809                        pll->ct.mclk_post_div_real = clk.mclk_post_div;
1810                        pll->ct.mclk_fb_mult = clk.mclk_fb_mult;
1811                        pll->ct.xclk_post_div_real = clk.xclk_post_div;
1812                        pll->ct.vclk_fb_div = clk.vclk_fb_div;
1813                        pll->ct.vclk_post_div_real = clk.vclk_post_div;
1814                        pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
1815                                ((clk.dsp_loop_latency & 0xf)<<16)| ((clk.dsp_precision & 7)<<20);
1816                        pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | ((clk.dsp_on & 0x7ff)<<16);
1817                        /*aty_calc_pll_ct(info, &pll->ct);*/
1818                        aty_set_pll_ct(info, pll);
1819                } else
1820                        return -EINVAL;
1821                break;
1822        case ATYIO_FEATR:
1823                if (get_user(par->features, (u32 __user *) arg))
1824                        return -EFAULT;
1825                break;
1826        case ATYIO_FEATW:
1827                if (put_user(par->features, (u32 __user *) arg))
1828                        return -EFAULT;
1829                break;
1830#endif /* DEBUG && CONFIG_FB_ATY_CT */
1831        default:
1832                return -EINVAL;
1833        }
1834        return 0;
1835}
1836
1837static int atyfb_sync(struct fb_info *info)
1838{
1839        struct atyfb_par *par = (struct atyfb_par *) info->par;
1840
1841        if (par->blitter_may_be_busy)
1842                wait_for_idle(par);
1843        return 0;
1844}
1845
1846#ifdef __sparc__
1847static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
1848{
1849        struct atyfb_par *par = (struct atyfb_par *) info->par;
1850        unsigned int size, page, map_size = 0;
1851        unsigned long map_offset = 0;
1852        unsigned long off;
1853        int i;
1854
1855        if (!par->mmap_map)
1856                return -ENXIO;
1857
1858        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1859                return -EINVAL;
1860
1861        off = vma->vm_pgoff << PAGE_SHIFT;
1862        size = vma->vm_end - vma->vm_start;
1863
1864        /* To stop the swapper from even considering these pages. */
1865        vma->vm_flags |= (VM_IO | VM_RESERVED);
1866
1867        if (((vma->vm_pgoff == 0) && (size == info->fix.smem_len)) ||
1868            ((off == info->fix.smem_len) && (size == PAGE_SIZE)))
1869                off += 0x8000000000000000UL;
1870
1871        vma->vm_pgoff = off >> PAGE_SHIFT;      /* propagate off changes */
1872
1873        /* Each page, see which map applies */
1874        for (page = 0; page < size;) {
1875                map_size = 0;
1876                for (i = 0; par->mmap_map[i].size; i++) {
1877                        unsigned long start = par->mmap_map[i].voff;
1878                        unsigned long end = start + par->mmap_map[i].size;
1879                        unsigned long offset = off + page;
1880
1881                        if (start > offset)
1882                                continue;
1883                        if (offset >= end)
1884                                continue;
1885
1886                        map_size = par->mmap_map[i].size - (offset - start);
1887                        map_offset =
1888                            par->mmap_map[i].poff + (offset - start);
1889                        break;
1890                }
1891                if (!map_size) {
1892                        page += PAGE_SIZE;
1893                        continue;
1894                }
1895                if (page + map_size > size)
1896                        map_size = size - page;
1897
1898                pgprot_val(vma->vm_page_prot) &=
1899                    ~(par->mmap_map[i].prot_mask);
1900                pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;
1901
1902                if (remap_pfn_range(vma, vma->vm_start + page,
1903                        map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))
1904                        return -EAGAIN;
1905
1906                page += map_size;
1907        }
1908
1909        if (!map_size)
1910                return -EINVAL;
1911
1912        if (!par->mmaped)
1913                par->mmaped = 1;
1914        return 0;
1915}
1916
1917static struct {
1918        u32 yoffset;
1919        u8 r[2][256];
1920        u8 g[2][256];
1921        u8 b[2][256];
1922} atyfb_save;
1923
1924static void atyfb_save_palette(struct atyfb_par *par, int enter)
1925{
1926        int i, tmp;
1927
1928        for (i = 0; i < 256; i++) {
1929                tmp = aty_ld_8(DAC_CNTL, par) & 0xfc;
1930                if (M64_HAS(EXTRA_BRIGHT))
1931                        tmp |= 0x2;
1932                aty_st_8(DAC_CNTL, tmp, par);
1933                aty_st_8(DAC_MASK, 0xff, par);
1934
1935                aty_st_8(DAC_R_INDEX, i, par);
1936                atyfb_save.r[enter][i] = aty_ld_8(DAC_DATA, par);
1937                atyfb_save.g[enter][i] = aty_ld_8(DAC_DATA, par);
1938                atyfb_save.b[enter][i] = aty_ld_8(DAC_DATA, par);
1939                aty_st_8(DAC_W_INDEX, i, par);
1940                aty_st_8(DAC_DATA, atyfb_save.r[1 - enter][i], par);
1941                aty_st_8(DAC_DATA, atyfb_save.g[1 - enter][i], par);
1942                aty_st_8(DAC_DATA, atyfb_save.b[1 - enter][i], par);
1943        }
1944}
1945
1946static void atyfb_palette(int enter)
1947{
1948        struct atyfb_par *par;
1949        struct fb_info *info;
1950        int i;
1951
1952        for (i = 0; i < FB_MAX; i++) {
1953                info = registered_fb[i];
1954                if (info && info->fbops == &atyfb_ops) {
1955                        par = (struct atyfb_par *) info->par;
1956                        
1957                        atyfb_save_palette(par, enter);
1958                        if (enter) {
1959                                atyfb_save.yoffset = info->var.yoffset;
1960                                info->var.yoffset = 0;
1961                                set_off_pitch(par, info);
1962                        } else {
1963                                info->var.yoffset = atyfb_save.yoffset;
1964                                set_off_pitch(par, info);
1965                        }
1966                        aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
1967                        break;
1968                }
1969        }
1970}
1971#endif /* __sparc__ */
1972
1973
1974
1975#if defined(CONFIG_PM) && defined(CONFIG_PCI)
1976
1977#ifdef CONFIG_PPC_PMAC
1978/* Power management routines. Those are used for PowerBook sleep.
1979 */
1980static int aty_power_mgmt(int sleep, struct atyfb_par *par)
1981{
1982        u32 pm;
1983        int timeout;
1984
1985        pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1986        pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
1987        aty_st_lcd(POWER_MANAGEMENT, pm, par);
1988        pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1989
1990        timeout = 2000;
1991        if (sleep) {
1992                /* Sleep */
1993                pm &= ~PWR_MGT_ON;
1994                aty_st_lcd(POWER_MANAGEMENT, pm, par);
1995                pm = aty_ld_lcd(POWER_MANAGEMENT, par);
1996                udelay(10);
1997                pm &= ~(PWR_BLON | AUTO_PWR_UP);
1998                pm |= SUSPEND_NOW;
1999                aty_st_lcd(POWER_MANAGEMENT, pm, par);
2000                pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2001                udelay(10);
2002                pm |= PWR_MGT_ON;
2003                aty_st_lcd(POWER_MANAGEMENT, pm, par);
2004                do {
2005                        pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2006                        mdelay(1);
2007                        if ((--timeout) == 0)
2008                                break;
2009                } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
2010        } else {
2011                /* Wakeup */
2012                pm &= ~PWR_MGT_ON;
2013                aty_st_lcd(POWER_MANAGEMENT, pm, par);
2014                pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2015                udelay(10);
2016                pm &= ~SUSPEND_NOW;
2017                pm |= (PWR_BLON | AUTO_PWR_UP);
2018                aty_st_lcd(POWER_MANAGEMENT, pm, par);
2019                pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2020                udelay(10);
2021                pm |= PWR_MGT_ON;
2022                aty_st_lcd(POWER_MANAGEMENT, pm, par);
2023                do {
2024                        pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2025                        mdelay(1);
2026                        if ((--timeout) == 0)
2027                                break;
2028                } while ((pm & PWR_MGT_STATUS_MASK) != 0);
2029        }
2030        mdelay(500);
2031
2032        return timeout ? 0 : -EIO;
2033}
2034#endif
2035
2036static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2037{
2038        struct fb_info *info = pci_get_drvdata(pdev);
2039        struct atyfb_par *par = (struct atyfb_par *) info->par;
2040
2041        if (state.event == pdev->dev.power.power_state.event)
2042                return 0;
2043
2044        acquire_console_sem();
2045
2046        fb_set_suspend(info, 1);
2047
2048        /* Idle & reset engine */
2049        wait_for_idle(par);
2050        aty_reset_engine(par);
2051
2052        /* Blank display and LCD */
2053        atyfb_blank(FB_BLANK_POWERDOWN, info);
2054
2055        par->asleep = 1;
2056        par->lock_blank = 1;
2057
2058#ifdef CONFIG_PPC_PMAC
2059        /* Set chip to "suspend" mode */
2060        if (aty_power_mgmt(1, par)) {
2061                par->asleep = 0;
2062                par->lock_blank = 0;
2063                atyfb_blank(FB_BLANK_UNBLANK, info);
2064                fb_set_suspend(info, 0);
2065                release_console_sem();
2066                return -EIO;
2067        }
2068#else
2069        pci_set_power_state(pdev, pci_choose_state(pdev, state));
2070#endif
2071
2072        release_console_sem();
2073
2074        pdev->dev.power.power_state = state;
2075
2076        return 0;
2077}
2078
2079static int atyfb_pci_resume(struct pci_dev *pdev)
2080{
2081        struct fb_info *info = pci_get_drvdata(pdev);
2082        struct atyfb_par *par = (struct atyfb_par *) info->par;
2083
2084        if (pdev->dev.power.power_state.event == PM_EVENT_ON)
2085                return 0;
2086
2087        acquire_console_sem();
2088
2089#ifdef CONFIG_PPC_PMAC
2090        if (pdev->dev.power.power_state.event == 2)
2091                aty_power_mgmt(0, par);
2092#else
2093        pci_set_power_state(pdev, PCI_D0);
2094#endif
2095
2096        aty_resume_chip(info);
2097
2098        par->asleep = 0;
2099
2100        /* Restore display */
2101        atyfb_set_par(info);
2102
2103        /* Refresh */
2104        fb_set_suspend(info, 0);
2105
2106        /* Unblank */
2107        par->lock_blank = 0;
2108        atyfb_blank(FB_BLANK_UNBLANK, info);
2109
2110        release_console_sem();
2111
2112        pdev->dev.power.power_state = PMSG_ON;
2113
2114        return 0;
2115}
2116
2117#endif /*  defined(CONFIG_PM) && defined(CONFIG_PCI) */
2118
2119/* Backlight */
2120#ifdef CONFIG_FB_ATY_BACKLIGHT
2121#define MAX_LEVEL 0xFF
2122
2123static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
2124{
2125        struct fb_info *info = pci_get_drvdata(par->pdev);
2126        int atylevel;
2127
2128        /* Get and convert the value */
2129        /* No locking of bl_curve since we read a single value */
2130        atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
2131
2132        if (atylevel < 0)
2133                atylevel = 0;
2134        else if (atylevel > MAX_LEVEL)
2135                atylevel = MAX_LEVEL;
2136
2137        return atylevel;
2138}
2139
2140static int aty_bl_update_status(struct backlight_device *bd)
2141{
2142        struct atyfb_par *par = bl_get_data(bd);
2143        unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
2144        int level;
2145
2146        if (bd->props.power != FB_BLANK_UNBLANK ||
2147            bd->props.fb_blank != FB_BLANK_UNBLANK)
2148                level = 0;
2149        else
2150                level = bd->props.brightness;
2151
2152        reg |= (BLMOD_EN | BIASMOD_EN);
2153        if (level > 0) {
2154                reg &= ~BIAS_MOD_LEVEL_MASK;
2155                reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);
2156        } else {
2157                reg &= ~BIAS_MOD_LEVEL_MASK;
2158                reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);
2159        }
2160        aty_st_lcd(LCD_MISC_CNTL, reg, par);
2161
2162        return 0;
2163}
2164
2165static int aty_bl_get_brightness(struct backlight_device *bd)
2166{
2167        return bd->props.brightness;
2168}
2169
2170static struct backlight_ops aty_bl_data = {
2171        .get_brightness = aty_bl_get_brightness,
2172        .update_status  = aty_bl_update_status,
2173};
2174
2175static void aty_bl_init(struct atyfb_par *par)
2176{
2177        struct fb_info *info = pci_get_drvdata(par->pdev);
2178        struct backlight_device *bd;
2179        char name[12];
2180
2181#ifdef CONFIG_PMAC_BACKLIGHT
2182        if (!pmac_has_backlight_type("ati"))
2183                return;
2184#endif
2185
2186        snprintf(name, sizeof(name), "atybl%d", info->node);
2187
2188        bd = backlight_device_register(name, info->dev, par, &aty_bl_data);
2189        if (IS_ERR(bd)) {
2190                info->bl_dev = NULL;
2191                printk(KERN_WARNING "aty: Backlight registration failed\n");
2192                goto error;
2193        }
2194
2195        info->bl_dev = bd;
2196        fb_bl_default_curve(info, 0,
2197                0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
2198                0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
2199
2200        bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
2201        bd->props.brightness = bd->props.max_brightness;
2202        bd->props.power = FB_BLANK_UNBLANK;
2203        backlight_update_status(bd);
2204
2205        printk("aty: Backlight initialized (%s)\n", name);
2206
2207        return;
2208
2209error:
2210        return;
2211}
2212
2213static void aty_bl_exit(struct backlight_device *bd)
2214{
2215        backlight_device_unregister(bd);
2216        printk("aty: Backlight unloaded\n");
2217}
2218
2219#endif /* CONFIG_FB_ATY_BACKLIGHT */
2220
2221static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
2222{
2223        const int ragepro_tbl[] = {
2224                44, 50, 55, 66, 75, 80, 100
2225        };
2226        const int ragexl_tbl[] = {
2227                50, 66, 75, 83, 90, 95, 100, 105,
2228                110, 115, 120, 125, 133, 143, 166
2229        };
2230        const int *refresh_tbl;
2231        int i, size;
2232
2233        if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) {
2234                refresh_tbl = ragexl_tbl;
2235                size = ARRAY_SIZE(ragexl_tbl);
2236        } else {
2237                refresh_tbl = ragepro_tbl;
2238                size = ARRAY_SIZE(ragepro_tbl);
2239        }
2240
2241        for (i=0; i < size; i++) {
2242                if (xclk < refresh_tbl[i])
2243                break;
2244        }
2245        par->mem_refresh_rate = i;
2246}
2247
2248    /*
2249     *  Initialisation
2250     */
2251
2252static struct fb_info *fb_list = NULL;
2253
2254#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2255static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
2256                                                struct fb_var_screeninfo *var)
2257{
2258        int ret = -EINVAL;
2259
2260        if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2261                *var = default_var;
2262                var->xres = var->xres_virtual = par->lcd_hdisp;
2263                var->right_margin = par->lcd_right_margin;
2264                var->left_margin = par->lcd_hblank_len -
2265                        (par->lcd_right_margin + par->lcd_hsync_dly +
2266                         par->lcd_hsync_len);
2267                var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly;
2268                var->yres = var->yres_virtual = par->lcd_vdisp;
2269                var->lower_margin = par->lcd_lower_margin;
2270                var->upper_margin = par->lcd_vblank_len -
2271                        (par->lcd_lower_margin + par->lcd_vsync_len);
2272                var->vsync_len = par->lcd_vsync_len;
2273                var->pixclock = par->lcd_pixclock;
2274                ret = 0;
2275        }
2276
2277        return ret;
2278}
2279#endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
2280
2281static int __devinit aty_init(struct fb_info *info)
2282{
2283        struct atyfb_par *par = (struct atyfb_par *) info->par;
2284        const char *ramname = NULL, *xtal;
2285        int gtb_memsize, has_var = 0;
2286        struct fb_var_screeninfo var;
2287
2288        init_waitqueue_head(&par->vblank.wait);
2289        spin_lock_init(&par->int_lock);
2290
2291#ifdef CONFIG_FB_ATY_GX
2292        if (!M64_HAS(INTEGRATED)) {
2293                u32 stat0;
2294                u8 dac_type, dac_subtype, clk_type;
2295                stat0 = aty_ld_le32(CONFIG_STAT0, par);
2296                par->bus_type = (stat0 >> 0) & 0x07;
2297                par->ram_type = (stat0 >> 3) & 0x07;
2298                ramname = aty_gx_ram[par->ram_type];
2299                /* FIXME: clockchip/RAMDAC probing? */
2300                dac_type = (aty_ld_le32(DAC_CNTL, par) >> 16) & 0x07;
2301#ifdef CONFIG_ATARI
2302                clk_type = CLK_ATI18818_1;
2303                dac_type = (stat0 >> 9) & 0x07;
2304                if (dac_type == 0x07)
2305                        dac_subtype = DAC_ATT20C408;
2306                else
2307                        dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, par) & 0xF0) | dac_type;
2308#else
2309                dac_type = DAC_IBMRGB514;
2310                dac_subtype = DAC_IBMRGB514;
2311                clk_type = CLK_IBMRGB514;
2312#endif
2313                switch (dac_subtype) {
2314                case DAC_IBMRGB514:
2315                        par->dac_ops = &aty_dac_ibm514;
2316                        break;
2317#ifdef CONFIG_ATARI
2318                case DAC_ATI68860_B:
2319                case DAC_ATI68860_C:
2320                        par->dac_ops = &aty_dac_ati68860b;
2321                        break;
2322                case DAC_ATT20C408:
2323                case DAC_ATT21C498:
2324                        par->dac_ops = &aty_dac_att21c498;
2325                        break;
2326#endif
2327                default:
2328                        PRINTKI("aty_init: DAC type not implemented yet!\n");
2329                        par->dac_ops = &aty_dac_unsupported;
2330                        break;
2331                }
2332                switch (clk_type) {
2333#ifdef CONFIG_ATARI
2334                case CLK_ATI18818_1:
2335                        par->pll_ops = &aty_pll_ati18818_1;
2336                        break;
2337#else
2338                case CLK_IBMRGB514:
2339                        par->pll_ops = &aty_pll_ibm514;
2340                        break;
2341#endif
2342#if 0 /* dead code */
2343                case CLK_STG1703:
2344                        par->pll_ops = &aty_pll_stg1703;
2345                        break;
2346                case CLK_CH8398:
2347                        par->pll_ops = &aty_pll_ch8398;
2348                        break;
2349                case CLK_ATT20C408:
2350                        par->pll_ops = &aty_pll_att20c408;
2351                        break;
2352#endif
2353                default:
2354                        PRINTKI("aty_init: CLK type not implemented yet!");
2355                        par->pll_ops = &aty_pll_unsupported;
2356                        break;
2357                }
2358        }
2359#endif /* CONFIG_FB_ATY_GX */
2360#ifdef CONFIG_FB_ATY_CT
2361        if (M64_HAS(INTEGRATED)) {
2362                par->dac_ops = &aty_dac_ct;
2363                par->pll_ops = &aty_pll_ct;
2364                par->bus_type = PCI;
2365                par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
2366                ramname = aty_ct_ram[par->ram_type];
2367                /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
2368                if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
2369                        par->pll_limits.mclk = 63;
2370                /* Mobility + 32bit memory interface need halved XCLK. */
2371                if (M64_HAS(MOBIL_BUS) && par->ram_type == SDRAM32)
2372                        par->pll_limits.xclk = (par->pll_limits.xclk + 1) >> 1;
2373        }
2374#endif
2375#ifdef CONFIG_PPC_PMAC
2376        /* The Apple iBook1 uses non-standard memory frequencies. We detect it
2377         * and set the frequency manually. */
2378        if (machine_is_compatible("PowerBook2,1")) {
2379                par->pll_limits.mclk = 70;
2380                par->pll_limits.xclk = 53;
2381        }
2382#endif
2383
2384        /* Allow command line to override clocks. */
2385        if (pll)
2386                par->pll_limits.pll_max = pll;
2387        if (mclk)
2388                par->pll_limits.mclk = mclk;
2389        if (xclk)
2390                par->pll_limits.xclk = xclk;
2391
2392        aty_calc_mem_refresh(par, par->pll_limits.xclk);
2393        par->pll_per = 1000000/par->pll_limits.pll_max;
2394        par->mclk_per = 1000000/par->pll_limits.mclk;
2395        par->xclk_per = 1000000/par->pll_limits.xclk;
2396
2397        par->ref_clk_per = 1000000000000ULL / 14318180;
2398        xtal = "14.31818";
2399
2400#ifdef CONFIG_FB_ATY_CT
2401        if (M64_HAS(GTB_DSP)) {
2402                u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
2403
2404                if (pll_ref_div) {
2405                        int diff1, diff2;
2406                        diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
2407                        diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
2408                        if (diff1 < 0)
2409                                diff1 = -diff1;
2410                        if (diff2 < 0)
2411                                diff2 = -diff2;
2412                        if (diff2 < diff1) {
2413                                par->ref_clk_per = 1000000000000ULL / 29498928;
2414                                xtal = "29.498928";
2415                        }
2416                }
2417        }
2418#endif /* CONFIG_FB_ATY_CT */
2419
2420        /* save previous video mode */
2421        aty_get_crtc(par, &saved_crtc);
2422        if(par->pll_ops->get_pll)
2423                par->pll_ops->get_pll(info, &saved_pll);
2424
2425        par->mem_cntl = aty_ld_le32(MEM_CNTL, par);
2426        gtb_memsize = M64_HAS(GTB_DSP);
2427        if (gtb_memsize)
2428                switch (par->mem_cntl & 0xF) {  /* 0xF used instead of MEM_SIZE_ALIAS */
2429                case MEM_SIZE_512K:
2430                        info->fix.smem_len = 0x80000;
2431                        break;
2432                case MEM_SIZE_1M:
2433                        info->fix.smem_len = 0x100000;
2434                        break;
2435                case MEM_SIZE_2M_GTB:
2436                        info->fix.smem_len = 0x200000;
2437                        break;
2438                case MEM_SIZE_4M_GTB:
2439                        info->fix.smem_len = 0x400000;
2440                        break;
2441                case MEM_SIZE_6M_GTB:
2442                        info->fix.smem_len = 0x600000;
2443                        break;
2444                case MEM_SIZE_8M_GTB:
2445                        info->fix.smem_len = 0x800000;
2446                        break;
2447                default:
2448                        info->fix.smem_len = 0x80000;
2449        } else
2450                switch (par->mem_cntl & MEM_SIZE_ALIAS) {
2451                case MEM_SIZE_512K:
2452                        info->fix.smem_len = 0x80000;
2453                        break;
2454                case MEM_SIZE_1M:
2455                        info->fix.smem_len = 0x100000;
2456                        break;
2457                case MEM_SIZE_2M:
2458                        info->fix.smem_len = 0x200000;
2459                        break;
2460                case MEM_SIZE_4M:
2461                        info->fix.smem_len = 0x400000;
2462                        break;
2463                case MEM_SIZE_6M:
2464                        info->fix.smem_len = 0x600000;
2465                        break;
2466                case MEM_SIZE_8M:
2467                        info->fix.smem_len = 0x800000;
2468                        break;
2469                default:
2470                        info->fix.smem_len = 0x80000;
2471                }
2472
2473        if (M64_HAS(MAGIC_VRAM_SIZE)) {
2474                if (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000)
2475                        info->fix.smem_len += 0x400000;
2476        }
2477
2478        if (vram) {
2479                info->fix.smem_len = vram * 1024;
2480                par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
2481                if (info->fix.smem_len <= 0x80000)
2482                        par->mem_cntl |= MEM_SIZE_512K;
2483                else if (info->fix.smem_len <= 0x100000)
2484                        par->mem_cntl |= MEM_SIZE_1M;
2485                else if (info->fix.smem_len <= 0x200000)
2486                        par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
2487                else if (info->fix.smem_len <= 0x400000)
2488                        par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
2489                else if (info->fix.smem_len <= 0x600000)
2490                        par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
2491                else
2492                        par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
2493                aty_st_le32(MEM_CNTL, par->mem_cntl, par);
2494        }
2495
2496        /*
2497         *  Reg Block 0 (CT-compatible block) is at mmio_start
2498         *  Reg Block 1 (multimedia extensions) is at mmio_start - 0x400
2499         */
2500        if (M64_HAS(GX)) {
2501                info->fix.mmio_len = 0x400;
2502                info->fix.accel = FB_ACCEL_ATI_MACH64GX;
2503        } else if (M64_HAS(CT)) {
2504                info->fix.mmio_len = 0x400;
2505                info->fix.accel = FB_ACCEL_ATI_MACH64CT;
2506        } else if (M64_HAS(VT)) {
2507                info->fix.mmio_start -= 0x400;
2508                info->fix.mmio_len = 0x800;
2509                info->fix.accel = FB_ACCEL_ATI_MACH64VT;
2510        } else {/* GT */
2511                info->fix.mmio_start -= 0x400;
2512                info->fix.mmio_len = 0x800;
2513                info->fix.accel = FB_ACCEL_ATI_MACH64GT;
2514        }
2515
2516        PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
2517               info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len >> 20),
2518               info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max,
2519               par->pll_limits.mclk, par->pll_limits.xclk);
2520
2521#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
2522        if (M64_HAS(INTEGRATED)) {
2523                int i;
2524                printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
2525                       "DSP_CONFIG DSP_ON_OFF CLOCK_CNTL\n"
2526                       "debug atyfb: %08x %08x %08x %08x     %08x      %08x   %08x   %08x\n"
2527                       "debug atyfb: PLL",
2528                        aty_ld_le32(BUS_CNTL, par), aty_ld_le32(DAC_CNTL, par),
2529                        aty_ld_le32(MEM_CNTL, par), aty_ld_le32(EXT_MEM_CNTL, par),
2530                        aty_ld_le32(CRTC_GEN_CNTL, par), aty_ld_le32(DSP_CONFIG, par),
2531                        aty_ld_le32(DSP_ON_OFF, par), aty_ld_le32(CLOCK_CNTL, par));
2532                for (i = 0; i < 40; i++)
2533                        printk(" %02x", aty_ld_pll_ct(i, par));
2534                printk("\n");
2535        }
2536#endif
2537        if(par->pll_ops->init_pll)
2538                par->pll_ops->init_pll(info, &par->pll);
2539        if (par->pll_ops->resume_pll)
2540                par->pll_ops->resume_pll(info, &par->pll);
2541
2542        /*
2543         *  Last page of 8 MB (4 MB on ISA) aperture is MMIO,
2544         *  unless the auxiliary register aperture is used.
2545         */
2546
2547        if (!par->aux_start &&
2548                (info->fix.smem_len == 0x800000 || (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
2549                info->fix.smem_len -= GUI_RESERVE;
2550
2551        /*
2552         *  Disable register access through the linear aperture
2553         *  if the auxiliary aperture is used so we can access
2554         *  the full 8 MB of video RAM on 8 MB boards.
2555         */
2556        if (par->aux_start)
2557                aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
2558
2559#ifdef CONFIG_MTRR
2560        par->mtrr_aper = -1;
2561        par->mtrr_reg = -1;
2562        if (!nomtrr) {
2563                /* Cover the whole resource. */
2564                 par->mtrr_aper = mtrr_add(par->res_start, par->res_size, MTRR_TYPE_WRCOMB, 1);
2565                 if (par->mtrr_aper >= 0 && !par->aux_start) {
2566                        /* Make a hole for mmio. */
2567                        par->mtrr_reg = mtrr_add(par->res_start + 0x800000 - GUI_RESERVE,
2568                                GUI_RESERVE, MTRR_TYPE_UNCACHABLE, 1);
2569                        if (par->mtrr_reg < 0) {
2570                                mtrr_del(par->mtrr_aper, 0, 0);
2571                                par->mtrr_aper = -1;
2572                        }
2573                 }
2574        }
2575#endif
2576
2577        info->fbops = &atyfb_ops;
2578        info->pseudo_palette = par->pseudo_palette;
2579        info->flags = FBINFO_DEFAULT           |
2580                      FBINFO_HWACCEL_IMAGEBLIT |
2581                      FBINFO_HWACCEL_FILLRECT  |
2582                      FBINFO_HWACCEL_COPYAREA  |
2583                      FBINFO_HWACCEL_YPAN;
2584
2585#ifdef CONFIG_PMAC_BACKLIGHT
2586        if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) {
2587                /* these bits let the 101 powerbook wake up from sleep -- paulus */
2588                aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par)
2589                           | (USE_F32KHZ | TRISTATE_MEM_EN), par);
2590        } else
2591#endif
2592        if (M64_HAS(MOBIL_BUS) && backlight) {
2593#ifdef CONFIG_FB_ATY_BACKLIGHT
2594                aty_bl_init (par);
2595#endif
2596        }
2597
2598        memset(&var, 0, sizeof(var));
2599#ifdef CONFIG_PPC
2600        if (machine_is(powermac)) {
2601                /*
2602                 *  FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
2603                 *         applies to all Mac video cards
2604                 */
2605                if (mode) {
2606                        if (mac_find_mode(&var, info, mode, 8))
2607                                has_var = 1;
2608                } else {
2609                        if (default_vmode == VMODE_CHOOSE) {
2610                                int sense;
2611                                if (M64_HAS(G3_PB_1024x768))
2612                                        /* G3 PowerBook with 1024x768 LCD */
2613                                        default_vmode = VMODE_1024_768_60;
2614                                else if (machine_is_compatible("iMac"))
2615                                        default_vmode = VMODE_1024_768_75;
2616                                else if (machine_is_compatible
2617                                         ("PowerBook2,1"))
2618                                        /* iBook with 800x600 LCD */
2619                                        default_vmode = VMODE_800_600_60;
2620                                else
2621                                        default_vmode = VMODE_640_480_67;
2622                                sense = read_aty_sense(par);
2623                                PRINTKI("monitor sense=%x, mode %d\n",
2624                                        sense,  mac_map_monitor_sense(sense));
2625                        }
2626                        if (default_vmode <= 0 || default_vmode > VMODE_MAX)
2627                                default_vmode = VMODE_640_480_60;
2628                        if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
2629                                default_cmode = CMODE_8;
2630                        if (!mac_vmode_to_var(default_vmode, default_cmode,
2631                                               &var))
2632                                has_var = 1;
2633                }
2634        }
2635
2636#endif /* !CONFIG_PPC */
2637
2638#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
2639        if (!atyfb_get_timings_from_lcd(par, &var))
2640                has_var = 1;
2641#endif
2642
2643        if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
2644                has_var = 1;
2645
2646        if (!has_var)
2647                var = default_var;
2648
2649        if (noaccel)
2650                var.accel_flags &= ~FB_ACCELF_TEXT;
2651        else
2652                var.accel_flags |= FB_ACCELF_TEXT;
2653
2654        if (comp_sync != -1) {
2655                if (!comp_sync)
2656                        var.sync &= ~FB_SYNC_COMP_HIGH_ACT;
2657                else
2658                        var.sync |= FB_SYNC_COMP_HIGH_ACT;
2659        }
2660
2661        if (var.yres == var.yres_virtual) {
2662                u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
2663                var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
2664                if (var.yres_virtual < var.yres)
2665                        var.yres_virtual = var.yres;
2666        }
2667
2668        if (atyfb_check_var(&var, info)) {
2669                PRINTKE("can't set default video mode\n");
2670                goto aty_init_exit;
2671        }
2672
2673#ifdef __sparc__
2674        atyfb_save_palette(par, 0);
2675#endif
2676
2677#ifdef CONFIG_FB_ATY_CT
2678        if (!noaccel && M64_HAS(INTEGRATED))
2679                aty_init_cursor(info);
2680#endif /* CONFIG_FB_ATY_CT */
2681        info->var = var;
2682
2683        fb_alloc_cmap(&info->cmap, 256, 0);
2684
2685        if (register_framebuffer(info) < 0)
2686                goto aty_init_exit;
2687
2688        fb_list = info;
2689
2690        PRINTKI("fb%d: %s frame buffer device on %s\n",
2691                info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
2692        return 0;
2693
2694aty_init_exit:
2695        /* restore video mode */
2696        aty_set_crtc(par, &saved_crtc);
2697        par->pll_ops->set_pll(info, &saved_pll);
2698
2699#ifdef CONFIG_MTRR
2700        if (par->mtrr_reg >= 0) {
2701            mtrr_del(par->mtrr_reg, 0, 0);
2702            par->mtrr_reg = -1;
2703        }
2704        if (par->mtrr_aper >= 0) {
2705            mtrr_del(par->mtrr_aper, 0, 0);
2706            par->mtrr_aper = -1;
2707        }
2708#endif
2709        return -1;
2710}
2711
2712static void aty_resume_chip(struct fb_info *info)
2713{
2714        struct atyfb_par *par = info->par;
2715
2716        aty_st_le32(MEM_CNTL, par->mem_cntl, par);
2717
2718        if (par->pll_ops->resume_pll)
2719                par->pll_ops->resume_pll(info, &par->pll);
2720
2721        if (par->aux_start)
2722                aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
2723}
2724
2725#ifdef CONFIG_ATARI
2726static int __devinit store_video_par(char *video_str, unsigned char m64_num)
2727{
2728        char *p;
2729        unsigned long vmembase, size, guiregbase;
2730
2731        PRINTKI("store_video_par() '%s' \n", video_str);
2732
2733        if (!(p = strsep(&video_str, ";")) || !*p)
2734                goto mach64_invalid;
2735        vmembase = simple_strtoul(p, NULL, 0);
2736        if (!(p = strsep(&video_str, ";")) || !*p)
2737                goto mach64_invalid;
2738        size = simple_strtoul(p, NULL, 0);
2739        if (!(p = strsep(&video_str, ";")) || !*p)
2740                goto mach64_invalid;
2741        guiregbase = simple_strtoul(p, NULL, 0);
2742
2743        phys_vmembase[m64_num] = vmembase;
2744        phys_size[m64_num] = size;
2745        phys_guiregbase[m64_num] = guiregbase;
2746        PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
2747               guiregbase);
2748        return 0;
2749
2750      mach64_invalid:
2751        phys_vmembase[m64_num] = 0;
2752        return -1;
2753}
2754#endif /* CONFIG_ATARI */
2755
2756    /*
2757     *  Blank the display.
2758     */
2759
2760static int atyfb_blank(int blank, struct fb_info *info)
2761{
2762        struct atyfb_par *par = (struct atyfb_par *) info->par;
2763        u32 gen_cntl;
2764
2765        if (par->lock_blank || par->asleep)
2766                return 0;
2767
2768#ifdef CONFIG_FB_ATY_BACKLIGHT
2769#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2770        if (par->lcd_table && blank > FB_BLANK_NORMAL &&
2771            (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2772                u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2773                pm &= ~PWR_BLON;
2774                aty_st_lcd(POWER_MANAGEMENT, pm, par);
2775        }
2776#endif
2777
2778        gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
2779        gen_cntl &= ~0x400004c;
2780        switch (blank) {
2781                case FB_BLANK_UNBLANK:
2782                        break;
2783                case FB_BLANK_NORMAL:
2784                        gen_cntl |= 0x4000040;
2785                        break;
2786                case FB_BLANK_VSYNC_SUSPEND:
2787                        gen_cntl |= 0x4000048;
2788                        break;
2789                case FB_BLANK_HSYNC_SUSPEND:
2790                        gen_cntl |= 0x4000044;
2791                        break;
2792                case FB_BLANK_POWERDOWN:
2793                        gen_cntl |= 0x400004c;
2794                        break;
2795        }
2796        aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
2797
2798#ifdef CONFIG_FB_ATY_BACKLIGHT
2799#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
2800        if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
2801            (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
2802                u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
2803                pm |= PWR_BLON;
2804                aty_st_lcd(POWER_MANAGEMENT, pm, par);
2805        }
2806#endif
2807
2808        return 0;
2809}
2810
2811static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
2812                       const struct atyfb_par *par)
2813{
2814        aty_st_8(DAC_W_INDEX, regno, par);
2815        aty_st_8(DAC_DATA, red, par);
2816        aty_st_8(DAC_DATA, green, par);
2817        aty_st_8(DAC_DATA, blue, par);
2818}
2819
2820    /*
2821     *  Set a single color register. The values supplied are already
2822     *  rounded down to the hardware's capabilities (according to the
2823     *  entries in the var structure). Return != 0 for invalid regno.
2824     *  !! 4 & 8 =  PSEUDO, > 8 = DIRECTCOLOR
2825     */
2826
2827static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2828        u_int transp, struct fb_info *info)
2829{
2830        struct atyfb_par *par = (struct atyfb_par *) info->par;
2831        int i, depth;
2832        u32 *pal = info->pseudo_palette;
2833
2834        depth = info->var.bits_per_pixel;
2835        if (depth == 16)
2836                depth = (info->var.green.length == 5) ? 15 : 16;
2837
2838        if (par->asleep)
2839                return 0;
2840
2841        if (regno > 255 ||
2842            (depth == 16 && regno > 63) ||
2843            (depth == 15 && regno > 31))
2844                return 1;
2845
2846        red >>= 8;
2847        green >>= 8;
2848        blue >>= 8;
2849
2850        par->palette[regno].red = red;
2851        par->palette[regno].green = green;
2852        par->palette[regno].blue = blue;
2853
2854        if (regno < 16) {
2855                switch (depth) {
2856                case 15:
2857                        pal[regno] = (regno << 10) | (regno << 5) | regno;
2858                        break;
2859                case 16:
2860                        pal[regno] = (regno << 11) | (regno << 5) | regno;
2861                        break;
2862                case 24:
2863                        pal[regno] = (regno << 16) | (regno << 8) | regno;
2864                        break;
2865                case 32:
2866                        i = (regno << 8) | regno;
2867                        pal[regno] = (i << 16) | i;
2868                        break;
2869                }
2870        }
2871
2872        i = aty_ld_8(DAC_CNTL, par) & 0xfc;
2873        if (M64_HAS(EXTRA_BRIGHT))
2874                i |= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
2875        aty_st_8(DAC_CNTL, i, par);
2876        aty_st_8(DAC_MASK, 0xff, par);
2877
2878        if (M64_HAS(INTEGRATED)) {
2879                if (depth == 16) {
2880                        if (regno < 32)
2881                                aty_st_pal(regno << 3, red,
2882                                           par->palette[regno<<1].green,
2883                                           blue, par);
2884                        red = par->palette[regno>>1].red;
2885                        blue = par->palette[regno>>1].blue;
2886                        regno <<= 2;
2887                } else if (depth == 15) {
2888                        regno <<= 3;
2889                        for(i = 0; i < 8; i++) {
2890                            aty_st_pal(regno + i, red, green, blue, par);
2891                        }
2892                }
2893        }
2894        aty_st_pal(regno, red, green, blue, par);
2895
2896        return 0;
2897}
2898
2899#ifdef CONFIG_PCI
2900
2901#ifdef __sparc__
2902
2903extern void (*prom_palette) (int);
2904
2905static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
2906                        struct fb_info *info, unsigned long addr)
2907{
2908        struct atyfb_par *par = info->par;
2909        struct device_node *dp;
2910        char prop[128];
2911        int node, len, i, j, ret;
2912        u32 mem, chip_id;
2913
2914        /*
2915         * Map memory-mapped registers.
2916         */
2917        par->ati_regbase = (void *)addr + 0x7ffc00UL;
2918        info->fix.mmio_start = addr + 0x7ffc00UL;
2919
2920        /*
2921         * Map in big-endian aperture.
2922         */
2923        info->screen_base = (char *) (addr + 0x800000UL);
2924        info->fix.smem_start = addr + 0x800000UL;
2925
2926        /*
2927         * Figure mmap addresses from PCI config space.
2928         * Split Framebuffer in big- and little-endian halfs.
2929         */
2930        for (i = 0; i < 6 && pdev->resource[i].start; i++)
2931                /* nothing */ ;
2932        j = i + 4;
2933
2934        par->mmap_map = kcalloc(j, sizeof(*par->mmap_map), GFP_ATOMIC);
2935        if (!par->mmap_map) {
2936                PRINTKE("atyfb_setup_sparc() can't alloc mmap_map\n");
2937                return -ENOMEM;
2938        }
2939
2940        for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
2941                struct resource *rp = &pdev->resource[i];
2942                int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
2943                unsigned long base;
2944                u32 size, pbase;
2945
2946                base = rp->start;
2947
2948                io = (rp->flags & IORESOURCE_IO);
2949
2950                size = rp->end - base + 1;
2951
2952                pci_read_config_dword(pdev, breg, &pbase);
2953
2954                if (io)
2955                        size &= ~1;
2956
2957                /*
2958                 * Map the framebuffer a second time, this time without
2959                 * the braindead _PAGE_IE setting. This is used by the
2960                 * fixed Xserver, but we need to maintain the old mapping
2961                 * to stay compatible with older ones...
2962                 */
2963                if (base == addr) {
2964                        par->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
2965                        par->mmap_map[j].poff = base & PAGE_MASK;
2966                        par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
2967                        par->mmap_map[j].prot_mask = _PAGE_CACHE;
2968                        par->mmap_map[j].prot_flag = _PAGE_E;
2969                        j++;
2970                }
2971
2972                /*
2973                 * Here comes the old framebuffer mapping with _PAGE_IE
2974                 * set for the big endian half of the framebuffer...
2975                 */
2976                if (base == addr) {
2977                        par->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
2978                        par->mmap_map[j].poff = (base + 0x800000) & PAGE_MASK;
2979                        par->mmap_map[j].size = 0x800000;
2980                        par->mmap_map[j].prot_mask = _PAGE_CACHE;
2981                        par->mmap_map[j].prot_flag = _PAGE_E | _PAGE_IE;
2982                        size -= 0x800000;
2983                        j++;
2984                }
2985
2986                par->mmap_map[j].voff = pbase & PAGE_MASK;
2987                par->mmap_map[j].poff = base & PAGE_MASK;
2988                par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
2989                par->mmap_map[j].prot_mask = _PAGE_CACHE;
2990                par->mmap_map[j].prot_flag = _PAGE_E;
2991                j++;
2992        }
2993
2994        if((ret = correct_chipset(par)))
2995                return ret;
2996
2997        if (IS_XL(pdev->device)) {
2998                /*
2999                 * Fix PROMs idea of MEM_CNTL settings...
3000                 */
3001                mem = aty_ld_le32(MEM_CNTL, par);
3002                chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
3003                if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
3004                        switch (mem & 0x0f) {
3005                        case 3:
3006                                mem = (mem & ~(0x0f)) | 2;
3007                                break;
3008                        case 7:
3009                                mem = (mem & ~(0x0f)) | 3;
3010                                break;
3011                        case 9:
3012                                mem = (mem & ~(0x0f)) | 4;
3013                                break;
3014                        case 11:
3015                                mem = (mem & ~(0x0f)) | 5;
3016                                break;
3017                        default:
3018                                break;
3019                        }
3020                        if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM)
3021                                mem &= ~(0x00700000);
3022                }
3023                mem &= ~(0xcf80e000);   /* Turn off all undocumented bits. */
3024                aty_st_le32(MEM_CNTL, mem, par);
3025        }
3026
3027        /*
3028         * If this is the console device, we will set default video
3029         * settings to what the PROM left us with.
3030         */
3031        node = prom_getchild(prom_root_node);
3032        node = prom_searchsiblings(node, "aliases");
3033        if (node) {
3034                len = prom_getproperty(node, "screen", prop, sizeof(prop));
3035                if (len > 0) {
3036                        prop[len] = '\0';
3037                        node = prom_finddevice(prop);
3038                } else
3039                        node = 0;
3040        }
3041
3042        dp = pci_device_to_OF_node(pdev);
3043        if (node == dp->node) {
3044                struct fb_var_screeninfo *var = &default_var;
3045                unsigned int N, P, Q, M, T, R;
3046                u32 v_total, h_total;
3047                struct crtc crtc;
3048                u8 pll_regs[16];
3049                u8 clock_cntl;
3050
3051                crtc.vxres = prom_getintdefault(node, "width", 1024);
3052                crtc.vyres = prom_getintdefault(node, "height", 768);
3053                var->bits_per_pixel = prom_getintdefault(node, "depth", 8);
3054                var->xoffset = var->yoffset = 0;
3055                crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
3056                crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
3057                crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
3058                crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
3059                crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
3060                aty_crtc_to_var(&crtc, var);
3061
3062                h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
3063                v_total = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
3064
3065                /*
3066                 * Read the PLL to figure actual Refresh Rate.
3067                 */
3068                clock_cntl = aty_ld_8(CLOCK_CNTL, par);
3069                /* DPRINTK("CLOCK_CNTL %02x\n", clock_cntl); */
3070                for (i = 0; i < 16; i++)
3071                        pll_regs[i] = aty_ld_pll_ct(i, par);
3072
3073                /*
3074                 * PLL Reference Divider M:
3075                 */
3076                M = pll_regs[2];
3077
3078                /*
3079                 * PLL Feedback Divider N (Dependant on CLOCK_CNTL):
3080                 */
3081                N = pll_regs[7 + (clock_cntl & 3)];
3082
3083                /*
3084                 * PLL Post Divider P (Dependant on CLOCK_CNTL):
3085                 */
3086                P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
3087
3088                /*
3089                 * PLL Divider Q:
3090                 */
3091                Q = N / P;
3092
3093                /*
3094                 * Target Frequency:
3095                 *
3096                 *      T * M
3097                 * Q = -------
3098                 *      2 * R
3099                 *
3100                 * where R is XTALIN (= 14318 or 29498 kHz).
3101                 */
3102                if (IS_XL(pdev->device))
3103                        R = 29498;
3104                else
3105                        R = 14318;
3106
3107                T = 2 * Q * R / M;
3108
3109                default_var.pixclock = 1000000000 / T;
3110        }
3111
3112        return 0;
3113}
3114
3115#else /* __sparc__ */
3116
3117#ifdef __i386__
3118#ifdef CONFIG_FB_ATY_GENERIC_LCD
3119static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base)
3120{
3121        u32 driv_inf_tab, sig;
3122        u16 lcd_ofs;
3123
3124        /* To support an LCD panel, we should know it's dimensions and
3125         *  it's desired pixel clock.
3126         * There are two ways to do it:
3127         *  - Check the startup video mode and calculate the panel
3128         *    size from it. This is unreliable.
3129         *  - Read it from the driver information table in the video BIOS.
3130        */
3131        /* Address of driver information table is at offset 0x78. */
3132        driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78));
3133
3134        /* Check for the driver information table signature. */
3135        sig = (*(u32 *)driv_inf_tab);
3136        if ((sig == 0x54504c24) || /* Rage LT pro */
3137                (sig == 0x544d5224) || /* Rage mobility */
3138                (sig == 0x54435824) || /* Rage XC */
3139                (sig == 0x544c5824)) { /* Rage XL */
3140                PRINTKI("BIOS contains driver information table.\n");
3141                lcd_ofs = (*(u16 *)(driv_inf_tab + 10));
3142                par->lcd_table = 0;
3143                if (lcd_ofs != 0) {
3144                        par->lcd_table = bios_base + lcd_ofs;
3145                }
3146        }
3147
3148        if (par->lcd_table != 0) {
3149                char model[24];
3150                char strbuf[16];
3151                char refresh_rates_buf[100];
3152                int id, tech, f, i, m, default_refresh_rate;
3153                char *txtcolour;
3154                char *txtmonitor;
3155                char *txtdual;
3156                char *txtformat;
3157                u16 width, height, panel_type, refresh_rates;
3158                u16 *lcdmodeptr;
3159                u32 format;
3160                u8 lcd_refresh_rates[16] = {50,56,60,67,70,72,75,76,85,90,100,120,140,150,160,200};
3161                /* The most important information is the panel size at
3162                 * offset 25 and 27, but there's some other nice information
3163                 * which we print to the screen.
3164                 */
3165                id = *(u8 *)par->lcd_table;
3166                strncpy(model,(char *)par->lcd_table+1,24);
3167                model[23]=0;
3168
3169                width = par->lcd_width = *(u16 *)(par->lcd_table+25);
3170                height = par->lcd_height = *(u16 *)(par->lcd_table+27);
3171                panel_type = *(u16 *)(par->lcd_table+29);
3172                if (panel_type & 1)
3173                        txtcolour = "colour";
3174                else
3175                        txtcolour = "monochrome";
3176                if (panel_type & 2)
3177                        txtdual = "dual (split) ";
3178                else
3179                        txtdual = "";
3180                tech = (panel_type>>2) & 63;
3181                switch (tech) {
3182                case 0:
3183                        txtmonitor = "passive matrix";
3184                        break;
3185                case 1:
3186                        txtmonitor = "active matrix";
3187                        break;
3188                case 2:
3189                        txtmonitor = "active addressed STN";
3190                        break;
3191                case 3:
3192                        txtmonitor = "EL";
3193                        break;
3194                case 4:
3195                        txtmonitor = "plasma";
3196                        break;
3197                default:
3198                        txtmonitor = "unknown";
3199                }
3200                format = *(u32 *)(par->lcd_table+57);
3201                if (tech == 0 || tech == 2) {
3202                        switch (format & 7) {
3203                        case 0:
3204                                txtformat = "12 bit interface";
3205                                break;
3206                        case 1:
3207                                txtformat = "16 bit interface";
3208                                break;
3209                        case 2:
3210                                txtformat = "24 bit interface";
3211                                break;
3212                        default:
3213                                txtformat = "unkown format";
3214                        }
3215                } else {
3216                        switch (format & 7) {
3217                        case 0:
3218                                txtformat = "8 colours";
3219                                break;
3220                        case 1:
3221                                txtformat = "512 colours";
3222                                break;
3223                        case 2:
3224                                txtformat = "4096 colours";
3225                                break;
3226                        case 4:
3227                                txtformat = "262144 colours (LT mode)";
3228                                break;
3229                        case 5:
3230                                txtformat = "16777216 colours";
3231                                break;
3232                        case 6:
3233                                txtformat = "262144 colours (FDPI-2 mode)";
3234                                break;
3235                        default:
3236                                txtformat = "unkown format";
3237                        }
3238                }
3239                PRINTKI("%s%s %s monitor detected: %s\n",
3240                        txtdual ,txtcolour, txtmonitor, model);
3241                PRINTKI("       id=%d, %dx%d pixels, %s\n",
3242                        id, width, height, txtformat);
3243                refresh_rates_buf[0] = 0;
3244                refresh_rates = *(u16 *)(par->lcd_table+62);
3245                m = 1;
3246                f = 0;
3247                for (i=0;i<16;i++) {
3248                        if (refresh_rates & m) {
3249                                if (f == 0) {
3250                                        sprintf(strbuf, "%d", lcd_refresh_rates[i]);
3251                                        f++;
3252                                } else {
3253                                        sprintf(strbuf, ",%d", lcd_refresh_rates[i]);
3254                                }
3255                                strcat(refresh_rates_buf,strbuf);
3256                        }
3257                        m = m << 1;
3258                }
3259                default_refresh_rate = (*(u8 *)(par->lcd_table+61) & 0xf0) >> 4;
3260                PRINTKI("       supports refresh rates [%s], default %d Hz\n",
3261                        refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
3262                par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
3263                /* We now need to determine the crtc parameters for the
3264                 * LCD monitor. This is tricky, because they are not stored
3265                 * individually in the BIOS. Instead, the BIOS contains a
3266                 * table of display modes that work for this monitor.
3267                 *
3268                 * The idea is that we search for a mode of the same dimensions
3269                 * as the dimensions of the LCD monitor. Say our LCD monitor
3270                 * is 800x600 pixels, we search for a 800x600 monitor.
3271                 * The CRTC parameters we find here are the ones that we need
3272                 * to use to simulate other resolutions on the LCD screen.
3273                 */
3274                lcdmodeptr = (u16 *)(par->lcd_table + 64);
3275                while (*lcdmodeptr != 0) {
3276                        u32 modeptr;
3277                        u16 mwidth, mheight, lcd_hsync_start, lcd_vsync_start;
3278                        modeptr = bios_base + *lcdmodeptr;
3279
3280                        mwidth = *((u16 *)(modeptr+0));
3281                        mheight = *((u16 *)(modeptr+2));
3282
3283                        if (mwidth == width && mheight == height) {
3284                                par->lcd_pixclock = 100000000 / *((u16 *)(modeptr+9));
3285                                par->lcd_htotal = *((u16 *)(modeptr+17)) & 511;
3286                                par->lcd_hdisp = *((u16 *)(modeptr+19)) & 511;
3287                                lcd_hsync_start = *((u16 *)(modeptr+21)) & 511;
3288                                par->lcd_hsync_dly = (*((u16 *)(modeptr+21)) >> 9) & 7;
3289                                par->lcd_hsync_len = *((u8 *)(modeptr+23)) & 63;
3290
3291                                par->lcd_vtotal = *((u16 *)(modeptr+24)) & 2047;
3292                                par->lcd_vdisp = *((u16 *)(modeptr+26)) & 2047;
3293                                lcd_vsync_start = *((u16 *)(modeptr+28)) & 2047;
3294                                par->lcd_vsync_len = (*((u16 *)(modeptr+28)) >> 11) & 31;
3295
3296                                par->lcd_htotal = (par->lcd_htotal + 1) * 8;
3297                                par->lcd_hdisp = (par->lcd_hdisp + 1) * 8;
3298                                lcd_hsync_start = (lcd_hsync_start + 1) * 8;
3299                                par->lcd_hsync_len = par->lcd_hsync_len * 8;
3300
3301                                par->lcd_vtotal++;
3302                                par->lcd_vdisp++;
3303                                lcd_vsync_start++;
3304
3305                                par->lcd_right_margin = lcd_hsync_start - par->lcd_hdisp;
3306                                par->lcd_lower_margin = lcd_vsync_start - par->lcd_vdisp;
3307                                par->lcd_hblank_len = par->lcd_htotal - par->lcd_hdisp;
3308                                par->lcd_vblank_len = par->lcd_vtotal - par->lcd_vdisp;
3309                                break;
3310                        }
3311
3312                        lcdmodeptr++;
3313                }
3314                if (*lcdmodeptr == 0) {
3315                        PRINTKE("LCD monitor CRTC parameters not found!!!\n");
3316                        /* To do: Switch to CRT if possible. */
3317                } else {
3318                        PRINTKI("       LCD CRTC parameters: %d.%d  %d %d %d %d  %d %d %d %d\n",
3319                                1000000 / par->lcd_pixclock, 1000000 % par->lcd_pixclock,
3320                                par->lcd_hdisp,
3321                                par->lcd_hdisp + par->lcd_right_margin,
3322                                par->lcd_hdisp + par->lcd_right_margin
3323                                        + par->lcd_hsync_dly + par->lcd_hsync_len,
3324                                par->lcd_htotal,
3325                                par->lcd_vdisp,
3326                                par->lcd_vdisp + par->lcd_lower_margin,
3327                                par->lcd_vdisp + par->lcd_lower_margin + par->lcd_vsync_len,
3328                                par->lcd_vtotal);
3329                        PRINTKI("                          : %d %d %d %d %d %d %d %d %d\n",
3330                                par->lcd_pixclock,
3331                                par->lcd_hblank_len - (par->lcd_right_margin +
3332                                        par->lcd_hsync_dly + par->lcd_hsync_len),
3333                                par->lcd_hdisp,
3334                                par->lcd_right_margin,
3335                                par->lcd_hsync_len,
3336                                par->lcd_vblank_len - (par->lcd_lower_margin + par->lcd_vsync_len),
3337                                par->lcd_vdisp,
3338                                par->lcd_lower_margin,
3339                                par->lcd_vsync_len);
3340                }
3341        }
3342}
3343#endif /* CONFIG_FB_ATY_GENERIC_LCD */
3344
3345static int __devinit init_from_bios(struct atyfb_par *par)
3346{
3347        u32 bios_base, rom_addr;
3348        int ret;
3349
3350        rom_addr = 0xc0000 + ((aty_ld_le32(SCRATCH_REG1, par) & 0x7f) << 11);
3351        bios_base = (unsigned long)ioremap(rom_addr, 0x10000);
3352
3353        /* The BIOS starts with 0xaa55. */
3354        if (*((u16 *)bios_base) == 0xaa55) {
3355
3356                u8 *bios_ptr;
3357                u16 rom_table_offset, freq_table_offset;
3358                PLL_BLOCK_MACH64 pll_block;
3359
3360                PRINTKI("Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr, bios_base);
3361
3362                /* check for frequncy table */
3363                bios_ptr = (u8*)bios_base;
3364                rom_table_offset = (u16)(bios_ptr[0x48] | (bios_ptr[0x49] << 8));
3365                freq_table_offset = bios_ptr[rom_table_offset + 16] | (bios_ptr[rom_table_offset + 17] << 8);
3366                memcpy(&pll_block, bios_ptr + freq_table_offset, sizeof(PLL_BLOCK_MACH64));
3367
3368                PRINTKI("BIOS frequency table:\n");
3369                PRINTKI("PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
3370                        pll_block.PCLK_min_freq, pll_block.PCLK_max_freq,
3371                        pll_block.ref_freq, pll_block.ref_divider);
3372                PRINTKI("MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
3373                        pll_block.MCLK_pwd, pll_block.MCLK_max_freq,
3374                        pll_block.XCLK_max_freq, pll_block.SCLK_freq);
3375
3376                par->pll_limits.pll_min = pll_block.PCLK_min_freq/100;
3377                par->pll_limits.pll_max = pll_block.PCLK_max_freq/100;
3378                par->pll_limits.ref_clk = pll_block.ref_freq/100;
3379                par->pll_limits.ref_div = pll_block.ref_divider;
3380                par->pll_limits.sclk = pll_block.SCLK_freq/100;
3381                par->pll_limits.mclk = pll_block.MCLK_max_freq/100;
3382                par->pll_limits.mclk_pm = pll_block.MCLK_pwd/100;
3383                par->pll_limits.xclk = pll_block.XCLK_max_freq/100;
3384#ifdef CONFIG_FB_ATY_GENERIC_LCD
3385                aty_init_lcd(par, bios_base);
3386#endif
3387                ret = 0;
3388        } else {
3389                PRINTKE("no BIOS frequency table found, use parameters\n");
3390                ret = -ENXIO;
3391        }
3392        iounmap((void* __iomem )bios_base);
3393
3394        return ret;
3395}
3396#endif /* __i386__ */
3397
3398static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, unsigned long addr)
3399{
3400        struct atyfb_par *par = info->par;
3401        u16 tmp;
3402        unsigned long raddr;
3403        struct resource *rrp;
3404        int ret = 0;
3405
3406        raddr = addr + 0x7ff000UL;
3407        rrp = &pdev->resource[2];
3408        if ((rrp->flags & IORESOURCE_MEM) && request_mem_region(rrp->start, rrp->end - rrp->start + 1, "atyfb")) {
3409                par->aux_start = rrp->start;
3410                par->aux_size = rrp->end - rrp->start + 1;
3411                raddr = rrp->start;
3412                PRINTKI("using auxiliary register aperture\n");
3413        }
3414
3415        info->fix.mmio_start = raddr;
3416        par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
3417        if (par->ati_regbase == 0)
3418                return -ENOMEM;
3419
3420        info->fix.mmio_start += par->aux_start ? 0x400 : 0xc00;
3421        par->ati_regbase += par->aux_start ? 0x400 : 0xc00;
3422
3423        /*
3424         * Enable memory-space accesses using config-space
3425         * command register.
3426         */
3427        pci_read_config_word(pdev, PCI_COMMAND, &tmp);
3428        if (!(tmp & PCI_COMMAND_MEMORY)) {
3429                tmp |= PCI_COMMAND_MEMORY;
3430                pci_write_config_word(pdev, PCI_COMMAND, tmp);
3431        }
3432#ifdef __BIG_ENDIAN
3433        /* Use the big-endian aperture */
3434        addr += 0x800000;
3435#endif
3436
3437        /* Map in frame buffer */
3438        info->fix.smem_start = addr;
3439        info->screen_base = ioremap(addr, 0x800000);
3440        if (info->screen_base == NULL) {
3441                ret = -ENOMEM;
3442                goto atyfb_setup_generic_fail;
3443        }
3444
3445        if((ret = correct_chipset(par)))
3446                goto atyfb_setup_generic_fail;
3447#ifdef __i386__
3448        if((ret = init_from_bios(par)))
3449                goto atyfb_setup_generic_fail;
3450#endif
3451        if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
3452                par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2;
3453        else
3454                par->clk_wr_offset = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
3455
3456        /* according to ATI, we should use clock 3 for acelerated mode */
3457        par->clk_wr_offset = 3;
3458
3459        return 0;
3460
3461atyfb_setup_generic_fail:
3462        iounmap(par->ati_regbase);
3463        par->ati_regbase = NULL;
3464        if (info->screen_base) {
3465                iounmap(info->screen_base);
3466                info->screen_base = NULL;
3467        }
3468        return ret;
3469}
3470
3471#endif /* !__sparc__ */
3472
3473static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3474{
3475        unsigned long addr, res_start, res_size;
3476        struct fb_info *info;
3477        struct resource *rp;
3478        struct atyfb_par *par;
3479        int i, rc = -ENOMEM;
3480
3481        for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--)
3482                if (pdev->device == aty_chips[i].pci_id)
3483                        break;
3484
3485        if (i < 0)
3486                return -ENODEV;
3487
3488        /* Enable device in PCI config */
3489        if (pci_enable_device(pdev)) {
3490                PRINTKE("Cannot enable PCI device\n");
3491                return -ENXIO;
3492        }
3493
3494        /* Find which resource to use */
3495        rp = &pdev->resource[0];
3496        if (rp->flags & IORESOURCE_IO)
3497                rp = &pdev->resource[1];
3498        addr = rp->start;
3499        if (!addr)
3500                return -ENXIO;
3501
3502        /* Reserve space */
3503        res_start = rp->start;
3504        res_size = rp->end - rp->start + 1;
3505        if (!request_mem_region (res_start, res_size, "atyfb"))
3506                return -EBUSY;
3507
3508        /* Allocate framebuffer */
3509        info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev);
3510        if (!info) {
3511                PRINTKE("atyfb_pci_probe() can't alloc fb_info\n");
3512                return -ENOMEM;
3513        }
3514        par = info->par;
3515        info->fix = atyfb_fix;
3516        info->device = &pdev->dev;
3517        par->pci_id = aty_chips[i].pci_id;
3518        par->res_start = res_start;
3519        par->res_size = res_size;
3520        par->irq = pdev->irq;
3521        par->pdev = pdev;
3522
3523        /* Setup "info" structure */
3524#ifdef __sparc__
3525        rc = atyfb_setup_sparc(pdev, info, addr);
3526#else
3527        rc = atyfb_setup_generic(pdev, info, addr);
3528#endif
3529        if (rc)
3530                goto err_release_mem;
3531
3532        pci_set_drvdata(pdev, info);
3533
3534        /* Init chip & register framebuffer */
3535        if (aty_init(info))
3536                goto err_release_io;
3537
3538#ifdef __sparc__
3539        if (!prom_palette)
3540                prom_palette = atyfb_palette;
3541
3542        /*
3543         * Add /dev/fb mmap values.
3544         */
3545        par->mmap_map[0].voff = 0x8000000000000000UL;
3546        par->mmap_map[0].poff = (unsigned long) info->screen_base & PAGE_MASK;
3547        par->mmap_map[0].size = info->fix.smem_len;
3548        par->mmap_map[0].prot_mask = _PAGE_CACHE;
3549        par->mmap_map[0].prot_flag = _PAGE_E;
3550        par->mmap_map[1].voff = par->mmap_map[0].voff + info->fix.smem_len;
3551        par->mmap_map[1].poff = (long)par->ati_regbase & PAGE_MASK;
3552        par->mmap_map[1].size = PAGE_SIZE;
3553        par->mmap_map[1].prot_mask = _PAGE_CACHE;
3554        par->mmap_map[1].prot_flag = _PAGE_E;
3555#endif /* __sparc__ */
3556
3557        return 0;
3558
3559err_release_io:
3560#ifdef __sparc__
3561        kfree(par->mmap_map);
3562#else
3563        if (par->ati_regbase)
3564                iounmap(par->ati_regbase);
3565        if (info->screen_base)
3566                iounmap(info->screen_base);
3567#endif
3568err_release_mem:
3569        if (par->aux_start)
3570                release_mem_region(par->aux_start, par->aux_size);
3571
3572        release_mem_region(par->res_start, par->res_size);
3573        framebuffer_release(info);
3574
3575        return rc;
3576}
3577
3578#endif /* CONFIG_PCI */
3579
3580#ifdef CONFIG_ATARI
3581
3582static int __init atyfb_atari_probe(void)
3583{
3584        struct atyfb_par *par;
3585        struct fb_info *info;
3586        int m64_num;
3587        u32 clock_r;
3588        int num_found = 0;
3589
3590        for (m64_num = 0; m64_num < mach64_count; m64_num++) {
3591                if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
3592                    !phys_guiregbase[m64_num]) {
3593                    PRINTKI("phys_*[%d] parameters not set => returning early. \n", m64_num);
3594                        continue;
3595                }
3596
3597                info = framebuffer_alloc(sizeof(struct atyfb_par), NULL);
3598                if (!info) {
3599                        PRINTKE("atyfb_atari_probe() can't alloc fb_info\n");
3600                        return -ENOMEM;
3601                }
3602                par = info->par;
3603
3604                info->fix = atyfb_fix;
3605
3606                par->irq = (unsigned int) -1; /* something invalid */
3607
3608                /*
3609                 *  Map the video memory (physical address given) to somewhere in the
3610                 *  kernel address space.
3611                 */
3612                info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
3613                info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
3614                par->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000) +
3615                                                0xFC00ul;
3616                info->fix.mmio_start = (unsigned long)par->ati_regbase; /* Fake! */
3617
3618                aty_st_le32(CLOCK_CNTL, 0x12345678, par);
3619                clock_r = aty_ld_le32(CLOCK_CNTL, par);
3620
3621                switch (clock_r & 0x003F) {
3622                case 0x12:
3623                        par->clk_wr_offset = 3; /*  */
3624                        break;
3625                case 0x34:
3626                        par->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
3627                        break;
3628                case 0x16:
3629                        par->clk_wr_offset = 1; /*  */
3630                        break;
3631                case 0x38:
3632                        par->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
3633                        break;
3634                }
3635
3636                /* Fake pci_id for correct_chipset() */
3637                switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) {
3638                case 0x00d7:
3639                        par->pci_id = PCI_CHIP_MACH64GX;
3640                        break;
3641                case 0x0057:
3642                        par->pci_id = PCI_CHIP_MACH64CX;
3643                        break;
3644                default:
3645                        break;
3646                }
3647
3648                if (correct_chipset(par) || aty_init(info)) {
3649                        iounmap(info->screen_base);
3650                        iounmap(par->ati_regbase);
3651                        framebuffer_release(info);
3652                } else {
3653                        num_found++;
3654                }
3655        }
3656
3657        return num_found ? 0 : -ENXIO;
3658}
3659
3660#endif /* CONFIG_ATARI */
3661
3662#ifdef CONFIG_PCI
3663
3664static void __devexit atyfb_remove(struct fb_info *info)
3665{
3666        struct atyfb_par *par = (struct atyfb_par *) info->par;
3667
3668        /* restore video mode */
3669        aty_set_crtc(par, &saved_crtc);
3670        par->pll_ops->set_pll(info, &saved_pll);
3671
3672        unregister_framebuffer(info);
3673
3674#ifdef CONFIG_FB_ATY_BACKLIGHT
3675        if (M64_HAS(MOBIL_BUS))
3676                aty_bl_exit(info->bl_dev);
3677#endif
3678
3679#ifdef CONFIG_MTRR
3680        if (par->mtrr_reg >= 0) {
3681            mtrr_del(par->mtrr_reg, 0, 0);
3682            par->mtrr_reg = -1;
3683        }
3684        if (par->mtrr_aper >= 0) {
3685            mtrr_del(par->mtrr_aper, 0, 0);
3686            par->mtrr_aper = -1;
3687        }
3688#endif
3689#ifndef __sparc__
3690        if (par->ati_regbase)
3691                iounmap(par->ati_regbase);
3692        if (info->screen_base)
3693                iounmap(info->screen_base);
3694#ifdef __BIG_ENDIAN
3695        if (info->sprite.addr)
3696                iounmap(info->sprite.addr);
3697#endif
3698#endif
3699#ifdef __sparc__
3700        kfree(par->mmap_map);
3701#endif
3702        if (par->aux_start)
3703                release_mem_region(par->aux_start, par->aux_size);
3704
3705        if (par->res_start)
3706                release_mem_region(par->res_start, par->res_size);
3707
3708        framebuffer_release(info);
3709}
3710
3711
3712static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
3713{
3714        struct fb_info *info = pci_get_drvdata(pdev);
3715
3716        atyfb_remove(info);
3717}
3718
3719/*
3720 * This driver uses its own matching table. That will be more difficult
3721 * to fix, so for now, we just match against any ATI ID and let the
3722 * probe() function find out what's up. That also mean we don't have
3723 * a module ID table though.
3724 */
3725static struct pci_device_id atyfb_pci_tbl[] = {
3726        { PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
3727          PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 },
3728        { 0, }
3729};
3730
3731static struct pci_driver atyfb_driver = {
3732        .name           = "atyfb",
3733        .id_table       = atyfb_pci_tbl,
3734        .probe          = atyfb_pci_probe,
3735        .remove         = __devexit_p(atyfb_pci_remove),
3736#ifdef CONFIG_PM
3737        .suspend        = atyfb_pci_suspend,
3738        .resume         = atyfb_pci_resume,
3739#endif /* CONFIG_PM */
3740};
3741
3742#endif /* CONFIG_PCI */
3743
3744#ifndef MODULE
3745static int __init atyfb_setup(char *options)
3746{
3747        char *this_opt;
3748
3749        if (!options || !*options)
3750                return 0;
3751
3752        while ((this_opt = strsep(&options, ",")) != NULL) {
3753                if (!strncmp(this_opt, "noaccel", 7)) {
3754                        noaccel = 1;
3755#ifdef CONFIG_MTRR
3756                } else if (!strncmp(this_opt, "nomtrr", 6)) {
3757                        nomtrr = 1;
3758#endif
3759                } else if (!strncmp(this_opt, "vram:", 5))
3760                        vram = simple_strtoul(this_opt + 5, NULL, 0);
3761                else if (!strncmp(this_opt, "pll:", 4))
3762                        pll = simple_strtoul(this_opt + 4, NULL, 0);
3763                else if (!strncmp(this_opt, "mclk:", 5))
3764                        mclk = simple_strtoul(this_opt + 5, NULL, 0);
3765                else if (!strncmp(this_opt, "xclk:", 5))
3766                        xclk = simple_strtoul(this_opt+5, NULL, 0);
3767                else if (!strncmp(this_opt, "comp_sync:", 10))
3768                        comp_sync = simple_strtoul(this_opt+10, NULL, 0);
3769                else if (!strncmp(this_opt, "backlight:", 10))
3770                        backlight = simple_strtoul(this_opt+10, NULL, 0);
3771#ifdef CONFIG_PPC
3772                else if (!strncmp(this_opt, "vmode:", 6)) {
3773                        unsigned int vmode =
3774                            simple_strtoul(this_opt + 6, NULL, 0);
3775                        if (vmode > 0 && vmode <= VMODE_MAX)
3776                                default_vmode = vmode;
3777                } else if (!strncmp(this_opt, "cmode:", 6)) {
3778                        unsigned int cmode =
3779                            simple_strtoul(this_opt + 6, NULL, 0);
3780                        switch (cmode) {
3781                        case 0:
3782                        case 8:
3783                                default_cmode = CMODE_8;
3784                                break;
3785                        case 15:
3786                        case 16:
3787                                default_cmode = CMODE_16;
3788                                break;
3789                        case 24:
3790                        case 32:
3791                                default_cmode = CMODE_32;
3792                                break;
3793                        }
3794                }
3795#endif
3796#ifdef CONFIG_ATARI
3797                /*
3798                 * Why do we need this silly Mach64 argument?
3799                 * We are already here because of mach64= so its redundant.
3800                 */
3801                else if (MACH_IS_ATARI
3802                         && (!strncmp(this_opt, "Mach64:", 7))) {
3803                        static unsigned char m64_num;
3804                        static char mach64_str[80];
3805                        strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
3806                        if (!store_video_par(mach64_str, m64_num)) {
3807                                m64_num++;
3808                                mach64_count = m64_num;
3809                        }
3810                }
3811#endif
3812                else
3813                        mode = this_opt;
3814        }
3815        return 0;
3816}
3817#endif  /*  MODULE  */
3818
3819static int __init atyfb_init(void)
3820{
3821    int err1 = 1, err2 = 1;
3822#ifndef MODULE
3823    char *option = NULL;
3824
3825    if (fb_get_options("atyfb", &option))
3826        return -ENODEV;
3827    atyfb_setup(option);
3828#endif
3829
3830#ifdef CONFIG_PCI
3831    err1 = pci_register_driver(&atyfb_driver);
3832#endif
3833#ifdef CONFIG_ATARI
3834    err2 = atyfb_atari_probe();
3835#endif
3836
3837    return (err1 && err2) ? -ENODEV : 0;
3838}
3839
3840static void __exit atyfb_exit(void)
3841{
3842#ifdef CONFIG_PCI
3843        pci_unregister_driver(&atyfb_driver);
3844#endif
3845}
3846
3847module_init(atyfb_init);
3848module_exit(atyfb_exit);
3849
3850MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
3851MODULE_LICENSE("GPL");
3852module_param(noaccel, bool, 0);
3853MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
3854module_param(vram, int, 0);
3855MODULE_PARM_DESC(vram, "int: override size of video ram");
3856module_param(pll, int, 0);
3857MODULE_PARM_DESC(pll, "int: override video clock");
3858module_param(mclk, int, 0);
3859MODULE_PARM_DESC(mclk, "int: override memory clock");
3860module_param(xclk, int, 0);
3861MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
3862module_param(comp_sync, int, 0);
3863MODULE_PARM_DESC(comp_sync,
3864                 "Set composite sync signal to low (0) or high (1)");
3865module_param(mode, charp, 0);
3866MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
3867#ifdef CONFIG_MTRR
3868module_param(nomtrr, bool, 0);
3869MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
3870#endif
3871