#include "rendition.h"
#include "vramdac.h"
#include "vos.h"
#include "v1kregs.h"
#include "v2kregs.h"
#undef DEBUG
#define BT485_WRITE_ADDR 0x00
#define BT485_RAMDAC_DATA 0x01
#define BT485_PIXEL_MASK 0x02
#define BT485_READ_ADDR 0x03
#define BT485_CURS_WR_ADDR 0x04
#define BT485_CURS_DATA 0x05
#define BT485_COMMAND_REG_0 0x06
#define BT485_CURS_RD_ADDR 0x07
#define BT485_COMMAND_REG_1 0x08
#define BT485_COMMAND_REG_2 0x09
#define BT485_STATUS_REG 0x0a
#define BT485_CURS_RAM_DATA 0x0b
#define BT485_CURS_X_LOW 0x0c
#define BT485_CURS_X_HIGH 0x0d
#define BT485_CURS_Y_LOW 0x0e
#define BT485_CURS_Y_HIGH 0x0f
#define BT485_COMMAND_REG_3 0x01
#define BT485_CR0_EXTENDED_REG_ACCESS 0x80
#define BT485_CR0_SCLK_SLEEP_DISABLE 0x40
#define BT485_CR0_BLANK_PEDESTAL 0x20
#define BT485_CR0_SYNC_ON_BLUE 0x10
#define BT485_CR0_SYNC_ON_GREEN 0x08
#define BT485_CR0_SYNC_ON_RED 0x04
#define BT485_CR0_8_BIT_DAC 0x02
#define BT485_CR0_SLEEP_ENABLE 0x01
#define BT485_CR1_24BPP 0x00
#define BT485_CR1_16BPP 0x20
#define BT485_CR1_8BPP 0x40
#define BT485_CR1_4BPP 0x60
#define BT485_CR1_1BPP 0x80
#define BT485_CR1_BYPASS_CLUT 0x10
#define BT485_CR1_565_16BPP 0x08
#define BT485_CR1_555_16BPP 0x00
#define BT485_CR1_1_TO_1_16BPP 0x04
#define BT485_CR1_2_TO_1_16BPP 0x00
#define BT485_CR1_PD7_PIXEL_SWITCH 0x02
#define BT485_CR1_PIXEL_PORT_CD 0x01
#define BT485_CR1_PIXEL_PORT_AB 0x00
#define BT485_CR2_SCLK_DISABLE 0x80
#define BT485_TEST_PATH_SELECT 0x40
#define BT485_PIXEL_INPUT_GATE 0x20
#define BT485_PIXEL_CLK_SELECT 0x10
#define BT485_INTERLACE_SELECT 0x08
#define BT485_16BPP_CLUT_PACKED 0x04
#define BT485_X_WINDOW_CURSOR 0x03
#define BT485_2_COLOR_CURSOR 0x02
#define BT485_3_COLOR_CURSOR 0x01
#define BT485_DISABLE_CURSOR 0x00
#define BT485_CURSOR_MASK 0x03
#define BT485_4BPP_NIBBLE_SWAP 0x10
#define BT485_CLOCK_DOUBLER 0x08
#define BT485_64_BY_64_CURSOR 0x04
#define BT485_32_BY_32_CURSOR 0x00
#define BT485_SIZE_MASK 0x04
#define BT485_INPUT_LIMIT 110000000
static void Bt485_write_masked(IOADDRESS port, vu8 reg, vu8 mask, vu8 data);
static void Bt485_write_cmd3_masked(IOADDRESS port, vu8 mask, vu8 data);
#if 0
static vu8 Bt485_read_masked(IOADDRESS port, vu8 reg, vu8 mask);
static vu8 Bt485_read_cmd3_masked(IOADDRESS port, vu8 mask);
#endif
static int Cursor_size=0;
void
verite_savedac (ScrnInfoPtr pScreenInfo)
{
renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
int iob=pRendition->board.io_base + RAMDACBASEADDR;
RenditionRegPtr reg = &pRendition->saveRegs;
reg->daccmd0 = verite_in8(iob+BT485_COMMAND_REG_0);
reg->daccmd1 = verite_in8(iob+BT485_COMMAND_REG_1);
reg->daccmd2 = verite_in8(iob+BT485_COMMAND_REG_2);
verite_out8(iob+BT485_COMMAND_REG_0,reg->daccmd0
| BT485_CR0_EXTENDED_REG_ACCESS);
verite_out8(iob+BT485_WRITE_ADDR, BT485_COMMAND_REG_3);
reg->daccmd3 = verite_in8(iob+BT485_STATUS_REG);
verite_out8(iob+BT485_COMMAND_REG_0,reg->daccmd0);
}
void
verite_restoredac (ScrnInfoPtr pScreenInfo, RenditionRegPtr reg)
{
renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
int iob=pRendition->board.io_base + RAMDACBASEADDR;
verite_out8(iob+BT485_COMMAND_REG_0, reg->daccmd0
| BT485_CR0_EXTENDED_REG_ACCESS);
verite_out8(iob+BT485_COMMAND_REG_1, reg->daccmd1);
verite_out8(iob+BT485_COMMAND_REG_2, reg->daccmd2);
verite_out8(iob+BT485_WRITE_ADDR, BT485_COMMAND_REG_3);
verite_out8(iob+BT485_STATUS_REG, reg->daccmd3);
verite_out8(iob+BT485_COMMAND_REG_0, reg->daccmd0);
}
int
verite_initdac(ScrnInfoPtr pScreenInfo, vu8 bpp, vu8 doubleclock)
{
renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR;
vu8 cmd0,cmd1,cmd2;
vu8 cmd3_data=0;
#ifdef DEBUG
ErrorF ("Rendition: Debug verite_initdac called\n");
#endif
if (doubleclock)
cmd3_data|=BT485_CLOCK_DOUBLER;
switch (bpp) {
case 1:
case 4:
xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
"color depth %d not (yet ?) supported\n",
bpp);
return -1;
case 8:
cmd0 = BT485_CR0_EXTENDED_REG_ACCESS |
BT485_CR0_8_BIT_DAC;
cmd1 = BT485_CR1_8BPP |
BT485_CR1_PIXEL_PORT_AB;
cmd2 = BT485_PIXEL_INPUT_GATE |
BT485_DISABLE_CURSOR;
verite_out8(iob+BT485_COMMAND_REG_0, cmd0);
verite_out8(iob+BT485_COMMAND_REG_1, cmd1);
verite_out8(iob+BT485_COMMAND_REG_2, cmd2);
break;
case 16:
cmd0 = BT485_CR0_EXTENDED_REG_ACCESS |
BT485_CR0_8_BIT_DAC;
cmd1 = BT485_CR1_16BPP |
BT485_CR1_2_TO_1_16BPP |
BT485_CR1_PIXEL_PORT_AB;
cmd2 = BT485_PIXEL_INPUT_GATE |
BT485_DISABLE_CURSOR;
if (pScreenInfo->defaultVisual == TrueColor)
cmd1 |= BT485_CR1_BYPASS_CLUT;
if (pScreenInfo->weight.green == 5)
cmd1 |= BT485_CR1_555_16BPP;
else
cmd1 |= BT485_CR1_565_16BPP;
verite_out8(iob+BT485_COMMAND_REG_0,cmd0);
verite_out8(iob+BT485_COMMAND_REG_1,cmd1);
verite_out8(iob+BT485_COMMAND_REG_2,cmd2);
break;
case 32:
cmd0 = BT485_CR0_EXTENDED_REG_ACCESS |
BT485_CR0_8_BIT_DAC;
cmd1 = BT485_CR1_24BPP |
BT485_CR1_PIXEL_PORT_AB;
cmd2 = BT485_PIXEL_INPUT_GATE |
BT485_DISABLE_CURSOR;
if (pScreenInfo->defaultVisual == TrueColor)
cmd1 |= BT485_CR1_BYPASS_CLUT;
verite_out8(iob+BT485_COMMAND_REG_0,cmd0);
verite_out8(iob+BT485_COMMAND_REG_1,cmd1);
verite_out8(iob+BT485_COMMAND_REG_2,cmd2);
break;
default:
xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
"Color depth not supported (%d bpp)\n", bpp);
return -1;
break;
}
verite_out8(iob+BT485_WRITE_ADDR, BT485_COMMAND_REG_3);
verite_out8(iob+BT485_STATUS_REG, cmd3_data);
verite_out8(iob+BT485_PIXEL_MASK, 0xff);
return 0;
}
void
verite_enablecursor(ScrnInfoPtr pScreenInfo, int type, int size)
{
renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
static vu8 ctypes[]={ BT485_DISABLE_CURSOR, BT485_2_COLOR_CURSOR,
BT485_3_COLOR_CURSOR, BT485_X_WINDOW_CURSOR };
static vu8 csizes[]={ BT485_32_BY_32_CURSOR, BT485_64_BY_64_CURSOR };
IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR;
#ifdef DEBUG
ErrorF ("Rendition: Debug verite_enablecursor called type=0x%x\n",type);
#endif
Bt485_write_masked(iob, BT485_COMMAND_REG_2, ~BT485_CURSOR_MASK,
ctypes[type]);
Bt485_write_cmd3_masked(iob, ~BT485_SIZE_MASK, csizes[size]);
if (type)
Cursor_size=(size ? 64 : 32);
#ifdef DEBUG
ErrorF ("Rendition: Debug verite_enablecursor Exit\n");
#endif
}
void
verite_movecursor(ScrnInfoPtr pScreenInfo, vu16 x, vu16 y, vu8 xo, vu8 yo)
{
renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR;
x+=Cursor_size-xo;
y+=Cursor_size-yo;
verite_out8(iob+BT485_CURS_X_LOW, x&0xff);
verite_out8(iob+BT485_CURS_X_HIGH, (x>>8)&0x0f);
verite_out8(iob+BT485_CURS_Y_LOW, y&0xff);
verite_out8(iob+BT485_CURS_Y_HIGH, (y>>8)&0x0f);
}
void
verite_setcursorcolor(ScrnInfoPtr pScreenInfo, vu32 fg, vu32 bg)
{
renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR;
#ifdef DEBUG
ErrorF ("Rendition: Debug verite_setcursorcolor called FG=0x%x BG=0x%x\n",
fg,bg);
#endif
verite_out8(iob+BT485_CURS_WR_ADDR, 0x00);
verite_out8(iob+BT485_CURS_DATA, 0x00);
verite_out8(iob+BT485_CURS_DATA, 0x00);
verite_out8(iob+BT485_CURS_DATA, 0x00);
verite_out8(iob+BT485_CURS_DATA, (fg>>16) & 0xff);
verite_out8(iob+BT485_CURS_DATA, (fg>>8) & 0xff);
verite_out8(iob+BT485_CURS_DATA, fg&0xff );
verite_out8(iob+BT485_CURS_DATA, (fg>>16) & 0xff);
verite_out8(iob+BT485_CURS_DATA, (fg>>8) & 0xff);
verite_out8(iob+BT485_CURS_DATA, fg & 0xff);
verite_out8(iob+BT485_CURS_DATA, (bg>>16)&0xff );
verite_out8(iob+BT485_CURS_DATA, (bg>>8)&0xff );
verite_out8(iob+BT485_CURS_DATA, bg&0xff );
}
void
verite_loadcursor(ScrnInfoPtr pScreenInfo, vu8 size, vu8 *cursorimage)
{
int c, bytes, row;
vu8 *src = cursorimage;
renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
IOADDRESS iob=pRendition->board.io_base+RAMDACBASEADDR;
vu8 tmp;
vu8 memend;
#ifdef DEBUG
ErrorF ("Rendition: Debug verite_loadcursor called\n");
#endif
if (NULL == cursorimage)
return;
memend = verite_in8(pRendition->board.io_base + MEMENDIAN);
verite_out8(pRendition->board.io_base + MEMENDIAN, MEMENDIAN_HW);
size&=1;
if (size)
bytes=64;
else
bytes=32;
bytes=(bytes*bytes)>>3;
if (pRendition->board.chip == V1000_DEVICE) {
tmp=verite_in8(iob+BT485_COMMAND_REG_0)&0x7f;
verite_out8(iob+BT485_COMMAND_REG_0, tmp|0x80);
verite_out8(iob+BT485_WRITE_ADDR, BT485_COMMAND_REG_3);
tmp=verite_in8(iob+BT485_STATUS_REG)&0xf8;
verite_out8(iob+BT485_STATUS_REG, tmp|(size<<2));
verite_out8(iob+BT485_WRITE_ADDR, 0x00);
src=cursorimage;
for (c=0; c<bytes; c++) {
verite_out8(iob+BT485_CURS_RAM_DATA, *src);
src+=2;
}
src=cursorimage+1;
for (c=0; c<bytes; c++) {
verite_out8(iob+BT485_CURS_RAM_DATA, *src);
src+=2;
}
}
else {
verite_out32(iob+CURSORBASE, pRendition->board.hwcursor_membase);
for (row=0; row<64; row++)
for (c=0, src=cursorimage+1+16*row; c<8; c++, src+=2)
verite_write_memory8(pRendition->board.vmem_base, 16*(63-row)+c,
(c&1)?(*(src-2)):(*(src+2)));
for (row=0; row<64; row++)
for (c=0, src=cursorimage+16*row; c<8; c++, src+=2)
verite_write_memory8(pRendition->board.vmem_base, 8+16*(63-row)+c,
(c&1)?(*(src-2)):(*(src+2)));
}
verite_out8(pRendition->board.io_base + MEMENDIAN, memend);
}
void
verite_setpalette(ScrnInfoPtr pScreenInfo, int numColors, int *indices,
LOCO *colors, VisualPtr pVisual)
{
renditionPtr pRendition = RENDITIONPTR(pScreenInfo);
IOADDRESS iob=pRendition->board.io_base;
vu32 crtc_status;
int i, index;
#ifdef DEBUG
ErrorF ("Rendition: Debug verite_setpalette called\n");
#endif
while (1) {
crtc_status=verite_in32(iob+CRTCSTATUS);
if (crtc_status & CRTCSTATUS_VERT_SYNC)
break;
};
iob+=RAMDACBASEADDR;
for (i = 0; i < numColors; i++) {
index = indices[i];
verite_out8(iob+BT485_WRITE_ADDR, index);
verite_out8(iob+BT485_RAMDAC_DATA, colors[index].red);
verite_out8(iob+BT485_RAMDAC_DATA, colors[index].green);
verite_out8(iob+BT485_RAMDAC_DATA, colors[index].blue);
}
}
static void
Bt485_write_masked(IOADDRESS port, vu8 reg, vu8 mask, vu8 data)
{
vu8 tmp;
tmp=verite_in8(port+reg)&mask;
verite_out8(port+reg, tmp|data);
}
static void
Bt485_write_cmd3_masked(IOADDRESS port, vu8 mask, vu8 data)
{
verite_out8(port+BT485_WRITE_ADDR, BT485_COMMAND_REG_3);
Bt485_write_masked(port, BT485_STATUS_REG, mask, data);
}
#if 0
static vu8
Bt485_read_masked(IOADDRESS port, vu8 reg, vu8 mask)
{
return verite_in8(port+reg)&mask;
}
static vu8
Bt485_read_cmd3_masked(IOADDRESS port, vu8 mask)
{
vu8 value;
Bt485_write_masked(port, BT485_COMMAND_REG_0, 0x7f, 0x80);
verite_out8(port+BT485_WRITE_ADDR, BT485_COMMAND_REG_3);
value=Bt485_read_masked(port, BT485_STATUS_REG, mask);
Bt485_write_masked(port, BT485_COMMAND_REG_0, 0x7f, 0x00);
return value;
}
#endif