home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
d
/
ddx-mips.zip
/
MIPS4000.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-06-10
|
22KB
|
1,043 lines
/*
* $XConsortium$
*
* Copyright 1991 MIPS Computer Systems, Inc.
*
* 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 MIPS not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. MIPS makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* MIPS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL MIPS
* 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.
*/
#ident "$Header: mips4000.c,v 1.11 92/06/10 15:21:05 dd Exp $"
/*
* Device support for the RC4030 VDRxx frame buffers
*
* Note: This code is used only when the RISC/os frame buffer device
* driver is not available (cf. mipsGenFb.c).
*/
#include <sys/types.h>
#include <X.h>
#include <Xproto.h>
#include <misc.h>
#include <cursorstr.h>
#include <input.h>
#include <scrnintstr.h>
#include <servermd.h>
#include "mipsFb.h"
#include "mips4000.h"
#include "fb_vdr1.h"
#include "fb_vdr2.h"
#ifdef _MIPSEL
#define VDR2_SUPPORT
#endif
#ifndef _MIPSEL
#define VDR_CURSOR_SUPPORT
#endif
#ifndef _KERNEL
#undef DELAY
#define DELAY(usec) mipsUsleep(usec)
#endif
#define ITEMSIN(a) (sizeof (a) / sizeof (a)[0])
#define ENDOF(a) (&(a)[ITEMSIN(a)])
#ifdef FBDEBUG
int fb_debug = FBDEBUG;
#define DEBUGF(level, args) if (fb_debug >= (level)) printf args; else
#else
#define DEBUGF(level, args) /* nothing */
#endif
#ifdef VDREXPORT
#define STATIC /* nothing */
#else
#define STATIC static
#endif
static int vdr1_set_video(), vdr1_get_video(),
vdr1_set_colormap(), vdr1_get_colormap();
#ifdef VDR2_SUPPORT
static int vdr2_set_video(), vdr2_get_video(),
vdr2_set_colormap(), vdr2_get_colormap();
#endif /* VDR2_SUPPORT */
static struct fb_ops {
int (*set_video)();
int (*get_video)();
int (*set_colormap)();
int (*get_colormap)();
} fb_ops[] = {
{
vdr1_set_video,
vdr1_get_video,
vdr1_set_colormap,
vdr1_get_colormap,
},
#ifdef VDR2_SUPPORT
{
vdr2_set_video,
vdr2_get_video,
vdr2_set_colormap,
vdr2_get_colormap,
},
#endif /* VDR2_SUPPORT */
};
/*
* RISCwindows ddx interface
*/
/* borrow unused entries in pm structure */
#define FBTYPE(pm) ((pm)->fd)
#define FBREG(pm) ((pm)->fbcache)
#define FBOPS(pm) ((pm)->fbspec)
#define FBOP(pm, func) (*((struct fb_ops *) (pm)->fbspec)->func)
extern char *mipsMapit();
static void Blank4000();
static void WriteCMap4000();
static void Close4000();
#ifdef VDR_CURSOR_SUPPORT
static Bool RealizeCursor4000();
static void SetCursor4000();
static void MoveCursor4000();
static void RecolorCursor4000();
#endif /* VDR_CURSOR_SUPPORT */
Bool
mipsMap4000(pm)
MipsScreenPtr pm;
{
if (!pm->fbreg && (
!(pm->fbnocache = (unsigned char *) mipsMapit((char *) 0,
RS4000_FBKEY, RS4000_FBSIZE)) ||
!(pm->fbreg = (unsigned char *) mipsMapit((char *) 0,
RS4000_REGKEY, RS4000_REGSIZE))))
return FALSE;
pm->fbnorm = pm->fbnocache;
mipsInitColor(pm);
if (Init4000(pm) < 0)
return FALSE;
pm->Blank = Blank4000;
pm->WriteCMap = WriteCMap4000;
pm->Close = Close4000;
#ifdef VDR_CURSOR_SUPPORT
if (!(pm->option & MIPS_SCR_NOHW) &&
FBTYPE(pm) > 0) {
pm->cap |= MIPS_SCR_CURSOR;
pm->RealizeCursor = RealizeCursor4000;
pm->SetCursor = SetCursor4000;
pm->MoveCursor = MoveCursor4000;
pm->RecolorCursor = RecolorCursor4000;
}
#endif /* VDR_CURSOR_SUPPORT */
return TRUE;
}
static void
Blank4000(pm, on)
MipsScreenPtr pm;
Bool on;
{
FBOP(pm, set_video)(FBREG(pm), on != SCREEN_SAVER_ON);
}
static void
WriteCMap4000(pm, index, count, rgb)
MipsScreenPtr pm;
int index;
int count;
unsigned char *rgb;
{
FBOP(pm, set_colormap)(FBREG(pm), index, count, rgb);
}
/* ARGSUSED */
static void
Close4000(pm)
MipsScreenPtr pm;
{
#ifdef VDR_CURSOR_SUPPORT
/* disable HW cursor */
SetCursor4000(pm, (CursorPtr) 0, (pointer) 0, 0, 0);
#endif /* VDR_CURSOR_SUPPORT */
}
/*
* Device support code
*/
union vdr_reg {
struct vdr1_reg vdr1;
struct vdr1f_reg vdr1f;
struct vdr2_reg vdr2;
};
/*
* Video timing parameters
*/
struct vdr_vtgval {
short w, h, vrate; /* width, height, vertical rate */
short type; /* parameter format (== 1 for now) */
short pixel; /* pixel rate, MHz */
short hfp, hs, hbp; /* horiz. parameters, pixels */
short vfp, vs, vbp; /* vert. parameters, pixels */
short opt; /* misc. video options */
#define VDR_VTGOPT_PLAINSYNC 1
#define VDR_VTGOPT_PEDESTAL 2
};
#define VDR_VTGVAL_FIELDS 12
STATIC struct vdr_vtgval *vdr_getvtg();
/*
* board characteristics
*/
struct vdr_opt {
char type; /* board ID */
char flags;
#define VDRT_X8 1 /* 8.125 MHz crystal (otherwise 5 MHz) */
#define VDRT_G365 2 /* has G365 RAMDAC */
#define VDRT_2M 4 /* has 2MB RAM, VRAM SAM len = 1024 */
#define VDRT_1M 8 /* has 1MB RAM, w = 1024 only */
#define VDRT_G364 16 /* has G364 RAMDAC (for 1M board) */
short pixel; /* max. pixel rate, MHz */
int memsize; /* VRAM size, bytes */
};
STATIC struct vdr_opt *vdr_getopt();
/* ARGSUSED */
Init4000(pm)
MipsScreenPtr pm;
{
int type;
struct vdr_vtgval vtg[1];
struct vdr_opt *opt;
struct vdr_vtgval *newvtg;
DEBUGF(3, ("Init4000()\n"));
bzero((char *) vtg, sizeof vtg);
vdr_getconf(vtg);
FBREG(pm) = pm->fbreg;
if ((type =
vdr_init((union vdr_reg **) &FBREG(pm), vtg)) < 0)
return -1;
DEBUGF(2, ("vdr_init returned type 0x%0x, %d x %d, %dK\n",
type, vtg->w, vtg->h, vdr_getopt(type)->memsize >> 10));
FBTYPE(pm) = type;
pm->scr_width = vtg->w;
pm->scr_height = vtg->h;
pm->fb_width =
vdr_getopt(type)->flags & VDRT_1M ? 2048 : pm->scr_width;
FBOPS(pm) = (unsigned char *) &fb_ops[type < 1];
return 0;
}
#define ISNUM(c) ((c) >= '0' && (c) <= '9')
/*
* vdr_getconf: extract video parameters from environment string
*/
STATIC
vdr_getconf(vtg)
struct vdr_vtgval *vtg;
{
char *cp;
int i, v;
extern char *getenv();
#ifdef FBDEBUG
if ((cp = getenv("fbdebug")))
fb_debug = atoi(cp);
#endif /* FBDEBUG */
if (!(cp = getenv("screensize")))
return;
for (i = 0; i < VDR_VTGVAL_FIELDS; i++) {
v = atoi(cp);
if (v <= 0 && i > 3)
break;
(&vtg->w)[i] = v;
do {
v = *cp++;
} while (ISNUM(v));
}
switch (vtg->type) {
case 0:
case 1:
/* options field is optional */
if (i == VDR_VTGVAL_FIELDS - 1 ||
i == VDR_VTGVAL_FIELDS) {
vtg->type = 1;
break;
}
/* fall through */
default:
vtg->type = 0;
}
DEBUGF(3, ("vdr_getconf: screensize = \"%s\", vtg->type = %d\n",
getenv("screensize"), vtg->type));
}
/*
* vdr_init: board identification
*/
static int
vdr_init(regarg, vtg)
union vdr_reg **regarg;
struct vdr_vtgval *vtg;
{
union vdr_reg *reg = *regarg;
int type;
/* start VDR2 (G300) PLL */
(void) vdr_vtginit(reg, vtg, 0, 1);
/*
* Try to write to VDR1 ID register address:
* VDR2: wraps to colormap
* VDR1: ID register
* Fission: ROM location
*/
reg->vdr1.id.r = 0;
type = reg->vdr1.id.r;
switch (type) {
case 0:
DEBUGF(3, ("vdr_init: possible type 0\n"));
/* confirm type 0 */
reg->vdr1.id.r = 0x5a;
if (reg->vdr1.id.r != 0)
return vdr_vtginit(reg, vtg, type, 0);
break;
case 1:
DEBUGF(3, ("vdr_init: possible type 1\n"));
/* start VDR1 (G364) PLL */
(void) vdr_vtginit(reg, vtg, type, 1);
reg->vdr1.ramdac.cmap[128].r = 0x5a3ca5;
/* try to write to VDR1 colormap (Fission ROM) */
if ((reg->vdr1.ramdac.cmap[128].r & 0xffffff) == 0x5a3ca5)
return vdr_vtginit(reg, vtg, type, 0);
break;
}
/* new style video board w/ROM */
type = reg->vdr1f.rom[0].r;
DEBUGF(3, ("vdr_init: ROM type 0x%0x\n", type));
if ((type = vdr_vtginit(reg, vtg, type, 0)) >= 0) {
DEBUGF(4, ("vdr_init: fixing register pointer\n"));
*regarg = (union vdr_reg *) ®->vdr1f.ramdac;
}
return type;
}
static struct vdr_vtgval
vdr_vtgval[] = {
/* w h hz typ pix hfp hs hbp vfp vs vbp opt */
{ 1280, 1024, 60, 1, 110, 40, 184, 224, 1, 3, 32, 0 },
{ 1280, 1024, 70, 1, 130, 40, 184, 224, 1, 3, 46, 0 },
{ 1280, 1024, 72, 1, 135, 40, 192, 228, 1, 3, 48, 0 },
{ 1024, 768, 60, 1, 65, 24, 136, 160, 1, 2, 35, 0 },
{ 1024, 768, 70, 1, 75, 24, 136, 144, 1, 2, 35, 0 },
{ 1024, 768, 72, 1, 80, 24, 136, 200, 1, 2, 36, 0 },
{ 1152, 900, 66, 1, 95, 32, 112, 208, 1, 3, 36, 0 },
{ 1152, 900, 76, 1, 110, 32, 128, 224, 1, 3, 40, 0 },
};
#define VTGVAL_BOOT (&vdr_vtgval[3])
static struct vdr_opt
vdr_opt[] = {
/* note: G364 is only spec-ed to 110 MHz,
usually works at 130 */
{ 0x10, VDRT_2M, 130, 2048 * 1024 },
{ 0x11, VDRT_2M | VDRT_G365, 135, 2048 * 1024 },
{ 0x12, VDRT_1M, 85, 1024 * 1024 },
{ 0x13, VDRT_1M | VDRT_G364, 110, 1024 * 1024 },
{ 0x01, VDRT_X8 | VDRT_2M, 110, 2048 * 1024 },
#ifdef VDR2_SUPPORT
{ 0x00, VDRT_X8 | VDRT_2M, 110, 2048 * 1024 },
#endif /* VDR2_SUPPORT */
};
/*
* vdr_getopt: look up characteristics of video board with given type
*/
STATIC struct vdr_opt *
vdr_getopt(type)
int type;
{
struct vdr_opt *p;
for (p = vdr_opt; p < ENDOF(vdr_opt); p++)
if (p->type == type)
return p;
return 0;
}
/*
* vdr_vtginit: locate video parameters, start VTG
*/
static int
vdr_vtginit(reg, vtg, type, boot)
union vdr_reg *reg;
struct vdr_vtgval *vtg;
int type, boot;
{
struct vdr_opt *opt;
struct vdr_vtgval *newvtg;
DEBUGF(3, ("vdr_vtginit()\n"));
if ((opt = vdr_getopt(type)) == 0)
return -1;
/* incorrect resolution reverts to default */
if (vtg->type == 0 || vdr_vtgck(vtg, opt)) {
if ((newvtg = vdr_getvtg(vtg, type, boot)) == 0) {
DEBUGF(2, ("vdr_vtginit: using default resolution\n"));
bzero((char *) vtg, sizeof *vtg);
if ((newvtg = vdr_getvtg(vtg, type, boot)) == 0)
return -1;
}
vtg = newvtg;
}
return vdr_vtgload(reg, vtg, type, boot);
}
/*
* vdr_getvtg: find video parameters to match specified screen size
*/
STATIC struct vdr_vtgval *
vdr_getvtg(vtgconf, type, boot)
struct vdr_vtgval *vtgconf;
int type, boot;
{
int w, h, vrate;
struct vdr_opt *opt;
struct vdr_vtgval *vtg;
DEBUGF(3, ("vdr_getvtg()\n"));
w = vtgconf->w;
h = vtgconf->h;
vrate = vtgconf->vrate;
DEBUGF(4, ("vdr_getvtg: %d x %d @ %d Hz, type = %d%s\n",
w, h, vrate, type, boot ? " (boot)" : ""));
if ((opt = vdr_getopt(type)) == 0)
return 0;
/* pick video parameters */
for (vtg = vdr_vtgval; vtg < ENDOF(vdr_vtgval); vtg++) {
DEBUGF(5, ("vtg w, h, vrate = %d, %d, %d\n",
vtg->w, vtg->h, vtg->vrate));
if (w != 0 && !(w == vtg->w && h == vtg->h))
continue;
if (vrate != 0 && vrate != vtg->vrate)
continue;
if (vdr_vtgck(vtg, opt))
continue;
if (!boot) {
vtgconf->w = vtg->w;
vtgconf->h = vtg->h;
vtgconf->vrate = vtg->vrate;
}
DEBUGF(3, ("vdr_getvtg: returning %d x %d @ %d Hz\n",
vtg->w, vtg->h, vtg->vrate));
return vtg;
}
return boot ? VTGVAL_BOOT : 0;
}
static int
vdr_vtgck(vtg, opt)
struct vdr_vtgval *vtg;
struct vdr_opt *opt;
{
DEBUGF(3, ("vdr_vtgck: %d x %d, flags = 0x%x\n",
vtg->w, vtg->h, opt->flags));
if (opt->flags & VDRT_1M && vtg->w != 1024 ||
vtg->pixel > opt->pixel ||
vtg->w * vtg->h > opt->memsize)
return -1;
return 0;
}
STATIC int
vdr_vtgload(reg, vtg, type, boot)
union vdr_reg *reg;
struct vdr_vtgval *vtg;
int type, boot;
{
DEBUGF(3, ("vdr_vtgload: type %d, boot %d\n", type, boot));
#ifdef VDR2_SUPPORT
if (type == 0)
return vdr2_init(®->vdr2, vtg, type, boot);
#endif /* VDR2_SUPPORT */
return vdr1_init(reg, vtg, type, boot);
}
/*
* VDR1 device dependent code
*/
static int
vdr1_init(reg, vtg, type, boot)
union vdr_reg *reg;
struct vdr_vtgval *vtg;
int type, boot;
{
struct g364 *ramdac;
int vdrflags = vdr_getopt(type)->flags;
int control, xferdelay, samlen;
DEBUGF(3, ("vdr1_init: type %d, boot %d\n", type, boot));
/* reset board, load boot register */
reg->vdr1.reset.r = 0;
ramdac = ®->vdr1.ramdac;
if (type > 1) {
reg->vdr1f.reset.r = 0;
#ifdef _MIPSEL
DEBUGF(3, ("vdr1_init: writing little endian register\n"));
reg->vdr1f.little_end.r = 0;
#else /* _MIPSEL */
DEBUGF(3, ("vdr1_init: writing big endian register\n"));
reg->vdr1f.big_end.r = 0;
#endif /* _MIPSEL */
ramdac = ®->vdr1f.ramdac;
}
DELAY(1);
ramdac->boot.r =
G364_BOOTVAL(vtg->pixel / (vdrflags & VDRT_X8 ? 8 : 5));
/* wait for PLL to stabilize */
DELAY(200);
/* just starting PLL for probe */
if (boot)
return type;
/* disable VTG (if running) */
ramdac->control.r = 0;
ramdac->controlb.r = 0;
control = G364_CONTROL_2M;
samlen = 1024;
if (vdrflags & VDRT_1M) {
control = G332_CONTROL_1M;
if (vdrflags & VDRT_G364)
control = G364_CONTROL_1M;
samlen = 512;
}
/*
* G364 C04 bug #4:
* "The second and subsequent serration pulses
* during PreEqualization are one screen unit in duration."
* We have to turn off serration if more vfp is needed.
*/
if (!(vdrflags & VDRT_G365) && vtg->vfp > 1)
control |= G364_CONTROL_PLAINSYNC;
/*
* Set misc. control register bits according to options...
*/
if (vtg->opt & VDR_VTGOPT_PLAINSYNC)
control |= G364_CONTROL_PLAINSYNC;
if (vtg->opt & VDR_VTGOPT_PEDESTAL)
control |= G364_CONTROL_PEDESTAL;
ramdac->control.r = control;
if (vdrflags & VDRT_G365)
ramdac->controlb.r =
G364_CONTROLB_EXTSAMP |
G364_CONTROLB_HSYNC_FLYBACK;
/* load datapath registers */
{
int w, hfp, hs, hbp, linetime;
xferdelay = G364_XFER_DELAY(vtg->pixel);
hfp = vtg->hfp >> 2;
hs = vtg->hs >> 2;
hbp = vtg->hbp >> 2;
if (hbp <= xferdelay)
hbp = xferdelay + 1;
w = vtg->w >> 2;
ramdac->halfsync.r = hs >> 1;
ramdac->backporch.r = hbp;
ramdac->display.r = w;
linetime = w + hfp + hs + hbp;
ramdac->linetime.r = linetime;
ramdac->broadpulse.r = (linetime / 2) - hfp;
ramdac->shortdisplay.r = (linetime / 2) - hfp - hs - hbp;
}
ramdac->vsync.r = vtg->vs << 1;
ramdac->vpreeq.r = vtg->vfp << 1;
ramdac->vposteq.r = 2;
ramdac->vblank.r = (vtg->vbp - 1) << 1;
ramdac->vdisplay.r = vtg->h << 1;
ramdac->linestart.r = 0;
ramdac->meminit.r = samlen - xferdelay;
ramdac->xferdelay.r = xferdelay;
/* set read mask */
ramdac->mask.r = ~0;
/* start VTG */
ramdac->control.r = control | G364_CONTROL_VTGON;
/*
* G364 C04 bug #6:
* "The action of starting the VTG may cause the TopOfScreen
* register to become corrupted."
*/
ramdac->top.r = 0;
return type;
}
static int
vdr1_set_video(reg, video)
unsigned char *reg;
int video;
{
g364_reg *control = &((struct vdr1_reg *) reg)->ramdac.control;
if (video)
control->r &= ~G364_CONTROL_BLANK;
else
control->r |= G364_CONTROL_BLANK;
return 0;
}
static int
vdr1_get_video(reg, video)
unsigned char *reg;
int *video;
{
g364_reg *control = &((struct vdr1_reg *) reg)->ramdac.control;
*video = (control->r & G364_CONTROL_BLANK) ? 0 : 1;
return 0;
}
static int
vdr1_set_colormap(reg, index, count, rgb)
unsigned char *reg;
int index, count;
unsigned char *rgb;
{
g364_reg *cmap = &((struct vdr1_reg *) reg)->ramdac.cmap[index];
u_int val;
while (--count >= 0) {
val = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
rgb += 3;
cmap->r = val;
cmap++;
}
return 0;
}
static int
vdr1_get_colormap(reg, index, count, rgb)
unsigned char *reg;
int index, count;
unsigned char *rgb;
{
g364_reg *cmap = &((struct vdr1_reg *) reg)->ramdac.cmap[index];
u_int val;
while (--count >= 0) {
val = cmap->r;
cmap++;
rgb[0] = val >> 16;
rgb[1] = val >> 8;
rgb[2] = val;
rgb += 3;
}
return 0;
}
#ifdef VDR_CURSOR_SUPPORT
/* XXX little-endian support */
/* ARGSUSED */
static Bool
RealizeCursor4000(pm, pCurs, pPriv)
MipsScreenPtr pm;
CursorPtr pCurs;
pointer *pPriv;
{
CursorBitsPtr bits = pCurs->bits;
int w, h;
int x, y;
int bytes;
int soffset;
short *ram, rmask;
unsigned char *source, *mask;
int ramt, st, mt;
int bit;
ram = (short *) xalloc(G364_CURSBYTES);
*pPriv = (pointer) ram;
if (!ram)
return FALSE;
h = bits->height;
if (h > G364_CURSMAX)
h = G364_CURSMAX;
w = bits->width;
/* line to line offset in source and mask bitmaps */
soffset = ((w + BITMAP_SCANLINE_PAD - 1) &
~(BITMAP_SCANLINE_PAD - 1)) >> 3;
if (w > G364_CURSMAX)
w = G364_CURSMAX;
/* right edge mask for cursor RAM */
rmask = 0xffff0000 >> ((w & 7) << 1);
/* bytes per line actually used in source and mask bitmaps */
bytes = (w + 7) >> 3;
source = bits->source;
mask = bits->mask;
/*
* M7 I7 .. M0 I0
*/
for (y = 0; y < h; y++) {
for (x = 0; x < bytes; x++) {
/*
* Repack 1 mask byte and 1 source byte into
* 1 G364 cursor RAM word.
*/
mt = mask[x];
st = source[x];
ramt = 0;
for (bit = 0; bit < 8; bit++)
if (mt & (0x80 >> bit)) {
ramt |= (1 << (bit * 2 + 1));
if (st & (0x80 >> bit))
ramt |= (1 << (bit * 2));
}
*ram++ = ramt;
}
/*
* Mask off garbage bits of partial word on right edge of
* cursor (if any).
*/
if (rmask)
ram[-1] &= rmask;
/* zero out blank space to right of cursor */
for (; x < G364_CURSMAX / 8; x++)
*ram++ = 0;
source += soffset;
mask += soffset;
}
/* zero out blank space below cursor */
for (; y < G364_CURSMAX; y++) {
for (x = 0; x < G364_CURSMAX / 8; x++)
ram[x] = 0;
ram += G364_CURSMAX / 8;
}
return TRUE;
}
static void
SetCursor4000(pm, pCurs, priv, x, y)
MipsScreenPtr pm;
CursorPtr pCurs;
pointer priv;
int x, y;
{
struct g364 *ramdac = &((struct vdr1_reg *) FBREG(pm))->ramdac;
unsigned short *ram;
int i;
/* turn cursor off */
ramdac->control.r |= G364_CONTROL_CURSDIS;
if (!pCurs)
return;
/* save hot spot */
pm->xhot = pCurs->bits->xhot;
pm->yhot = pCurs->bits->yhot;
/* position cursor */
MoveCursor4000(pm, x, y);
/* load colormap */
RecolorCursor4000(pm, pCurs);
ram = (unsigned short *) priv;
/*
* Load cursor RAM from preformatted buffer
*/
for (i = 0; i < G364_CURSBYTES / 2; i++) {
/* G364 C04 bug workaround */
(void) ramdac->curpat[i].r;
ramdac->curpat[i].r = ram[i];
}
/* turn cursor on */
ramdac->control.r &= ~G364_CONTROL_CURSDIS;
}
static void
MoveCursor4000(pm, x, y)
MipsScreenPtr pm;
int x, y;
{
struct g364 *ramdac = &((struct vdr1_reg *) FBREG(pm))->ramdac;
x -= pm->xhot;
y -= pm->yhot;
if (x < -G364_CURSMAX)
x = -G364_CURSMAX;
if (x > (pm->scr_width + 1))
x = pm->scr_width + 1;
if (y < -G364_CURSMAX)
y = -G364_CURSMAX;
if (x > 2047)
y = 2047;
ramdac->curpos.r = (x << 12) | y;
}
static void
RecolorCursor4000(pm, pCurs)
MipsScreenPtr pm;
CursorPtr pCurs;
{
struct g364 *ramdac = &((struct vdr1_reg *) FBREG(pm))->ramdac;
ramdac->curcmap[1].r =
(pCurs->backRed >> 8) << 16 |
(pCurs->backGreen >> 8) << 8 |
(pCurs->backBlue >> 8);
ramdac->curcmap[2].r =
(pCurs->foreRed >> 8) << 16 |
(pCurs->foreGreen >> 8) << 8 |
(pCurs->foreBlue >> 8);
}
#endif /* VDR_CURSOR_SUPPORT */
#ifdef VDR2_SUPPORT
/*
* VDR2 device dependent code
*/
/* ARGSUSED */
static int
vdr2_init(reg, vtg, type, boot)
struct vdr2_reg *reg;
struct vdr_vtgval *vtg;
int type, boot;
{
struct g300 *ramdac = ®->ramdac;
struct bt431 *curs = ®->cursor;
int i;
DEBUGF(3, ("vdr2_init: type %d, boot %d\n", type, boot));
/* start PLL */
if (ramdac->boot.r != (i = G300_BOOTVAL(vtg->pixel / 8))) {
ramdac->boot.r = i;
DELAY(200);
}
if (boot)
return 0;
/* initialize cursor chips */
BT431_SETADDR(curs, 0);
for (i = 0; i < 13; i++)
curs->ctrl.r = 0;
BT431_SETADDR(curs, 0);
for (i = 0; i < 512; i++)
curs->ram.r = 0;
/* turn off HW cursor */
BT431_SETADDR(curs, BT431_COMMAND);
curs->ctrl.r = BT431_COMMAND_CURSOFF;
/* disable G300 VTG (if running) */
ramdac->control.r = G300_CONTROL_OFF;
/* load datapath registers */
{
int w, hfp, hs, hbp, linetime;
hfp = vtg->hfp >> 2;
hs = vtg->hs >> 2;
hbp = vtg->hbp >> 2;
w = vtg->w >> 2;
ramdac->halfsync.r = hs >> 1;
ramdac->backporch.r = hbp;
ramdac->display.r = w;
linetime = w + hfp + hs + hbp;
ramdac->linetime.r = linetime;
ramdac->broadpulse.r = (linetime / 2) - hfp;
ramdac->shortdisplay.r = (linetime / 2) - hfp - hs - hbp;
}
ramdac->vsync.r = vtg->vs << 1;
ramdac->vblank.r = (vtg->vfp + vtg->vbp) << 1;
ramdac->vdisplay.r = vtg->h << 1;
ramdac->linestart.r = 0;
ramdac->meminit.r = 1024 - G300_XFER_DELAY;
ramdac->xferdelay.r = G300_XFER_DELAY;
/* set read mask */
reg->ramdac.mask.r = ~0;
/* start VTG */
ramdac->control.r = G300_CONTROL_ON;
return 0;
}
/*ARGSUSED*/
static int
vdr2_set_video(reg, video)
unsigned char *reg;
int video;
{
return -1;
}
/*ARGSUSED*/
static int
vdr2_get_video(reg, video)
unsigned char *reg;
int *video;
{
return -1;
}
static int
vdr2_set_colormap(reg, index, count, rgb)
char * reg;
int index, count;
unsigned char *rgb;
{
g300_reg *cmap = &((struct vdr2_reg *) reg)->ramdac.cmap[index];
u_int val;
while (--count >= 0) {
val = (rgb[2] << 16) | (rgb[1] << 8) | rgb[0];
rgb += 3;
cmap->r = val;
cmap++;
}
return 0;
}
static int
vdr2_get_colormap(reg, index, count, rgb)
char * reg;
int index, count;
unsigned char *rgb;
{
g300_reg *cmap = &((struct vdr2_reg *) reg)->ramdac.cmap[index];
u_int val;
while (--count >= 0) {
val = cmap->r;
cmap++;
rgb[0] = val;
rgb[1] = val >> 8;
rgb[2] = val >> 16;
rgb += 3;
}
return 0;
}
#endif /* VDR2_SUPPORT */