summaryrefslogtreecommitdiff
path: root/src/atiadjust.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/atiadjust.c')
-rw-r--r--src/atiadjust.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/src/atiadjust.c b/src/atiadjust.c
new file mode 100644
index 00000000..df2ac649
--- /dev/null
+++ b/src/atiadjust.c
@@ -0,0 +1,224 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiadjust.c,v 1.14 2003/01/01 19:16:30 tsi Exp $ */
+/*
+ * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * 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 Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE 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.
+ */
+
+#include "ati.h"
+#include "atiadjust.h"
+#include "atichip.h"
+#include "aticrtc.h"
+#include "atilock.h"
+#include "atimach64io.h"
+#include "atiwonderio.h"
+
+/*
+ * The display start address is expressed in units of 32-bit (VGA) or 64-bit
+ * (accelerator) words where all planar modes are considered as 4bpp modes.
+ * These functions ensure the start address does not exceed architectural
+ * limits. Also, to avoid colour changes while panning, these 32-bit or 64-bit
+ * boundaries may not fall within a pixel.
+ */
+
+/*
+ * ATIAjustPreInit --
+ *
+ * This function calculates values needed to speed up the setting of the
+ * display start address.
+ */
+void
+ATIAdjustPreInit
+(
+ ATIPtr pATI
+)
+{
+ unsigned long MaxBase;
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->CPIO_VGAWonder) &&
+ (pATI->Chip <= ATI_CHIP_18800_1) &&
+ (pATI->VideoRAM == 256) &&
+ (pATI->depth >= 8))
+ {
+ /* Strange, to say the least ... */
+ pATI->AdjustDepth = (pATI->bitsPerPixel + 3) >> 2;
+ pATI->AdjustMask = (unsigned long)(-32);
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+ pATI->AdjustDepth = (pATI->bitsPerPixel + 7) >> 3;
+
+ pATI->AdjustMask = 64;
+ while (pATI->AdjustMask % (unsigned long)(pATI->AdjustDepth))
+ pATI->AdjustMask += 64;
+ pATI->AdjustMask =
+ ~(((pATI->AdjustMask / (unsigned long)(pATI->AdjustDepth)) >> 3) -
+ 1);
+ }
+
+ switch (pATI->NewHW.crtc)
+ {
+
+#ifndef AVOID_CPIO
+
+ case ATI_CRTC_VGA:
+ if (pATI->Chip >= ATI_CHIP_264CT)
+ {
+ pATI->AdjustMaxBase = MaxBits(CRTC_OFFSET_VGA) << 2;
+ if (pATI->depth <= 4)
+ pATI->AdjustMaxBase <<= 1;
+ }
+ else if (!pATI->CPIO_VGAWonder)
+ pATI->AdjustMaxBase = 0xFFFFU << 3;
+ else if (pATI->Chip <= ATI_CHIP_28800_6)
+ pATI->AdjustMaxBase = 0x03FFFFU << 3;
+ else /* Mach32 & Mach64 */
+ pATI->AdjustMaxBase = 0x0FFFFFU << 3;
+ break;
+
+#endif /* AVOID_CPIO */
+
+ case ATI_CRTC_MACH64:
+ pATI->AdjustMaxBase = MaxBits(CRTC_OFFSET) << 3;
+ break;
+
+ default:
+ pATI->AdjustMaxBase = 0;
+ break;
+ }
+
+ MaxBase = (pATI->AdjustMaxBase / (unsigned long)pATI->AdjustDepth) |
+ ~pATI->AdjustMask;
+
+ pATI->AdjustMaxX = MaxBase % pATI->displayWidth;
+ pATI->AdjustMaxY = MaxBase / pATI->displayWidth;
+}
+
+/*
+ * ATIAdjustFrame --
+ *
+ * This function is used to initialise the SVGA Start Address - the first
+ * displayed location in video memory. This is used to implement the virtual
+ * window.
+ */
+void
+ATIAdjustFrame
+(
+ int scrnIndex,
+ int x,
+ int y,
+ int flags
+)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[scrnIndex];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ int Base, xy;
+
+ /*
+ * Assume the caller has already done its homework in ensuring the physical
+ * screen is still contained in the virtual resolution.
+ */
+ if (y >= pATI->AdjustMaxY)
+ {
+ y = pATI->AdjustMaxY;
+ if (x > pATI->AdjustMaxX)
+ y--;
+ }
+
+ Base = ((((y * pATI->displayWidth) + x) & pATI->AdjustMask) *
+ pATI->AdjustDepth) >> 3;
+
+ if (!pATI->currentMode)
+ {
+ /*
+ * Not in DGA. This reverse-calculates pScreenInfo->frame[XY][01] so
+ * that the cursor does not move on mode switches.
+ */
+ xy = (Base << 3) / pATI->AdjustDepth;
+ pScreenInfo->frameX0 = xy % pATI->displayWidth;
+ pScreenInfo->frameY0 = xy / pATI->displayWidth;
+ pScreenInfo->frameX1 =
+ pScreenInfo->frameX0 + pScreenInfo->currentMode->HDisplay - 1;
+ pScreenInfo->frameY1 =
+ pScreenInfo->frameY0 + pScreenInfo->currentMode->VDisplay - 1;
+ }
+
+ /* Unlock registers */
+ ATIUnlock(pATI);
+
+#ifndef AVOID_CPIO
+
+ if ((pATI->NewHW.crtc == ATI_CRTC_VGA) && (pATI->Chip < ATI_CHIP_264CT))
+ {
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x0CU, GetByte(Base, 1));
+ PutReg(CRTX(pATI->CPIO_VGABase), 0x0DU, GetByte(Base, 0));
+
+ if (pATI->CPIO_VGAWonder)
+ {
+ if (pATI->Chip <= ATI_CHIP_18800_1)
+ ATIModifyExtReg(pATI, 0xB0U, -1, 0x3FU, Base >> 10);
+ else
+ {
+ ATIModifyExtReg(pATI, 0xB0U, -1, 0xBFU, Base >> 10);
+ ATIModifyExtReg(pATI, 0xA3U, -1, 0xEFU, Base >> 13);
+
+ /*
+ * I don't know if this also applies to Mach64's, but give it a
+ * shot...
+ */
+ if (pATI->Chip >= ATI_CHIP_68800)
+ ATIModifyExtReg(pATI, 0xADU, -1, 0xF3U, Base >> 16);
+ }
+ }
+ }
+ else
+ /*
+ * On integrated controllers, there is only one set of CRTC control bits,
+ * many of which are simultaneously accessible through both VGA and
+ * accelerator I/O ports. Given VGA's architectural limitations, setting
+ * the CRTC's offset register to more than 256k needs to be done through
+ * the accelerator port.
+ */
+ if (pATI->depth <= 4)
+ {
+ outr(CRTC_OFF_PITCH, SetBits(pATI->displayWidth >> 4, CRTC_PITCH) |
+ SetBits(Base, CRTC_OFFSET));
+ }
+ else
+
+#endif /* AVOID_CPIO */
+
+ {
+
+#ifndef AVOID_CPIO
+
+ if (pATI->NewHW.crtc == ATI_CRTC_VGA)
+ Base <<= 1; /* LSBit must be zero */
+
+#endif /* AVOID_CPIO */
+
+ outr(CRTC_OFF_PITCH, SetBits(pATI->displayWidth >> 3, CRTC_PITCH) |
+ SetBits(Base, CRTC_OFFSET));
+ }
+}