summaryrefslogtreecommitdiff
path: root/hw/xfree86/ramdac/IBM.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/ramdac/IBM.c')
-rw-r--r--hw/xfree86/ramdac/IBM.c633
1 files changed, 633 insertions, 0 deletions
diff --git a/hw/xfree86/ramdac/IBM.c b/hw/xfree86/ramdac/IBM.c
new file mode 100644
index 000000000..d62a9ba56
--- /dev/null
+++ b/hw/xfree86/ramdac/IBM.c
@@ -0,0 +1,633 @@
+/*
+ * Copyright 1998 by Alan Hourihane, Wigan, England.
+ *
+ * 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 Alan Hourihane not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Alan Hourihane makes no representations
+ * about the suitability of this software for any purpose. It is provided
+ * "as is" without express or implied warranty.
+ *
+ * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ALAN HOURIHANE 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.
+ *
+ * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
+ *
+ * IBM RAMDAC routines.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/ramdac/IBM.c,v 1.12 2003/02/17 16:08:29 dawes Exp $ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+
+#include "xf86Cursor.h"
+
+#define INIT_IBM_RAMDAC_INFO
+#include "IBMPriv.h"
+#include "xf86RamDacPriv.h"
+
+#define INITIALFREQERR 100000
+
+unsigned long
+IBMramdac640CalculateMNPCForClock(
+ unsigned long RefClock, /* In 100Hz units */
+ unsigned long ReqClock, /* In 100Hz units */
+ char IsPixClock, /* boolean, is this the pixel or the sys clock */
+ unsigned long MinClock, /* Min VCO rating */
+ unsigned long MaxClock, /* Max VCO rating */
+ unsigned long *rM, /* M Out */
+ unsigned long *rN, /* N Out */
+ unsigned long *rP, /* Min P In, P Out */
+ unsigned long *rC /* C Out */
+)
+{
+ unsigned long M, N, P, iP = *rP;
+ unsigned long IntRef, VCO, Clock;
+ long freqErr, lowestFreqErr = INITIALFREQERR;
+ unsigned long ActualClock = 0;
+
+ for (N = 0; N <= 63; N++)
+ {
+ IntRef = RefClock / (N + 1);
+ if (IntRef < 10000)
+ break; /* IntRef needs to be >= 1MHz */
+ for (M = 2; M <= 127; M++)
+ {
+ VCO = IntRef * (M + 1);
+ if ((VCO < MinClock) || (VCO > MaxClock))
+ continue;
+ for (P = iP; P <= 4; P++)
+ {
+ if (P != 0)
+ Clock = (RefClock * (M + 1)) / ((N + 1) * 2 * P);
+ else
+ Clock = (RefClock * (M + 1)) / (N + 1);
+
+ freqErr = (Clock - ReqClock);
+
+ if (freqErr < 0)
+ {
+ /* PixelClock gets rounded up always so monitor reports
+ correct frequency. */
+ if (IsPixClock)
+ continue;
+ freqErr = -freqErr;
+ }
+
+ if (freqErr < lowestFreqErr)
+ {
+ *rM = M;
+ *rN = N;
+ *rP = P;
+ *rC = (VCO <= 1280000 ? 1 : 2);
+ ActualClock = Clock;
+
+ lowestFreqErr = freqErr;
+ /* Return if we found an exact match */
+ if (freqErr == 0)
+ return (ActualClock);
+ }
+ }
+ }
+ }
+
+ return (ActualClock);
+}
+
+unsigned long
+IBMramdac526CalculateMNPCForClock(
+ unsigned long RefClock, /* In 100Hz units */
+ unsigned long ReqClock, /* In 100Hz units */
+ char IsPixClock, /* boolean, is this the pixel or the sys clock */
+ unsigned long MinClock, /* Min VCO rating */
+ unsigned long MaxClock, /* Max VCO rating */
+ unsigned long *rM, /* M Out */
+ unsigned long *rN, /* N Out */
+ unsigned long *rP, /* Min P In, P Out */
+ unsigned long *rC /* C Out */
+)
+{
+ unsigned long M, N, P, iP = *rP;
+ unsigned long IntRef, VCO, Clock;
+ long freqErr, lowestFreqErr = INITIALFREQERR;
+ unsigned long ActualClock = 0;
+
+ for (N = 0; N <= 63; N++)
+ {
+ IntRef = RefClock / (N + 1);
+ if (IntRef < 10000)
+ break; /* IntRef needs to be >= 1MHz */
+ for (M = 0; M <= 63; M++)
+ {
+ VCO = IntRef * (M + 1);
+ if ((VCO < MinClock) || (VCO > MaxClock))
+ continue;
+ for (P = iP; P <= 4; P++)
+ {
+ if (P)
+ Clock = (RefClock * (M + 1)) / ((N + 1) * 2 * P);
+ else
+ Clock = VCO;
+
+ freqErr = (Clock - ReqClock);
+
+ if (freqErr < 0)
+ {
+ /* PixelClock gets rounded up always so monitor reports
+ correct frequency. */
+ if (IsPixClock)
+ continue;
+ freqErr = -freqErr;
+ }
+
+ if (freqErr < lowestFreqErr)
+ {
+ *rM = M;
+ *rN = N;
+ *rP = P;
+ *rC = (VCO <= 1280000 ? 1 : 2);
+ ActualClock = Clock;
+
+ lowestFreqErr = freqErr;
+ /* Return if we found an exact match */
+ if (freqErr == 0)
+ return (ActualClock);
+ }
+ }
+ }
+ }
+
+ return (ActualClock);
+}
+
+void
+IBMramdacRestore(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
+ RamDacRegRecPtr ramdacReg)
+{
+ int i, maxreg, dacreg;
+
+ switch (ramdacPtr->RamDacType) {
+ case IBM640_RAMDAC:
+ maxreg = 0x300;
+ dacreg = 1024;
+ break;
+ default:
+ maxreg = 0x100;
+ dacreg = 768;
+ break;
+ }
+
+ /* Here we pass a short, so that we can evaluate a mask too */
+ /* So that the mask is the high byte and the data the low byte */
+ for (i=0;i<maxreg;i++)
+ (*ramdacPtr->WriteDAC)
+ (pScrn, i, (ramdacReg->DacRegs[i] & 0xFF00) >> 8,
+ ramdacReg->DacRegs[i]);
+
+ (*ramdacPtr->WriteAddress)(pScrn, 0);
+ for (i=0;i<dacreg;i++)
+ (*ramdacPtr->WriteData)(pScrn, ramdacReg->DAC[i]);
+}
+
+void
+IBMramdacSave(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPtr,
+ RamDacRegRecPtr ramdacReg)
+{
+ int i, maxreg, dacreg;
+
+ switch (ramdacPtr->RamDacType) {
+ case IBM640_RAMDAC:
+ maxreg = 0x300;
+ dacreg = 1024;
+ break;
+ default:
+ maxreg = 0x100;
+ dacreg = 768;
+ break;
+ }
+
+ (*ramdacPtr->ReadAddress)(pScrn, 0);
+ for (i=0;i<dacreg;i++)
+ ramdacReg->DAC[i] = (*ramdacPtr->ReadData)(pScrn);
+
+ for (i=0;i<maxreg;i++)
+ ramdacReg->DacRegs[i] = (*ramdacPtr->ReadDAC)(pScrn, i);
+}
+
+RamDacHelperRecPtr
+IBMramdacProbe(ScrnInfoPtr pScrn, RamDacSupportedInfoRecPtr ramdacs/* , RamDacRecPtr ramdacPtr*/)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+ RamDacHelperRecPtr ramdacHelperPtr = NULL;
+ Bool RamDacIsSupported = FALSE;
+ int IBMramdac_ID = -1;
+ int i;
+ unsigned char id, rev, id2, rev2;
+
+ /* read ID and revision */
+ rev = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_rev);
+ id = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_id);
+
+ /* check if ID and revision are read only */
+ (*ramdacPtr->WriteDAC)(pScrn, ~rev, 0, IBMRGB_rev);
+ (*ramdacPtr->WriteDAC)(pScrn, ~id, 0, IBMRGB_id);
+ rev2 = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_rev);
+ id2 = (*ramdacPtr->ReadDAC)(pScrn, IBMRGB_id);
+
+ switch (id) {
+ case 0x30:
+ if (rev == 0xc0) IBMramdac_ID = IBM624_RAMDAC;
+ if (rev == 0x80) IBMramdac_ID = IBM624DB_RAMDAC;
+ break;
+ case 0x12:
+ if (rev == 0x1c) IBMramdac_ID = IBM640_RAMDAC;
+ break;
+ case 0x01:
+ IBMramdac_ID = IBM525_RAMDAC;
+ break;
+ case 0x02:
+ if (rev == 0xf0) IBMramdac_ID = IBM524_RAMDAC;
+ if (rev == 0xe0) IBMramdac_ID = IBM524A_RAMDAC;
+ if (rev == 0xc0) IBMramdac_ID = IBM526_RAMDAC;
+ if (rev == 0x80) IBMramdac_ID = IBM526DB_RAMDAC;
+ break;
+ }
+
+ if (id == 1 || id == 2) {
+ if (id == id2 && rev == rev2) { /* IBM RGB52x found */
+ /* check for 128bit VRAM -> RGB528 */
+ if (((*ramdacPtr->ReadDAC)(pScrn, IBMRGB_misc1) & 0x03) == 0x03) {
+ IBMramdac_ID = IBM528_RAMDAC; /* 128bit DAC found */
+ if (rev == 0xe0)
+ IBMramdac_ID = IBM528A_RAMDAC;
+ }
+ }
+ }
+
+ (*ramdacPtr->WriteDAC)(pScrn, rev, 0, IBMRGB_rev);
+ (*ramdacPtr->WriteDAC)(pScrn, id, 0, IBMRGB_id);
+
+ if (IBMramdac_ID == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Cannot determine IBM RAMDAC type, aborting\n");
+ return NULL;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Attached RAMDAC is %s\n", IBMramdacDeviceInfo[IBMramdac_ID&0xFFFF]);
+ }
+
+ for (i=0;ramdacs[i].token != -1;i++) {
+ if (ramdacs[i].token == IBMramdac_ID)
+ RamDacIsSupported = TRUE;
+ }
+
+ if (!RamDacIsSupported) {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "This IBM RAMDAC is NOT supported by this driver, aborting\n");
+ return NULL;
+ }
+
+ ramdacHelperPtr = RamDacHelperCreateInfoRec();
+ switch (IBMramdac_ID) {
+ case IBM526_RAMDAC:
+ case IBM526DB_RAMDAC:
+ ramdacHelperPtr->SetBpp = IBMramdac526SetBpp;
+ ramdacHelperPtr->HWCursorInit = IBMramdac526HWCursorInit;
+ break;
+ case IBM640_RAMDAC:
+ ramdacHelperPtr->SetBpp = IBMramdac640SetBpp;
+ ramdacHelperPtr->HWCursorInit = IBMramdac640HWCursorInit;
+ break;
+ }
+ ramdacPtr->RamDacType = IBMramdac_ID;
+ ramdacHelperPtr->RamDacType = IBMramdac_ID;
+ ramdacHelperPtr->Save = IBMramdacSave;
+ ramdacHelperPtr->Restore = IBMramdacRestore;
+
+ return ramdacHelperPtr;
+}
+
+void
+IBMramdac526SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg)
+{
+ ramdacReg->DacRegs[IBMRGB_key_control] = 0x00; /* Disable Chroma Key */
+
+ switch (pScrn->bitsPerPixel) {
+ case 32:
+ ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_32BPP;
+ ramdacReg->DacRegs[IBMRGB_32bpp] = B32_DCOL_DIRECT;
+ ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
+ if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
+ ramdacReg->DacRegs[IBMRGB_key_control] = 0x01; /* Enable Key */
+ ramdacReg->DacRegs[IBMRGB_key] = 0xFF;
+ ramdacReg->DacRegs[IBMRGB_key_mask] = 0xFF;
+ }
+ break;
+ case 24:
+ ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_24BPP;
+ ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_24bpp] = B24_DCOL_DIRECT;
+ ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
+ break;
+ case 16:
+ if (pScrn->depth == 16) {
+ ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_16BPP;
+ ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_16bpp] = B16_DCOL_DIRECT|B16_LINEAR |
+ B16_CONTIGUOUS | B16_565;
+ ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
+ } else {
+ ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_16BPP;
+ ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_16bpp] = B16_DCOL_DIRECT|B16_LINEAR |
+ B16_CONTIGUOUS | B16_555;
+ ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
+ }
+ break;
+ case 8:
+ ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_8BPP;
+ ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_8bpp] = B8_DCOL_INDIRECT;
+ break;
+ case 4:
+ ramdacReg->DacRegs[IBMRGB_pix_fmt] = PIXEL_FORMAT_4BPP;
+ ramdacReg->DacRegs[IBMRGB_32bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_24bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_16bpp] = 0;
+ ramdacReg->DacRegs[IBMRGB_8bpp] = 0;
+ }
+}
+
+void
+IBMramdac640SetBpp(ScrnInfoPtr pScrn, RamDacRegRecPtr ramdacReg)
+{
+ unsigned char bpp = 0x00;
+ unsigned char overlaybpp = 0x00;
+ unsigned char offset = 0x00;
+ unsigned char dispcont = 0x44;
+
+ ramdacReg->DacRegs[RGB640_SER_WID_03_00] = 0x00;
+ ramdacReg->DacRegs[RGB640_SER_WID_07_04] = 0x00;
+ ramdacReg->DacRegs[RGB640_DIAGS] = 0x07;
+
+ switch (pScrn->depth) {
+ case 8:
+ ramdacReg->DacRegs[RGB640_SER_07_00] = 0x00;
+ ramdacReg->DacRegs[RGB640_SER_15_08] = 0x00;
+ ramdacReg->DacRegs[RGB640_SER_23_16] = 0x00;
+ ramdacReg->DacRegs[RGB640_SER_31_24] = 0x00;
+ ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_16_1; /*16:1 Mux*/
+ ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
+ bpp = 0x03;
+ break;
+ case 15:
+ ramdacReg->DacRegs[RGB640_SER_07_00] = 0x10;
+ ramdacReg->DacRegs[RGB640_SER_15_08] = 0x11;
+ ramdacReg->DacRegs[RGB640_SER_23_16] = 0x00;
+ ramdacReg->DacRegs[RGB640_SER_31_24] = 0x00;
+ ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_8_1; /* 8:1 Mux*/
+ ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
+ bpp = 0x0E;
+ break;
+ case 16:
+ ramdacReg->DacRegs[RGB640_SER_07_00] = 0x10;
+ ramdacReg->DacRegs[RGB640_SER_15_08] = 0x11;
+ ramdacReg->DacRegs[RGB640_SER_23_16] = 0x00;
+ ramdacReg->DacRegs[RGB640_SER_31_24] = 0x00;
+ ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_8_1; /* 8:1 Mux*/
+ ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
+ bpp = 0x05;
+ break;
+ case 24:
+ ramdacReg->DacRegs[RGB640_SER_07_00] = 0x30;
+ ramdacReg->DacRegs[RGB640_SER_15_08] = 0x31;
+ ramdacReg->DacRegs[RGB640_SER_23_16] = 0x32;
+ ramdacReg->DacRegs[RGB640_SER_31_24] = 0x33;
+ ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_4_1; /* 4:1 Mux*/
+ ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PCLK_8; /* pll / 8 */
+ bpp = 0x09;
+ if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
+ ramdacReg->DacRegs[RGB640_SER_WID_07_04] = 0x04;
+ ramdacReg->DacRegs[RGB640_CHROMA_KEY0] = 0xFF;
+ ramdacReg->DacRegs[RGB640_CHROMA_MASK0] = 0xFF;
+ offset = 0x04;
+ overlaybpp = 0x04;
+ dispcont = 0x48;
+ }
+ break;
+ case 30: /* 10 bit dac */
+ ramdacReg->DacRegs[RGB640_SER_07_00] = 0x30;
+ ramdacReg->DacRegs[RGB640_SER_15_08] = 0x31;
+ ramdacReg->DacRegs[RGB640_SER_23_16] = 0x32;
+ ramdacReg->DacRegs[RGB640_SER_31_24] = 0x33;
+ ramdacReg->DacRegs[RGB640_SER_MODE] = IBM640_SER_4_1; /* 4:1 Mux*/
+ ramdacReg->DacRegs[RGB640_MISC_CONF] = IBM640_PSIZE10 |
+ IBM640_PCLK_8; /* pll / 8 */
+ bpp = 0x0D;
+ break;
+ }
+
+ {
+ int i;
+ for (i=0x100;i<0x140;i+=4) {
+ /* Initialize FrameBuffer Window Attribute Table */
+ ramdacReg->DacRegs[i+0] = bpp;
+ ramdacReg->DacRegs[i+1] = offset;
+ ramdacReg->DacRegs[i+2] = 0x00;
+ ramdacReg->DacRegs[i+3] = 0x00;
+ /* Initialize Overlay Window Attribute Table */
+ ramdacReg->DacRegs[i+0x100] = overlaybpp;
+ ramdacReg->DacRegs[i+0x101] = 0x00;
+ ramdacReg->DacRegs[i+0x102] = 0x00;
+ ramdacReg->DacRegs[i+0x103] = dispcont;
+ }
+ }
+}
+
+static void
+IBMramdac526ShowCursor(ScrnInfoPtr pScrn)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+
+ /* Enable cursor - X11 mode */
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs, 0x00, 0x07);
+}
+
+static void
+IBMramdac640ShowCursor(ScrnInfoPtr pScrn)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+
+ /* Enable cursor - mode2 (x11 mode) */
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURSOR_CONTROL, 0x00, 0x0B);
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CROSSHAIR_CONTROL, 0x00, 0x00);
+}
+
+static void
+IBMramdac526HideCursor(ScrnInfoPtr pScrn)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+
+ /* Disable cursor - X11 mode */
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs, 0x00, 0x24);
+}
+
+static void
+IBMramdac640HideCursor(ScrnInfoPtr pScrn)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+
+ /* Disable cursor - mode2 (x11 mode) */
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURSOR_CONTROL, 0x00, 0x08);
+}
+
+static void
+IBMramdac526SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+
+ x += 64;
+ y += 64;
+
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_hot_x, 0x00, 0x3f);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_hot_y, 0x00, 0x3f);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_xl, 0x00, x & 0xff);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_xh, 0x00, (x>>8) & 0xf);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_yl, 0x00, y & 0xff);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_yh, 0x00, (y>>8) & 0xf);
+}
+
+static void
+IBMramdac640SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+
+ x += 64;
+ y += 64;
+
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_OFFSETX, 0x00, 0x3f);
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_OFFSETY, 0x00, 0x3f);
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_X_LOW, 0x00, x & 0xff);
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_X_HIGH, 0x00, (x>>8) & 0xf);
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_Y_LOW, 0x00, y & 0xff);
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_Y_HIGH, 0x00, (y>>8) & 0xf);
+}
+
+static void
+IBMramdac526SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col1_r, 0x00, bg >> 16);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col1_g, 0x00, bg >> 8);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col1_b, 0x00, bg);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col2_r, 0x00, fg >> 16);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col2_g, 0x00, fg >> 8);
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_col2_b, 0x00, fg);
+}
+
+static void
+IBMramdac640SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_COL0, 0x00, 0);
+ (*ramdacPtr->WriteData)(pScrn, fg>>16);
+ (*ramdacPtr->WriteData)(pScrn, fg>>8);
+ (*ramdacPtr->WriteData)(pScrn, fg);
+ (*ramdacPtr->WriteData)(pScrn, bg>>16);
+ (*ramdacPtr->WriteData)(pScrn, bg>>8);
+ (*ramdacPtr->WriteData)(pScrn, bg);
+ (*ramdacPtr->WriteData)(pScrn, fg>>16);
+ (*ramdacPtr->WriteData)(pScrn, fg>>8);
+ (*ramdacPtr->WriteData)(pScrn, fg);
+ (*ramdacPtr->WriteData)(pScrn, bg>>16);
+ (*ramdacPtr->WriteData)(pScrn, bg>>8);
+ (*ramdacPtr->WriteData)(pScrn, bg);
+}
+
+static void
+IBMramdac526LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+ int i;
+ /*
+ * Output the cursor data. The realize function has put the planes into
+ * their correct order, so we can just blast this out.
+ */
+ for (i = 0; i < 1024; i++)
+ (*ramdacPtr->WriteDAC)(pScrn, IBMRGB_curs_array + i, 0x00, (*src++));
+}
+
+static void
+IBMramdac640LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+ RamDacRecPtr ramdacPtr = RAMDACSCRPTR(pScrn);
+ int i;
+ /*
+ * Output the cursor data. The realize function has put the planes into
+ * their correct order, so we can just blast this out.
+ */
+ for (i = 0; i < 1024; i++)
+ (*ramdacPtr->WriteDAC)(pScrn, RGB640_CURS_WRITE + i, 0x00, (*src++));
+}
+
+static Bool
+IBMramdac526UseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
+{
+ return TRUE;
+}
+
+static Bool
+IBMramdac640UseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
+{
+ return TRUE;
+}
+
+void
+IBMramdac526HWCursorInit(xf86CursorInfoPtr infoPtr)
+{
+ infoPtr->MaxWidth = 64;
+ infoPtr->MaxHeight = 64;
+ infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+ HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
+ infoPtr->SetCursorColors = IBMramdac526SetCursorColors;
+ infoPtr->SetCursorPosition = IBMramdac526SetCursorPosition;
+ infoPtr->LoadCursorImage = IBMramdac526LoadCursorImage;
+ infoPtr->HideCursor = IBMramdac526HideCursor;
+ infoPtr->ShowCursor = IBMramdac526ShowCursor;
+ infoPtr->UseHWCursor = IBMramdac526UseHWCursor;
+}
+
+void
+IBMramdac640HWCursorInit(xf86CursorInfoPtr infoPtr)
+{
+ infoPtr->MaxWidth = 64;
+ infoPtr->MaxHeight = 64;
+ infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
+ HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
+ infoPtr->SetCursorColors = IBMramdac640SetCursorColors;
+ infoPtr->SetCursorPosition = IBMramdac640SetCursorPosition;
+ infoPtr->LoadCursorImage = IBMramdac640LoadCursorImage;
+ infoPtr->HideCursor = IBMramdac640HideCursor;
+ infoPtr->ShowCursor = IBMramdac640ShowCursor;
+ infoPtr->UseHWCursor = IBMramdac640UseHWCursor;
+}