aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/kdrive/ati/ati.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/kdrive/ati/ati.c')
-rw-r--r--xorg-server/hw/kdrive/ati/ati.c761
1 files changed, 761 insertions, 0 deletions
diff --git a/xorg-server/hw/kdrive/ati/ati.c b/xorg-server/hw/kdrive/ati/ati.c
new file mode 100644
index 000000000..c4f67e171
--- /dev/null
+++ b/xorg-server/hw/kdrive/ati/ati.c
@@ -0,0 +1,761 @@
+/*
+ * Copyright © 2003 Eric Anholt
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Eric Anholt not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Eric Anholt makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+#include "ati.h"
+#include "ati_reg.h"
+#if defined(USE_DRI) && defined(GLXEXT)
+#include "ati_sarea.h"
+#endif
+
+static Bool ATIIsAGP(ATICardInfo *atic);
+
+#define CAP_SERIESMASK 0xf
+#define CAP_R128 0x1 /* If it's a Rage 128 */
+#define CAP_R100 0x2 /* If it's an r100 series radeon. */
+#define CAP_R200 0x3 /* If it's an r200 series radeon. */
+#define CAP_R300 0x4 /* If it's an r300 series radeon. */
+
+#define CAP_FEATURESMASK 0xf0
+#define CAP_NOAGP 0x10 /* If it's a PCI-only card. */
+
+struct pci_id_entry ati_pci_ids[] = {
+ {0x1002, 0x4136, 0x2, "ATI Radeon RS100"},
+ {0x1002, 0x4137, 0x2, "ATI Radeon RS200"},
+ {0x1002, 0x4237, 0x2, "ATI Radeon RS250"},
+ {0x1002, 0x4144, 0x4, "ATI Radeon R300 AD"},
+ {0x1002, 0x4145, 0x4, "ATI Radeon R300 AE"},
+ {0x1002, 0x4146, 0x4, "ATI Radeon R300 AF"},
+ {0x1002, 0x4147, 0x4, "ATI Radeon R300 AG"},
+ {0x1002, 0x4148, 0x4, "ATI Radeon R350 AH"},
+ {0x1002, 0x4149, 0x4, "ATI Radeon R350 AI"},
+ {0x1002, 0x414a, 0x4, "ATI Radeon R350 AJ"},
+ {0x1002, 0x414b, 0x4, "ATI Radeon R350 AK"},
+ {0x1002, 0x4150, 0x4, "ATI Radeon RV350 AP"},
+ {0x1002, 0x4151, 0x4, "ATI Radeon RV350 AQ"},
+ {0x1002, 0x4152, 0x4, "ATI Radeon RV350 AR"},
+ {0x1002, 0x4153, 0x4, "ATI Radeon RV350 AS"},
+ {0x1002, 0x4154, 0x4, "ATI Radeon RV350 AT"},
+ {0x1002, 0x4156, 0x4, "ATI Radeon RV350 AV"},
+ {0x1002, 0x4242, 0x3, "ATI Radeon R200 BB"},
+ {0x1002, 0x4243, 0x3, "ATI Radeon R200 BC"},
+ {0x1002, 0x4336, 0x2, "ATI Radeon RS100"},
+ {0x1002, 0x4337, 0x2, "ATI Radeon RS200"},
+ {0x1002, 0x4437, 0x2, "ATI Radeon RS250"},
+ {0x1002, 0x4964, 0x2, "ATI Radeon RV250 Id"},
+ {0x1002, 0x4965, 0x2, "ATI Radeon RV250 Ie"},
+ {0x1002, 0x4966, 0x2, "ATI Radeon RV250 If"},
+ {0x1002, 0x4967, 0x2, "ATI Radeon R250 Ig"},
+ {0x1002, 0x4c45, 0x11, "ATI Rage 128 LE"},
+ {0x1002, 0x4c46, 0x1, "ATI Rage 128 LF"},
+ {0x1002, 0x4c57, 0x2, "ATI Radeon Mobiliy M7 RV200 LW (7500)"},
+ {0x1002, 0x4c58, 0x2, "ATI Radeon Mobiliy M7 RV200 LX (7500)"},
+ {0x1002, 0x4c59, 0x2, "ATI Radeon Mobility M6 LY"},
+ {0x1002, 0x4c5a, 0x2, "ATI Radeon Mobility M6 LZ"},
+ {0x1002, 0x4c64, 0x3, "ATI Radeon RV250 Ld"},
+ {0x1002, 0x4c65, 0x3, "ATI Radeon RV250 Le"},
+ {0x1002, 0x4c66, 0x3, "ATI Radeon Mobility M9 RV250 Lf"},
+ {0x1002, 0x4c67, 0x3, "ATI Radeon RV250 Lg"},
+ {0x1002, 0x4d46, 0x1, "ATI Rage 128 MF"},
+ {0x1002, 0x4d46, 0x1, "ATI Rage 128 ML"},
+ {0x1002, 0x4e44, 0x4, "ATI Radeon R300 ND"},
+ {0x1002, 0x4e45, 0x4, "ATI Radeon R300 NE"},
+ {0x1002, 0x4e46, 0x4, "ATI Radeon R300 NF"},
+ {0x1002, 0x4e47, 0x4, "ATI Radeon R300 NG"},
+ {0x1002, 0x4e48, 0x4, "ATI Radeon R350 NH"},
+ {0x1002, 0x4e49, 0x4, "ATI Radeon R350 NI"},
+ {0x1002, 0x4e4a, 0x4, "ATI Radeon R350 NJ"},
+ {0x1002, 0x4e4b, 0x4, "ATI Radeon R350 NK"},
+ {0x1002, 0x4e50, 0x4, "ATI Radeon Mobility RV350 NP"},
+ {0x1002, 0x4e51, 0x4, "ATI Radeon Mobility RV350 NQ"},
+ {0x1002, 0x4e52, 0x4, "ATI Radeon Mobility RV350 NR"},
+ {0x1002, 0x4e53, 0x4, "ATI Radeon Mobility RV350 NS"},
+ {0x1002, 0x4e54, 0x4, "ATI Radeon Mobility RV350 NT"},
+ {0x1002, 0x4e56, 0x4, "ATI Radeon Mobility RV350 NV"},
+ {0x1002, 0x5041, 0x1, "ATI Rage 128 PA"},
+ {0x1002, 0x5042, 0x1, "ATI Rage 128 PB"},
+ {0x1002, 0x5043, 0x1, "ATI Rage 128 PC"},
+ {0x1002, 0x5044, 0x11, "ATI Rage 128 PD"},
+ {0x1002, 0x5045, 0x1, "ATI Rage 128 PE"},
+ {0x1002, 0x5046, 0x1, "ATI Rage 128 PF"},
+ {0x1002, 0x5047, 0x1, "ATI Rage 128 PG"},
+ {0x1002, 0x5048, 0x1, "ATI Rage 128 PH"},
+ {0x1002, 0x5049, 0x1, "ATI Rage 128 PI"},
+ {0x1002, 0x504a, 0x1, "ATI Rage 128 PJ"},
+ {0x1002, 0x504b, 0x1, "ATI Rage 128 PK"},
+ {0x1002, 0x504c, 0x1, "ATI Rage 128 PL"},
+ {0x1002, 0x504d, 0x1, "ATI Rage 128 PM"},
+ {0x1002, 0x504e, 0x1, "ATI Rage 128 PN"},
+ {0x1002, 0x504f, 0x1, "ATI Rage 128 PO"},
+ {0x1002, 0x5050, 0x11, "ATI Rage 128 PP"},
+ {0x1002, 0x5051, 0x1, "ATI Rage 128 PQ"},
+ {0x1002, 0x5052, 0x11, "ATI Rage 128 PR"},
+ {0x1002, 0x5053, 0x1, "ATI Rage 128 PS"},
+ {0x1002, 0x5054, 0x1, "ATI Rage 128 PT"},
+ {0x1002, 0x5055, 0x1, "ATI Rage 128 PU"},
+ {0x1002, 0x5056, 0x1, "ATI Rage 128 PV"},
+ {0x1002, 0x5057, 0x1, "ATI Rage 128 PW"},
+ {0x1002, 0x5058, 0x1, "ATI Rage 128 PX"},
+ {0x1002, 0x5144, 0x2, "ATI Radeon R100 QD"},
+ {0x1002, 0x5145, 0x2, "ATI Radeon R100 QE"},
+ {0x1002, 0x5146, 0x2, "ATI Radeon R100 QF"},
+ {0x1002, 0x5147, 0x2, "ATI Radeon R100 QG"},
+ {0x1002, 0x5148, 0x3, "ATI Radeon R200 QH"},
+ {0x1002, 0x514c, 0x3, "ATI Radeon R200 QL"},
+ {0x1002, 0x514d, 0x3, "ATI Radeon R200 QM"},
+ {0x1002, 0x5157, 0x2, "ATI Radeon RV200 QW (7500)"},
+ {0x1002, 0x5158, 0x2, "ATI Radeon RV200 QX (7500)"},
+ {0x1002, 0x5159, 0x2, "ATI Radeon RV100 QY"},
+ {0x1002, 0x515a, 0x2, "ATI Radeon RV100 QZ"},
+ {0x1002, 0x5245, 0x11, "ATI Rage 128 RE"},
+ {0x1002, 0x5246, 0x1, "ATI Rage 128 RF"},
+ {0x1002, 0x5247, 0x1, "ATI Rage 128 RG"},
+ {0x1002, 0x524b, 0x11, "ATI Rage 128 RK"},
+ {0x1002, 0x524c, 0x1, "ATI Rage 128 RL"},
+ {0x1002, 0x5345, 0x1, "ATI Rage 128 SE"},
+ {0x1002, 0x5346, 0x1, "ATI Rage 128 SF"},
+ {0x1002, 0x5347, 0x1, "ATI Rage 128 SG"},
+ {0x1002, 0x5348, 0x1, "ATI Rage 128 SH"},
+ {0x1002, 0x534b, 0x1, "ATI Rage 128 SK"},
+ {0x1002, 0x534c, 0x1, "ATI Rage 128 SL"},
+ {0x1002, 0x534d, 0x1, "ATI Rage 128 SM"},
+ {0x1002, 0x534e, 0x1, "ATI Rage 128 SN"},
+ {0x1002, 0x5446, 0x1, "ATI Rage 128 TF"},
+ {0x1002, 0x544c, 0x1, "ATI Rage 128 TL"},
+ {0x1002, 0x5452, 0x1, "ATI Rage 128 TR"},
+ {0x1002, 0x5453, 0x1, "ATI Rage 128 TS"},
+ {0x1002, 0x5454, 0x1, "ATI Rage 128 TT"},
+ {0x1002, 0x5455, 0x1, "ATI Rage 128 TU"},
+ {0x1002, 0x5834, 0x3, "ATI Radeon RS300"},
+ {0x1002, 0x5835, 0x3, "ATI Radeon RS300 Mobility"},
+ {0x1002, 0x5941, 0x3, "ATI Radeon RV280 (9200)"},
+ {0x1002, 0x5961, 0x3, "ATI Radeon RV280 (9200 SE)"},
+ {0x1002, 0x5964, 0x3, "ATI Radeon RV280 (9200 SE)"},
+ {0x1002, 0x5c60, 0x3, "ATI Radeon RV280"},
+ {0x1002, 0x5c61, 0x3, "ATI Radeon RV280 Mobility"},
+ {0x1002, 0x5c62, 0x3, "ATI Radeon RV280"},
+ {0x1002, 0x5c63, 0x3, "ATI Radeon RV280 Mobility"},
+ {0x1002, 0x5c64, 0x3, "ATI Radeon RV280"},
+ {0, 0, 0, NULL}
+};
+
+static char *
+make_busid(KdCardAttr *attr)
+{
+ char *busid;
+
+ busid = xalloc(20);
+ if (busid == NULL)
+ return NULL;
+ snprintf(busid, 20, "pci:%04x:%02x:%02x.%d", attr->domain, attr->bus,
+ attr->slot, attr->func);
+ return busid;
+}
+
+static Bool
+ATICardInit(KdCardInfo *card)
+{
+ ATICardInfo *atic;
+ int i;
+ Bool initialized = FALSE;
+
+ atic = xcalloc(sizeof(ATICardInfo), 1);
+ if (atic == NULL)
+ return FALSE;
+
+#ifdef KDRIVEFBDEV
+ if (!initialized && fbdevInitialize(card, &atic->backend_priv.fbdev)) {
+ atic->use_fbdev = TRUE;
+ initialized = TRUE;
+ atic->backend_funcs.cardfini = fbdevCardFini;
+ atic->backend_funcs.scrfini = fbdevScreenFini;
+ atic->backend_funcs.initScreen = fbdevInitScreen;
+ atic->backend_funcs.finishInitScreen = fbdevFinishInitScreen;
+ atic->backend_funcs.createRes = fbdevCreateResources;
+ atic->backend_funcs.preserve = fbdevPreserve;
+ atic->backend_funcs.restore = fbdevRestore;
+ atic->backend_funcs.dpms = fbdevDPMS;
+ atic->backend_funcs.enable = fbdevEnable;
+ atic->backend_funcs.disable = fbdevDisable;
+ atic->backend_funcs.getColors = fbdevGetColors;
+ atic->backend_funcs.putColors = fbdevPutColors;
+#ifdef RANDR
+ atic->backend_funcs.randrSetConfig = fbdevRandRSetConfig;
+#endif
+ }
+#endif
+#ifdef KDRIVEVESA
+ if (!initialized && vesaInitialize(card, &atic->backend_priv.vesa)) {
+ atic->use_vesa = TRUE;
+ initialized = TRUE;
+ atic->backend_funcs.cardfini = vesaCardFini;
+ atic->backend_funcs.scrfini = vesaScreenFini;
+ atic->backend_funcs.initScreen = vesaInitScreen;
+ atic->backend_funcs.finishInitScreen = vesaFinishInitScreen;
+ atic->backend_funcs.createRes = vesaCreateResources;
+ atic->backend_funcs.preserve = vesaPreserve;
+ atic->backend_funcs.restore = vesaRestore;
+ atic->backend_funcs.dpms = vesaDPMS;
+ atic->backend_funcs.enable = vesaEnable;
+ atic->backend_funcs.disable = vesaDisable;
+ atic->backend_funcs.getColors = vesaGetColors;
+ atic->backend_funcs.putColors = vesaPutColors;
+#ifdef RANDR
+ atic->backend_funcs.randrSetConfig = vesaRandRSetConfig;
+#endif
+ }
+#endif
+
+ if (!initialized || !ATIMapReg(card, atic)) {
+ xfree(atic);
+ return FALSE;
+ }
+
+ atic->busid = make_busid(&card->attr);
+ if (atic->busid == NULL) {
+ xfree(atic);
+ return FALSE;
+ }
+
+#ifdef USE_DRI
+ /* We demand identification by busid, not driver name */
+ atic->drmFd = drmOpen(NULL, atic->busid);
+ if (atic->drmFd < 0)
+ ErrorF("Failed to open DRM, DRI disabled.\n");
+#endif /* USE_DRI */
+
+ card->driver = atic;
+
+ for (i = 0; ati_pci_ids[i].name != NULL; i++) {
+ if (ati_pci_ids[i].device == card->attr.deviceID) {
+ atic->pci_id = &ati_pci_ids[i];
+ break;
+ }
+ }
+
+ if ((atic->pci_id->caps & CAP_SERIESMASK) != CAP_R128)
+ atic->is_radeon = TRUE;
+ if ((atic->pci_id->caps & CAP_SERIESMASK) == CAP_R100)
+ atic->is_r100 = TRUE;
+ if ((atic->pci_id->caps & CAP_SERIESMASK) == CAP_R200)
+ atic->is_r200 = TRUE;
+ if ((atic->pci_id->caps & CAP_SERIESMASK) == CAP_R300)
+ atic->is_r300 = TRUE;
+
+ atic->is_agp = ATIIsAGP(atic);
+
+ ErrorF("Using ATI card: %s (%s) at %s\n", atic->pci_id->name,
+ atic->is_agp ? "AGP" : "PCI", atic->busid);
+
+ return TRUE;
+}
+
+static void
+ATICardFini(KdCardInfo *card)
+{
+ ATICardInfo *atic = (ATICardInfo *)card->driver;
+
+ ATIUnmapReg(card, atic);
+ atic->backend_funcs.cardfini(card);
+}
+
+/*
+ * Once screen->off_screen_base is set, this function
+ * allocates the remaining memory appropriately
+ */
+
+static void
+ATISetOffscreen (KdScreenInfo *screen)
+{
+ ATICardInfo(screen);
+#if defined(USE_DRI) && defined(GLXEXT)
+ ATIScreenInfo *atis = (ATIScreenInfo *)screen->driver;
+ int l;
+#endif
+ int screen_size;
+ char *mmio = atic->reg_base;
+
+ /* check (and adjust) pitch */
+ if (mmio)
+ {
+ int byteStride = screen->fb[0].byteStride;
+ int bitStride;
+ int pixelStride;
+ int bpp = screen->fb[0].bitsPerPixel;
+
+ /*
+ * Ensure frame buffer is correctly aligned
+ */
+ if (byteStride & 0x3f)
+ {
+ byteStride = (byteStride + 0x3f) & ~0x3f;
+ bitStride = byteStride * 8;
+ pixelStride = bitStride / bpp;
+
+ screen->fb[0].byteStride = byteStride;
+ screen->fb[0].pixelStride = pixelStride;
+ }
+ }
+
+ screen_size = screen->fb[0].byteStride * screen->height;
+
+ screen->off_screen_base = screen_size;
+
+#if defined(USE_DRI) && defined(GLXEXT)
+ /* Reserve a static area for the back buffer the same size as the
+ * visible screen. XXX: This would be better initialized in ati_dri.c
+ * when GLX is set up, but the offscreen memory manager's allocations
+ * don't last through VT switches, while the kernel's understanding of
+ * offscreen locations does.
+ */
+ atis->frontOffset = 0;
+ atis->frontPitch = screen->fb[0].byteStride;
+
+ if (screen->off_screen_base + screen_size <= screen->memory_size) {
+ atis->backOffset = screen->off_screen_base;
+ atis->backPitch = screen->fb[0].byteStride;
+ screen->off_screen_base += screen_size;
+ }
+
+ /* Reserve the depth span for Rage 128 */
+ if (!atic->is_radeon && screen->off_screen_base +
+ screen->fb[0].byteStride <= screen->memory_size) {
+ atis->spanOffset = screen->off_screen_base;
+ screen->off_screen_base += screen->fb[0].byteStride;
+ }
+
+ /* Reserve the static depth buffer, which happens to be the same
+ * bitsPerPixel as the screen.
+ */
+ if (screen->off_screen_base + screen_size <= screen->memory_size) {
+ atis->depthOffset = screen->off_screen_base;
+ atis->depthPitch = screen->fb[0].byteStride;
+ screen->off_screen_base += screen_size;
+ }
+
+ /* Reserve approx. half of remaining offscreen memory for local
+ * textures. Round down to a whole number of texture regions.
+ */
+ atis->textureSize = (screen->memory_size - screen->off_screen_base) / 2;
+ l = ATILog2(atis->textureSize / ATI_NR_TEX_REGIONS);
+ if (l < ATI_LOG_TEX_GRANULARITY)
+ l = ATI_LOG_TEX_GRANULARITY;
+ atis->textureSize = (atis->textureSize >> l) << l;
+ if (atis->textureSize >= 512 * 1024) {
+ atis->textureOffset = screen->off_screen_base;
+ screen->off_screen_base += atis->textureSize;
+ } else {
+ /* Minimum texture size is for 2 256x256x32bpp textures */
+ atis->textureSize = 0;
+ }
+#endif /* USE_DRI && GLXEXT */
+}
+
+static void
+ATISetPitch (KdScreenInfo *screen)
+{
+ ATICardInfo(screen);
+#if defined(USE_DRI) && defined(GLXEXT)
+ ATIScreenInfo *atis = (ATIScreenInfo *)screen->driver;
+ int l;
+#endif
+ char *mmio = atic->reg_base;
+
+ /* check (and adjust) pitch for radeon */
+ if (mmio)
+ {
+ int byteStride = screen->fb[0].byteStride;
+ int bitStride;
+ int pixelStride;
+ int bpp = screen->fb[0].bitsPerPixel;
+ CARD32 crtc_pitch;
+ CARD32 crtc2_pitch;
+#if 0
+ CARD32 crtc_ext_cntl;
+ CARD32 dac_cntl;
+#endif
+ bitStride = byteStride * 8;
+ pixelStride = bitStride / bpp;
+
+ crtc_pitch = (pixelStride >> 3);
+ crtc_pitch |= crtc_pitch << 16;
+ crtc2_pitch = (pixelStride >> 3);
+ crtc2_pitch |= crtc2_pitch << 16;
+#if 0
+ crtc_ext_cntl = MMIO_IN32 (mmio, ATI_REG_CRTC_EXT_CNTL);
+ dac_cntl = MMIO_IN32 (mmio, ATI_REG_DAC_CNTL);
+ /* Turn off the screen */
+ MMIO_OUT32 (mmio, ATI_REG_CRTC_EXT_CNTL,
+ crtc_ext_cntl |
+ ATI_CRTC_VSYNC_DIS |
+ ATI_CRTC_HSYNC_DIS |
+ ATI_CRTC_DISPLAY_DIS);
+ MMIO_OUT32 (mmio, ATI_REG_DAC_CNTL,
+ dac_cntl |
+ ATI_DAC_RANGE_CNTL |
+ ATI_DAC_BLANKING);
+#endif
+ MMIO_OUT32 (mmio, ATI_REG_CRTC_PITCH, crtc_pitch);
+ MMIO_OUT32 (mmio, ATI_REG_CRTC2_PITCH, crtc2_pitch);
+#if 0
+ /* Turn the screen back on */
+ MMIO_OUT32 (mmio, ATI_REG_CRTC_EXT_CNTL,
+ crtc_ext_cntl);
+ MMIO_OUT32 (mmio, ATI_REG_DAC_CNTL,
+ dac_cntl);
+#endif
+ }
+}
+
+static Bool
+ATIScreenInit(KdScreenInfo *screen)
+{
+ ATIScreenInfo *atis;
+ ATICardInfo(screen);
+ Bool success = FALSE;
+
+ atis = xcalloc(sizeof(ATIScreenInfo), 1);
+ if (atis == NULL)
+ return FALSE;
+
+ atis->atic = atic;
+ atis->screen = screen;
+ screen->driver = atis;
+
+ if (screen->fb[0].depth == 0)
+ screen->fb[0].depth = 16;
+#ifdef KDRIVEFBDEV
+ if (atic->use_fbdev) {
+ success = fbdevScreenInitialize(screen,
+ &atis->backend_priv.fbdev);
+ }
+#endif
+#ifdef KDRIVEVESA
+ if (atic->use_vesa) {
+ success = vesaScreenInitialize(screen,
+ &atis->backend_priv.vesa);
+ }
+#endif
+
+ if (!success) {
+ screen->driver = NULL;
+ xfree(atis);
+ return FALSE;
+ }
+
+ ATISetOffscreen (screen);
+
+ return TRUE;
+}
+
+#ifdef RANDR
+static Bool
+ATIRandRSetConfig (ScreenPtr pScreen,
+ Rotation randr,
+ int rate,
+ RRScreenSizePtr pSize)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ ATICardInfo *atic = screen->card->driver;
+ Bool ret;
+
+ ATIDrawDisable (pScreen);
+ ret = atic->backend_funcs.randrSetConfig(pScreen, randr, rate, pSize);
+ ATISetOffscreen (screen);
+ ATISetPitch (screen);
+ /*
+ * Set frame buffer mapping
+ */
+ (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
+ pScreen->width,
+ pScreen->height,
+ screen->fb[0].depth,
+ screen->fb[0].bitsPerPixel,
+ screen->fb[0].byteStride,
+ screen->fb[0].frameBuffer);
+
+ ATIDrawEnable (pScreen);
+ return ret;
+}
+
+static Bool
+ATIRandRInit (ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+
+ pScrPriv = rrGetScrPriv(pScreen);
+ pScrPriv->rrSetConfig = ATIRandRSetConfig;
+ return TRUE;
+}
+#endif
+
+static void
+ATIScreenFini(KdScreenInfo *screen)
+{
+ ATIScreenInfo *atis = (ATIScreenInfo *)screen->driver;
+ ATICardInfo *atic = screen->card->driver;
+
+#ifdef XV
+ ATIFiniVideo(screen->pScreen);
+#endif
+
+ atic->backend_funcs.scrfini(screen);
+ xfree(atis);
+ screen->driver = 0;
+}
+
+Bool
+ATIMapReg(KdCardInfo *card, ATICardInfo *atic)
+{
+ atic->reg_base = (char *)KdMapDevice(ATI_REG_BASE(card),
+ ATI_REG_SIZE(card));
+
+ if (atic->reg_base == NULL)
+ return FALSE;
+
+ KdSetMappedMode(ATI_REG_BASE(card), ATI_REG_SIZE(card),
+ KD_MAPPED_MODE_REGISTERS);
+
+ return TRUE;
+}
+
+void
+ATIUnmapReg(KdCardInfo *card, ATICardInfo *atic)
+{
+ if (atic->reg_base) {
+ KdResetMappedMode(ATI_REG_BASE(card), ATI_REG_SIZE(card),
+ KD_MAPPED_MODE_REGISTERS);
+ KdUnmapDevice((void *)atic->reg_base, ATI_REG_SIZE(card));
+ atic->reg_base = 0;
+ }
+}
+
+static Bool
+ATIInitScreen(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ ATICardInfo(pScreenPriv);
+
+#ifdef XV
+ ATIInitVideo(pScreen);
+#endif
+ return atic->backend_funcs.initScreen(pScreen);
+}
+
+static Bool
+ATIFinishInitScreen(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ ATICardInfo(pScreenPriv);
+
+ if (!atic->backend_funcs.finishInitScreen(pScreen))
+ return FALSE;
+#ifdef RANDR
+ if (!ATIRandRInit (pScreen))
+ return FALSE;
+#endif
+ return TRUE;
+}
+
+static Bool
+ATICreateResources(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ ATICardInfo(pScreenPriv);
+
+ return atic->backend_funcs.createRes(pScreen);
+}
+
+static void
+ATIPreserve(KdCardInfo *card)
+{
+ ATICardInfo *atic = card->driver;
+ char *mmio = atic->reg_base;
+
+ atic->backend_funcs.preserve(card);
+ if (atic->is_radeon && mmio)
+ {
+ atic->crtc_pitch = MMIO_IN32(mmio, ATI_REG_CRTC_PITCH);
+ atic->crtc2_pitch = MMIO_IN32(mmio, ATI_REG_CRTC2_PITCH);
+
+ }
+}
+
+static void
+ATIRestore(KdCardInfo *card)
+{
+ ATICardInfo *atic = card->driver;
+ char *mmio = atic->reg_base;
+
+ if (mmio)
+ {
+ MMIO_OUT32(mmio, ATI_REG_CRTC_PITCH, atic->crtc_pitch);
+ MMIO_OUT32(mmio, ATI_REG_CRTC2_PITCH, atic->crtc2_pitch);
+ }
+ ATIUnmapReg(card, atic);
+
+ atic->backend_funcs.restore(card);
+}
+
+static Bool
+ATIDPMS(ScreenPtr pScreen, int mode)
+{
+ KdScreenPriv(pScreen);
+ ATICardInfo(pScreenPriv);
+
+ return atic->backend_funcs.dpms(pScreen, mode);
+}
+
+static Bool
+ATIEnable(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ ATICardInfo(pScreenPriv);
+
+ if (!atic->backend_funcs.enable(pScreen))
+ return FALSE;
+
+ if ((atic->reg_base == NULL) && !ATIMapReg(pScreenPriv->screen->card,
+ atic))
+ return FALSE;
+
+ ATISetOffscreen (pScreenPriv->screen);
+
+ ATISetPitch (pScreenPriv->screen);
+
+ return TRUE;
+}
+
+static void
+ATIDisable(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+#if defined(USE_DRI) && defined(GLXEXT)
+ ATIScreenInfo(pScreenPriv);
+#endif /* USE_DRI && GLXEXT */
+ ATICardInfo(pScreenPriv);
+
+ ATIUnmapReg(pScreenPriv->card, atic);
+
+ atic->backend_funcs.disable(pScreen);
+}
+
+static void
+ATIGetColors(ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ ATICardInfo(pScreenPriv);
+
+ atic->backend_funcs.getColors(pScreen, fb, n, pdefs);
+}
+
+static void
+ATIPutColors(ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ ATICardInfo(pScreenPriv);
+
+ atic->backend_funcs.putColors(pScreen, fb, n, pdefs);
+}
+
+/* Compute log base 2 of val. */
+int
+ATILog2(int val)
+{
+ int bits;
+
+ for (bits = 0; val != 0; val >>= 1, ++bits)
+ ;
+ return bits - 1;
+}
+
+static Bool
+ATIIsAGP(ATICardInfo *atic)
+{
+ char *mmio = atic->reg_base;
+ CARD32 cap_ptr, cap_id;
+
+ if (mmio == NULL)
+ return FALSE;
+
+ if (MMIO_IN32(mmio, ATI_REG_PCI_CFG_STATUS) & ATI_CAP_LIST) {
+ cap_ptr = MMIO_IN32(mmio, ATI_REG_PCI_CFG_CAPABILITIES_PTR) &
+ ATI_CAP_PTR_MASK;
+ while (cap_ptr != ATI_CAP_ID_NULL) {
+ cap_id = MMIO_IN32(mmio, ATI_PCI_CFG_OFFSET + cap_ptr);
+ if ((cap_id & 0xff) == ATI_CAP_ID_AGP)
+ return TRUE;
+ cap_ptr = (cap_id >> 8) & ATI_CAP_PTR_MASK;
+ }
+ }
+
+ return FALSE;
+}
+
+/* This function is required to work around a hardware bug in some (all?)
+ * revisions of the R300. This workaround should be called after every
+ * CLOCK_CNTL_INDEX register access. If not, register reads afterward
+ * may not be correct.
+ */
+void R300CGWorkaround(ATIScreenInfo *atis) {
+ ATICardInfo *atic = atis->atic;
+ char *mmio = atic->reg_base;
+ CARD32 save;
+
+ save = MMIO_IN32(mmio, ATI_REG_CLOCK_CNTL_INDEX);
+ MMIO_OUT32(mmio, ATI_REG_CLOCK_CNTL_INDEX, save & ~(0x3f |
+ ATI_PLL_WR_EN));
+ MMIO_IN32(mmio, ATI_REG_CLOCK_CNTL_INDEX);
+ MMIO_OUT32(mmio, ATI_REG_CLOCK_CNTL_INDEX, save);
+}
+
+KdCardFuncs ATIFuncs = {
+ ATICardInit, /* cardinit */
+ ATIScreenInit, /* scrinit */
+ ATIInitScreen, /* initScreen */
+ ATIFinishInitScreen, /* finishInitScreen */
+ ATICreateResources, /* createRes */
+ ATIPreserve, /* preserve */
+ ATIEnable, /* enable */
+ ATIDPMS, /* dpms */
+ ATIDisable, /* disable */
+ ATIRestore, /* restore */
+ ATIScreenFini, /* scrfini */
+ ATICardFini, /* cardfini */
+
+ ATICursorInit, /* initCursor */
+ ATICursorEnable, /* enableCursor */
+ ATICursorDisable, /* disableCursor */
+ ATICursorFini, /* finiCursor */
+ ATIRecolorCursor, /* recolorCursor */
+
+ ATIDrawInit, /* initAccel */
+ ATIDrawEnable, /* enableAccel */
+ ATIDrawDisable, /* disableAccel */
+ ATIDrawFini, /* finiAccel */
+
+ ATIGetColors, /* getColors */
+ ATIPutColors, /* putColors */
+};