📄 config.cpp
字号:
dwDisplayClock));
dwDesiredDisplayClock = dwDisplayClock;
DEBUGMSG(1,
(TEXT("AMADisp: Searching available parameters for ICD2053B ")
TEXT("programmable clock generator...\r\n")));
bRet = CalcICD2053PLLParams(
dwPLLBaseClock, dwDesiredDisplayClock, &dwDisplayClock,
&dwPLLDividerP, &dwPLLDividerQ, &dwPLLOutputMux);
if (!bRet) return FALSE; // No available configuration.
// VCO frequency is used later.
dwVCOFrequency = dwPLLBaseClock
* 2 * dwPLLDividerP / dwPLLDividerQ;
}
}
// Check display clock frequency.
if (dwDisplayClock > DO_MAXDISPLAYCLOCK) {
RETAILMSG(1,
(TEXT("AMADisp: Display clock %d is too high. ")
TEXT("(%dMHz max)\r\n"),
dwDisplayClock, DO_MAXDISPLAYCLOCK / 1000000));
return FALSE;
}
// Set default value to each missed hardware parameter.
// LocalMemoryAddress, the top address of HD64404 local SDRAM.
if (dwLocalMemoryAddress == REG_NOTSPECIFIED) {
dwLocalMemoryAddress = DEFAULT_LOCALMEMORY_ADDRESS;
DEBUGMSG(1,
(TEXT("AMADisp: Failed to get LocalMemoryAddress from registry, ")
TEXT("using default value 0x%08x.\r\n"), dwLocalMemoryAddress));
}
else DEBUGMSG(1,
(TEXT("AMADisp: LocalMemoryAddress is found, value is 0x%08x.\r\n"),
dwLocalMemoryAddress));
// VideoMemoryOffset, video memory area start offset in HD64404 SDRAM.
if (dwVideoMemoryOffset == REG_NOTSPECIFIED) {
dwVideoMemoryOffset = DEFAULT_VIDEOMEMORY_OFFSET;
DEBUGMSG(1,
(TEXT("AMADisp: Failed to get VideoMemoryOffset from registry, ")
TEXT("using default value 0x%08x.\r\n"), dwVideoMemoryOffset));
}
else DEBUGMSG(1,
(TEXT("AMADisp: VideoMemoryOffset is found, value is 0x%08x.\r\n"),
dwVideoMemoryOffset));
// VideoMemorySize, how large the RAM space is assigned for display.
if (dwVideoMemorySize == REG_NOTSPECIFIED) {
dwVideoMemorySize = DEFAULT_VIDEOMEMORY_SIZE;
DEBUGMSG(1,
(TEXT("AMADisp: Failed to get VideoMemorySize from registry, ")
TEXT("using default value 0x%08x.\r\n"), dwVideoMemorySize));
}
else DEBUGMSG(1,
(TEXT("AMADisp: VideoMemorySize is found, value is 0x%08x.\r\n"),
dwVideoMemorySize));
// RegisterAddress, the top address of HD64404 control registers.
if (dwRegisterAddress == REG_NOTSPECIFIED) {
dwRegisterAddress = DEFAULT_REGISTER_ADDRESS;
DEBUGMSG(1,
(TEXT("AMADisp: Failed to get RegisterAddress from registry, ")
TEXT("using default value 0x%08x.\r\n"), dwRegisterAddress));
}
else DEBUGMSG(1,
(TEXT("AMADisp: RegisterAddress is found, value is 0x%08x.\r\n"),
dwRegisterAddress));
// First, prepare register value independent to display configuration.
AMADispMode[0].DORegs[DO_SYSR ] = 0x00004000; // system control, do reset
AMADispMode[0].DORegs[DO_SRCR ] = 0x00008840; // status clear, clear all bits
AMADispMode[0].DORegs[DO_IER ] = 0x00000000; // DO interrupts, initially disabled
AMADispMode[0].DORegs[DO_REMR ] = 0x00004000; // extended rendering(?) mode enabled
AMADispMode[0].DORegs[DO_DUBG ] = 0; // BG mode, set when used
AMADispMode[0].DORegs[DO_DUW ] = 0; // PIP mode, set when used
// Unlike Q2SD, display off color is treated as lowest priority screen.
AMADispMode[0].DORegs[DO_DOORH ] = 0x00000000; // display off color R
AMADispMode[0].DORegs[DO_DOORL ] = 0x00000000; // display off color G, B
AMADispMode[0].DORegs[DO_HVP ] = 0; // PIP start X, set when used
AMADispMode[0].DORegs[DO_VVP ] = 0; // PIP start Y, set when used
AMADispMode[0].DORegs[DO_VSAR0H ] = 0; // PIP address 0 H, set when used
AMADispMode[0].DORegs[DO_VSAR0L ] = 0; // PIP address 0 L, set when used
AMADispMode[0].DORegs[DO_VSAR1H ] = 0; // PIP address 1 H, set when used
AMADispMode[0].DORegs[DO_VSAR1L ] = 0; // PIP address 1 L, set when used
AMADispMode[0].DORegs[DO_VSAR2H ] = 0; // PIP address 2 H, set when used
AMADispMode[0].DORegs[DO_VSAR2L ] = 0; // PIP address 2 L, set when used
AMADispMode[0].DORegs[DO_VSIZEX ] = 0; // PIP width, set when used
AMADispMode[0].DORegs[DO_VSIZEY ] = 0; // PIP height, set when used
AMADispMode[0].DORegs[DO_HCS1 ] = 0; // cursor 1 position X and interval
AMADispMode[0].DORegs[DO_VCS1 ] = 0; // position Y and interval, set later
AMADispMode[0].DORegs[DO_HCS2 ] = 0; // cursor 2 position X
AMADispMode[0].DORegs[DO_VCS2 ] = 0; // position Y, set when used
AMADispMode[0].DORegs[DO_WRPY ] = 0; // linear mode wraparound, unused
AMADispMode[0].DORegs[DO_DBR1 ] = 0x00000000; // display blending, turn off it
AMADispMode[0].DORegs[DO_DBR2 ] = 0; // blending alpha value, not used
AMADispMode[0].DORegs[DO_TRNFGR ] = 0; // FG transparency, set when used
AMADispMode[0].DORegs[DO_TRNC1R ] = CURSOR_TRANSPARENT_COLOR; // Cursor 1
AMADispMode[0].DORegs[DO_TRNC2R ] = 0; // Cursor 2 transparent color
AMADispMode[0].DORegs[DO_ECR ] = 0x08840F88; // extended control, 64x64 cursor,
// no blink on cursor2, data output
// on DOTCK falling edge, tile mode
AMADispMode[0].GERegs[GE_RCR ] = 0x00008000; // rendering control, do reset
AMADispMode[0].GERegs[GE_SRCR ] = 0x00000007; // clear all GE status flags
AMADispMode[0].GERegs[GE_IER ] = 0x00000000; // GE interrupts, initially disabled
AMADispMode[0].GERegs[GE_DLSARH ] = 0x00000000; // DL start H, set in each rendering
AMADispMode[0].GERegs[GE_DLSARL ] = 0x00000000; // DL start L, set in each rendering
AMADispMode[0].GERegs[GE_RMR ] = 0x00000000; // rendering mode, set in each rendering
AMADispMode[0].GERegs[GE_SSAR ] = 0x00000000; // source area address, set when used
AMADispMode[0].GERegs[GE_RSAR ] = 0x00000000; // rendering addr, set in each rendering
// Display clock settings, currently not considering TV sync mode.
if (dwDisplayClockMode == 0) { // using HD64404 display clock PLL
// Display clock is generated internally from pixel bus clock
// using PLL. DOT_CLK pin is set to dot clock output.
// DO_DSMR setting, TVM bits are set to master mode.
AMADispMode[0].DORegs[DO_DSMR] = 0x00000000;
AMADispMode[0].DORegs[DO_PLL] =
0x03700003 // RBF=0, ME=1, FDT=23, PCKE=1, PLLE=1
| (dwPLLDividerN - 1) << 2 // DIVN
| dwPLLDividerP << 5 // DIVP (prescaler)
| (dwPLLDividerA - 1) << 9 // DIVA
| (dwPLLDividerB - 1) << 13 // DIVB
| (dwPLLDividerC - 1) << 17; // DIVC
// ICD2053B is not used in this case. (All 0 means "not used".)
AMADispMode[0].PCGRegs[PCG_P] = 0;
AMADispMode[0].PCGRegs[PCG_D] = 0;
AMADispMode[0].PCGRegs[PCG_M] = 0;
AMADispMode[0].PCGRegs[PCG_Q] = 0;
AMADispMode[0].PCGRegs[PCG_I] = 0;
}
else if (dwDisplayClockMode == 1) { // using external oscillator
// Display clock is supplied from external oscillator. DOT_CLK pin
// is configured as display clock input.
// DO_DSMR setting, TVM bits are set to external DOT_CLK mode.
AMADispMode[0].DORegs[DO_DSMR] = 0x000000C0;
// DO_PLL setting, HD64404 built-in PLL is not turned on.
// RBF=0, ME=1, FDT=23, DIVP=1, PCKE=1
AMADispMode[0].DORegs[DO_PLL] = 0x03700022;
// ICD2053B is not used in this case. (All 0 means "not used".)
AMADispMode[0].PCGRegs[PCG_P] = 0;
AMADispMode[0].PCGRegs[PCG_D] = 0;
AMADispMode[0].PCGRegs[PCG_M] = 0;
AMADispMode[0].PCGRegs[PCG_Q] = 0;
AMADispMode[0].PCGRegs[PCG_I] = 0;
}
else { // dwDisplayClockMode == 2, using ICD2053B clock generator.
// Display clock is supplied from ICD2053B clock generator.
// On the HD64404 I/O board of S1-E, ICD2053B is controlled via
// HD64404 GPIO ports. SCLK is connected to GPIO5, DATA is GPIO6,
// and _MUXREF/OE is GPIO7.
// DO_DSMR setting, TVM bits are set to external DOT_CLK mode.
AMADispMode[0].DORegs[DO_DSMR] = 0x000000C0;
// DO_PLL setting, HD64404 built-in PLL is not turned on.
// RBF=0, ME=1, FDT=23, DIVP=1, PCKE=1
AMADispMode[0].DORegs[DO_PLL] = 0x03700022;
// ICD2053B configuration parameters is prepared here.
AMADispMode[0].PCGRegs[PCG_P] = (BYTE)dwPLLDividerP - 3;
AMADispMode[0].PCGRegs[PCG_D] = 1;
AMADispMode[0].PCGRegs[PCG_M] = (BYTE)dwPLLOutputMux;
AMADispMode[0].PCGRegs[PCG_Q] = (BYTE)dwPLLDividerQ - 2;
if (dwVCOFrequency > 80000000) AMADispMode[0].PCGRegs[PCG_I] = 8;
else AMADispMode[0].PCGRegs[PCG_I] = 0;
}
if (dwVideoOutputMode == 0) { // RGB mode
nHc = dwDisplayClock / dwScanFrequency;
nVc = dwScanFrequency / dwFrameRate;
nHsw = nHc * 10 / 100; // 10% of HC
nXs = nHc * 5 / 100; // 5% of HC
nXe = 0;
nVsw = 3; // Various screen format uses 3 for VSYNC pulse width.
nYs = 12;
// FG is on, C1/C2/PIP are off, CSYNC/HSYNC pin is set to HSYNC
dwDsmr2 = 0x00000040;
dwEqwr = 0;
dwSpwr = 0;
g_szModeString = TEXT("RGB only");
}
else if (dwVideoOutputMode == 1) { // NTSC mode
nHc = dwDisplayClock / dwScanFrequency;
nVc = dwScanFrequency / dwFrameRate;
nHsw = (int)(4.7E-6 * (double)dwDisplayClock);
nXs = (int)(4.7E-6 * (double)dwDisplayClock);
nVsw = 9;
nYs = 12;
nXe = (int)(1.4E-6 * (double)dwDisplayClock);
// FG is on, C1/C2/PIP are off, CSYNC is set to NTSC timing.
dwDsmr2 = 0x00000080;
dwEqwr = (DWORD)(2.35E-6 * (double)dwDisplayClock);
dwSpwr = (DWORD)((0.5 / (double)dwScanFrequency - 4.7E-6)
* (double)dwDisplayClock);
g_szModeString = TEXT("NTSC video output");
}
else if (dwVideoOutputMode == 2) { // PAL mode
nHc = dwDisplayClock / dwScanFrequency;
nVc = dwScanFrequency / dwFrameRate;
nHsw = (int)(4.7E-6 * (double)dwDisplayClock);
nXs = (int)(5.8E-6 * (double)dwDisplayClock);
nVsw = 7;
nYs = 20;
nXe = (int)(1.4E-6 * (double)dwDisplayClock);
// FG is on, C1/C2/PIP are off, CSYNC is set to PAL timing.
dwDsmr2 = 0x000000c0;
dwEqwr = (DWORD)(2.35E-6 * (double)dwDisplayClock);
dwSpwr = (DWORD)((0.5 / (double)dwScanFrequency - 4.7E-6)
* (double)dwDisplayClock);
g_szModeString = TEXT("PAL video output");
}
else { // illegal mode
RETAILMSG(1,
(TEXT("AMADisp: Illegal video output mode specified.\r\n")));
return FALSE;
}
nHOffset = (nHc - (int)dwScreenWidth - nHsw - nXs - nXe) / 2
+ (int)dwScreenOffsetX;
nVOffset = (nVc - (int)dwScreenHeight - nVsw - nYs) / 2
+ (int)dwScreenOffsetY;
nHds = nHsw + nXs - 11 + nHOffset;
nVds = nYs - 2 + nVOffset;
// display size X
AMADispMode[0].DORegs[DO_DSX ] = dwScreenWidth;
// display size Y
AMADispMode[0].DORegs[DO_DSY ] = dwScreenHeight;
// display start position H
AMADispMode[0].DORegs[DO_HDS ] = (DWORD)nHds;
// display end position H
AMADispMode[0].DORegs[DO_HDE ] = (DWORD)nHds + dwScreenWidth;
// display start position V
AMADispMode[0].DORegs[DO_VDS ] = (DWORD)nVds;
// display end position V
AMADispMode[0].DORegs[DO_VDE ] = (DWORD)nVds + dwScreenHeight;
// HSYNC pulse width
AMADispMode[0].DORegs[DO_HSWR ] = (DWORD)(nHsw - 1);
// horizontal total count
AMADispMode[0].DORegs[DO_HCR ] = (DWORD)(nHc - 1);
// VSYNC pulse start position
AMADispMode[0].DORegs[DO_VSP ] = (DWORD)(nVc - nVsw - 1);
// vertical total count
AMADispMode[0].DORegs[DO_VCR ] = (DWORD)(nVc - 1);
// display mode 2 (contains sync pulse mode bit)
AMADispMode[0].DORegs[DO_DSMR2 ] = dwDsmr2;
// equalizing pulse width
AMADispMode[0].DORegs[DO_EQWR ] = dwEqwr;
// separation pulse width
AMADispMode[0].DORegs[DO_SPWR ] = dwSpwr;
// To get the longest timing margin from frame interrupt to internal
// modification of display control registers, using scan line interrupt
// for frame change interrupt. (Currently interrupts are not used.)
AMADispMode[0].DORegs[DO_LIR ] = (DWORD)nVds;
if (dwScreenWidth > 1024 || dwScreenHeight > 768) {
RETAILMSG(1,
(TEXT("AMADisp: Screen too large.\r\n")));
return FALSE;
}
if ((int)dwScreenWidth + nHsw + nXs >= nHc - 1) {
RETAILMSG(1,
(TEXT("AMADisp: Invalid horizontal display timing.\r\n")));
return FALSE;
}
if ((int)dwScreenHeight + nVsw + nYs >= nVc) {
RETAILMSG(1,
(TEXT("AMADisp: Invalid vertical display timing.\r\n")));
return FALSE;
}
if (dwBpp == 0) dwBpp = 8;
else if (dwBpp != 8 && dwBpp != 16) {
RETAILMSG(1,
(TEXT("AMADisp: Unsupported bit-per-pixel value.\r\n")));
return FALSE;
}
if (dwBpp == 8) { // FG=8bpp, 1024 pixel width
AMADispMode[0].MPXIFRegs[MPXIF_DTMR] = 0x00000011;
AMADispMode[0].DORegs[DO_DUFG] = 0x00000040;
}
else { // FG=16bpp, 1024 pixel width
AMADispMode[0].MPXIFRegs[MPXIF_DTMR] = 0x00000010;
AMADispMode[0].DORegs[DO_DUFG] = 0x00000041;
}
// Frame buffer is allocated at the top of video memory area.
// Note that the start address must be placed at 64kB boundary when
// using Q2SD/RU for acceleration. (2DGE not requires this.)
// Currently, this driver does not use acceleration.
dwVideoMemoryOffset
= (dwVideoMemoryOffset + 0x0000FFFF) & 0x07FFF0000; // align in 64kB
g_dwFrameBufferOffset = dwVideoMemoryOffset;
// Frame buffer memory size, allocate memory in 32kB boundary.
if (dwBpp == 16)
g_dwFrameBufferSize = (dwScreenHeight * 2048) & 0x001F8000;
else
g_dwFrameBufferSize = (dwScreenHeight * 1024) & 0x000F8000;
if (dwVideoMemorySize != 0x00080000
&& dwVideoMemorySize != 0x00100000
&& dwVideoMemorySize != 0x00200000
&& dwVideoMemorySize != 0x00400000
&& dwVideoMemorySize != 0x00800000) {
RETAILMSG(1,
(TEXT("AMADisp: Unsupported video memory size.\r\n")));
return FALSE;
}
g_dwLocalMemoryAddress = dwLocalMemoryAddress;
g_dwVideoMemoryOffset = dwVideoMemoryOffset;
g_dwVideoMemorySize = dwVideoMemorySize;
g_dwRegisterAddress = dwRegisterAddress; // HD64404 register space
// required memory size
g_dwWorkAreaSize = 0x00000000; // currently not used
g_dwSystemDLAreaSize = 0x00000000; // currently not used
g_dwCursorAreaSize = 0x00008000; // 32kB
// Hardware cursor pattern area is recommended to placed within
// non tile-linear conversion space but this driver sets all of
// video memory area for conversion, so the cursor pattern looks
// as if they are splitted in 32 pixels. The address bit 5-13 in
// 8bpp/1024w or 16bpp/512w, 5-14 in 16bpp/1024w are different
// between CPU and DisplayOut module, so we placed this area in
// 32kB alignment.
// In this implementation, Cursor1 patterns and Cursor 2 patterns
// are located bottom of the video memory space. Each cursor uses
// pattern A and B for blinking so 4 pattern space is required.
g_dwCursorAreaOffset =
dwVideoMemoryOffset
+ (dwVideoMemorySize - DO_CURSORBYTES * 4) & 0x07FF8000;
// They are actually not used now.
g_dwSystemDLAreaOffset = g_dwCursorAreaOffset - g_dwSystemDLAreaSize;
g_dwWorkAreaOffset = g_dwSystemDLAreaOffset - g_dwWorkAreaSize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -