📄 smilynx.c
字号:
/* smiLynx.c - Silicon Motion WindML graphics driver */
/* Copyright 2001 Silicon Motion, Inc. */
/*
modification history
--------------------
01a,29jun01,dmh first draft released to the wild
*/
/*
DESCRIPTION
Silicon Motion Lynx WindML 2.0 graphics driver.
Verified on a LynxEM4+
640x480 and 800x600 work very well in both 8bit and 16bit color
1024x768 appears too wide. will fix soon
*/
#include <ugl/uglugi.h>
#include <ugl/uglmem.h>
#include <ugl/driver/graphics/smi/smiLynx.h>
int * smiBaseAddress;
int colorBit;/*颜色位:8或16*/
#define UGL_BIG_ENDIAN
#ifdef DEBUG
SMI_DRIVER * driver;
#endif
/*
* Video processor control
*/
typedef struct {
unsigned int control;
unsigned int colorKey;
unsigned int colorKeyMask;
unsigned int start;
unsigned short offset;
unsigned short width;
unsigned int fifoPrio;
unsigned int fifoERL;
unsigned int YUVtoRGB;
} SmiVideoProc;
/*
* Video window control
*/
typedef struct {
unsigned short top;
unsigned short left;
unsigned short bottom;
unsigned short right;
unsigned int srcStart;
unsigned short width;
unsigned short offset;
unsigned char hStretch;
unsigned char vStretch;
} SmiVideoWin;
/*
* Capture port control
*/
typedef struct {
unsigned int control;
unsigned short topClip;
unsigned short leftClip;
unsigned short srcHeight;
unsigned short srcWidth;
unsigned int srcBufStart1;
unsigned int srcBufStart2;
unsigned short srcOffset;
unsigned short fifoControl;
} SmiCapturePort;
UGL_MODE smiModes[] =
{
/* 640, 480, 8Bit Color */
{640, 480, 8, 60, UGL_MODE_CRT, UGL_MODE_INDEXED_COLOR},
{640, 480, 8, 85, UGL_MODE_CRT, UGL_MODE_INDEXED_COLOR},
/* 640, 480, 16Bit Color */
{640, 480, 16, 60, UGL_MODE_CRT, UGL_MODE_DIRECT_COLOR},
{640, 480, 16, 85, UGL_MODE_CRT, UGL_MODE_DIRECT_COLOR},
/* 800, 600, 8Bit Color */
{800, 600, 8, 56, UGL_MODE_CRT, UGL_MODE_INDEXED_COLOR},
{800, 600, 8, 72, UGL_MODE_CRT, UGL_MODE_INDEXED_COLOR},
/* 800, 600, 16Bit Color */
{800, 600, 16, 56, UGL_MODE_CRT, UGL_MODE_DIRECT_COLOR},
{800, 600, 16, 72, UGL_MODE_CRT, UGL_MODE_DIRECT_COLOR},
/* 1024, 768, 8Bit Color */
{1024, 768, 8, 60, UGL_MODE_CRT, UGL_MODE_INDEXED_COLOR},
{1024, 768, 8, 70, UGL_MODE_CRT, UGL_MODE_INDEXED_COLOR},
/* 1024, 768, 16Bit Color */
{1024, 768, 16, 60, UGL_MODE_CRT, UGL_MODE_DIRECT_COLOR},
{1024, 768, 16, 70, UGL_MODE_CRT, UGL_MODE_DIRECT_COLOR},
};
/* needed modification that differed from suggested values
because using values from the docs resulted in too much jitter */
/* number and order of modeSets entrys must match those in smiModes
so I don't have to rewrite uglGenericModeFind */
char modeSets[12][4] =
{
{0x40, 0x00, 0x66, 0x9D}, /* 640x480, 60Hz, VCLK=25.180Mhz */
{0x20, 0x00, 0x58, 0x94}, /* 640x480, 85Hz, VCLK=31.5Mhz */
{0x40, 0x00, 0x66, 0x9D}, /* 640x480, 60Hz, VCLK=25.180Mhz */
{0x20, 0x00, 0x58, 0x94}, /* 640x480, 85Hz, VCLK=31.5Mhz */
{0x20, 0x04, 0x72, 0x97}, /* 800x600, 56Hz, VCLK=35.484Mhz */
{0x40, 0x00, 0x53, 0x18}, /* 800x600, 72Hz, VCLK=49.517Mhz */
{0x20, 0x04, 0x72, 0x97}, /* 800x600, 56Hz, VCLK=35.484Mhz */
{0x40, 0x00, 0x53, 0x18}, /* 800x600, 72Hz, VCLK=49.517Mhz */
{0x40, 0x00, 0x6e, 0x14}, /* 1024x768, 75Hz, VCLK=78.750Mhz */
{0x40, 0x00, 0x6e, 0x14}, /* 1024x768, 75Hz, VCLK=78.750Mhz */
{0x40, 0x00, 0x6e, 0x14}, /* 1024x768, 75Hz, VCLK=78.750Mhz */
{0x40, 0x00, 0x6e, 0x14}, /* 1024x768, 75Hz, VCLK=78.750Mhz */
};
void smiSetMode(SMI_DRIVER* pDriver)
{
int width = pDriver->generic.ugi.pMode->width;
int depth = pDriver->generic.ugi.pMode->colorDepth;
int Bpp = depth >> 3; /* 1 byte per pix for 8 bit color, 2 for 16 */
char tmp;
int tmp32;
/* CCR68 */
tmp = smiReadVgaIndexed(pDriver, VGA_SEQUENCER_REG, VGA_SEQUENCER_DATA, 0x68);
tmp = (tmp & ~0xe0) | modeSets[pDriver->modeIndex][0];
smiWriteVgaIndexed(pDriver, VGA_SEQUENCER_REG, VGA_SEQUENCER_DATA, 0x68, tmp);
/* Misc Output Register */
tmp = (smiReadVga(pDriver, VGA_MISC_IN_REG) & ~0x0c) | modeSets[pDriver->modeIndex][1];
smiWriteVga(pDriver, VGA_MISC_OUT_REG, tmp);
if(depth == 8)
tmp32 = 0x00000000;
else /* else depth is 16 */
tmp32 = 0x00020000;
WRITE_VPR(pDriver, 0x0, tmp32);
WRITE_VPR(pDriver, 0x0C, 0);
/* stride? */
tmp32 = ((((width * Bpp) >> 3)) << 16) | ((width * Bpp) >> 3);
WRITE_VPR(pDriver, 0x10, tmp32);
/*FPR30*/
tmp = smiReadVgaIndexed(pDriver, VGA_SEQUENCER_REG,
VGA_SEQUENCER_DATA, 0x30);
switch(width)
{
case 640:
tmp = tmp & ~0x0c;
break;
case 800:
tmp = (tmp & ~0x0c) | 0x04;
break;
case 1024:
tmp = (tmp & ~0x0c) | 0x08;
break;
case 1280:
tmp = (tmp & ~0x0c) | 0x0c;
break;
}
smiWriteVgaIndexed(pDriver, VGA_SEQUENCER_REG,
VGA_SEQUENCER_DATA, 0x30, tmp);
/* VNR */
smiWriteVgaIndexed(pDriver, VGA_SEQUENCER_REG,
VGA_SEQUENCER_DATA, 0x6c, modeSets[pDriver->modeIndex][2]);
/* VDR */
smiWriteVgaIndexed(pDriver, VGA_SEQUENCER_REG,
VGA_SEQUENCER_DATA, 0x6d, modeSets[pDriver->modeIndex][3]);
}
UGL_UGI_DRIVER * smiLynxDevCreate
(
UGL_ORD instance,
UGL_UINT32 notUsed0,
UGL_UINT32 notUsed1
)
{
UGL_UGI_DRIVER * pDriver = UGL_NULL;
UGL_GENERIC_DRIVER * pGenDriver = UGL_NULL;
SMI_DRIVER * pSmiDriver = UGL_NULL;
if (instance > 0)
return(UGL_NULL);
pSmiDriver = (SMI_DRIVER *)UGL_CALLOC(1, sizeof(SMI_DRIVER));
#ifdef DEBUG
driver = pSmiDriver;
#endif
if(UGL_NULL != pSmiDriver)
{
/* Initialize the driver (mandatory) */
pDriver = (UGL_UGI_DRIVER *)pSmiDriver;
uglUgiDevInit(pDriver);
pGenDriver = (UGL_GENERIC_DRIVER *)pSmiDriver;
pGenDriver->fbAddress = smiBaseAddress;
#ifdef UGL_BIG_ENDIAN
/*pGenDriver->fbAddress += 0x800000;*/
#endif
/* hardware resources - revisit */
pSmiDriver->dpPort = pGenDriver->fbAddress + 0x400000;
pSmiDriver->dpBase = (int*)((char*)(pSmiDriver->dpPort) + 0x8000);
pSmiDriver->vpBase = (int*)((char*)(pSmiDriver->dpPort) + 0xc000);
pSmiDriver->cpBase = (int*)((char*)(pSmiDriver->dpPort) + 0xe000);
pSmiDriver->minClock = 20000;
pSmiDriver->maxClock = 135000;
/* Set Standard Driver API Functions */
pDriver->modeAvailGet = smiLynxModeAvailGet;
pDriver->modeSet = smiLynxModeSet;
pDriver->clutSet = smiLynxClutSet;
pDriver->clutGet = smiLynxClutGet;
pDriver->destroy = smiLynxDestroy;
pDriver->info = smiLynxInfo;
pDriver->pageDrawSet = smiLynxPageDrawSet;
pDriver->pageVisibleSet = smiLynxPageVisibleSet;
pDriver->transBitmapCreate = uglGenericTransBitmapCreate;
pDriver->transBitmapDestroy = uglGenericTransBitmapDestroy;
pDriver->transBitmapRead = uglGenericTransBitmapRead;
pDriver->transBitmapWrite = uglGenericTransBitmapWrite;
pDriver->transBitmapCreateFromDdb = uglGenericTransBitmapCreateFromDdb;
pDriver->cursorBitmapCreate = uglGenericCursorBitmapCreate;
pDriver->cursorBitmapDestroy = uglGenericCursorBitmapDestroy;
pDriver->cursorInit = uglGenericCursorInit;
pDriver->cursorDeinit = uglGenericCursorDeinit;
pDriver->cursorHide = uglGenericCursorHide;
pDriver->cursorImageGet = uglGenericCursorImageGet;
pDriver->cursorImageSet = uglGenericCursorImageSet;
pDriver->cursorMove = uglGenericCursorMove;
pDriver->cursorPositionGet = uglGenericCursorPositionGet;
pDriver->cursorOff = uglGenericCursorOff;
pDriver->cursorOn = uglGenericCursorOn;
pDriver->cursorShow = uglGenericCursorShow;
pDriver->ellipse = uglGenericEllipse;
pDriver->gcCopy = uglGenericGcCopy;
pDriver->gcCreate = uglGenericGcCreate;
pDriver->gcDestroy = uglGenericGcDestroy;
pDriver->gcSet = uglGenericGcSet;
pDriver->line = uglGenericLine;
pDriver->polygon = uglGenericPolygon;
pDriver->rectangle = uglGenericRectangle;
pDriver->pageCopy = uglGenericPageCopy;
pDriver->pageCreate = uglGenericPageCreate;
pDriver->pageDestroy = uglGenericPageDestroy;
pDriver->pageDrawGet = uglGenericPageDrawGet;
pDriver->pageVisibleGet = uglGenericPageVisibleGet;
pDriver->memPoolCreate = uglGenericMemPoolCreate;
pDriver->memPoolDestroy = uglGenericMemPoolDestroy;
pGenDriver->gpWait = UGL_NULL;
}
return(pDriver);
}
UGL_STATUS smiLynxModeAvailGet (UGL_DEVICE_ID devId,
UGL_UINT32 * pNumModes,
const UGL_MODE ** pModeArray )
{
TRACK;
return(UGL_STATUS_OK);
}
UGL_STATUS smiLynxInfo(UGL_DEVICE_ID devId, UGL_INFO_REQ infoRequest,
void *info)
{
UGL_UGI_DRIVER * pDriver = (UGL_UGI_DRIVER *)devId;
UGL_GENERIC_DRIVER * pGenDriver = (UGL_GENERIC_DRIVER *)pDriver;
TRACK;
if(pDriver->pMode == UGL_NULL)
return(UGL_STATUS_ERROR);
switch (infoRequest)
{
case UGL_FB_INFO_REQ:
{
UGL_FB_INFO *fbInfo = (UGL_FB_INFO *)info;
fbInfo->width = pDriver->pMode->width;
fbInfo->height = pDriver->pMode->height;
fbInfo->fbAddrs = pGenDriver->fbAddress;
fbInfo->dsMemAmount = 0x400000; /* revisit */
fbInfo->flags = 0; /* revisit */
break;
}
case UGL_COLOR_INFO_REQ:
{
UGL_COLOR_INFO *colorInfo = (UGL_COLOR_INFO *)info;
if(pDriver->pMode->colorDepth == 8)
colorInfo->cmodel = UGL_CMODEL_INDEXED;
else
colorInfo->cmodel = UGL_CMODEL_DIRECT;
colorInfo->cspace = UGL_CSPACE_RGB; /* revisit */
colorInfo->depth = pDriver->pMode->colorDepth;
colorInfo->clutSize = 256; /* revisit */
colorInfo->flags = UGL_CLUT_WRITE; /* revisit */
break;
}
case UGL_MODE_INFO_REQ:
{
UGL_MODE_INFO * modeInfo = (UGL_MODE_INFO *)info;
modeInfo->width = pDriver->pMode->width;
modeInfo->height = pDriver->pMode->height;
modeInfo->colorDepth = pDriver->pMode->colorDepth;
modeInfo->clutSize = 256; /* revisit */
if(pDriver->pMode->colorDepth == 8)
modeInfo->colorModel = UGL_INDEXED_8;
else
modeInfo->colorModel = UGL_DIRECT;
modeInfo->colorFormat = 0; /* revisit */
modeInfo->fbAddress = pGenDriver->fbAddress;
modeInfo->displayMemAvail = 0x400000; /* revisit */
modeInfo->flags = pDriver->pMode->flags;
break;
}
case UGL_EXT_INFO_REQ:
{
UGL_EXT_INFO * extInfo = (UGL_EXT_INFO *)info;
break;
}
default:
return (UGL_STATUS_ERROR);
}
return(UGL_STATUS_OK);
}
void smiMcrRegSet(SMI_DRIVER * pSmiDriver)
{
/*MCR60*/
smiWriteVgaIndexed(pSmiDriver,VGA_SEQUENCER_REG,VGA_SEQUENCER_DATA,0x60,0x00);
/*MCR61*/
smiWriteVgaIndexed(pSmiDriver,VGA_SEQUENCER_REG,VGA_SEQUENCER_DATA,0x61,0x00);
/*MCR62*/
smiWriteVgaIndexed(pSmiDriver,VGA_SEQUENCER_REG,VGA_SEQUENCER_DATA,0x62,/*0x34*/0x3e);
/*MCR6A*/
smiWriteVgaIndexed(pSmiDriver,VGA_SEQUENCER_REG,VGA_SEQUENCER_DATA,0x6a,0x12);
/*MCR6B*/
smiWriteVgaIndexed(pSmiDriver,VGA_SEQUENCER_REG,VGA_SEQUENCER_DATA,0x6b,0x2);
}
/*******************************************************************************
*
* Init video processor registers
*/
void smiInitVideoProc(SMI_DRIVER * pSmiDriver)
{
SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -