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