^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* $Id: aty128fb.c,v 1.1.1.1.36.1 1999/12/11 09:03:05 Exp $
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/drivers/video/aty128fb.c -- Frame buffer device for ATI Rage128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1999-2003, Brad Douglas <brad@neruo.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1999, Anthony Tong <atong@uiuc.edu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Ani Joshi / Jeff Garzik
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * - Code cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Michel Danzer <michdaen@iiic.ethz.ch>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * - 15/16 bit cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * - fix panning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Benjamin Herrenschmidt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * - pmac-specific PM stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * - various fixes & cleanups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Andreas Hundt <andi@convergence.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * - FB_ACTIVATE fixes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Paul Mackerras <paulus@samba.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * - Convert to new framebuffer API,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * fix colormap setting at 16 bits/pixel (565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Paul Mundt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * - PCI hotplug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Jon Smirl <jonsmirl@yahoo.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - PCI ID update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * - replace ROM BIOS search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * Based off of Geert's atyfb.c and vfb.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * - monitor sensing (DDC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * - virtual display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * - other platform support (only ppc/x86 supported)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * - hardware cursor support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Please cc: your patches to brad@neruo.com.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * A special note of gratitude to ATI's devrel for providing documentation,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * example code and hardware. Thanks Nitya. -atong and brad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include <linux/backlight.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #include <asm/machdep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #include <asm/pmac_feature.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #include "../macmodes.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #ifdef CONFIG_PMAC_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #include <asm/backlight.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #ifdef CONFIG_BOOTX_TEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #include <asm/btext.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #endif /* CONFIG_BOOTX_TEXT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #include <video/aty128.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* Debug flag */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define DBG(fmt, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) printk(KERN_DEBUG "aty128fb: %s " fmt, __func__, ##args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define DBG(fmt, args...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #ifndef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* default mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static const struct fb_var_screeninfo default_var = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) 640, 480, 640, 480, 0, 0, 8, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 0, FB_VMODE_NONINTERLACED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #else /* CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* default to 1024x768 at 75Hz on PPC - this will work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * on the iMac, the usual 640x480 @ 60Hz doesn't. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static const struct fb_var_screeninfo default_var = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 1024, 768, 1024, 768, 0, 0, 8, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 0, 0, -1, -1, 0, 12699, 160, 32, 28, 1, 96, 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) FB_VMODE_NONINTERLACED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #endif /* CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* default modedb mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static const struct fb_videomode defaultmode = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .refresh = 60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .xres = 640,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .yres = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .pixclock = 39722,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .left_margin = 48,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .right_margin = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .upper_margin = 33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .lower_margin = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .hsync_len = 96,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .vsync_len = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .sync = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .vmode = FB_VMODE_NONINTERLACED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* Chip generations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) rage_128,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) rage_128_pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) rage_128_pro,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) rage_128_pro_pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) rage_M3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) rage_M3_pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) rage_M4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) rage_128_ultra,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* Must match above enum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static char * const r128_family[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "AGP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) "PCI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) "PRO AGP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) "PRO PCI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) "M3 AGP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) "M3 PCI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) "M4 AGP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) "Ultra AGP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * PCI driver prototypes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int aty128_probe(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) const struct pci_device_id *ent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void aty128_remove(struct pci_dev *pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static int aty128_pci_suspend_late(struct device *dev, pm_message_t state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static int __maybe_unused aty128_pci_suspend(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int __maybe_unused aty128_pci_hibernate(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static int __maybe_unused aty128_pci_freeze(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int __maybe_unused aty128_pci_resume(struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static int aty128_do_resume(struct pci_dev *pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static const struct dev_pm_ops aty128_pci_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .suspend = aty128_pci_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .resume = aty128_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .freeze = aty128_pci_freeze,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .thaw = aty128_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .poweroff = aty128_pci_hibernate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .restore = aty128_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* supported Rage128 chipsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static const struct pci_device_id aty128_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3_pci },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_MF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_ML,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_M4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PJ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro_pci },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pro },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_RL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_pci },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_SN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_TU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) PCI_ANY_ID, PCI_ANY_ID, 0, 0, rage_128_ultra },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) MODULE_DEVICE_TABLE(pci, aty128_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static struct pci_driver aty128fb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .name = "aty128fb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .id_table = aty128_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .probe = aty128_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .remove = aty128_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .driver.pm = &aty128_pci_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /* packed BIOS settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) #ifndef CONFIG_PPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) typedef struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) u8 clock_chip_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) u8 struct_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) u8 accelerator_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) u8 VGA_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) u16 VGA_table_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) u16 POST_table_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) u16 XCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) u16 MCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) u8 num_PLL_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) u8 size_PLL_blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) u16 PCLK_ref_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) u16 PCLK_ref_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) u32 PCLK_min_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) u32 PCLK_max_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) u16 MCLK_ref_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) u16 MCLK_ref_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u32 MCLK_min_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) u32 MCLK_max_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) u16 XCLK_ref_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u16 XCLK_ref_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) u32 XCLK_min_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) u32 XCLK_max_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) } __attribute__ ((packed)) PLL_BLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) #endif /* !CONFIG_PPC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* onboard memory information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct aty128_meminfo {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) u8 ML;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) u8 MB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) u8 Trcd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) u8 Trp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) u8 Twr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) u8 CL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u8 Tr2w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) u8 LoopLatency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) u8 DspOn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) u8 Rloop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* various memory configurations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static const struct aty128_meminfo sdr_128 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .ML = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .MB = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .Trcd = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .Trp = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .Twr = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) .CL = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .Tr2w = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .LoopLatency = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .DspOn = 30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .Rloop = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) .name = "128-bit SDR SGRAM (1:1)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static const struct aty128_meminfo sdr_sgram = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) .ML = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) .MB = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) .Trcd = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) .Trp = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .Twr = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .CL = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) .Tr2w = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .LoopLatency = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) .DspOn = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) .Rloop = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) .name = "64-bit SDR SGRAM (2:1)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static const struct aty128_meminfo ddr_sgram = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) .ML = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) .MB = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) .Trcd = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) .Trp = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) .Twr = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) .CL = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) .Tr2w = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) .LoopLatency = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .DspOn = 31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .Rloop = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .name = "64-bit DDR SGRAM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static const struct fb_fix_screeninfo aty128fb_fix = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .id = "ATY Rage128",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .type = FB_TYPE_PACKED_PIXELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .visual = FB_VISUAL_PSEUDOCOLOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .xpanstep = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .ypanstep = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .mmio_len = 0x2000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .accel = FB_ACCEL_ATI_RAGE128,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static char *mode_option = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static int default_vmode = VMODE_1024_768_60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static int default_cmode = CMODE_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static int default_crt_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static int default_lcd_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static bool mtrr = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) #ifdef CONFIG_FB_ATY128_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int backlight = IS_BUILTIN(CONFIG_PMAC_BACKLIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* PLL constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct aty128_constants {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) u32 ref_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) u32 ppll_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) u32 ppll_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) u32 ref_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) u32 xclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) u32 fifo_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) u32 fifo_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct aty128_crtc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) u32 gen_cntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) u32 h_total, h_sync_strt_wid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) u32 v_total, v_sync_strt_wid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) u32 pitch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) u32 offset, offset_cntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) u32 xoffset, yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) u32 vxres, vyres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) u32 depth, bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct aty128_pll {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) u32 post_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) u32 feedback_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) u32 vclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct aty128_ddafifo {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) u32 dda_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) u32 dda_on_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* register values for a specific mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) struct aty128fb_par {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) struct aty128_crtc crtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct aty128_pll pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) struct aty128_ddafifo fifo_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) u32 accel_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct aty128_constants constants; /* PLL and others */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) void __iomem *regbase; /* remapped mmio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) u32 vram_size; /* onboard video ram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) int chip_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) const struct aty128_meminfo *mem; /* onboard mem info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) int wc_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) int blitter_may_be_busy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) int fifo_slots; /* free slots in FIFO (64 max) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) int crt_on, lcd_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct fb_info *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) int asleep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) int lock_blank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) u8 red[32]; /* see aty128fb_setcolreg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) u8 green[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) u8 blue[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) u32 pseudo_palette[16]; /* used for TRUECOLOR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) #define round_div(n, d) ((n+(d/2))/d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static int aty128fb_check_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct fb_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static int aty128fb_set_par(struct fb_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) u_int transp, struct fb_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static int aty128fb_pan_display(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct fb_info *fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static int aty128fb_blank(int blank, struct fb_info *fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static int aty128fb_sync(struct fb_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * Internal routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) static int aty128_encode_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) const struct aty128fb_par *par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int aty128_decode_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct aty128fb_par *par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static void aty128_timings(struct aty128fb_par *par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static void aty128_init_engine(struct aty128fb_par *par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static void aty128_reset_engine(const struct aty128fb_par *par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) static void aty128_flush_pixel_cache(const struct aty128fb_par *par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static void wait_for_idle(struct aty128fb_par *par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static u32 depth_to_dst(u32 depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) #ifdef CONFIG_FB_ATY128_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static void aty128_bl_set_power(struct fb_info *info, int power);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) #define BIOS_IN8(v) (readb(bios + (v)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) #define BIOS_IN16(v) (readb(bios + (v)) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) (readb(bios + (v) + 1) << 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) #define BIOS_IN32(v) (readb(bios + (v)) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) (readb(bios + (v) + 1) << 8) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) (readb(bios + (v) + 2) << 16) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) (readb(bios + (v) + 3) << 24))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static const struct fb_ops aty128fb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .fb_check_var = aty128fb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .fb_set_par = aty128fb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .fb_setcolreg = aty128fb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .fb_pan_display = aty128fb_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .fb_blank = aty128fb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) .fb_ioctl = aty128fb_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) .fb_sync = aty128fb_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) .fb_fillrect = cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) .fb_copyarea = cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) .fb_imageblit = cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * Functions to read from/write to the mmio registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * - endian conversions may possibly be avoided by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * using the other register aperture. TODO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static inline u32 _aty_ld_le32(volatile unsigned int regindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return readl (par->regbase + regindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static inline void _aty_st_le32(volatile unsigned int regindex, u32 val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) writel (val, par->regbase + regindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static inline u8 _aty_ld_8(unsigned int regindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return readb (par->regbase + regindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) static inline void _aty_st_8(unsigned int regindex, u8 val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) writeb (val, par->regbase + regindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) #define aty_ld_le32(regindex) _aty_ld_le32(regindex, par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) #define aty_st_le32(regindex, val) _aty_st_le32(regindex, val, par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) #define aty_ld_8(regindex) _aty_ld_8(regindex, par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) #define aty_st_8(regindex, val) _aty_st_8(regindex, val, par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * Functions to read from/write to the pll registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) #define aty_ld_pll(pll_index) _aty_ld_pll(pll_index, par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) #define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val, par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) static u32 _aty_ld_pll(unsigned int pll_index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x3F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) return aty_ld_le32(CLOCK_CNTL_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static void _aty_st_pll(unsigned int pll_index, u32 val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x3F) | PLL_WR_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) aty_st_le32(CLOCK_CNTL_DATA, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* return true when the PLL has completed an atomic update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static int aty_pll_readupdate(const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static void aty_pll_wait_readupdate(const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) unsigned long timeout = jiffies + HZ/100; // should be more than enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int reset = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) while (time_before(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (aty_pll_readupdate(par)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) reset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (reset) /* reset engine?? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) printk(KERN_DEBUG "aty128fb: PLL write timeout!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /* tell PLL to update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) static void aty_pll_writeupdate(const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) aty_pll_wait_readupdate(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) aty_st_pll(PPLL_REF_DIV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) aty_ld_pll(PPLL_REF_DIV) | PPLL_ATOMIC_UPDATE_W);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* write to the scratch register to test r/w functionality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) static int register_test(const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) val = aty_ld_le32(BIOS_0_SCRATCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) aty_st_le32(BIOS_0_SCRATCH, 0x55555555);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (aty_ld_le32(BIOS_0_SCRATCH) == 0x55555555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) aty_st_le32(BIOS_0_SCRATCH, val); // restore value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * Accelerator engine functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) for (i = 0; i < 2000000; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) par->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (par->fifo_slots >= entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) aty128_reset_engine(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) static void wait_for_idle(struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) do_wait_for_fifo(64, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) for (i = 0; i < 2000000; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (!(aty_ld_le32(GUI_STAT) & (1 << 31))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) aty128_flush_pixel_cache(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) par->blitter_may_be_busy = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) aty128_reset_engine(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static void wait_for_fifo(u16 entries, struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (par->fifo_slots < entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) do_wait_for_fifo(64, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) par->fifo_slots -= entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static void aty128_flush_pixel_cache(const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) tmp = aty_ld_le32(PC_NGUI_CTLSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) tmp &= ~(0x00ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) tmp |= 0x00ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) aty_st_le32(PC_NGUI_CTLSTAT, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) for (i = 0; i < 2000000; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (!(aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static void aty128_reset_engine(const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) u32 gen_reset_cntl, clock_cntl_index, mclk_cntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) aty128_flush_pixel_cache(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) clock_cntl_index = aty_ld_le32(CLOCK_CNTL_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) mclk_cntl = aty_ld_pll(MCLK_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) aty_st_pll(MCLK_CNTL, mclk_cntl | 0x00030000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) gen_reset_cntl = aty_ld_le32(GEN_RESET_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) aty_ld_le32(GEN_RESET_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl & ~(SOFT_RESET_GUI));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) aty_ld_le32(GEN_RESET_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) aty_st_pll(MCLK_CNTL, mclk_cntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) aty_st_le32(CLOCK_CNTL_INDEX, clock_cntl_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /* use old pio mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) DBG("engine reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static void aty128_init_engine(struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) u32 pitch_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) wait_for_idle(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* 3D scaler not spoken here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) wait_for_fifo(1, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) aty_st_le32(SCALE_3D_CNTL, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) aty128_reset_engine(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) pitch_value = par->crtc.pitch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (par->crtc.bpp == 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) pitch_value = pitch_value * 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) wait_for_fifo(4, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /* setup engine offset registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) aty_st_le32(DEFAULT_OFFSET, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) /* setup engine pitch registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) aty_st_le32(DEFAULT_PITCH, pitch_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* set the default scissor register to max dimensions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) aty_st_le32(DEFAULT_SC_BOTTOM_RIGHT, (0x1FFF << 16) | 0x1FFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /* set the drawing controls registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) aty_st_le32(DP_GUI_MASTER_CNTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) GMC_SRC_PITCH_OFFSET_DEFAULT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) GMC_DST_PITCH_OFFSET_DEFAULT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) GMC_SRC_CLIP_DEFAULT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) GMC_DST_CLIP_DEFAULT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) GMC_BRUSH_SOLIDCOLOR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) (depth_to_dst(par->crtc.depth) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) GMC_SRC_DSTCOLOR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) GMC_BYTE_ORDER_MSB_TO_LSB |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) GMC_DP_CONVERSION_TEMP_6500 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) ROP3_PATCOPY |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) GMC_DP_SRC_RECT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) GMC_3D_FCN_EN_CLR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) GMC_DST_CLR_CMP_FCN_CLEAR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) GMC_AUX_CLIP_CLEAR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) GMC_WRITE_MASK_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) wait_for_fifo(8, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /* clear the line drawing registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) aty_st_le32(DST_BRES_ERR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) aty_st_le32(DST_BRES_INC, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) aty_st_le32(DST_BRES_DEC, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /* set brush color registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF); /* white */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000); /* black */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /* set source color registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF); /* white */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000); /* black */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) /* default write mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) /* Wait for all the writes to be completed before returning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) wait_for_idle(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* convert depth values to their register representation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static u32 depth_to_dst(u32 depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (depth <= 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return DST_8BPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) else if (depth <= 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return DST_15BPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) else if (depth == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return DST_16BPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) else if (depth <= 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return DST_24BPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) else if (depth <= 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return DST_32BPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * PLL informations retreival
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) #ifndef __sparc__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static void __iomem *aty128_map_ROM(const struct aty128fb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) u16 dptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) u8 rom_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) void __iomem *bios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) size_t rom_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* Fix from ATI for problem with Rage128 hardware not leaving ROM enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) unsigned int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) temp = aty_ld_le32(RAGE128_MPP_TB_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) temp &= 0x00ffffffu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) temp |= 0x04 << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) aty_st_le32(RAGE128_MPP_TB_CONFIG, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) temp = aty_ld_le32(RAGE128_MPP_TB_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) bios = pci_map_rom(dev, &rom_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) if (!bios) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) printk(KERN_ERR "aty128fb: ROM failed to map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /* Very simple test to make sure it appeared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (BIOS_IN16(0) != 0xaa55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) printk(KERN_DEBUG "aty128fb: Invalid ROM signature %x should "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) " be 0xaa55\n", BIOS_IN16(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /* Look for the PCI data to check the ROM type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) dptr = BIOS_IN16(0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) /* Check the PCI data signature. If it's wrong, we still assume a normal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * x86 ROM for now, until I've verified this works everywhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * The goal here is more to phase out Open Firmware images.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * Currently, we only look at the first PCI data, we could iteratre and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * deal with them all, and we should use fb_bios_start relative to start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * of image and not relative start of ROM, but so far, I never found a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * dual-image ATI card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * typedef struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * u32 signature; + 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * u16 vendor; + 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * u16 device; + 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * u16 reserved_1; + 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * u16 dlen; + 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) * u8 drevision; + 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) * u8 class_hi; + 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) * u16 class_lo; + 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * u16 ilen; + 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * u16 irevision; + 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) * u8 type; + 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * u8 indicator; + 0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * u16 reserved_2; + 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * } pci_data_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (BIOS_IN32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) printk(KERN_WARNING "aty128fb: PCI DATA signature in ROM incorrect: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) BIOS_IN32(dptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) goto anyway;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) rom_type = BIOS_IN8(dptr + 0x14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) switch(rom_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) printk(KERN_INFO "aty128fb: Found Intel x86 BIOS ROM Image\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) printk(KERN_INFO "aty128fb: Found Open Firmware ROM Image\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) printk(KERN_INFO "aty128fb: Found HP PA-RISC ROM Image\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) printk(KERN_INFO "aty128fb: Found unknown type %d ROM Image\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) rom_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) anyway:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return bios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) pci_unmap_rom(dev, bios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) static void aty128_get_pllinfo(struct aty128fb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) unsigned char __iomem *bios)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) unsigned int bios_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) unsigned int bios_pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) bios_hdr = BIOS_IN16(0x48);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) bios_pll = BIOS_IN16(bios_hdr + 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) par->constants.ppll_max = BIOS_IN32(bios_pll + 0x16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) par->constants.ppll_min = BIOS_IN32(bios_pll + 0x12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) par->constants.xclk = BIOS_IN16(bios_pll + 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) par->constants.ref_divider = BIOS_IN16(bios_pll + 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) par->constants.ref_clk = BIOS_IN16(bios_pll + 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d ref clock %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) par->constants.ppll_max, par->constants.ppll_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) par->constants.xclk, par->constants.ref_divider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) par->constants.ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* I simplified this code as we used to miss the signatures in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * a lot of case. It's now closer to XFree, we just don't check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * for signatures at all... Something better will have to be done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * if we end up having conflicts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) u32 segstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) unsigned char __iomem *rom_base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) rom_base = ioremap(segstart, 0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (rom_base == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) iounmap(rom_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) rom_base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return rom_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) #endif /* ndef(__sparc__) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /* fill in known card constants if pll_block is not available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static void aty128_timings(struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) #ifdef CONFIG_PPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) /* instead of a table lookup, assume OF has properly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) * setup the PLL registers and use their values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * to set the XCLK values and reference divider values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) u32 x_mpll_ref_fb_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) u32 xclk_cntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) u32 Nx, M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (!par->constants.ref_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) par->constants.ref_clk = 2950;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) #ifdef CONFIG_PPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) M = x_mpll_ref_fb_div & 0x0000ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) par->constants.xclk = round_div((2 * Nx * par->constants.ref_clk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) (M * PostDivSet[xclk_cntl]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) par->constants.ref_divider =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (!par->constants.ref_divider) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) par->constants.ref_divider = 0x3b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) aty_pll_writeupdate(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) aty_pll_writeupdate(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) /* from documentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!par->constants.ppll_min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) par->constants.ppll_min = 12500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (!par->constants.ppll_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) par->constants.ppll_max = 25000; /* 23000 on some cards? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (!par->constants.xclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) par->constants.xclk = 0x1d4d; /* same as mclk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) par->constants.fifo_width = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) par->constants.fifo_depth = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) switch (aty_ld_le32(MEM_CNTL) & 0x3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) par->mem = &sdr_128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) par->mem = &sdr_sgram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) par->mem = &ddr_sgram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) par->mem = &sdr_sgram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * CRTC programming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) /* Program the CRTC registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) static void aty128_set_crtc(const struct aty128_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) aty_st_le32(CRTC_PITCH, crtc->pitch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) aty_st_le32(CRTC_OFFSET, crtc->offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) aty_st_le32(CRTC_OFFSET_CNTL, crtc->offset_cntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /* Disable ATOMIC updating. Is this the right place? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~(0x00030000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static int aty128_var_to_crtc(const struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) struct aty128_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp, dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) u32 left, right, upper, lower, hslen, vslen, sync, vmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) u32 depth, bytpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) u8 mode_bytpp[7] = { 0, 0, 1, 2, 2, 3, 4 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) /* input */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) xres = var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) yres = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) vxres = var->xres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) vyres = var->yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) xoffset = var->xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) yoffset = var->yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) bpp = var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) left = var->left_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) right = var->right_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) upper = var->upper_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) lower = var->lower_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) hslen = var->hsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) vslen = var->vsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) sync = var->sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) vmode = var->vmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (bpp != 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) depth = bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) depth = (var->green.length == 6) ? 16 : 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /* check for mode eligibility
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * accept only non interlaced modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) /* convert (and round up) and validate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) xres = (xres + 7) & ~7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) xoffset = (xoffset + 7) & ~7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (vxres < xres + xoffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) vxres = xres + xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (vyres < yres + yoffset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) vyres = yres + yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) /* convert depth into ATI register depth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) dst = depth_to_dst(depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) if (dst == -EINVAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) printk(KERN_ERR "aty128fb: Invalid depth or RGBA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) /* convert register depth to bytes per pixel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) bytpp = mode_bytpp[dst];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) /* make sure there is enough video ram for the mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if ((u32)(vxres * vyres * bytpp) > par->vram_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) printk(KERN_ERR "aty128fb: Not enough memory for mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) h_disp = (xres >> 3) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) h_total = (((xres + right + hslen + left) >> 3) - 1) & 0xFFFFL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) v_disp = yres - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) v_total = (yres + upper + vslen + lower - 1) & 0xFFFFL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) /* check to make sure h_total and v_total are in range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (((h_total >> 3) - 1) > 0x1ff || (v_total - 1) > 0x7FF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) printk(KERN_ERR "aty128fb: invalid width ranges\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) h_sync_wid = (hslen + 7) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if (h_sync_wid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) h_sync_wid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) else if (h_sync_wid > 0x3f) /* 0x3f = max hwidth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) h_sync_wid = 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) h_sync_strt = (h_disp << 3) + right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) v_sync_wid = vslen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (v_sync_wid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) v_sync_wid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) else if (v_sync_wid > 0x1f) /* 0x1f = max vwidth */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) v_sync_wid = 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) v_sync_strt = v_disp + lower;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) crtc->gen_cntl = 0x3000000L | c_sync | (dst << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) crtc->h_total = h_total | (h_disp << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) crtc->v_total = v_total | (v_disp << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) crtc->h_sync_strt_wid = h_sync_strt | (h_sync_wid << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) (h_sync_pol << 23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) (v_sync_pol << 23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) crtc->pitch = vxres >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) crtc->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) crtc->offset_cntl = 0x00010000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) crtc->offset_cntl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) crtc->vxres = vxres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) crtc->vyres = vyres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) crtc->xoffset = xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) crtc->yoffset = yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) crtc->depth = depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) crtc->bpp = bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) static int aty128_pix_width_to_var(int pix_width, struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* fill in pixel info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) var->red.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) var->green.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) var->blue.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) var->transp.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) var->transp.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) var->transp.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) switch (pix_width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) case CRTC_PIX_WIDTH_8BPP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) var->bits_per_pixel = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) var->red.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) var->green.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) case CRTC_PIX_WIDTH_15BPP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) var->bits_per_pixel = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) var->red.offset = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) var->red.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) var->green.offset = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) var->green.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) var->blue.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) case CRTC_PIX_WIDTH_16BPP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) var->bits_per_pixel = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) var->red.offset = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) var->red.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) var->green.offset = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) var->green.length = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) var->blue.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) case CRTC_PIX_WIDTH_24BPP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) var->bits_per_pixel = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) var->red.offset = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) var->green.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) case CRTC_PIX_WIDTH_32BPP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) var->bits_per_pixel = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) var->red.offset = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) var->green.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) var->transp.offset = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) var->transp.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) printk(KERN_ERR "aty128fb: Invalid pixel width\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) static int aty128_crtc_to_var(const struct aty128_crtc *crtc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) u32 xres, yres, left, right, upper, lower, hslen, vslen, sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) u32 pix_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) /* fun with masking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) h_total = crtc->h_total & 0x1ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) h_disp = (crtc->h_total >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) h_sync_strt = (crtc->h_sync_strt_wid >> 3) & 0x1ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) h_sync_dly = crtc->h_sync_strt_wid & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) h_sync_pol = (crtc->h_sync_strt_wid >> 23) & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) v_total = crtc->v_total & 0x7ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) v_disp = (crtc->v_total >> 16) & 0x7ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) v_sync_pol = (crtc->v_sync_strt_wid >> 23) & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) /* do conversions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) xres = (h_disp + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) yres = v_disp + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) left = ((h_total - h_sync_strt - h_sync_wid) << 3) - h_sync_dly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) right = ((h_sync_strt - h_disp) << 3) + h_sync_dly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) hslen = h_sync_wid << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) upper = v_total - v_sync_strt - v_sync_wid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) lower = v_sync_strt - v_disp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) vslen = v_sync_wid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) aty128_pix_width_to_var(pix_width, var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) var->xres = xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) var->yres = yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) var->xres_virtual = crtc->vxres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) var->yres_virtual = crtc->vyres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) var->xoffset = crtc->xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) var->yoffset = crtc->yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) var->left_margin = left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) var->right_margin = right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) var->upper_margin = upper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) var->lower_margin = lower;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) var->hsync_len = hslen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) var->vsync_len = vslen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) var->sync = sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) var->vmode = FB_VMODE_NONINTERLACED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) CRT_CRTC_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) aty_st_le32(DAC_CNTL, (aty_ld_le32(DAC_CNTL) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) DAC_PALETTE2_SNOOP_EN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) aty_st_le32(CRTC_EXT_CNTL, aty_ld_le32(CRTC_EXT_CNTL) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) ~CRT_CRTC_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) #ifdef CONFIG_FB_ATY128_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) struct fb_info *info = pci_get_drvdata(par->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) reg = aty_ld_le32(LVDS_GEN_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) reg &= ~LVDS_DISPLAY_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) aty_st_le32(LVDS_GEN_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) #ifdef CONFIG_FB_ATY128_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) aty128_bl_set_power(info, FB_BLANK_UNBLANK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) #ifdef CONFIG_FB_ATY128_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) aty128_bl_set_power(info, FB_BLANK_POWERDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) reg = aty_ld_le32(LVDS_GEN_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) reg |= LVDS_DISPLAY_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) aty_st_le32(LVDS_GEN_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) mdelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) reg &= ~(LVDS_ON /*| LVDS_EN*/);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) aty_st_le32(LVDS_GEN_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) static void aty128_set_pll(struct aty128_pll *pll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) u32 div3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) unsigned char post_conv[] = /* register values for post dividers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) /* select PPLL_DIV_3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) /* reset PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) aty_st_pll(PPLL_CNTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) /* write the reference divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) aty_pll_wait_readupdate(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider & 0x3ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) aty_pll_writeupdate(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) div3 = aty_ld_pll(PPLL_DIV_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) div3 &= ~PPLL_FB3_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) div3 |= pll->feedback_divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) div3 &= ~PPLL_POST3_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) div3 |= post_conv[pll->post_divider] << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) /* write feedback and post dividers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) aty_pll_wait_readupdate(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) aty_st_pll(PPLL_DIV_3, div3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) aty_pll_writeupdate(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) aty_pll_wait_readupdate(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) aty_st_pll(HTOTAL_CNTL, 0); /* no horiz crtc adjustment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) aty_pll_writeupdate(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) /* clear the reset, just in case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) const struct aty128_constants c = par->constants;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) unsigned char post_dividers[] = {1,2,4,8,3,6,12};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) u32 output_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) u32 vclk; /* in .01 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) u32 n, d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) vclk = 100000000 / period_in_ps; /* convert units to 10 kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) /* adjust pixel clock if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) if (vclk > c.ppll_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) vclk = c.ppll_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (vclk * 12 < c.ppll_min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) vclk = c.ppll_min/12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) /* now, find an acceptable divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) for (i = 0; i < ARRAY_SIZE(post_dividers); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) output_freq = post_dividers[i] * vclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) pll->post_divider = post_dividers[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) if (i == ARRAY_SIZE(post_dividers))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) /* calculate feedback divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) n = c.ref_divider * output_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) d = c.ref_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) pll->feedback_divider = round_div(n, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) pll->vclk = vclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) DBG("post %d feedback %d vlck %d output %d ref_divider %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) "vclk_per: %d\n", pll->post_divider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) pll->feedback_divider, vclk, output_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) c.ref_divider, period_in_ps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) static int aty128_pll_to_var(const struct aty128_pll *pll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) var->pixclock = 100000000 / pll->vclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) static void aty128_set_fifo(const struct aty128_ddafifo *dsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) aty_st_le32(DDA_CONFIG, dsp->dda_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) aty_st_le32(DDA_ON_OFF, dsp->dda_on_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) static int aty128_ddafifo(struct aty128_ddafifo *dsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) const struct aty128_pll *pll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) u32 depth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) const struct aty128_meminfo *m = par->mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) u32 xclk = par->constants.xclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) u32 fifo_width = par->constants.fifo_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) u32 fifo_depth = par->constants.fifo_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) s32 x, b, p, ron, roff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) u32 n, d, bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) /* round up to multiple of 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) bpp = (depth+7) & ~7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) n = xclk * fifo_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) d = pll->vclk * bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) x = round_div(n, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) ron = 4 * m->MB +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 2 * m->Trp +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) m->Twr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) m->CL +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) m->Tr2w +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) DBG("x %x\n", x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) b = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) while (x) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) x >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) b++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) p = b + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) ron <<= (11 - p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) n <<= (11 - p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) x = round_div(n, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) roff = x * (fifo_depth - 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) if ((ron + m->Rloop) >= roff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) printk(KERN_ERR "aty128fb: Mode out of range!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) p, m->Rloop, x, ron, roff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) dsp->dda_config = p << 16 | m->Rloop << 20 | x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) dsp->dda_on_off = ron << 16 | roff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) * This actually sets the video mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) static int aty128fb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) struct aty128fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) u32 config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if ((err = aty128_decode_var(&info->var, par)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (par->blitter_may_be_busy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) wait_for_idle(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) /* clear all registers that may interfere with mode setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) aty_st_le32(OVR_CLR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) aty_st_le32(OVR_WID_LEFT_RIGHT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) aty_st_le32(OVR_WID_TOP_BOTTOM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) aty_st_le32(OV0_SCALE_CNTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) aty_st_le32(MPP_TB_CONFIG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) aty_st_le32(MPP_GP_CONFIG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) aty_st_le32(SUBPIC_CNTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) aty_st_le32(VIPH_CONTROL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) aty_st_le32(I2C_CNTL_1, 0); /* turn off i2c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) aty_st_le32(GEN_INT_CNTL, 0); /* turn off interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) aty_st_le32(CAP0_TRIG_CNTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) aty_st_le32(CAP1_TRIG_CNTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) aty_st_8(CRTC_EXT_CNTL + 1, 4); /* turn video off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) aty128_set_crtc(&par->crtc, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) aty128_set_pll(&par->pll, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) aty128_set_fifo(&par->fifo_reg, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) config = aty_ld_le32(CNFG_CNTL) & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) #if defined(__BIG_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (par->crtc.bpp == 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) config |= 2; /* make aperture do 32 bit swapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) else if (par->crtc.bpp == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) config |= 1; /* make aperture do 16 bit swapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) aty_st_le32(CNFG_CNTL, config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) info->fix.visual = par->crtc.bpp == 8 ? FB_VISUAL_PSEUDOCOLOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) : FB_VISUAL_DIRECTCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (par->chip_gen == rage_M3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) aty128_set_crt_enable(par, par->crt_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) aty128_set_lcd_enable(par, par->lcd_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) if (par->accel_flags & FB_ACCELF_TEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) aty128_init_engine(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) #ifdef CONFIG_BOOTX_TEXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) btext_update_display(info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) (((par->crtc.h_total>>16) & 0xff)+1)*8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) ((par->crtc.v_total>>16) & 0x7ff)+1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) par->crtc.bpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) par->crtc.vxres*par->crtc.bpp/8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) #endif /* CONFIG_BOOTX_TEXT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) * encode/decode the User Defined Part of the Display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) static int aty128_decode_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) struct aty128_crtc crtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) struct aty128_pll pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) struct aty128_ddafifo fifo_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) if ((err = aty128_var_to_crtc(var, &crtc, par)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) if ((err = aty128_var_to_pll(var->pixclock, &pll, par)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) if ((err = aty128_ddafifo(&fifo_reg, &pll, crtc.depth, par)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) par->crtc = crtc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) par->pll = pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) par->fifo_reg = fifo_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) par->accel_flags = var->accel_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) static int aty128_encode_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) const struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) if ((err = aty128_crtc_to_var(&par->crtc, var)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) if ((err = aty128_pll_to_var(&par->pll, var)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) var->nonstd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) var->activate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) var->height = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) var->width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) var->accel_flags = par->accel_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) static int aty128fb_check_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) struct aty128fb_par par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) par = *(struct aty128fb_par *)info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) if ((err = aty128_decode_var(var, &par)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) aty128_encode_var(var, &par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) * Pan or Wrap the Display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) static int aty128fb_pan_display(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) struct fb_info *fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) struct aty128fb_par *par = fb->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) u32 xoffset, yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) u32 xres, yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) xoffset = (var->xoffset +7) & ~7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) yoffset = var->yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) par->crtc.xoffset = xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) par->crtc.yoffset = yoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) offset = ((yoffset * par->crtc.vxres + xoffset) * (par->crtc.bpp >> 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) & ~7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) if (par->crtc.bpp == 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) offset += 8 * (offset % 3); /* Must be multiple of 8 and 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) aty_st_le32(CRTC_OFFSET, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) * Helper function to store a single palette register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) static void aty128_st_pal(u_int regno, u_int red, u_int green, u_int blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) if (par->chip_gen == rage_M3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) ~DAC_PALETTE_ACCESS_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) aty_st_8(PALETTE_INDEX, regno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) aty_st_le32(PALETTE_DATA, (red<<16)|(green<<8)|blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) static int aty128fb_sync(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) struct aty128fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if (par->blitter_may_be_busy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) wait_for_idle(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) static int aty128fb_setup(char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) char *this_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (!options || !*options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) while ((this_opt = strsep(&options, ",")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) if (!strncmp(this_opt, "lcd:", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) default_lcd_on = simple_strtoul(this_opt+4, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) } else if (!strncmp(this_opt, "crt:", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) default_crt_on = simple_strtoul(this_opt+4, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) } else if (!strncmp(this_opt, "backlight:", 10)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) #ifdef CONFIG_FB_ATY128_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) backlight = simple_strtoul(this_opt+10, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) if(!strncmp(this_opt, "nomtrr", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) mtrr = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) /* vmode and cmode deprecated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) if (!strncmp(this_opt, "vmode:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) if (vmode > 0 && vmode <= VMODE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) default_vmode = vmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) } else if (!strncmp(this_opt, "cmode:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) switch (cmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) default_cmode = CMODE_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) case 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) default_cmode = CMODE_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) default_cmode = CMODE_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) #endif /* CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) mode_option = this_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) #endif /* MODULE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) /* Backlight */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) #ifdef CONFIG_FB_ATY128_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) #define MAX_LEVEL 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) struct fb_info *info = pci_get_drvdata(par->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) int atylevel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) /* Get and convert the value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) /* No locking of bl_curve since we read a single value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) atylevel = MAX_LEVEL -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) if (atylevel < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) atylevel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) else if (atylevel > MAX_LEVEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) atylevel = MAX_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) return atylevel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) /* We turn off the LCD completely instead of just dimming the backlight.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) * This provides greater power saving and the display is useless without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) * backlight anyway
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) #define BACKLIGHT_LVDS_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) /* That one prevents proper CRT output with LCD off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) #undef BACKLIGHT_DAC_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) static int aty128_bl_update_status(struct backlight_device *bd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) struct aty128fb_par *par = bl_get_data(bd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) if (bd->props.power != FB_BLANK_UNBLANK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) bd->props.fb_blank != FB_BLANK_UNBLANK ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) !par->lcd_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) level = bd->props.brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) reg |= LVDS_BL_MOD_EN | LVDS_BLON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) if (level > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) reg |= LVDS_DIGION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) if (!(reg & LVDS_ON)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) reg &= ~LVDS_BLON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) aty_st_le32(LVDS_GEN_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) aty_ld_le32(LVDS_GEN_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) mdelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) reg |= LVDS_BLON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) aty_st_le32(LVDS_GEN_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) reg &= ~LVDS_BL_MOD_LEVEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) reg |= (aty128_bl_get_level_brightness(par, level) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) LVDS_BL_MOD_LEVEL_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) #ifdef BACKLIGHT_LVDS_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) reg |= LVDS_ON | LVDS_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) reg &= ~LVDS_DISPLAY_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) aty_st_le32(LVDS_GEN_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) #ifdef BACKLIGHT_DAC_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) reg &= ~LVDS_BL_MOD_LEVEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) reg |= (aty128_bl_get_level_brightness(par, 0) <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) LVDS_BL_MOD_LEVEL_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) #ifdef BACKLIGHT_LVDS_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) reg |= LVDS_DISPLAY_DIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) aty_st_le32(LVDS_GEN_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) aty_ld_le32(LVDS_GEN_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) aty_st_le32(LVDS_GEN_CNTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) #ifdef BACKLIGHT_DAC_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) static const struct backlight_ops aty128_bl_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) .update_status = aty128_bl_update_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) static void aty128_bl_set_power(struct fb_info *info, int power)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) if (info->bl_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) info->bl_dev->props.power = power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) backlight_update_status(info->bl_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) static void aty128_bl_init(struct aty128fb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) struct backlight_properties props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) struct fb_info *info = pci_get_drvdata(par->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) struct backlight_device *bd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) char name[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) /* Could be extended to Rage128Pro LVDS output too */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) if (par->chip_gen != rage_M3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) #ifdef CONFIG_PMAC_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) if (!pmac_has_backlight_type("ati"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) snprintf(name, sizeof(name), "aty128bl%d", info->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) memset(&props, 0, sizeof(struct backlight_properties));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) props.type = BACKLIGHT_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) bd = backlight_device_register(name, info->dev, par, &aty128_bl_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) &props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) if (IS_ERR(bd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) info->bl_dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) printk(KERN_WARNING "aty128: Backlight registration failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) info->bl_dev = bd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) fb_bl_default_curve(info, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) 219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) bd->props.brightness = bd->props.max_brightness;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) bd->props.power = FB_BLANK_UNBLANK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) backlight_update_status(bd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) printk("aty128: Backlight initialized (%s)\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) static void aty128_bl_exit(struct backlight_device *bd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) backlight_device_unregister(bd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) printk("aty128: Backlight unloaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) #endif /* CONFIG_FB_ATY128_BACKLIGHT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) * Initialisation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) #ifdef CONFIG_PPC_PMAC__disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) static void aty128_early_resume(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) struct aty128fb_par *par = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) if (!console_trylock())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) pci_restore_state(par->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) aty128_do_resume(par->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) #endif /* CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) struct fb_info *info = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) struct aty128fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) struct fb_var_screeninfo var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) char video_card[50];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) u8 chip_rev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) u32 dac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) /* Get the chip revision */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) strcpy(video_card, "Rage128 XX ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) video_card[8] = ent->device >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) video_card[9] = ent->device & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) /* range check to make sure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) if (ent->driver_data < ARRAY_SIZE(r128_family))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) strlcat(video_card, r128_family[ent->driver_data],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) sizeof(video_card));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) if (par->vram_size % (1024 * 1024) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) printk("%dM %s\n", par->vram_size / (1024*1024), par->mem->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) printk("%dk %s\n", par->vram_size / 1024, par->mem->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) par->chip_gen = ent->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) /* fill in info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) info->fbops = &aty128fb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) info->flags = FBINFO_FLAG_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) par->lcd_on = default_lcd_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) par->crt_on = default_crt_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) var = default_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) if (machine_is(powermac)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) /* Indicate sleep capability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) if (par->chip_gen == rage_M3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) #if 0 /* Disable the early video resume hack for now as it's causing problems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) * among others we now rely on the PCI core restoring the config space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) * for us, which isn't the case with that hack, and that code path causes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) * various things to be called with interrupts off while they shouldn't.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) * I'm leaving the code in as it can be useful for debugging purposes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) pmac_set_early_video_resume(aty128_early_resume, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) /* Find default mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) if (mode_option) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) if (!mac_find_mode(&var, info, mode_option, 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) var = default_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) if (default_vmode <= 0 || default_vmode > VMODE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) default_vmode = VMODE_1024_768_60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) /* iMacs need that resolution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) * PowerMac2,1 first r128 iMacs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) * PowerMac2,2 summer 2000 iMacs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) * PowerMac4,1 january 2001 iMacs "flower power"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) if (of_machine_is_compatible("PowerMac2,1") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) of_machine_is_compatible("PowerMac2,2") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) of_machine_is_compatible("PowerMac4,1"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) default_vmode = VMODE_1024_768_75;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) /* iBook SE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) if (of_machine_is_compatible("PowerBook2,2"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) default_vmode = VMODE_800_600_60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) /* PowerBook Firewire (Pismo), iBook Dual USB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) if (of_machine_is_compatible("PowerBook3,1") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) of_machine_is_compatible("PowerBook4,1"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) default_vmode = VMODE_1024_768_60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) /* PowerBook Titanium */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) if (of_machine_is_compatible("PowerBook3,2"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) default_vmode = VMODE_1152_768_60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) if (default_cmode > 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) default_cmode = CMODE_32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) else if (default_cmode > 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) default_cmode = CMODE_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) default_cmode = CMODE_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) if (mac_vmode_to_var(default_vmode, default_cmode, &var))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) var = default_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) #endif /* CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) if (mode_option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) if (fb_find_mode(&var, info, mode_option, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) 0, &defaultmode, 8) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) var = default_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) var.accel_flags &= ~FB_ACCELF_TEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) // var.accel_flags |= FB_ACCELF_TEXT;/* FIXME Will add accel later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) if (aty128fb_check_var(&var, info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) /* setup the DAC the way we like it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) dac = aty_ld_le32(DAC_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) dac |= DAC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) if (par->chip_gen == rage_M3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) dac |= DAC_PALETTE2_SNOOP_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) aty_st_le32(DAC_CNTL, dac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) /* turn off bus mastering, just in case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) info->var = var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) fb_alloc_cmap(&info->cmap, 256, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) var.activate = FB_ACTIVATE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) aty128_init_engine(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) par->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) par->asleep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) par->lock_blank = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) #ifdef CONFIG_FB_ATY128_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) if (backlight)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) aty128_bl_init(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) if (register_framebuffer(info) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) fb_info(info, "%s frame buffer device on %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) info->fix.id, video_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) return 1; /* success! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) /* register a card ++ajoshi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) unsigned long fb_addr, reg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) struct aty128fb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) #ifndef __sparc__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) void __iomem *bios = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) /* Enable device in PCI config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) if ((err = pci_enable_device(pdev))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) fb_addr = pci_resource_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) "aty128fb FB")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) printk(KERN_ERR "aty128fb: cannot reserve frame "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) "buffer memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) reg_addr = pci_resource_start(pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) if (!request_mem_region(reg_addr, pci_resource_len(pdev, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) "aty128fb MMIO")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) printk(KERN_ERR "aty128fb: cannot reserve MMIO region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) goto err_free_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) /* We have the resources. Now virtualize them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) info = framebuffer_alloc(sizeof(struct aty128fb_par), &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) goto err_free_mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) info->pseudo_palette = par->pseudo_palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) /* Virtualize mmio region */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) info->fix.mmio_start = reg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) par->regbase = pci_ioremap_bar(pdev, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) if (!par->regbase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) goto err_free_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) /* Grab memory size from the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) // How does this relate to the resource length from the PCI hardware?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) /* Virtualize the framebuffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) info->screen_base = ioremap_wc(fb_addr, par->vram_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) if (!info->screen_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) goto err_unmap_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) /* Set up info->fix */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) info->fix = aty128fb_fix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) info->fix.smem_start = fb_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) info->fix.smem_len = par->vram_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) info->fix.mmio_start = reg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) /* If we can't test scratch registers, something is seriously wrong */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) if (!register_test(par)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) printk(KERN_ERR "aty128fb: Can't write to video register!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) #ifndef __sparc__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) bios = aty128_map_ROM(par, pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) if (bios == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) bios = aty128_find_mem_vbios(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) if (bios == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) printk(KERN_INFO "aty128fb: BIOS not located, guessing timings.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) printk(KERN_INFO "aty128fb: Rage128 BIOS located\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) aty128_get_pllinfo(par, bios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) pci_unmap_rom(pdev, bios);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) #endif /* __sparc__ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) aty128_timings(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) pci_set_drvdata(pdev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) if (!aty128_init(pdev, ent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) if (mtrr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) par->vram_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) err_unmap_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) iounmap(par->regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) err_free_info:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) err_free_mmio:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) release_mem_region(pci_resource_start(pdev, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) pci_resource_len(pdev, 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) err_free_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) release_mem_region(pci_resource_start(pdev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) pci_resource_len(pdev, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) static void aty128_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) struct fb_info *info = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) struct aty128fb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) #ifdef CONFIG_FB_ATY128_BACKLIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) aty128_bl_exit(info->bl_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) arch_phys_wc_del(par->wc_cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) iounmap(par->regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) release_mem_region(pci_resource_start(pdev, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) pci_resource_len(pdev, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) release_mem_region(pci_resource_start(pdev, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) pci_resource_len(pdev, 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) #endif /* CONFIG_PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) * Blank the display.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) static int aty128fb_blank(int blank, struct fb_info *fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) struct aty128fb_par *par = fb->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) u8 state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) if (par->lock_blank || par->asleep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) switch (blank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) case FB_BLANK_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) state = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) case FB_BLANK_VSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) state = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) case FB_BLANK_HSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) state = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) case FB_BLANK_POWERDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) state = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) case FB_BLANK_UNBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) aty_st_8(CRTC_EXT_CNTL+1, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) if (par->chip_gen == rage_M3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) aty128_set_crt_enable(par, par->crt_on && !blank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) aty128_set_lcd_enable(par, par->lcd_on && !blank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) * Set a single color register. The values supplied are already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) * rounded down to the hardware's capabilities (according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) * entries in the var structure). Return != 0 for invalid regno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) u_int transp, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) struct aty128fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) if (regno > 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) || (par->crtc.depth == 16 && regno > 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) || (par->crtc.depth == 15 && regno > 31))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) red >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) green >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) blue >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) if (regno < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) u32 *pal = info->pseudo_palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) switch (par->crtc.depth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) case 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) pal[regno] = (regno << 10) | (regno << 5) | regno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) pal[regno] = (regno << 11) | (regno << 6) | regno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) pal[regno] = (regno << 16) | (regno << 8) | regno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) i = (regno << 8) | regno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) pal[regno] = (i << 16) | i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) if (par->crtc.depth == 16 && regno > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) * With the 5-6-5 split of bits for RGB at 16 bits/pixel, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) * have 32 slots for R and B values but 64 slots for G values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) * Thus the R and B values go in one slot but the G value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) * goes in a different slot, and we have to avoid disturbing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) * the other fields in the slots we touch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) par->green[regno] = green;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) if (regno < 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) par->red[regno] = red;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) par->blue[regno] = blue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) aty128_st_pal(regno * 8, red, par->green[regno*2],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) blue, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) red = par->red[regno/2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) blue = par->blue[regno/2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) regno <<= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) } else if (par->crtc.bpp == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) regno <<= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) aty128_st_pal(regno, red, green, blue, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) #define ATY_MIRROR_LCD_ON 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) #define ATY_MIRROR_CRT_ON 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) /* out param: u32* backlight value: 0 to 15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) #define FBIO_ATY128_GET_MIRROR _IOR('@', 1, __u32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) /* in param: u32* backlight value: 0 to 15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) #define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) struct aty128fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) case FBIO_ATY128_SET_MIRROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) if (par->chip_gen != rage_M3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) rc = get_user(value, (__u32 __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) par->lcd_on = (value & 0x01) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) par->crt_on = (value & 0x02) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) if (!par->crt_on && !par->lcd_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) par->lcd_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) aty128_set_crt_enable(par, par->crt_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) aty128_set_lcd_enable(par, par->lcd_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) case FBIO_ATY128_GET_MIRROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) if (par->chip_gen != rage_M3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) value = (par->crt_on << 1) | par->lcd_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) return put_user(value, (__u32 __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) u32 pmgt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) if (!par->pdev->pm_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) /* Set the chip into the appropriate suspend mode (we use D2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) * D3 would require a complete re-initialisation of the chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) * including PCI config registers, clocks, AGP configuration, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) * For resume, the core will have already brought us back to D0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) if (suspend) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) /* Make sure CRTC2 is reset. Remove that the day we decide to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) * actually use CRTC2 and replace it with real code for disabling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) * the CRTC2 output during sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) aty_st_le32(CRTC2_GEN_CNTL, aty_ld_le32(CRTC2_GEN_CNTL) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) ~(CRTC2_EN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) /* Set the power management mode to be PCI based */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) /* Use this magic value for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) pmgt = 0x0c005407;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) aty_st_pll(POWER_MANAGEMENT, pmgt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) (void)aty_ld_pll(POWER_MANAGEMENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) aty_st_le32(BUS_CNTL1, 0x00000010);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) aty_st_le32(MEM_POWER_MISC, 0x0c830000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) static int aty128_pci_suspend_late(struct device *dev, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) struct pci_dev *pdev = to_pci_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) struct fb_info *info = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) struct aty128fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) /* We don't do anything but D2, for now we return 0, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) * we may want to change that. How do we know if the BIOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) * can properly take care of D3 ? Also, with swsusp, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) * know we'll be rebooted, ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) #ifndef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) /* HACK ALERT ! Once I find a proper way to say to each driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) * individually what will happen with it's PCI slot, I'll change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) * that. On laptops, the AGP slot is just unclocked, so D2 is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) * expected, while on desktops, the card is powered off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) #endif /* CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) if (state.event == pdev->dev.power.power_state.event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) printk(KERN_DEBUG "aty128fb: suspending...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) fb_set_suspend(info, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) /* Make sure engine is reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) wait_for_idle(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) aty128_reset_engine(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) wait_for_idle(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) /* Blank display and LCD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) aty128fb_blank(FB_BLANK_POWERDOWN, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) /* Sleep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) par->asleep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) par->lock_blank = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) /* On powermac, we have hooks to properly suspend/resume AGP now,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) * use them here. We'll ultimately need some generic support here,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) * but the generic code isn't quite ready for that yet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) pmac_suspend_agp_for_card(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) #endif /* CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) /* We need a way to make sure the fbdev layer will _not_ touch the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) * framebuffer before we put the chip to suspend state. On 2.4, I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) * used dummy fb ops, 2.5 need proper support for this at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) * fbdev level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) if (state.event != PM_EVENT_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) aty128_set_suspend(par, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) pdev->dev.power.power_state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) static int __maybe_unused aty128_pci_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) return aty128_pci_suspend_late(dev, PMSG_SUSPEND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) static int __maybe_unused aty128_pci_hibernate(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) return aty128_pci_suspend_late(dev, PMSG_HIBERNATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) static int __maybe_unused aty128_pci_freeze(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) return aty128_pci_suspend_late(dev, PMSG_FREEZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) static int aty128_do_resume(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) struct fb_info *info = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) struct aty128fb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) if (pdev->dev.power.power_state.event == PM_EVENT_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) /* PCI state will have been restored by the core, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) * we should be in D0 now with our config space fully
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) * restored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) /* Wakeup chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) aty128_set_suspend(par, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) par->asleep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) /* Restore display & engine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) aty128_reset_engine(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) wait_for_idle(par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) aty128fb_set_par(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) fb_pan_display(info, &info->var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) fb_set_cmap(&info->cmap, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) /* Refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) fb_set_suspend(info, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) /* Unblank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) par->lock_blank = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) aty128fb_blank(0, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) #ifdef CONFIG_PPC_PMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) /* On powermac, we have hooks to properly suspend/resume AGP now,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) * use them here. We'll ultimately need some generic support here,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) * but the generic code isn't quite ready for that yet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) pmac_resume_agp_for_card(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) #endif /* CONFIG_PPC_PMAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) pdev->dev.power.power_state = PMSG_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) printk(KERN_DEBUG "aty128fb: resumed !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) static int __maybe_unused aty128_pci_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) rc = aty128_do_resume(to_pci_dev(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) static int aty128fb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) char *option = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) if (fb_get_options("aty128fb", &option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) aty128fb_setup(option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) return pci_register_driver(&aty128fb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) static void __exit aty128fb_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) pci_unregister_driver(&aty128fb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) module_init(aty128fb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) module_exit(aty128fb_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) MODULE_AUTHOR("(c)1999-2003 Brad Douglas <brad@neruo.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) module_param(mode_option, charp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) module_param_named(nomtrr, mtrr, invbool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) MODULE_PARM_DESC(nomtrr, "bool: Disable MTRR support (0 or 1=disabled) (default=0)");