1200 lines
30 KiB
C
1200 lines
30 KiB
C
/*
|
|
* Copyright 2001 by Alan Hourihane, Sychdyn, North Wales, UK.
|
|
*
|
|
* 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>
|
|
*
|
|
* A driver for the following PCMCIA cards...
|
|
* Hewlett Packards HP VGA Out (Model F1252A)
|
|
* Colorgraphics Voyager VGA
|
|
*
|
|
* Tested running under a Compaq IPAQ Pocket PC running Linux
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <kdrive-config.h>
|
|
#endif
|
|
#include "pcmcia.h"
|
|
#define extern
|
|
#include <asm/io.h>
|
|
#undef extern
|
|
|
|
#define CLOCK 14318 /* KHz */
|
|
#define CLK_N(a,b) (a & 0xff)
|
|
#define CLK_M(a,b) ((b) & 0x3f)
|
|
#define CLK_K(a,b) (((b) >> 6) & 3)
|
|
#define CLK_FREQ(a,b) (((CLK_N(a,b) + 8) * CLOCK) / ((CLK_M(a,b)+2) << CLK_K(a,b)))
|
|
|
|
extern void
|
|
tridentUpdatePacked (ScreenPtr pScreen,
|
|
shadowBufPtr pBuf);
|
|
extern void
|
|
cirrusUpdatePacked (ScreenPtr pScreen,
|
|
shadowBufPtr pBuf);
|
|
|
|
static Bool
|
|
tridentSetCLK(int clock, CARD8 *a, CARD8 *b);
|
|
|
|
static Bool
|
|
CirrusFindClock(int freq, int *num_out, int *den_out);
|
|
|
|
Bool
|
|
pcmciaCardInit (KdCardInfo *card)
|
|
{
|
|
pcmciaCardInfo *pcmciac;
|
|
CARD8 r9;
|
|
|
|
pcmciac = (pcmciaCardInfo *) xalloc (sizeof (pcmciaCardInfo));
|
|
if (!pcmciac)
|
|
return FALSE;
|
|
|
|
pcmciac->cop_base = (CARD8 *) KdMapDevice (PCMCIA_COP_BASE(card),
|
|
PCMCIA_COP_SIZE(card));
|
|
|
|
r9 = pcmciaReadIndex (pcmciac, 0x3c4, 0x09);
|
|
/*
|
|
* Crude detection....
|
|
* The trident chip has a read only register at 0x09, which returns 0x4.
|
|
* If it's not that, we assume the cirrus chip.
|
|
* BREAKAGE.! If we have an anonymous PCMCIA card inserted, we could
|
|
* potentially smash something here. FIXME !
|
|
*/
|
|
if (r9 == 0x04) {
|
|
ErrorF("PCMCIA: Found HP VGA card\n");
|
|
pcmciac->HP = TRUE; /* Select HP VGA Out Card */
|
|
} else {
|
|
ErrorF("PCMCIA: Found Voyager VGA card\n");
|
|
pcmciac->HP = FALSE; /* Select Voyager VGA Card */
|
|
}
|
|
|
|
if (pcmciac->HP) {
|
|
/* needed by the accelerator - later */
|
|
pcmciac->cop = (Cop *) (pcmciac->cop_base + TRIDENT_COP_OFF(card));
|
|
}
|
|
|
|
/*
|
|
* Map frame buffer
|
|
*/
|
|
if (pcmciac->HP)
|
|
pcmciac->fb = KdMapDevice (0x2ce00000, 0x80000);
|
|
else
|
|
pcmciac->fb = KdMapDevice (0x2c0a0000, 0x10000); /*64K bank switched*/
|
|
|
|
if (!pcmciac->fb)
|
|
return FALSE;
|
|
|
|
pcmciac->window = 0;
|
|
|
|
card->driver = pcmciac;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
pcmciaModeSupported (KdScreenInfo *screen,
|
|
const KdMonitorTiming *t)
|
|
{
|
|
KdCardInfo *card = screen->card;
|
|
pcmciaCardInfo *pcmciac = (pcmciaCardInfo *) card->driver;
|
|
|
|
if (pcmciac->HP)
|
|
{
|
|
CARD8 a, b;
|
|
if (!tridentSetCLK (t->clock, &a, &b))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
int a, b;
|
|
if (!CirrusFindClock (t->clock, &a, &b))
|
|
return FALSE;
|
|
}
|
|
|
|
/* width must be a multiple of 16 */
|
|
if (t->horizontal & 0xf)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
pcmciaModeUsable (KdScreenInfo *screen)
|
|
{
|
|
KdCardInfo *card = screen->card;
|
|
pcmciaCardInfo *pcmciac = (pcmciaCardInfo *) card->driver;
|
|
int screen_size;
|
|
int pixel_width;
|
|
int byte_width;
|
|
int fb;
|
|
|
|
if (screen->fb[0].depth == 8)
|
|
screen->fb[0].bitsPerPixel = 8;
|
|
else if (screen->fb[0].depth == 15 || screen->fb[0].depth == 16)
|
|
screen->fb[0].bitsPerPixel = 16;
|
|
else
|
|
return FALSE;
|
|
|
|
screen_size = 0;
|
|
screen->fb[0].pixelStride = screen->width;
|
|
screen->fb[0].byteStride = screen->width * (screen->fb[0].bitsPerPixel >>3);
|
|
screen->fb[0].frameBuffer = pcmciac->fb;
|
|
screen_size = screen->fb[0].byteStride * screen->height;
|
|
|
|
return screen_size <= pcmciac->memory;
|
|
}
|
|
|
|
Bool
|
|
pcmciaScreenInit (KdScreenInfo *screen)
|
|
{
|
|
pcmciaCardInfo *pcmciac = screen->card->driver;
|
|
pcmciaScreenInfo *pcmcias;
|
|
int screen_size, memory;
|
|
int i;
|
|
const KdMonitorTiming *t;
|
|
|
|
pcmcias = (pcmciaScreenInfo *) xalloc (sizeof (pcmciaScreenInfo));
|
|
if (!pcmcias)
|
|
return FALSE;
|
|
memset (pcmcias, '\0', sizeof (pcmciaScreenInfo));
|
|
|
|
/* if (!pcmciac->cop) */
|
|
screen->dumb = TRUE;
|
|
|
|
if (screen->fb[0].depth < 8)
|
|
screen->fb[0].depth = 8;
|
|
|
|
/* default to 16bpp */
|
|
if (!screen->fb[0].depth)
|
|
screen->fb[0].depth = 16;
|
|
|
|
/* default to 60Hz refresh */
|
|
if (!screen->width || !screen->height)
|
|
{
|
|
screen->width = 640;
|
|
screen->height = 400;
|
|
screen->rate = 60;
|
|
}
|
|
|
|
pcmciac->memory = 512 * 1024;
|
|
if (pcmciac->HP && !screen->softCursor && screen->fb[0].depth == 8)
|
|
{
|
|
/* ack, bail on the HW cursor for everything -- no ARGB falback */
|
|
pcmcias->cursor_base = 0;
|
|
#if 0
|
|
/* Let's do hw cursor for the HP card, only in 8bit mode though */
|
|
pcmcias->cursor_base = pcmcias->screen + pcmciac->memory - 4096;
|
|
pcmciac->memory -= 4096;
|
|
#endif
|
|
}
|
|
|
|
pcmcias->screen = pcmciac->fb;
|
|
screen->driver = pcmcias;
|
|
|
|
t = KdFindMode (screen, pcmciaModeSupported);
|
|
|
|
screen->rate = t->rate;
|
|
screen->width = t->horizontal;
|
|
screen->height = t->vertical;
|
|
|
|
pcmcias->randr = screen->randr;
|
|
|
|
if (!KdTuneMode (screen, pcmciaModeUsable, pcmciaModeSupported))
|
|
{
|
|
xfree (pcmcias);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (screen->fb[0].depth) {
|
|
case 4:
|
|
screen->fb[0].visuals = ((1 << StaticGray) |
|
|
(1 << GrayScale) |
|
|
(1 << StaticColor));
|
|
screen->fb[0].blueMask = 0x00;
|
|
screen->fb[0].greenMask = 0x00;
|
|
screen->fb[0].redMask = 0x00;
|
|
break;
|
|
case 8:
|
|
screen->fb[0].visuals = ((1 << StaticGray) |
|
|
(1 << GrayScale) |
|
|
(1 << StaticColor) |
|
|
(1 << PseudoColor) |
|
|
(1 << TrueColor) |
|
|
(1 << DirectColor));
|
|
screen->fb[0].blueMask = 0x00;
|
|
screen->fb[0].greenMask = 0x00;
|
|
screen->fb[0].redMask = 0x00;
|
|
break;
|
|
case 15:
|
|
screen->fb[0].visuals = (1 << TrueColor);
|
|
screen->fb[0].blueMask = 0x001f;
|
|
screen->fb[0].greenMask = 0x03e0;
|
|
screen->fb[0].redMask = 0x7c00;
|
|
break;
|
|
case 16:
|
|
screen->fb[0].visuals = (1 << TrueColor);
|
|
screen->fb[0].blueMask = 0x001f;
|
|
screen->fb[0].greenMask = 0x07e0;
|
|
screen->fb[0].redMask = 0xf800;
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void *
|
|
tridentWindowLinear (ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size,
|
|
void *closure)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
pcmciaCardInfo *pcmciac = pScreenPriv->card->driver;
|
|
|
|
if (!pScreenPriv->enabled)
|
|
return 0;
|
|
|
|
*size = pScreenPriv->screen->fb[0].byteStride;
|
|
return (CARD8 *) pcmciac->fb + row * pScreenPriv->screen->fb[0].byteStride + offset;
|
|
}
|
|
|
|
void *
|
|
cirrusWindowWindowed (ScreenPtr pScreen,
|
|
CARD32 row,
|
|
CARD32 offset,
|
|
int mode,
|
|
CARD32 *size,
|
|
void *closure)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
pcmciaCardInfo *pcmciac = pScreenPriv->card->driver;
|
|
int bank, boffset;
|
|
|
|
if (!pScreenPriv->enabled)
|
|
return 0;
|
|
|
|
bank = (row * pScreenPriv->screen->fb[0].byteStride) / 0x1000;
|
|
pcmciaWriteIndex(pcmciac, 0x3ce, 0x0B, 0x0c);
|
|
pcmciaWriteIndex(pcmciac, 0x3ce, 0x09, bank);
|
|
pcmciaWriteIndex(pcmciac, 0x3ce, 0x0A, bank);
|
|
*size = pScreenPriv->screen->fb[0].byteStride;
|
|
return (CARD8 *) pcmciac->fb + (row * pScreenPriv->screen->fb[0].byteStride) - (bank * 0x1000) + offset;
|
|
}
|
|
|
|
LayerPtr
|
|
pcmciaLayerCreate (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
pcmciaCardInfo *pcmciac = pScreenPriv->card->driver;
|
|
pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) pScreenPriv->screen->driver;
|
|
ShadowUpdateProc update;
|
|
ShadowWindowProc window;
|
|
PixmapPtr pPixmap;
|
|
int kind;
|
|
|
|
if (pcmciac->HP) {
|
|
window = tridentWindowLinear;
|
|
if (pcmcias->randr == RR_Rotate_0)
|
|
update = tridentUpdatePacked;
|
|
else
|
|
update = pcmciaUpdateRotatePacked;
|
|
} else {
|
|
window = cirrusWindowWindowed;
|
|
if (pcmcias->randr == RR_Rotate_0)
|
|
update = cirrusUpdatePacked;
|
|
else
|
|
update = pcmciaUpdateRotatePacked;
|
|
}
|
|
|
|
if (!update)
|
|
abort ();
|
|
|
|
kind = LAYER_SHADOW;
|
|
pPixmap = 0;
|
|
|
|
return LayerCreate (pScreen, kind, screen->fb[0].depth,
|
|
pPixmap, update, window, pcmcias->randr, 0);
|
|
}
|
|
|
|
void
|
|
pcmciaConfigureScreen (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
FbdevPriv *priv = pScreenPriv->card->driver;
|
|
pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) screen->driver;
|
|
KdMouseMatrix m;
|
|
|
|
KdComputeMouseMatrix (&m, pcmcias->randr,
|
|
screen->width, screen->height);
|
|
|
|
if (m.matrix[0][0])
|
|
{
|
|
pScreen->width = screen->width;
|
|
pScreen->height = screen->height;
|
|
pScreen->mmWidth = screen->width_mm;
|
|
pScreen->mmHeight = screen->height_mm;
|
|
}
|
|
else
|
|
{
|
|
pScreen->width = screen->height;
|
|
pScreen->height = screen->width;
|
|
pScreen->mmWidth = screen->height_mm;
|
|
pScreen->mmHeight = screen->width_mm;
|
|
}
|
|
KdSetMouseMatrix (&m);
|
|
}
|
|
|
|
#ifdef RANDR
|
|
|
|
Bool
|
|
pcmciaRandRSupported (ScreenPtr pScreen,
|
|
const KdMonitorTiming *t)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
pcmciaCardInfo *pcmciac = pScreenPriv->card->driver;
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
int screen_size;
|
|
int byteStride;
|
|
|
|
/* Make sure the clock is supported */
|
|
if (!pcmciaModeSupported (screen, t))
|
|
return FALSE;
|
|
/* Check for sufficient memory */
|
|
byteStride = screen->width * (screen->fb[0].bitsPerPixel >>3);
|
|
screen_size = byteStride * screen->height;
|
|
|
|
return screen_size <= pcmciac->memory;
|
|
}
|
|
|
|
Bool
|
|
pcmciaRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) pScreenPriv->screen->driver;
|
|
|
|
*rotations = (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270|
|
|
RR_Reflect_X|RR_Reflect_Y);
|
|
|
|
return KdRandRGetInfo (pScreen, pcmcias->randr, pcmciaRandRSupported);
|
|
}
|
|
|
|
int
|
|
pcmciaLayerAdd (WindowPtr pWin, pointer value)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
LayerPtr pLayer = (LayerPtr) value;
|
|
|
|
if (!LayerWindowAdd (pScreen, pLayer, pWin))
|
|
return WT_STOPWALKING;
|
|
|
|
return WT_WALKCHILDREN;
|
|
}
|
|
|
|
int
|
|
pcmciaLayerRemove (WindowPtr pWin, pointer value)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
LayerPtr pLayer = (LayerPtr) value;
|
|
|
|
LayerWindowRemove (pScreen, pLayer, pWin);
|
|
|
|
return WT_WALKCHILDREN;
|
|
}
|
|
|
|
pcmciaRandRSetConfig (ScreenPtr pScreen,
|
|
Rotation randr,
|
|
int rate,
|
|
RRScreenSizePtr pSize)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
FbdevPriv *priv = pScreenPriv->card->driver;
|
|
pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) pScreenPriv->screen->driver;
|
|
Bool wasEnabled = pScreenPriv->enabled;
|
|
int newwidth, newheight;
|
|
LayerPtr pNewLayer;
|
|
int kind;
|
|
int oldrandr = pcmcias->randr;
|
|
PixmapPtr pPixmap;
|
|
const KdMonitorTiming *t;
|
|
|
|
randr = KdAddRotation (screen->randr, randr);
|
|
|
|
t = KdRandRGetTiming (pScreen, pcmciaRandRSupported, rate, pSize);
|
|
|
|
if (wasEnabled)
|
|
KdDisableScreen (pScreen);
|
|
|
|
screen->rate = t->rate;
|
|
screen->width = t->horizontal;
|
|
screen->height = t->vertical;
|
|
|
|
pcmcias->randr = randr;
|
|
pcmciaConfigureScreen (pScreen);
|
|
|
|
pNewLayer = pcmciaLayerCreate (pScreen);
|
|
|
|
if (!pNewLayer)
|
|
{
|
|
pcmcias->randr = oldrandr;
|
|
pcmciaConfigureScreen (pScreen);
|
|
if (wasEnabled)
|
|
KdEnableScreen (pScreen);
|
|
return FALSE;
|
|
}
|
|
|
|
if (WalkTree (pScreen, pcmciaLayerAdd, (pointer) pNewLayer) == WT_STOPWALKING)
|
|
{
|
|
WalkTree (pScreen, pcmciaLayerRemove, (pointer) pNewLayer);
|
|
LayerDestroy (pScreen, pNewLayer);
|
|
pcmcias->randr = oldrandr;
|
|
pcmciaConfigureScreen (pScreen);
|
|
if (wasEnabled)
|
|
KdEnableScreen (pScreen);
|
|
return FALSE;
|
|
}
|
|
WalkTree (pScreen, pcmciaLayerRemove, (pointer) pcmcias->pLayer);
|
|
LayerDestroy (pScreen, pcmcias->pLayer);
|
|
pcmcias->pLayer = pNewLayer;
|
|
if (wasEnabled)
|
|
KdEnableScreen (pScreen);
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
pcmciaRandRInit (ScreenPtr pScreen)
|
|
{
|
|
rrScrPrivPtr pScrPriv;
|
|
|
|
if (!RRScreenInit (pScreen))
|
|
return FALSE;
|
|
|
|
pScrPriv = rrGetScrPriv(pScreen);
|
|
pScrPriv->rrGetInfo = pcmciaRandRGetInfo;
|
|
pScrPriv->rrSetConfig = pcmciaRandRSetConfig;
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
Bool
|
|
pcmciaInitScreen (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
FbdevPriv *priv = pScreenPriv->card->driver;
|
|
pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) pScreenPriv->screen->driver;
|
|
|
|
if (!LayerStartInit (pScreen))
|
|
return FALSE;
|
|
if (!LayerFinishInit (pScreen))
|
|
return FALSE;
|
|
|
|
pcmciaConfigureScreen (pScreen);
|
|
|
|
pcmcias->pLayer = pcmciaLayerCreate (pScreen);
|
|
if (!pcmcias->pLayer)
|
|
return FALSE;
|
|
#ifdef RANDR
|
|
if (!pcmciaRandRInit (pScreen))
|
|
return FALSE;
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
CARD8
|
|
pcmciaReadIndex (pcmciaCardInfo *pcmciac, CARD16 port, CARD8 index)
|
|
{
|
|
CARD8 value;
|
|
|
|
pcmciac->cop_base[port] = index;
|
|
value = pcmciac->cop_base[port+1];
|
|
return value;
|
|
}
|
|
|
|
void
|
|
pcmciaWriteIndex (pcmciaCardInfo *pcmciac, CARD16 port, CARD8 index, CARD8 value)
|
|
{
|
|
pcmciac->cop_base[port] = index;
|
|
pcmciac->cop_base[port+1] = value;
|
|
}
|
|
|
|
CARD8
|
|
pcmciaReadReg (pcmciaCardInfo *pcmciac, CARD16 port)
|
|
{
|
|
CARD8 value;
|
|
|
|
value = pcmciac->cop_base[port];
|
|
|
|
return value;
|
|
}
|
|
|
|
void
|
|
pcmciaWriteReg (pcmciaCardInfo *pcmciac, CARD16 port, CARD8 value)
|
|
{
|
|
pcmciac->cop_base[port] = value;
|
|
}
|
|
|
|
|
|
void
|
|
pcmciaPause ()
|
|
{
|
|
struct timeval tv;
|
|
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = 50 * 1000;
|
|
select (1, 0, 0, 0, &tv);
|
|
}
|
|
|
|
void
|
|
pcmciaPreserve (KdCardInfo *card)
|
|
{
|
|
}
|
|
|
|
/* CLOCK_FACTOR is double the osc freq in kHz (osc = 14.31818 MHz) */
|
|
#define CLOCK_FACTOR 28636
|
|
|
|
/* stability constraints for internal VCO -- MAX_VCO also determines the maximum Video pixel clock */
|
|
#define MIN_VCO CLOCK_FACTOR
|
|
#define MAX_VCO 111000
|
|
|
|
/* clock in kHz is (numer * CLOCK_FACTOR / (denom & 0x3E)) >> (denom & 1) */
|
|
#define VCOVAL(n, d) \
|
|
((((n) & 0x7F) * CLOCK_FACTOR / ((d) & 0x3E)) )
|
|
|
|
#define CLOCKVAL(n, d) \
|
|
(VCOVAL(n, d) >> ((d) & 1))
|
|
|
|
static Bool
|
|
CirrusFindClock(int freq, int *num_out, int *den_out)
|
|
{
|
|
int n;
|
|
int num = 0, den = 0;
|
|
int mindiff;
|
|
|
|
/*
|
|
* If max_clock is greater than the MAX_VCO default, ignore
|
|
* MAX_VCO. On the other hand, if MAX_VCO is higher than max_clock,
|
|
* make use of the higher MAX_VCO value.
|
|
*/
|
|
|
|
mindiff = freq;
|
|
for (n = 0x10; n < 0x7f; n++) {
|
|
int d;
|
|
for (d = 0x14; d < 0x3f; d++) {
|
|
int c, diff;
|
|
/* Avoid combinations that can be unstable. */
|
|
if ((VCOVAL(n, d) < MIN_VCO) || (VCOVAL(n, d) > MAX_VCO))
|
|
continue;
|
|
c = CLOCKVAL(n, d);
|
|
diff = abs(c - freq);
|
|
if (diff < mindiff) {
|
|
mindiff = diff;
|
|
num = n;
|
|
den = d;
|
|
}
|
|
}
|
|
}
|
|
if (n == 0x80)
|
|
return FALSE;
|
|
|
|
*num_out = num;
|
|
*den_out = den;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static Bool
|
|
tridentSetCLK(int clock, CARD8 *a, CARD8 *b)
|
|
{
|
|
int powerup[4] = { 1,2,4,8 };
|
|
int clock_diff = 750;
|
|
int freq, ffreq;
|
|
int m, n, k;
|
|
int p, q, r, s;
|
|
int startn, endn;
|
|
int endm, endk;
|
|
|
|
p = q = r = s = 0;
|
|
|
|
startn = 0;
|
|
endn = 121;
|
|
endm = 31;
|
|
endk = 1;
|
|
|
|
freq = clock;
|
|
|
|
for (k=0;k<=endk;k++)
|
|
for (n=startn;n<=endn;n++)
|
|
for (m=1;m<=endm;m++)
|
|
{
|
|
ffreq = ( ( ((n + 8) * CLOCK) / ((m + 2) * powerup[k]) ));
|
|
if ((ffreq > freq - clock_diff) && (ffreq < freq + clock_diff))
|
|
{
|
|
clock_diff = (freq > ffreq) ? freq - ffreq : ffreq - freq;
|
|
p = n; q = m; r = k; s = ffreq;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
ErrorF ("ffreq %d clock %d\n", s, clock);
|
|
#endif
|
|
if (s == 0)
|
|
return FALSE;
|
|
|
|
/* N is first 7bits, first M bit is 8th bit */
|
|
*a = ((1 & q) << 7) | p;
|
|
/* first 4bits are rest of M, 1bit for K value */
|
|
*b = (((q & 0xFE) >> 1) | (r << 4));
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
pcmciaEnable (ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
KdScreenInfo *screen = pScreenPriv->screen;
|
|
pcmciaCardInfo *pcmciac = pScreenPriv->card->driver;
|
|
pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) screen->driver;
|
|
int i,j;
|
|
unsigned char Sequencer[6];
|
|
unsigned char CRTC[31];
|
|
unsigned char Graphics[9];
|
|
unsigned char Attribute[21];
|
|
unsigned char MiscOutReg;
|
|
const KdMonitorTiming *t;
|
|
int hactive, hblank, hfp, hbp;
|
|
int vactive, vblank, vfp, vbp;
|
|
|
|
int h_active;
|
|
int h_total;
|
|
int h_display_end;
|
|
int h_sync_start;
|
|
int h_sync_end;
|
|
int h_skew = 0;
|
|
|
|
int v_active;
|
|
int v_total;
|
|
int v_sync_start;
|
|
int v_sync_end;
|
|
int v_skew = 0;
|
|
|
|
t = KdFindMode (screen, pcmciaModeSupported);
|
|
|
|
hactive = t->horizontal;
|
|
hfp = t->hfp;
|
|
hbp = t->hbp;
|
|
hblank = t->hblank;
|
|
|
|
h_active = hactive;
|
|
h_sync_start = hactive + hfp;
|
|
h_sync_end = hactive + hblank - hbp;
|
|
h_total = hactive + hblank;
|
|
|
|
vactive = t->vertical;
|
|
vfp = t->vfp;
|
|
vbp = t->vbp;
|
|
vblank = t->vblank;
|
|
|
|
v_active = vactive;
|
|
v_sync_start = vactive + vfp;
|
|
v_sync_end = vactive + vblank - vbp;
|
|
v_total = vactive + vblank;
|
|
|
|
/*
|
|
* compute correct Hsync & Vsync polarity
|
|
*/
|
|
|
|
MiscOutReg = 0x23;
|
|
if (t->hpol == KdSyncNegative)
|
|
MiscOutReg |= 0x40;
|
|
if (t->vpol == KdSyncNegative)
|
|
MiscOutReg |= 0x80;
|
|
|
|
/*
|
|
* Time Sequencer
|
|
*/
|
|
if (pScreenPriv->screen->fb[0].depth == 4)
|
|
Sequencer[0] = 0x02;
|
|
else
|
|
Sequencer[0] = 0x00;
|
|
Sequencer[1] = 0x01;
|
|
Sequencer[2] = 0x0F;
|
|
Sequencer[3] = 0x00; /* Font select */
|
|
if (pScreenPriv->screen->fb[0].depth < 8)
|
|
Sequencer[4] = 0x06; /* Misc */
|
|
else
|
|
Sequencer[4] = 0x0E; /* Misc */
|
|
Sequencer[5] = 0x00;
|
|
|
|
/*
|
|
* CRTC Controller
|
|
*/
|
|
CRTC[0] = ((h_total) >> 3) - 5;
|
|
CRTC[1] = (hactive >> 3) - 1;
|
|
CRTC[2] = ((min(h_sync_start,h_active)) >> 3) - 1;
|
|
CRTC[3] = ((((min(h_sync_end,h_total)) >> 3) - 1) & 0x1F) | 0x80;
|
|
i = (((h_skew << 2) + 0x10) & ~0x1F);
|
|
if (i < 0x80)
|
|
CRTC[3] |= i;
|
|
CRTC[4] = (h_sync_start >> 3);
|
|
CRTC[5] = (((((min(h_sync_end,h_total)) >> 3) - 1) & 0x20) << 2)
|
|
| (((h_sync_end >> 3)) & 0x1F);
|
|
|
|
CRTC[6] = (v_total - 2) & 0xFF;
|
|
CRTC[7] = (((v_total - 2) & 0x100) >> 8)
|
|
| (((v_active - 1) & 0x100) >> 7)
|
|
| ((v_sync_start & 0x100) >> 6)
|
|
| ((((min(v_sync_start,v_active)) - 1) & 0x100) >> 5)
|
|
| 0x10
|
|
| (((v_total - 2) & 0x200) >> 4)
|
|
| (((v_active - 1) & 0x200) >> 3)
|
|
| ((v_sync_start & 0x200) >> 2);
|
|
CRTC[8] = 0x00;
|
|
CRTC[9] = ((((min(v_sync_start,v_active))-1) & 0x200) >> 4) | 0x40;
|
|
CRTC[10] = 0x00;
|
|
CRTC[11] = 0x00;
|
|
CRTC[12] = 0x00;
|
|
CRTC[13] = 0x00;
|
|
CRTC[14] = 0x00;
|
|
CRTC[15] = 0x00;
|
|
CRTC[16] = v_sync_start & 0xFF;
|
|
CRTC[17] = (v_sync_end & 0x0F) | 0x20;
|
|
CRTC[18] = (v_active - 1) & 0xFF;
|
|
if (pScreenPriv->screen->fb[0].depth == 4)
|
|
CRTC[19] = pScreenPriv->screen->fb[0].pixelStride >> 4;
|
|
else
|
|
if (pScreenPriv->screen->fb[0].depth == 8)
|
|
CRTC[19] = pScreenPriv->screen->fb[0].pixelStride >> 3;
|
|
else
|
|
if (pScreenPriv->screen->fb[0].depth == 16 ||
|
|
pScreenPriv->screen->fb[0].depth == 15)
|
|
CRTC[19] = pScreenPriv->screen->fb[0].pixelStride >> 2;
|
|
CRTC[20] = 0x00;
|
|
CRTC[21] = ((min(v_sync_end,v_active)) - 1) & 0xFF;
|
|
CRTC[22] = ((min(v_sync_end,v_active)) - 1) & 0xFF;
|
|
if (pScreenPriv->screen->fb[0].depth < 8)
|
|
CRTC[23] = 0xE3;
|
|
else
|
|
CRTC[23] = 0xC3;
|
|
CRTC[24] = 0xFF;
|
|
CRTC[25] = 0x00;
|
|
CRTC[26] = 0x00;
|
|
#if 0
|
|
if (!pcmciac->HP)
|
|
if (mode.Flags & V_INTERLACE) CRTC[26] |= 0x01;
|
|
#endif
|
|
if (pcmciac->HP)
|
|
CRTC[27] = 0x00;
|
|
else
|
|
CRTC[27] = 0x22;
|
|
CRTC[28] = 0x00;
|
|
CRTC[29] = 0x00;
|
|
CRTC[30] = 0x80;
|
|
#if 0
|
|
if (pcmciac->HP)
|
|
if (mode.Flags & V_INTERLACE) CRTC[30] |= 0x04;
|
|
#endif
|
|
|
|
{
|
|
int nExtBits = 0;
|
|
CARD32 ExtBits;
|
|
CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6;
|
|
|
|
CRTC[3] = (CRTC[3] & ~0x1F)
|
|
| ((((min(h_sync_end,h_total)) >> 3) - 1) & 0x1F);
|
|
CRTC[5] = (CRTC[5] & ~0x80)
|
|
| (((((min(h_sync_end,h_total)) >> 3) - 1) & 0x20) << 2);
|
|
ExtBits = (((min(h_sync_end,h_total)) >> 3) - 1) & ExtBitMask;
|
|
|
|
/* First the horizontal case */
|
|
if ((((min(h_sync_end,h_total)) >> 3) == (h_total >> 3)))
|
|
{
|
|
int i = (CRTC[3] & 0x1F)
|
|
| ((CRTC[5] & 0x80) >> 2)
|
|
| ExtBits;
|
|
if ((i-- > ((((min(h_sync_start,h_active)) >> 3) - 1)
|
|
& (0x3F | ExtBitMask)))
|
|
&& ((min(h_sync_end,h_total)) == h_total))
|
|
i = 0;
|
|
CRTC[3] = (CRTC[3] & ~0x1F) | (i & 0x1F);
|
|
CRTC[5] = (CRTC[5] & ~0x80) | ((i << 2) & 0x80);
|
|
ExtBits = i & ExtBitMask;
|
|
}
|
|
}
|
|
{
|
|
CARD32 ExtBits;
|
|
CARD32 ExtBitMask = 0;
|
|
/* If width is not known nBits should be 0. In this
|
|
* case BitMask is set to 0 so we can check for it. */
|
|
CARD32 BitMask = 0;
|
|
int VBlankStart = ((min(v_sync_start,v_active)) - 1) & 0xFF;
|
|
CRTC[22] = ((min(v_sync_end,v_total)) - 1) & 0xFF;
|
|
ExtBits = ((min(v_sync_end,v_total)) - 1) & ExtBitMask;
|
|
|
|
if ((min(v_sync_end,v_total)) == v_total)
|
|
/* Null top overscan */
|
|
{
|
|
int i = CRTC[22] | ExtBits;
|
|
if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask)))
|
|
|| ((i > VBlankStart) && /* 8-bit case */
|
|
((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */
|
|
!(CRTC[9] & 0x9F)) /* 1 scanline/row */
|
|
i = 0;
|
|
else
|
|
i = (i - 1);
|
|
CRTC[22] = i & 0xFF;
|
|
ExtBits = i & 0xFF00;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Graphics Display Controller
|
|
*/
|
|
Graphics[0] = 0x00;
|
|
Graphics[1] = 0x00;
|
|
Graphics[2] = 0x00;
|
|
Graphics[3] = 0x00;
|
|
Graphics[4] = 0x00;
|
|
if (pScreenPriv->screen->fb[0].depth == 4)
|
|
Graphics[5] = 0x02;
|
|
else
|
|
Graphics[5] = 0x40;
|
|
Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */
|
|
Graphics[7] = 0x0F;
|
|
Graphics[8] = 0xFF;
|
|
|
|
Attribute[0] = 0x00; /* standard colormap translation */
|
|
Attribute[1] = 0x01;
|
|
Attribute[2] = 0x02;
|
|
Attribute[3] = 0x03;
|
|
Attribute[4] = 0x04;
|
|
Attribute[5] = 0x05;
|
|
Attribute[6] = 0x06;
|
|
Attribute[7] = 0x07;
|
|
Attribute[8] = 0x08;
|
|
Attribute[9] = 0x09;
|
|
Attribute[10] = 0x0A;
|
|
Attribute[11] = 0x0B;
|
|
Attribute[12] = 0x0C;
|
|
Attribute[13] = 0x0D;
|
|
Attribute[14] = 0x0E;
|
|
Attribute[15] = 0x0F;
|
|
if (pScreenPriv->screen->fb[0].depth == 4)
|
|
Attribute[16] = 0x81;
|
|
else
|
|
Attribute[16] = 0x41;
|
|
if (pScreenPriv->screen->fb[0].bitsPerPixel == 16)
|
|
Attribute[17] = 0x00;
|
|
else
|
|
Attribute[17] = 0xFF;
|
|
Attribute[18] = 0x0F;
|
|
Attribute[19] = 0x00;
|
|
Attribute[20] = 0x00;
|
|
|
|
/* Wake up the card */
|
|
if (pcmciac->HP) {
|
|
pcmciaWriteReg(pcmciac, 0x3c3, 0x1);
|
|
pcmciaWriteReg(pcmciac, 0x46e8, 0x10);
|
|
} else {
|
|
pcmciaWriteReg(pcmciac, 0x105, 0x1);
|
|
pcmciaWriteReg(pcmciac, 0x46e8, 0x1f);
|
|
pcmciaWriteReg(pcmciac, 0x102, 0x1);
|
|
pcmciaWriteReg(pcmciac, 0x46e8, 0xf);
|
|
pcmciaWriteReg(pcmciac, 0x3c3, 0x1);
|
|
}
|
|
|
|
if (pcmciac->HP) {
|
|
/* unlock */
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x11, 0x92);
|
|
j = pcmciaReadIndex(pcmciac, 0x3c4, 0xb);
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0xe, 0xc2);
|
|
|
|
/* switch on dac */
|
|
pcmciaWriteIndex(pcmciac, 0x3d4, 0x29, 0x24);
|
|
/* switch on the accelerator */
|
|
pcmciaWriteIndex(pcmciac, 0x3d4, 0x36, 0x80);
|
|
|
|
/* bump up memory clk */
|
|
pcmciaWriteReg(pcmciac, 0x43c6, 0x65);
|
|
pcmciaWriteReg(pcmciac, 0x43c7, 0x00);
|
|
} else {
|
|
/* unlock */
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x06, 0x12);
|
|
pcmciaWriteReg(pcmciac, 0x3c2, MiscOutReg);
|
|
}
|
|
|
|
/* synchronous reset */
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0, 0);
|
|
|
|
pcmciaWriteReg(pcmciac, 0x3da, 0x10);
|
|
|
|
for (i=0;i<6;i++)
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, i, Sequencer[i]);
|
|
|
|
if (pcmciac->HP) {
|
|
/* Stick chip into color mode */
|
|
pcmciaWriteIndex(pcmciac, 0x3ce, 0x2f, 0x06);
|
|
/* Switch on Linear addressing */
|
|
pcmciaWriteIndex(pcmciac, 0x3d4, 0x21, 0x2e);
|
|
} else {
|
|
/* Stick chip into 8bit access mode - ugh! */
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x0F, 0x20); /* 0x26 ? */
|
|
/* reset mclk */
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x1F, 0);
|
|
}
|
|
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0, 0x3);
|
|
|
|
for (i=0;i<31;i++)
|
|
pcmciaWriteIndex(pcmciac, 0x3d4, i, CRTC[i]);
|
|
|
|
for (i=0;i<9;i++)
|
|
pcmciaWriteIndex(pcmciac, 0x3ce, i, Graphics[i]);
|
|
|
|
j = pcmciaReadReg(pcmciac, 0x3da);
|
|
|
|
for (i=0;i<21;i++) {
|
|
pcmciaWriteReg(pcmciac, 0x3c0, i);
|
|
pcmciaWriteReg(pcmciac, 0x3c0, Attribute[i]);
|
|
}
|
|
|
|
j = pcmciaReadReg(pcmciac, 0x3da);
|
|
pcmciaWriteReg(pcmciac, 0x3c0, 0x20);
|
|
|
|
j = pcmciaReadReg(pcmciac, 0x3c8);
|
|
j = pcmciaReadReg(pcmciac, 0x3c6);
|
|
j = pcmciaReadReg(pcmciac, 0x3c6);
|
|
j = pcmciaReadReg(pcmciac, 0x3c6);
|
|
j = pcmciaReadReg(pcmciac, 0x3c6);
|
|
switch (pScreenPriv->screen->fb[0].depth) {
|
|
/* This is here for completeness, when/if we ever do 4bpp */
|
|
case 4:
|
|
pcmciaWriteReg(pcmciac, 0x3c6, 0x0);
|
|
if (pcmciac->HP) {
|
|
pcmciaWriteIndex(pcmciac, 0x3ce, 0x0f, 0x90);
|
|
pcmciaWriteIndex(pcmciac, 0x3d4, 0x38, 0x00);
|
|
} else
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x07, 0x00);
|
|
break;
|
|
case 8:
|
|
pcmciaWriteReg(pcmciac, 0x3c6, 0x0);
|
|
if (pcmciac->HP) {
|
|
pcmciaWriteIndex(pcmciac, 0x3ce, 0x0f, 0x92);
|
|
pcmciaWriteIndex(pcmciac, 0x3d4, 0x38, 0x00);
|
|
} else
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x07, 0x01);
|
|
break;
|
|
case 15:
|
|
if (pcmciac->HP) {
|
|
pcmciaWriteReg(pcmciac, 0x3c6, 0x10);
|
|
pcmciaWriteIndex(pcmciac, 0x3ce, 0x0f, 0x9a);
|
|
pcmciaWriteIndex(pcmciac, 0x3d4, 0x38, 0x04);
|
|
} else {
|
|
pcmciaWriteReg(pcmciac, 0x3c6, 0xC0);
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x07, 0x03);
|
|
}
|
|
break;
|
|
case 16:
|
|
if (pcmciac->HP) {
|
|
pcmciaWriteReg(pcmciac, 0x3c6, 0x30);
|
|
pcmciaWriteIndex(pcmciac, 0x3ce, 0x0f, 0x9a);
|
|
pcmciaWriteIndex(pcmciac, 0x3d4, 0x38, 0x04);
|
|
} else {
|
|
pcmciaWriteReg(pcmciac, 0x3c6, 0xC1);
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x07, 0x03);
|
|
}
|
|
break;
|
|
}
|
|
j = pcmciaReadReg(pcmciac, 0x3c8);
|
|
|
|
pcmciaWriteReg(pcmciac, 0x3c6, 0xff);
|
|
|
|
for (i=0;i<256;i++) {
|
|
pcmciaWriteReg(pcmciac, 0x3c8, i);
|
|
pcmciaWriteReg(pcmciac, 0x3c9, i);
|
|
pcmciaWriteReg(pcmciac, 0x3c9, i);
|
|
pcmciaWriteReg(pcmciac, 0x3c9, i);
|
|
}
|
|
|
|
/* Set the Clock */
|
|
if (pcmciac->HP) {
|
|
CARD8 a,b;
|
|
int clock = t->clock;
|
|
if (pScreenPriv->screen->fb[0].bitsPerPixel == 16)
|
|
clock *= 2;
|
|
tridentSetCLK(clock, &a, &b);
|
|
pcmciaWriteReg(pcmciac, 0x43c8, a);
|
|
pcmciaWriteReg(pcmciac, 0x43c9, b);
|
|
} else {
|
|
int num, den;
|
|
unsigned char tmp;
|
|
int clock = t->clock;
|
|
if (pScreenPriv->screen->fb[0].bitsPerPixel == 16)
|
|
clock *= 2;
|
|
|
|
CirrusFindClock(clock, &num, &den);
|
|
|
|
tmp = pcmciaReadIndex(pcmciac, 0x3c4, 0x0d);
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x0d, (tmp & 0x80) | num);
|
|
tmp = pcmciaReadIndex(pcmciac, 0x3c4, 0x1d);
|
|
pcmciaWriteIndex(pcmciac, 0x3c4, 0x1d, (tmp & 0xc0) | den);
|
|
}
|
|
pcmciaWriteReg(pcmciac, 0x3c2, MiscOutReg | 0x08);
|
|
|
|
#if 1
|
|
for (i=1;i<0x3f;i++)
|
|
ErrorF("0x3c4:%02x: 0x%x\n",i,pcmciaReadIndex(pcmciac, 0x3c4, i));
|
|
|
|
ErrorF("\n");
|
|
|
|
for (i=0;i<0x3f;i++)
|
|
ErrorF("0x3ce:%02x: 0x%x\n",i,pcmciaReadIndex(pcmciac, 0x3ce, i));
|
|
|
|
ErrorF("\n");
|
|
|
|
for (i=0;i<0x3f;i++)
|
|
ErrorF("0x3d4:%02x: 0x%x\n",i,pcmciaReadIndex(pcmciac, 0x3d4, i));
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
pcmciaDisable (ScreenPtr pScreen)
|
|
{
|
|
}
|
|
|
|
const CARD8 tridentDPMSModes[4] = {
|
|
0x00, /* KD_DPMS_NORMAL */
|
|
0x01, /* KD_DPMS_STANDBY */
|
|
0x02, /* KD_DPMS_SUSPEND */
|
|
0x03, /* KD_DPMS_POWERDOWN */
|
|
};
|
|
|
|
Bool
|
|
pcmciaDPMS (ScreenPtr pScreen, int mode)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
pcmciaCardInfo *pcmciac = pScreenPriv->card->driver;
|
|
|
|
if (pcmciac->HP) {
|
|
pcmciaWriteIndex (pcmciac, 0x3ce, 0x23, tridentDPMSModes[mode]);
|
|
pcmciaPause ();
|
|
} else {
|
|
/* Voyager */
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
pcmciaRestore (KdCardInfo *card)
|
|
{
|
|
}
|
|
|
|
void
|
|
pcmciaScreenFini (KdScreenInfo *screen)
|
|
{
|
|
pcmciaScreenInfo *pcmcias = (pcmciaScreenInfo *) screen->driver;
|
|
|
|
xfree (pcmcias);
|
|
screen->driver = 0;
|
|
}
|
|
|
|
void
|
|
pcmciaCardFini (KdCardInfo *card)
|
|
{
|
|
pcmciaCardInfo *pcmciac = card->driver;
|
|
|
|
if (pcmciac->cop_base)
|
|
KdUnmapDevice ((void *) pcmciac->cop_base, PCMCIA_COP_SIZE(card));
|
|
}
|
|
|
|
void
|
|
pcmciaGetColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
pcmciaCardInfo *pcmciac = pScreenPriv->card->driver;
|
|
|
|
while (ndef--)
|
|
{
|
|
pcmciaWriteReg (pcmciac, 0x3C7, pdefs->pixel);
|
|
pdefs->red = pcmciaReadReg (pcmciac, 0x3C9) << 10;
|
|
pdefs->green = pcmciaReadReg (pcmciac, 0x3C9) << 10;
|
|
pdefs->blue = pcmciaReadReg (pcmciac, 0x3C9) << 10;
|
|
pdefs++;
|
|
}
|
|
}
|
|
|
|
void
|
|
pcmciaPutColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
pcmciaCardInfo *pcmciac = pScreenPriv->card->driver;
|
|
|
|
while (ndef--)
|
|
{
|
|
pcmciaWriteReg (pcmciac, 0x3C8, pdefs->pixel);
|
|
pcmciaWriteReg (pcmciac, 0x3C9, pdefs->red >> 10);
|
|
pcmciaWriteReg (pcmciac, 0x3C9, pdefs->green >> 10);
|
|
pcmciaWriteReg (pcmciac, 0x3C9, pdefs->blue >> 10);
|
|
pdefs++;
|
|
}
|
|
}
|
|
|
|
|
|
KdCardFuncs pcmciaFuncs = {
|
|
pcmciaCardInit, /* cardinit */
|
|
pcmciaScreenInit, /* scrinit */
|
|
pcmciaInitScreen, /* initScreen */
|
|
pcmciaPreserve, /* preserve */
|
|
pcmciaEnable, /* enable */
|
|
pcmciaDPMS, /* dpms */
|
|
pcmciaDisable, /* disable */
|
|
pcmciaRestore, /* restore */
|
|
pcmciaScreenFini, /* scrfini */
|
|
pcmciaCardFini, /* cardfini */
|
|
|
|
pcmciaCursorInit, /* initCursor */
|
|
pcmciaCursorEnable, /* enableCursor */
|
|
pcmciaCursorDisable, /* disableCursor */
|
|
pcmciaCursorFini, /* finiCursor */
|
|
pcmciaRecolorCursor, /* recolorCursor */
|
|
|
|
#if 0 /* not yet */
|
|
pcmciaDrawInit, /* initAccel */
|
|
pcmciaDrawEnable, /* enableAccel */
|
|
pcmciaDrawSync, /* syncAccel */
|
|
pcmciaDrawDisable, /* disableAccel */
|
|
pcmciaDrawFini, /* finiAccel */
|
|
#else
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
#endif
|
|
|
|
pcmciaGetColors, /* getColors */
|
|
pcmciaPutColors, /* putColors */
|
|
};
|