mode.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,370 行 · 第 1/3 页
C
1,370 行
PERM3_SURFACE *
GetPrimarySurface()
{
// GetPrimarySurface
// This function returns a PERM_SURFACE structure for the primary surface.
// This can be used in the various drawing operation parameter structures,
// as well as for other purposes. Includes virtual address of video memory
// currently being DAC'd out of. No Enter/Exit semantics for inlined
// functions.
return (&l_PrimarySurface);
}
void
SetMode(
ULONG DisplayMode
)
{
// SetMode
// This routine changes the current display mode to the mode whose number is
// passed.
// Local variables.
PERM3_BLT_PARAM BltParameters;
RECT DestRect;
USHORT VideoMode;
USHORT PixelFormat;
// Check parameters.
Assert(DisplayMode < GetDisplayModeCount());
Enter(L"SetMode");
VideoMode = l_DisplayModeTable[DisplayMode].VideoMode;
PixelFormat = l_DisplayModeTable[DisplayMode].PixelFormat;
// Disable the video for the duration of the mode set operation.
WriteMaskedRegUlong(r_VideoControl,
b_VideoControl_Enable,
0);
// Step 1 : Program the RAMDAC, including the LUT.
RamdacSetMode(VideoMode, PixelFormat);
// Step 2 : Setup video.
VideoSetMode(VideoMode, PixelFormat);
// Step 3 : Program the primary surface.
PrimarySurfaceSetMode(VideoMode, PixelFormat);
// Step 4 : Setup everything else.
MiscSetMode(VideoMode, PixelFormat);
// Enable video!
WriteMaskedRegUlong(r_VideoControl,
b_VideoControl_Enable,
b_VideoControl_Enable);
// We're done. Store the new mode number.
l_CurrentDisplayMode = DisplayMode;
// Clear the primary surface with one quick blt.
DestRect.left = 0;
DestRect.top = 0;
DestRect.right = l_PrimarySurface.Size.cx;
DestRect.bottom = l_PrimarySurface.Size.cy;
memset(&BltParameters, 0, sizeof(PERM3_BLT_PARAM));
BltParameters.Destination = (const SURFACE *)&l_PrimarySurface;
BltParameters.DestRect = &DestRect;
BltParameters.Rop = 0x0000F0F0; // PATCOPY
BltParameters.PatternType = SolidPattern;
BltParameters.FillValue = 0x00000000; // 0 is always black.
HardwareBlt(&BltParameters);
Exit(L"SetMode");
}
ULONG
ComputeStride(
USHORT VideoMode,
USHORT PixelFormat
)
{
// ComputeStride
// This function computes the number of bytes necessary to provide enough
// color data for one scan line in the display mode defined by the supplied
// VideoMode and PixelFormat. Currently uses a simplistic formula: pixels
// per line times bytes per pixel. This function returns an unsigned
// number as we never use bottom-up bitmaps for the primary surface.
// Local variables.
ULONG Stride; // Return value for this function.
// Check parameters.
Assert(VideoMode < l_NumVideoModeTable);
Assert(PixelFormat < l_NumPixelTable);
Enter(L"ComputeStride");
Stride = l_VideoModeTable[VideoMode].HResolution * l_PixelTable[PixelFormat].BitsPerPixel / 8;
Exit(L"ComputeStride");
return Stride;
}
ULONG
ComputeMemRequired(
USHORT VideoMode,
USHORT PixelFormat
)
{
// ComputeMemRequired
// This function computes the amount of video memory that's necessary for
// a given display mode, as defined by the video mode and the pixel format
// passed. Currently, this is a simplistic computation. It will become more
// complex if palettized primaries are supported: you'll need space for the
// palette.
// Local variables.
ULONG BytesRequired; // Return value for this function.
// Check parameters.
Assert(VideoMode < l_NumVideoModeTable);
Assert(PixelFormat < l_NumPixelTable);
Enter(L"ComputeMemRequired");
BytesRequired = ComputeStride(VideoMode, PixelFormat) * l_VideoModeTable[VideoMode].VResolution;
Exit(L"ComputeMemRequired");
return BytesRequired;
}
void
RamdacSetMode(
USHORT VideoMode,
USHORT PixelFormat
)
{
// RamdacSetMode
// This function is the first step in setting a display mode : it programs
// the Permedia3's Ramdac, including all of the clock setup including the
// dot clock (DClk.) This function is not intended to be reuseable, rather
// it makes the SetMode function much easir to read.
// Local variables.
ULONG LockTimeout;
ULONG RefClkFrequency;
ULONG DClkFrequency;
ULONG KClkFrequency;
ULONG SClkFrequency;
ULONG MClkFrequency;
ULONG i;
BYTE LinearRamp[NUM_LUT_ENTRIES];
BYTE DClkControl;
BYTE KClkControl;
BYTE SClkControl;
BYTE MClkControl;
BYTE M, N, P;
BYTE SyncControl;
// Check parameters.
Assert(VideoMode < l_NumVideoModeTable);
Assert(PixelFormat < l_NumPixelTable);
Enter(L"RamdacSetMode");
// !TODO! WaitForInputFIFO()
// Make certain we do NOT autoincrement the index. It would mess up our
// masked reads and writes.
WriteRegByte(r_RDIndexControl, 0);
// Setup sync signal polarity. (The shift left by 3 is to position the
// vysnc polarity value over the b_RDSyncControl_VSyncCtl register.)
SyncControl = (BYTE)(
(l_VideoModeTable[VideoMode].HSyncPolarity) |
(l_VideoModeTable[VideoMode].VSyncPolarity << 3)
);
WriteMaskedRdReg(r_RDSyncControl,
b_RDSyncControl_HSyncCtl | b_RDSyncControl_VSyncCtl,
SyncControl);
// Enable blank level pedestal.
WriteMaskedRdReg(r_RDDACControl,
b_RDDACControl_BlankPedestal,
b_RDDACControl_BlankPedestal);
// Stop all clocks.
WriteRdReg(r_RDDClkControl, 0);
WriteRdReg(r_RDKClkControl, 0);
WriteRdReg(r_RDMClkControl, 0);
WriteRdReg(r_RDSClkControl, 0);
// !TODO! Use the HaveExtendedClocks and related data members of
// PERM3_CONFIG.
RefClkFrequency = DEFAULT_REFCLK_FREQUENCY; // 100 Hrtz units.
SClkFrequency = DEFAULT_SCLK_FREQUENCY; // 100 Hrtz units.
MClkFrequency = DEFAULT_MCLK_FREQUENCY; // 100 Hrtz units.
// Startup the setup clock.
SClkControl = 0;
// The default source for the setup clock (SClk.) is KClk.
// 6 << 4 is the same as setting b_RDSClkControl_Source = 6, or KClk.
SClkControl |= (0x6 << 4);
// Setting the b_RDSClkControl_Clock bit starts the clock.
SClkControl |= b_RDSClkControl_Clock;
// (2 << 2) is the bits to set b_RDSClkControl_State to 2 or Run.
SClkControl |= (2 << 2);
WriteMaskedRdReg(r_RDSClkControl,
b_RDSClkControl_Clock |
b_RDSClkControl_State |
b_RDSClkControl_Source,
SClkControl);
// Startup the memory clock.
MClkControl = 0;
// The default source for the memory clock (MClk.) is KClk.
// 6 << 4 is the same as setting b_RDMClkControl_Source = 6, or KClk.
MClkControl |= (0x6 << 4);
// Setting the b_RDMClkControl_Clock bit starts the clock.
MClkControl |= b_RDMClkControl_Clock;
// (2 << 2) is the bits to set b_RDMClkControl_State to 2 or Run.
MClkControl |= (2 << 2);
WriteMaskedRdReg(r_RDMClkControl,
b_RDMClkControl_Clock |
b_RDMClkControl_State |
b_RDMClkControl_Source,
MClkControl);
// Now, we need to set up the pixel (or dot) clock (DClk.) We load both
// of the selctable dot clock scale factors (Dclk2 and DClk3.)
DClkFrequency = l_VideoModeTable[VideoMode].PixelClock;
if (CalculateMNPForClock(RefClkFrequency,
DClkFrequency,
&M, &N, &P) == 0) {
Error(L"Invalid dot clock!\n");
}
WriteRdReg(r_RDDClk2PreScale, N);
WriteRdReg(r_RDDClk2FeedbackScale, M);
WriteMaskedRdReg(r_RDDClk2PostScale, b_RDDClk2PostScale_Scale, P);
WriteRdReg(r_RDDClk3PreScale, N);
WriteRdReg(r_RDDClk3FeedbackScale, M);
WriteMaskedRdReg(r_RDDClk3PostScale, b_RDDClk3PostScale_Scale, P);
// Pick the RAMDAC control registers to control the DClk Pll.
// We'll use set #3 (RDDClk3PreScale, RDDClk3PostScale, and
// RDDClk3FeedbackScale.)
WriteRegUlong(r_VClkRDacCtl, 3);
// Set up the KClk.
// !TODO! Use the HaveExtendedClocks and related data members of
// PERM3_CONFIG.
KClkFrequency = DEFAULT_KCLK_FREQUENCY; // In 100 Hrtz. units
if (CalculateMNPForClock(RefClkFrequency,
KClkFrequency,
&M, &N, &P) == 0) {
Error(L"Invalid core clock!\n");
}
WriteRdReg(r_RDKClkPreScale, N);
WriteRdReg(r_RDKClkFeedbackScale, M);
WriteMaskedRdReg(r_RDKClkPostScale, b_RDKClkPostScale_Scale, P);
// Enable the dot clock (DClk) then verify that it is working (by
// waiting for it to lock.)
DClkControl = 0;
// Setting the b_RDDClkControl_Clock bit starts the clock.
DClkControl |= b_RDDClkControl_Clock;
// (2 << 2) is the bits to set b_RDDClkControl_State to 2 or Run.
DClkControl |= (2 << 2);
WriteMaskedRdReg(r_RDDClkControl,
b_RDDClkControl_Clock |
b_RDDClkControl_State,
DClkControl);
LockTimeout = LOCK_TIMEOUT;
while ((ReadRdReg(r_RDDClkControl) & b_RDDClkControl_Lock) == 0 &&
--LockTimeout);
if (LockTimeout == 0) {
Error(L"Pixel clock failed to lock.\n");
}
// Enable the core clock (KClk) then verify that it is working (by
// waiting for it to lock.)
KClkControl = 0;
// Setting the b_RDKClkControl_Clock bit starts the clock.
KClkControl |= b_RDKClkControl_Clock;
// (2 << 2) is the bits to set b_RDKClkControl_State to 2 or Run.
KClkControl |= (2 << 2);
// (2 << 4) is the bits to set b_RDKClkControl_Source to 2, or the PLL.
KClkControl |= (2 << 4);
WriteMaskedRdReg(r_RDKClkControl,
b_RDKClkControl_Clock |
b_RDKClkControl_State |
b_RDKClkControl_Source,
KClkControl);
LockTimeout = LOCK_TIMEOUT;
while ((ReadRdReg(r_RDKClkControl) & b_RDKClkControl_Lock) == 0 &&
--LockTimeout);
if (LockTimeout == 0) {
Error(L"Core clock failed to lock.\n");
}
// Setup the color format.
WriteRdReg(r_RDColorFormat, l_PixelTable[PixelFormat].RDColorFormat);
// Disable direct color. We do this for all bits per pixel sizes because,
// we need the LUTs for gamma correction. Also, we need all 8 bits for
// each entry in the palette, so enable "HighColorResolution"
WriteMaskedRdReg(r_RDMiscControl,
b_RDMiscControl_DirectColor |
b_RDMiscControl_HighColorResolution,
b_RDMiscControl_HighColorResolution);
// Setup the pixel size in the RAMDAC.
if (l_PixelTable[PixelFormat].BitsPerPixel == 16) {
WriteRdReg(r_RDPixelSize, 1); // 1 == 16 Bpp.
}
else if (l_PixelTable[PixelFormat].BitsPerPixel == 32) {
WriteRdReg(r_RDPixelSize, 2); // 2 == 32 Bpp.
}
else {
Error(L"Unknown bits per pixel detected!\n");
}
// Make sure we setup the pixel mask so that no bits are turned off by
// the mask.
WriteRegByte(r_RDPixelMask, 0xFF);
// Setup the default LUT values for gamma correction. We will default to
// a linear ramp for all three components as a default.
for (i = 0; i < NUM_LUT_ENTRIES; i++) LinearRamp[i] = (BYTE)i;
// No need to wait for v-sync for SetGammaRamp. The video is disabled.
SetGammaRamp(LinearRamp, LinearRamp, LinearRamp);
Exit(L"RamdacSetMode");
}
ULONG
CalculateMNPForClock(
ULONG RefClockFrequency,
ULONG RequiredFrequency,
BYTE * ReturnM,
BYTE * ReturnN,
BYTE * ReturnP
)
{
// CalculateMNPForClock
// This function takes a desired clock frequency, the frequency of the
// refrence clock and computes the necessary feedback scaler (M,)
// prescaler (N,) and postscaler (P.) It usees the formula (from pg. 89
// Permedia3 Programmer's Guide)
//
// OutputFrequency = (Refrence Clock Frequency * M) / (N * (1 << P))
//
// Both the desired frequency and the refrence clock frequency must be passed
// in 100 Hrtz. units.
//
// We use an extra 2 in the computation for M becuase there is a clock
// multiplier in the P3 that we need to consider. This is to say, we must
// compute M, N and P as if we desired a clock speed 1/2 of what was given
// to us. The Permedia will double the resulting frequency from the PLL.
//
// Because we cannot match the exact frequency desired, we return the actual
// frequncy that the values of M, N, and P returned will result in.
//
// VCO is the output frequency of the PLL. (it's the frequency of the
// refrence clock after it's been multiplied by M and divided by N.)
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?