📄 clcd.c
字号:
static void DispPowerOn(BOOL bInPowerHandler);
static void DispPowerOff(BOOL bInPowerHandler);
// Convert 24bit RGB into 16bit value to fit into CLCD palette register
#ifndef CLCD_565 // in original 1555 mode
//I|BBBBB|GGGGG|RRRRR
//(1) >>3 red lsb
//(2) >>3 then <<5 so <<2
//(3) >>3 then <<10 so <<7
#define PALCONV(_v_) (((((UINT32)(_v_).peRed ) >> 3) & 0x001f) | \
((((UINT32)(_v_).peGreen) << 2) & 0x03e0) | \
((((UINT32)(_v_).peBlue ) << 7) & 0x7c00))
#else // new 565 true 16 bit mapping
//RRRRR|GGGGGG|BBBBB
//(1) >>3 then <<11 so <<8
//(2) >>2 then <<5 so <<3
//(3) >>3
#define PALCONV(_v_) (((((UINT32)(_v_).peRed ) << 8) & 0xF800) | \
((((UINT32)(_v_).peGreen) << 3) & 0x07e0) | \
((((UINT32)(_v_).peBlue ) >> 3) & 0x001f))
#endif
/******************************************************************************\
* Description: Find the required ratio of the Panel Clock to the CLCD clock. *
* Operation: The Panel Clock is generated by a divisor applied to the CLCD *
* Clock. This function uses values from the parameter structure *
* to generate a divisor that gives a refresh rate close to that *
* requested. *
* This is done by calculating the effective clocked area of the *
* LCD, and using the requested refresh rate to find the Panel *
* Clock frequency that gives the desired refresh rate. From this *
* the required divisor is derived. *
* The ratio is often a small integer so the refresh rate set up *
* can be (considerably) different from that requested. Because *
* of this the actual refresh rate expected is computed and saved *
* in the parameter structure. *
* NOTE: The LCD display is clocked across its active area and additional *
* regions around its edge. These extra regions are the Horizontal Front *
* and Back Porches, the Vertical Front and Back Porches, the Horizontal *
* and vertical synch regions. This affects the total number of clock *
* ticks needed to process a single frame. *
* Since each LCD pixel is made up of a number of discrete elements, *
* another factor determines the number of elements clocked by each tick *
* so there may be a non-integral number of clock ticks per pixel. *
* This value varies between different panel types. *
\******************************************************************************/
/*
int CLCD_ClockRatioCompute(void)
{
ULONG PixPerFrame;
ULONG PanelClockFrequency;
int Ratio; // This could be negative
// For TFT displays, PCD can go down to 0, ie the ratio is 2. However,
// if the ratio is less than 2, the pixel clock divisor is bypassed,
// and so that this case can be detected the minimum value is 1
int MinRatio = 1; // This gives PCD = 0, the minimum for TFT
// Calculate raw number of clocks per frame
// Firstly find the total number of pixels over to whole display, both
// active and inactive. This is the total clocked width (Nominal width +
// Horizontal Front + Back Porche) multiplied by the total clocked height
// (Nominal height + Vertical Front and Back Porches)
PixPerFrame = ( ( DISPDRVR_CXSCREEN + HSYNC_VALUE
+ HFRONT_VALUE + HBACK_VALUE )
*
( DispDrvr_cyScreen + VSYNC_VALUE
+ VFRONT_VALUE + VBACK_VALUE ));
// Deduce the nominal required Clock frequency for the refresh rate
PanelClockFrequency = PixPerFrame * FRAME_RATE;
Ratio = (LCD_CLOCK / PanelClockFrequency);
if(Ratio < MinRatio) // Ensure value used is sensible
{
Ratio = MinRatio;
}
return Ratio;
}
*/
/******************************************************************************\
* Description: CLCD Timing0 register setup *
* Operation: Generates the appropriate pattern for the Timing0 register *
* from the current parameters defined and loads the register *
\******************************************************************************/
void CLCD_Timing0Set(void)
{
ULONG reg = 0;
apBIT_SET(reg, CLCD_TIMING0_PPL, DispDrvr_cxScreen / 16 - 1); //14
apBIT_SET(reg, CLCD_TIMING0_HSW, HSYNC_VALUE - 1);
apBIT_SET(reg, CLCD_TIMING0_HFP, HFRONT_VALUE -1);
apBIT_SET(reg, CLCD_TIMING0_HBP, HBACK_VALUE - 1);
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_TIMING0_OFFSET, TIM0_VALUE);
}
/******************************************************************************\
* Description: Timing1 register setup *
* Operation: Generates the appropriate pattern for the Timing1 register *
* from the current parameters defined and loads the register *
\******************************************************************************/
void CLCD_Timing1Set(void)
{
ULONG reg = 0;
apBIT_SET(reg, CLCD_TIMING1_LPP, DispDrvr_cyScreen - 1);
if(VSYNC_VALUE)
{
apBIT_SET(reg, CLCD_TIMING1_VSW, VSYNC_VALUE - 1);
}
else
{
apBIT_SET(reg, CLCD_TIMING1_VSW, VSYNC_VALUE);
}
apBIT_SET(reg, CLCD_TIMING1_VFP, VFRONT_VALUE);
apBIT_SET(reg, CLCD_TIMING1_VBP, VBACK_VALUE);
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_TIMING1_OFFSET, TIM1_VALUE);
}
/******************************************************************************\
* Description: Timing2 register setup *
* Operation: Uses the current parameters to generate the Timing2 register *
* and loads the register *
\******************************************************************************/
void CLCD_Timing2Set(void)
{
ULONG reg = 0;
//int PCD;
/* PCD = CLCD_ClockRatioCompute();
if(PCD < 2) // This can only happen if its TFT
{
reg |= CLCD_TIMING2_MASK_BCD; // Bypass Clock divisor instead of PCD
}
else
{
apBIT_SET(reg, CLCD_TIMING2_PCD, PCD - 2);
}*/
/*BCD=0 to NOT bypass the clcd clock*/
//reg |= CLCD_TIMING2_MASK_BCD;
apBIT_SET(reg, CLCD_TIMING2_CPL, DispDrvr_cxScreen-1);
apBIT_SET(reg, CLCD_TIMING2_ACB, ACBIAS);
reg |= ( (ULONG)((ULONG) VSYNCACTIVE << bsCLCD_TIMING2_IVS)
| (ULONG)((ULONG) HSYNCACTIVE << bsCLCD_TIMING2_IHS)
| (ULONG)((ULONG) DATADRIVE << bsCLCD_TIMING2_IPC)
| (ULONG)((ULONG) CLOCKSOURCE << bsCLCD_TIMING2_CLKSEL)
| (ULONG)((ULONG) TFTCLAC << bsCLCD_TIMING2_IEO)
| (ULONG)((ULONG) PCD_VALUE << bsCLCD_TIMING2_PCD)
);
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_TIMING2_OFFSET,TIM2_VALUE);
}
/******************************************************************************\
* Description: Timing3 register setup *
* Operation: Generates the appropriate pattern for the Timing3 register *
* from the current parameters and loads the register *
\******************************************************************************/
void CLCD_Timing3Set(void)
{
ULONG reg = CLLEDELAY;
if (reg != 0)
{
reg -= 1;
reg |= CLCD_TIMING3_MASK_LEE;
}
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_TIMING3_OFFSET, reg);
}
/******************************************************************************\
* Description: Set up CLCD palette registers *
* Operation: Convert the palatte value from 24bit into 16bits so it can be *
* fit into 32x128 palatte registers in CLCD *
\******************************************************************************/
void DispDrvrSetupPalette(void)
{
UINT i;
/*
** Table has 24-bit RGB, and 256 entries
** CLCD palette is 16-bit, with 2 values in each of 128 entries.
*/
ASSERT(PALETTE_SIZE==256);
for (i = 0; i < 128; i++)
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_PALETTE_OFFSET + i*4,
PALCONV(_rgbIdentity[2*i]) |
(PALCONV(_rgbIdentity[2*i+1]) << 16)) ;
}
/******************************************************************************\
* Description: Initialize CLCD registers *
* Operation: Set up virtual memory to access CLCD registers *
* Call CLCD Powerup rountine to set up registers *
\******************************************************************************/
void DispDrvrInitialize (void)
{
PHYSICAL_ADDRESS PhysicalAddress;
DEBUGMSG( TRUE, (TEXT("MODULE NAME: %s\r\n"),part_name) );
DEBUGMSG( TRUE, (TEXT("MODULE VERSION: %s\r\n"),part_num) );
// RETAILMSG (1,(TEXT("Initializing ARM Color LCD\r\n")));
PhysicalAddress.HighPart = 0;
PhysicalAddress.LowPart = PHYS_CLCD_CNTL_BASE;
v_pDisplayRegs = (P_BYTE) MmMapIoSpace (PhysicalAddress,
SIZE_CLCD_CNTL_REGS, FALSE);
if(v_pDisplayRegs == NULL)
{
ERRORMSG(1,(TEXT("DispDrvrInit: MmMapIoSpace of v_pDisplayRegs failed! (1)\r\n")));
goto error_return;
}
// Make sure that power is off.
Cntrl = READ_REGISTER_ULONG(v_pDisplayRegs + LCD_CONTROL_OFFSET);
if ((Cntrl & LCD_CONTROL_PWR) || (Cntrl & LCD_CONTROL_ENABLE))
{
// Turn the power off
DispPowerOff(FALSE);
}
// Power up the LCD
DispPowerOn(FALSE);
return;
error_return:
if( (v_pDisplayRegs ))
{
MmUnmapIoSpace( (void *) v_pDisplayRegs, SIZE_CLCD_CNTL_REGS );
}
if( v_pSYS_CTRLRegisters )
{
MmUnmapIoSpace( (void *) v_pSYS_CTRLRegisters, SIZE_SYS_CNTL_REGS );
}
return;
}
/******************************************************************************\
* Description: Routine to power on/off the display hardware. *
* Note: This function is usually called in kernel context, and should *
* not make any system calls. So, implement delays as spin loops *
* instead of using Sleep(). *
\******************************************************************************/
void DispDrvrPowerHandler(BOOL bOff)
{
if(bOff)
DispPowerOff(TRUE);
else
DispPowerOn(TRUE);
}
/******************************************************************************\
* Description: CLCD power on routine *
* Operation: This function configures CLCD registers to a working state *
\******************************************************************************/
static void DispPowerOn(BOOL bInPowerHandler)
{
#if 1
ULONG Cntrl_BPP;
Cntrl = READ_REGISTER_ULONG(v_pDisplayRegs + LCD_CONTROL_OFFSET);
switch(DispDrvr_cdwStride * 24 / DispDrvr_cxScreen)
{
case 8:
Cntrl_BPP = LCD_CONTROL_8BPP;
/* when power on, also initiate the palette table registers */
DispDrvrSetupPalette();
break;
case 16:
Cntrl_BPP = LCD_CONTROL_16BPP;
break;
case 24:
Cntrl_BPP = LCD_CONTROL_24BPP;
break;
default:
Cntrl_BPP = LCD_CONTROL_16BPP;
break;
}
//water mark level 16
Cntrl = 0x00030000|
LCD_CONTROL_VCOMP_BACKP |
LCD_CONTROL_TFT |
Cntrl_BPP |
LCD_CONTROL_BEPO ;
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_CONTROL_OFFSET,Cntrl);
// Setup the timing registers
CLCD_Timing0Set();
CLCD_Timing1Set();
CLCD_Timing2Set();
CLCD_Timing3Set();
// Setup the Frame buffer address
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_FRAMBUF_OFFSET,
CLCD_FRAME_BUFFER);
Cntrl = LCD_CONTROL_VCOMP_BACKP |
LCD_CONTROL_TFT |
Cntrl_BPP |
LCD_CONTROL_ENABLE |
LCD_CONTROL_BEPO |
LCD_CONTROL_BGR;
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_CONTROL_OFFSET,Cntrl);
// TRM indicates that some displays must have a delay between power on/off
// and enabling/disabling the LCD peripheral.
// If your display requires such a delay it should be inserted here.
Cntrl |= LCD_CONTROL_PWR;
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_CONTROL_OFFSET,Cntrl);
RETAILMSG( 1,(TEXT("CLCD DispPowerOn\r\n")));
#endif
#if 0
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_CONTROL_OFFSET, LCD_LCDCTRL_CLOSE_VALUE);
// Setup the timing registers
CLCD_Timing0Set();
CLCD_Timing1Set();
CLCD_Timing2Set();
CLCD_Timing3Set();
// Setup the Frame buffer address
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_FRAMBUF_OFFSET,
CLCD_FRAME_BUFFER);
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_CONTROL_OFFSET, LCD_LCDCTRL_OPEN_VALUE);
RETAILMSG( 1,(TEXT("DispPowerOn new\r\n")));
#endif
}
/******************************************************************************\
* Description: CLCD power off routine *
* Operation: This function configures registers to turn off the CLCD *
\******************************************************************************/
static void DispPowerOff(BOOL bInPowerHandler)
{
Cntrl &= ~LCD_CONTROL_PWR;
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_CONTROL_OFFSET, Cntrl);
// TRM indicates that some displays must have a delay between power on/off
// and enabling/disabling the LCD peripheral.
// If your display requires such a delay it should be inserted here.
Cntrl &= ~LCD_CONTROL_ENABLE;
WRITE_REGISTER_ULONG(v_pDisplayRegs + LCD_CONTROL_OFFSET, Cntrl);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -