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