xserver-multidpi/hw/kdrive/ati/ati.c
Eric Anholt 545c082cf9 - Replace the syncAccel hook in the kdrive structure with a pair of hooks
in the kaa structure: markSync and waitMarker. The first, if set,
    returns a hardware-dependent marker number which can then be waited for
    with waitMarker. If markSync is absent (which is the case on all
    drivers currently), waitMarker must wait for idle on any given marker
    number. The intention is to allow for more parallelism when we get
    downloading from framebuffer, or more fine-grained idling.
- Replace the KdMarkSync/KdCheckSync functions with kaaMarkSync and
    kaaWaitSync. These will need to be refined when KAA starts being smart
    about using them. Merge kpict.c into kasync.c since kasyn.c has all the
    rest of these fallback funcs.
- Restructure all drivers to initialize a KaaInfo structure by hand rather
    than statically in dubious order.
- Whack the i810 driver into shape in hopes that it'll work after this
    change (it certainly wouldn't have before this). Doesn't support my
    i845 though.
- Make a new KXV helper to avoid duplicated code to fill the region with
    the necessary color key. Use it in i810 and mach64 (tested).
2005-06-09 10:44:45 +00:00

765 lines
21 KiB
C

/*
* $Id$
*
* 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.
*/
/* $Header$ */
#ifdef HAVE_CONFIG_H
#include <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 = (CARD8 *)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 */
};