xserver-multidpi/hw/kdrive/mach64/mach64.c
2001-07-24 21:26:17 +00:00

451 lines
11 KiB
C

/*
* Copyright © 2001 Keith Packard
*
* 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 Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD 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.
*/
/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64.c,v 1.7 2001/07/24 19:06:03 keithp Exp $ */
#include "mach64.h"
#include <sys/io.h>
Bool
mach64CardInit (KdCardInfo *card)
{
Mach64CardInfo *mach64c;
mach64c = (Mach64CardInfo *) xalloc (sizeof (Mach64CardInfo));
if (!mach64c)
return FALSE;
(void) mach64MapReg (card, mach64c);
mach64c->lcdEnabled = FALSE;
if (!vesaInitialize (card, &mach64c->vesa))
{
xfree (mach64c);
return FALSE;
}
card->driver = mach64c;
return TRUE;
}
Bool
mach64ScreenInit (KdScreenInfo *screen)
{
Mach64CardInfo *mach64c = screen->card->driver;
Mach64ScreenInfo *mach64s;
int screen_size, memory;
mach64s = (Mach64ScreenInfo *) xalloc (sizeof (Mach64ScreenInfo));
if (!mach64s)
return FALSE;
memset (mach64s, '\0', sizeof (Mach64ScreenInfo));
if (!vesaScreenInitialize (screen, &mach64s->vesa))
{
xfree (mach64s);
return FALSE;
}
if (!mach64c->reg)
screen->dumb = TRUE;
if (mach64s->vesa.mapping != VESA_LINEAR)
screen->dumb = TRUE;
mach64s->screen = mach64s->vesa.fb;
switch (screen->fb[0].depth) {
case 8:
mach64s->colorKey = 0xff;
break;
case 15:
case 16:
mach64s->colorKey = 0x001e;
break;
case 24:
mach64s->colorKey = 0x0000fe;
break;
default:
mach64s->colorKey = 1;
break;
}
memory = mach64s->vesa.fb_size;
screen_size = screen->fb[0].byteStride * screen->height;
if (mach64s->screen && memory >= screen_size + 2048)
{
memory -= 2048;
mach64s->cursor_base = mach64s->screen + memory - 2048;
}
else
mach64s->cursor_base = 0;
screen->softCursor = TRUE; /* XXX for now */
memory -= screen_size;
if (memory > screen->fb[0].byteStride)
{
mach64s->off_screen = mach64s->screen + screen_size;
mach64s->off_screen_size = memory;
}
else
{
mach64s->off_screen = 0;
mach64s->off_screen_size = 0;
}
screen->driver = mach64s;
return TRUE;
}
Bool
mach64InitScreen (ScreenPtr pScreen)
{
#ifdef XV
KdScreenPriv(pScreen);
Mach64CardInfo *mach64c = pScreenPriv->screen->card->driver;
if (mach64c->media_reg && mach64c->reg)
mach64InitVideo(pScreen);
#endif
return vesaInitScreen (pScreen);
}
#ifdef RANDR
mach64RandRSetConfig (ScreenPtr pScreen,
Rotation rotation,
RRScreenSizePtr pSize,
RRVisualGroupPtr pVisualGroup)
{
KdScreenPriv(pScreen);
KdCheckSync (pScreen);
if (!vesaRandRSetConfig (pScreen, rotation, pSize, pVisualGroup))
return FALSE;
return TRUE;
}
void
mach64RandRInit (ScreenPtr pScreen)
{
rrScrPriv(pScreen);
pScrPriv->rrSetConfig = mach64RandRSetConfig;
}
#endif
Bool
mach64FinishInitScreen (ScreenPtr pScreen)
{
Bool ret;
ret = vesaFinishInitScreen (pScreen);
#ifdef RANDR
mach64RandRInit (pScreen);
#endif
return ret;
}
CARD32
mach64ReadLCD (Reg *reg, int id)
{
CARD32 LCD_INDEX;
LCD_INDEX = reg->LCD_INDEX & ~(0x3f);
reg->LCD_INDEX = (LCD_INDEX | id);
return reg->LCD_DATA;
}
void
mach64WriteLCD (Reg *reg, int id, CARD32 data)
{
CARD32 LCD_INDEX;
LCD_INDEX = reg->LCD_INDEX & ~(0x3f);
reg->LCD_INDEX = (LCD_INDEX | id);
reg->LCD_DATA = data;
}
void
mach64Preserve (KdCardInfo *card)
{
Mach64CardInfo *mach64c = card->driver;
Reg *reg = mach64c->reg;
vesaPreserve(card);
if (reg)
{
mach64c->save.LCD_GEN_CTRL = mach64ReadLCD (reg, 1);
}
}
Bool
mach64MapReg (KdCardInfo *card, Mach64CardInfo *mach64c)
{
mach64c->reg_base = (CARD8 *) KdMapDevice (MACH64_REG_BASE(card),
MACH64_REG_SIZE(card));
if (!mach64c->reg_base)
{
mach64c->reg = 0;
mach64c->media_reg = 0;
return FALSE;
}
KdSetMappedMode (MACH64_REG_BASE(card),
MACH64_REG_SIZE(card),
KD_MAPPED_MODE_REGISTERS);
mach64c->reg = (Reg *) (mach64c->reg_base + MACH64_REG_OFF(card));
mach64c->media_reg = (MediaReg *) (mach64c->reg_base + MACH64_MEDIA_REG_OFF(card));
return TRUE;
}
void
mach64UnmapReg (KdCardInfo *card, Mach64CardInfo *mach64c)
{
if (mach64c->reg_base)
{
KdResetMappedMode (MACH64_REG_BASE(card),
MACH64_REG_SIZE(card),
KD_MAPPED_MODE_REGISTERS);
KdUnmapDevice ((void *) mach64c->reg_base, MACH64_REG_SIZE(card));
mach64c->reg_base = 0;
mach64c->reg = 0;
mach64c->media_reg = 0;
}
}
void
mach64SetMMIO (KdCardInfo *card, Mach64CardInfo *mach64c)
{
if (!mach64c->reg_base)
mach64MapReg (card, mach64c);
if (mach64c->reg)
{
if (mach64c->reg->GUI_STAT == 0xffffffff)
FatalError ("Mach64 REG not visible\n");
}
}
void
mach64ResetMMIO (KdCardInfo *card, Mach64CardInfo *mach64c)
{
mach64UnmapReg (card, mach64c);
}
Bool
mach64Enable (ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
Mach64CardInfo *mach64c = pScreenPriv->card->driver;
if (!vesaEnable (pScreen))
return FALSE;
mach64SetMMIO (pScreenPriv->card, mach64c);
mach64DPMS (pScreen, KD_DPMS_NORMAL);
#ifdef XV
KdXVEnable (pScreen);
#endif
return TRUE;
}
void
mach64Disable (ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
Mach64CardInfo *mach64c = pScreenPriv->card->driver;
#ifdef XV
KdXVDisable (pScreen);
#endif
mach64ResetMMIO (pScreenPriv->card, mach64c);
vesaDisable (pScreen);
}
const CARD8 mach64DPMSModes[4] = {
0x80, /* KD_DPMS_NORMAL */
0x8c, /* KD_DPMS_STANDBY */
0x8c, /* KD_DPMS_STANDBY */
0x8c, /* KD_DPMS_STANDBY */
/* 0xb0, /* KD_DPMS_SUSPEND */
/* 0xbc, /* KD_DPMS_POWERDOWN */
};
#define PWR_MGT_ON (1 << 0)
#define PWR_MGT_MODE (3 << 1)
#define PWR_MGT_MODE_PIN (0 << 1)
#define PWR_MGT_MODE_REG (1 << 1)
#define PWR_MGT_MODE_TIMER (2 << 1)
#define PWR_MGR_MODE_PCI (3 << 1)
#define AUTO_PWRUP_EN (1 << 3)
#define ACTIVITY_PIN_ON (1 << 4)
#define STANDBY_POL (1 << 5)
#define SUSPEND_POL (1 << 6)
#define SELF_REFRESH (1 << 7)
#define ACTIVITY_PIN_EN (1 << 8)
#define KEYBD_SNOOP (1 << 9)
#define DONT_USE_F32KHZ (1 << 10)
#define TRISTATE_MEM_EN (1 << 11)
#define LCDENG_TEST_MODE (0xf << 12)
#define STANDBY_COUNT (0xf << 16)
#define SUSPEND_COUNT (0xf << 20)
#define BIASON (1 << 24)
#define BLON (1 << 25)
#define DIGON (1 << 26)
#define PM_D3_RST_ENB (1 << 27)
#define STANDBY_NOW (1 << 28)
#define SUSPEND_NOW (1 << 29)
#define PWR_MGT_STATUS (3 << 30)
#define PWR_MGT_STATUS_ON (0 << 30)
#define PWR_MGT_STATUS_STANDBY (1 << 30)
#define PWR_MGT_STATUS_SUSPEND (2 << 30)
#define PWR_MGT_STATUS_TRANSITION (3 << 30)
Bool
mach64DPMS (ScreenPtr pScreen, int mode)
{
KdScreenPriv(pScreen);
Mach64CardInfo *mach64c = pScreenPriv->card->driver;
int hsync_off, vsync_off, blank;
CARD32 CRTC_GEN_CNTL;
CARD32 LCD_GEN_CTRL;
Reg *reg = mach64c->reg;
if (!reg)
return FALSE;
CRTC_GEN_CNTL = reg->CRTC_GEN_CNTL;
LCD_GEN_CTRL = mach64ReadLCD (reg, 1);
switch (mode) {
case KD_DPMS_NORMAL:
hsync_off = 0;
vsync_off = 0;
blank = 0;
break;
case KD_DPMS_STANDBY:
hsync_off = 1;
vsync_off = 0;
blank = 1;
break;
case KD_DPMS_SUSPEND:
hsync_off = 0;
vsync_off = 1;
blank = 1;
break;
case KD_DPMS_POWERDOWN:
hsync_off = 1;
vsync_off = 1;
blank = 1;
}
if (hsync_off)
CRTC_GEN_CNTL |= (1 << 2);
else
CRTC_GEN_CNTL &= ~(1 << 2);
if (vsync_off)
CRTC_GEN_CNTL |= (1 << 3);
else
CRTC_GEN_CNTL &= ~(1 << 3);
if (blank)
{
mach64c->lcdEnabled = (LCD_GEN_CTRL & (1 << 1)) != 0;
LCD_GEN_CTRL &= ~(1 << 1);
CRTC_GEN_CNTL |= (1 << 6);
}
else
{
if (!(LCD_GEN_CTRL & 3) || mach64c->lcdEnabled)
LCD_GEN_CTRL |= (1 << 1);
CRTC_GEN_CNTL &= ~(1 << 6);
}
KdCheckSync (pScreen);
mach64WriteLCD (reg, 1, LCD_GEN_CTRL);
reg->CRTC_GEN_CNTL = CRTC_GEN_CNTL;
return TRUE;
}
void
mach64Restore (KdCardInfo *card)
{
Mach64CardInfo *mach64c = card->driver;
Reg *reg = mach64c->reg;
if (reg)
{
mach64WriteLCD (reg, 1, mach64c->save.LCD_GEN_CTRL);
}
mach64ResetMMIO (card, mach64c);
vesaRestore (card);
}
void
mach64ScreenFini (KdScreenInfo *screen)
{
Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver;
vesaScreenFini (screen);
xfree (mach64s);
screen->driver = 0;
}
void
mach64CardFini (KdCardInfo *card)
{
Mach64CardInfo *mach64c = card->driver;
mach64UnmapReg (card, mach64c);
vesaCardFini (card);
}
#define mach64CursorInit 0 /* initCursor */
#define mach64CursorEnable 0 /* enableCursor */
#define mach64CursorDisable 0 /* disableCursor */
#define mach64CursorFini 0 /* finiCursor */
#define mach64RecolorCursor 0 /* recolorCursor */
KdCardFuncs mach64Funcs = {
mach64CardInit, /* cardinit */
mach64ScreenInit, /* scrinit */
mach64InitScreen, /* initScreen */
mach64Preserve, /* preserve */
mach64Enable, /* enable */
mach64DPMS, /* dpms */
mach64Disable, /* disable */
mach64Restore, /* restore */
mach64ScreenFini, /* scrfini */
mach64CardFini, /* cardfini */
mach64CursorInit, /* initCursor */
mach64CursorEnable, /* enableCursor */
mach64CursorDisable, /* disableCursor */
mach64CursorFini, /* finiCursor */
mach64RecolorCursor, /* recolorCursor */
mach64DrawInit, /* initAccel */
mach64DrawEnable, /* enableAccel */
mach64DrawSync, /* syncAccel */
mach64DrawDisable, /* disableAccel */
mach64DrawFini, /* finiAccel */
vesaGetColors, /* getColors */
vesaPutColors, /* putColors */
mach64FinishInitScreen, /* finishInitScreen */
};