PXA270下 LCD驱动
一、硬件
1 LCD的分类
主要分2类,主动式的TFT LCD和被动式的STN 和 DSTN。当然它们的制造原理是不同的,但对我们应用工程师来说,最大的区别就是驱动时钟不同。TFT的时钟一直有,数据通讯是通过使能芯片的方式进行的。STN和DSTN的时钟只有在数据通讯的时候才有。
2 我们的系统同时支持TFT和STN、DSTN,硬件上面使用了模拟开关。
其它PCLK,LCLK,VCLK等的接线方式一样。
二、软件
1 Eboot下的驱动
原来的Eboot不支持LCD,我们将PXA270_LCD目录下的dispdrvr.c移植到eboot下。由于此驱动是为WinCE操作系统写的,在Eboot下要做较大的调整
1.1 原来LCD的配置信息在注册表里,Eboot下没有注册表,我们把有关信息保存在 Flash中,修改如下:
BOOL ReadRegistryData()
{
LONG regError;
HKEY hKey;
DWORD dwDataSize;
TCHAR DisplayType[64];
v_pCFG = (PEBOOT_CFG)VirtualAllocCopyPhysical(sizeof(EBOOT_CFG),"DispDrvrInitialize : v_pCFG",(PVOID)(XSBASE270_G_BASE_PA_BOOT_FLASH+IMAGE_BOOT_CONFIG_FLASH_OFFSET));
RETAILMSG(1, (TEXT("Type:%d"r"n"),v_pCFG->dwDisplayType));
nDisplayType=v_pCFG->dwDisplayType;
switch(nDisplayType)
{
case NANYALM702:
DispDrvr_cxScreen=640;
DispDrvr_cyScreen=480;
bpp=8;
break;
case AU104:
DispDrvr_cxScreen=800;
DispDrvr_cyScreen=600;
bpp=16;
break;
default:
case VLFSDD320240:
DispDrvr_cxScreen=320;
DispDrvr_cyScreen=240;
bpp=8;
break;
}
// bDoRotation is used to indicate whether or not a rotation of the frame buffer
// is required in order to orient it correctly for the target display.
bDoRotation = FALSE;
switch (nDisplayType)
{
case LTM04C380K: // native landscape 640x480
case LM8V31: // native landscape 640x480
case VLFSDD320240: // native landscape 320x240
case NANYALM702: // native landscape 640x480
if (DispDrvr_cxScreen < DispDrvr_cyScreen)
{
bDoRotation = TRUE;
}
break;
case LQ64D341: // native portrait, 176x220
case LTM035A776C: // native portrait, 240x320
if (DispDrvr_cxScreen > DispDrvr_cyScreen)
{
bDoRotation = TRUE;
}
break;
default:
break;
}
// Calculate the stride of the frame buffer
DispDrvr_cdwStride = DispDrvr_cxScreen * bpp / 8;
return (TRUE);
}
1.2 指定LCD Buffer,配置LCD控制寄存器
BOOL MapVirtualAddress()
{
g_DisplayBaseVirtual =(DWORD)OALPAtoVA(0xA3A80000, FALSE);
g_DisplayBasePhysical=(DWORD)(0xA3A80000);
v_pDMAC = (P_XLLP_DMAC_T)OALPAtoVA(BULVERDE_BASE_REG_PA_DMAC, FALSE);
if (!v_pDMAC)
{
Cleanup();
return FALSE;
}
v_pI2C = (volatile unsigned int *)OALPAtoVA(BULVERDE_BASE_REG_PA_I2C, FALSE);
if (!v_pI2C)
{
Cleanup();
return FALSE;
}
v_pOSTRegs = (volatile unsigned int *)OALPAtoVA(BULVERDE_BASE_REG_PA_OST, FALSE);
if (!v_pOSTRegs)
{
Cleanup();
return FALSE;
}
v_pLcdRegs = (volatile LCDRegs *)OALPAtoVA(BULVERDE_BASE_REG_PA_LCD, FALSE);
if (!v_pLcdRegs)
{
Cleanup();
return FALSE;
}
v_pClkRegs = (volatile XLLP_CLKMGR_T *)OALPAtoVA(BULVERDE_BASE_REG_PA_CLKMGR, FALSE);
if (!v_pClkRegs)
{
Cleanup();
return FALSE;
}
v_pGPIORegs = (volatile XLLP_GPIO_T *)OALPAtoVA(BULVERDE_BASE_REG_PA_GPIO, FALSE);
if (!v_pGPIORegs)
{
Cleanup();
return FALSE;
}
v_pCPLDRegs = (volatile XSBASE270_G_CPLD_REGS *)OALPAtoVA(XSBASE270_G_BASE_REG_PA_CPLD, FALSE);
if (!v_pCPLDRegs)
{
Cleanup();
return FALSE;
}
frameDescriptorCh0fd1 = (volatile LCD_FRAME_DESCRIPTOR *)(DMA_CHANNEL_0_FRAME_DESCRIPTOR_BASE_VIRTUAL);
frameDescriptorCh0fd2 = (volatile LCD_FRAME_DESCRIPTOR *)(DMA_CHANNEL_0_ALT_FRAME_DESCRIPTOR_BASE_VIRTUAL);
frameDescriptorCh1 = (volatile LCD_FRAME_DESCRIPTOR *)(DMA_CHANNEL_1_FRAME_DESCRIPTOR_BASE_VIRTUAL);
frameDescriptorPalette = (volatile LCD_FRAME_DESCRIPTOR *)(PALETTE_FRAME_DESCRIPTOR_BASE_VIRTUAL);
v_pPaletteBuffer = (volatile LCD_PALETTE *)(PALETTE_BUFFER_BASE_VIRTUAL);
gFrameBuffer =(PBYTE)FRAME_BUFFER_0_BASE_VIRTUAL;// (PBYTE)OALPAtoVA(FRAME_BUFFER_0_BASE_PHYSICAL, FALSE);
if (!gFrameBuffer)
{
Cleanup();
return FALSE;
}
return TRUE;
}
1.3 加入LCD 测试代码
void lcd_test()
{
DWORD i,j;
int color = 0;
unsigned int DispDrvr_cxScreen,DispDrvr_cyScreen;
// DWORD rmask=0xF800F800, gmask=0x07E007E0, bmask = 0x001F001F;
// DWORD rmask=0x88888888, gmask=0x66666666, bmask = 0x33333333;
DWORD bmask[] ={0x00000000,0x00010001,0x00030003,0x00070007,0x000F000F,0x001F001F};
BYTE r = 0x7F, g = 0x7F , b = 0x7F;
UINT32 CurrTime,PreTime=0;
unsigned * fbp = (unsigned *)gFrameBuffer + (activeFrameBuffer * frameBufferSize);
DisplayLightConvert((unsigned char)(g_EbootCFG.dwContrast)*(255/9));
// EdbgOutputDebugString("DispDrvr_cxScreen=%d,DispDrvr_cyScreen=%d"r"n",DispDrvr_cxScreen,DispDrvr_cyScreen);
// for(j=0;j<10;j++)
// {
// CurrTime = OEMEthGetSecs();
// if(CurrTime>PreTime+2)
// {
// PreTime=CurrTime;
// color++;
// if(color>1)
// color=0;
// r=0;
// g=0;
// b=0;
// fbp = (unsigned *)gFrameBuffer + (activeFrameBuffer * frameBufferSize);
// EdbgOutputDebugString("fbp=%d"n",fbp);
// }
// else
// continue;
// for(i=0;i<15;i++)
// {
// DisplayOneChar(F8X14DotsTbl['A'+i],0,i);
// }
//
// DisplayString("Welcome to RTPO MTCN",10,7);
// }
fbp = (unsigned *)gFrameBuffer + (activeFrameBuffer * frameBufferSize);
DisplayLogo(fbp,GetDisplayType());
GetDispalyXY(&DispDrvr_cxScreen,&DispDrvr_cyScreen);
if(DispDrvr_cxScreen>MAX_BMP_WIDTH)
return;
if(DispDrvr_cyScreen>MAX_BMP_HEIGHT)
return;
DisplayVersion();
fbp = (unsigned *)gFrameBuffer + (activeFrameBuffer * frameBufferSize);
ProgressBar_Init(fbp,DispDrvr_cxScreen/6,DispDrvr_cyScreen*3/4,DispDrvr_cxScreen*4/6,DispDrvr_cxScreen/12,DispDrvr_cxScreen);
}
2 WinCE下LCD的修改
2.1 LCD的配置信息原来从注册表,现在从Flash中读取
这和eboot一样,修改BOOL ReadRegistryData()函数。
2.2 加入对黑白灰度屏的支持
void DispDrvrSetPalette (const PALETTEENTRY source[],unsigned short firstEntry,unsigned short numEntries)
{
int i;
int end = firstEntry + numEntries;
#if 0
// Don't walk off the end of the palette buffer.
if (firstEntry > sizeof(source) || end >= sizeof(source))
{
return;
}
#endif
EnterCriticalSection(&frameDescriptorMutex);
RETAILMSG(1,(TEXT("DispDrvrSetPalette: firstEntry=%d, numEntries=%d"r"n"), firstEntry, numEntries));
if( (VLFSDD320240 == XllpLCD.DisplayType || NANYALM702 == XllpLCD.DisplayType) && 256 == numEntries)
{
// store 256 gray-scale palette data
// Y = 0.3*R + 0.59*G + 0.11*B
for(i = 0; i < 256; i++)
{
v_pPaletteBuffer->palette[i] = (30 * source[i].peRed + 59 * source[i].peGreen + 11 * source[i].peBlue) / 100;
}
v_pPaletteBuffer->palette[0] = 0;
}
else
{
// Store the palette entries into palette ram
for(i=firstEntry;i<end;i++)
{
// store 5 bits red, 6 bits green, and 5 bits blue
v_pPaletteBuffer->palette[i] = (
(source[i].peBlue) >> 3 |
((source[i].peGreen & 0xfc) << 3) |
((source[i].peRed & 0xf8) << 8)
);
}
}
XllpLCDLoadPalette(&XllpLCD);
LeaveCriticalSection(&frameDescriptorMutex);
}
2.3 增加显示屏的类型
void LCDInitController(P_XLLP_LCD_T pXllpLCD)
{
int i = 0;
int BPP = 0;
int PCD = 0;
unsigned int CCCR_L = 0;
volatile LCDRegs *p_LCDRegs;
volatile XLLP_CLKMGR_T *p_CLKRegs;
volatile XLLP_SSPREGS_T *p_SSPRegs;
volatile XLLP_GPIO_T *p_GPIORegs;
XLLP_OST_T *p_OSTRegs;
int LCLK = 0;
XLLP_UINT32_T LockID;
XLLP_UINT32_T LockID2;
p_LCDRegs = (LCDRegs *) pXllpLCD->LCDC;
p_CLKRegs = (XLLP_CLKMGR_T *) pXllpLCD->CLKMan;
p_GPIORegs = (XLLP_GPIO_T *) pXllpLCD->GPIO;
p_OSTRegs = (XLLP_OST_T *) pXllpLCD->OST;
p_SSPRegs = (XLLP_SSPREGS_T *) pXllpLCD->SSP;
p_LCDRegs->LCCR0 = 0;
p_LCDRegs->LCCR1 = 0;
p_LCDRegs->LCCR2 = 0;
p_LCDRegs->LCCR3 = 0;
p_LCDRegs->LCCR4 = 0;
p_LCDRegs->LCCR5 = (LCD_SOFM1|LCD_SOFM2|LCD_SOFM3|LCD_SOFM4|LCD_SOFM5|LCD_SOFM6|
LCD_EOFM1|LCD_EOFM2|LCD_EOFM3|LCD_EOFM4|LCD_EOFM5|LCD_EOFM6|
LCD_BSM1 |LCD_BSM2 |LCD_BSM3 |LCD_BSM4 |LCD_BSM5 |LCD_BSM6 |
LCD_IUM1 |LCD_IUM2 |LCD_IUM3 |LCD_IUM4 |LCD_IUM5 |LCD_IUM6 );
// Determine the frame buffer size for the DMA transfer length.
// Scale the size based on the bpp of the frame buffer to determine
// an actual size in bytes
pXllpLCD->FrameBufferSize = pXllpLCD->FrameBufferWidth * pXllpLCD->FrameBufferHeight;
switch (pXllpLCD->BPP)
{
case BPP_1:
pXllpLCD->FrameBufferSize >>= 3;
pXllpLCD->PaletteSize = 8;
break;
case BPP_2:
pXllpLCD->FrameBufferSize >>= 2;
pXllpLCD->PaletteSize = 8;
break;
case BPP_4:
pXllpLCD->FrameBufferSize >>= 1;
pXllpLCD->PaletteSize = 32;
break;
case BPP_8:
pXllpLCD->PaletteSize = 512;
break;
case BPP_16:
pXllpLCD->FrameBufferSize <<= 1;
break;
case BPP_18: /* Fall through */
case BPP_18_PACKED:
case BPP_19:
case BPP_19_PACKED:
case BPP_24:
case BPP_25:
pXllpLCD->FrameBufferSize <<= 2;
break;
default:
break;
}
// Enable the LCD and SRAM clocks
LockID = XllpLock(CKEN);
p_CLKRegs->cken = (p_CLKRegs->cken & XLLP_CLKEN_MASK) | CLK_LCD | CLK_SRAM;
XllpUnlock(LockID);
// Configure the general purpose frame descriptors
// Set the physical address of the frame descriptor
pXllpLCD->frameDescriptorCh0fd1->FDADR = LCD_FDADR(pXllpLCD->_DMA_CHANNEL_0_FRAME_DESCRIPTOR_BASE_PHYSICAL);
// Set the physical address of the frame buffer
pXllpLCD->frameDescriptorCh0fd1->FSADR = LCD_FSADR(pXllpLCD->_FRAME_BUFFER_BASE_PHYSICAL + pXllpLCD->CurrentPage*pXllpLCD->FrameBufferSize);
// Clear the frame ID
pXllpLCD->frameDescriptorCh0fd1->FIDR = LCD_FIDR(0);
// Set the DMA transfer length to the size of the frame buffer
pXllpLCD->frameDescriptorCh0fd1->LDCMD = LCD_Len(pXllpLCD->FrameBufferSize);
// Store the physical address of this frame descriptor in the frame descriptor
pXllpLCD->frameDescriptorCh0fd1->PHYSADDR = pXllpLCD->frameDescriptorCh0fd1->FDADR;
// frameDescriptorCh0fd2 is used only if a palette load is performed.
// Set the physical address of the frame descriptor
pXllpLCD->frameDescriptorCh0fd2->FDADR = LCD_FDADR(pXllpLCD->_DMA_CHANNEL_0_ALT_FRAME_DESCRIPTOR_BASE_PHYSICAL);
// Set the physical address of the frame buffer
pXllpLCD->frameDescriptorCh0fd2->FSADR = LCD_FSADR(pXllpLCD->_FRAME_BUFFER_BASE_PHYSICAL + pXllpLCD->CurrentPage*pXllpLCD->FrameBufferSize);
// Clear the frame ID
pXllpLCD->frameDescriptorCh0fd2->FIDR = LCD_FIDR(0);
// Set the DMA transfer length to the size of the frame buffer
pXllpLCD->frameDescriptorCh0fd2->LDCMD = LCD_Len(pXllpLCD->FrameBufferSize);
// Store the physical address of this frame descriptor in the frame descriptor
pXllpLCD->frameDescriptorCh0fd2->PHYSADDR = pXllpLCD->frameDescriptorCh0fd2->FDADR;
// FBR0 is cleared and is not used.
p_LCDRegs->FBR0 = 0;
// Load the contents of FDADR0 with the physical address of this frame descriptor
p_LCDRegs->FDADR0 = LCD_FDADR(pXllpLCD->frameDescriptorCh0fd1->FDADR);
// Determine the LCLK frequency programmed into the CCCR.
// This value will be used to calculate a Pixel Clock Divisor (PCD)
// for a given display type.
CCCR_L = (p_CLKRegs->cccr & 0x0000001F);
if (CCCR_L < 8) // L = [2 - 7]
LCLK = (13 * CCCR_L) * 100;
else if (CCCR_L < 17) // L = [8 - 16]
LCLK = ((13 * CCCR_L) * 100) >> 1;
else if (CCCR_L < 32) // L = [17 - 31]
LCLK = ((13 * CCCR_L) * 100) >> 2;
// Convert the bpp setting into a value that the LCD controller understands.
switch(pXllpLCD->BPP)
{
case BPP_1:
BPP = 0;
break;
case BPP_2:
BPP = 1;
break;
case BPP_4:
BPP = 2;
break;
case BPP_8:
BPP = 3;
break;
case BPP_16:
BPP = 4;
break;
case BPP_18:
BPP = 5;
break;
case BPP_18_PACKED:
BPP = 6;
break;
case BPP_19:
BPP = 7;
break;
case BPP_19_PACKED:
BPP = 8;
break;
case BPP_24:
BPP = 9;
break;
case BPP_25:
BPP = 10;
break;
default:
{
BPP = 0;
break;
}
}
switch(pXllpLCD->DisplayType)
{
case NANYALM702: // 640x480x8 landscape
{
//
// The actual equation requires that we take the ceiling of a floating point result.
// Rather than use floats, we'll calculate an approximation to the correct PCD value
// using integers.
//
PCD = (LCLK / (2 * NANYALM702_PCLOCK_FREQUENCY));
RETAILMSG(1,(TEXT("NANYA-LM-702: LCLK=%d, L_PCLK=%d KHz, PCD=%d"r"n"), LCLK, NANYALM702_PCLOCK_FREQUENCY*10, PCD));
// Reconfigure the upper panel frame descriptors for dual panel operation by
// setting the DMA transfer length to half the size of the frame buffer
pXllpLCD->frameDescriptorCh0fd1->LDCMD = pXllpLCD->FrameBufferSize >> 1;
pXllpLCD->frameDescriptorCh0fd2->LDCMD = pXllpLCD->FrameBufferSize >> 1;
// Configure the lower panel frame descriptor for dual panel operation.
// Set the physical address of the frame descriptor
pXllpLCD->frameDescriptorCh1->FDADR = LCD_FDADR(pXllpLCD->_DMA_CHANNEL_1_FRAME_DESCRIPTOR_BASE_PHYSICAL);
// Set the physical address of the frame buffer
pXllpLCD->frameDescriptorCh1->FSADR = LCD_FSADR(pXllpLCD->_FRAME_BUFFER_BASE_PHYSICAL + pXllpLCD->CurrentPage*pXllpLCD->FrameBufferSize + (pXllpLCD->FrameBufferSize >> 1));
// Clear the frame ID
pXllpLCD->frameDescriptorCh1->FIDR = LCD_FIDR(0);
// Set the DMA transfer length to half the size of the frame buffer
pXllpLCD->frameDescriptorCh1->LDCMD = LCD_Len(pXllpLCD->FrameBufferSize >> 1);
// Store the physical address of this frame descriptor in the frame descriptor
pXllpLCD->frameDescriptorCh1->PHYSADDR = pXllpLCD->frameDescriptorCh1->FDADR;
// FBR1 is cleared and is not used in this implementation
p_LCDRegs->FBR1 = 0;
// Load the contents of FDADR1 with the physical address of this frame descriptor
p_LCDRegs->FDADR1 = pXllpLCD->frameDescriptorCh1->FDADR;
// Configure the TMED dithering engine
// Use the magic number described in the EAS, 0x00AA5500;
p_LCDRegs->TRGBR = LCD_TRS(0x00) | LCD_TGS(0x55) | LCD_TBS(0xAA);
// Use the magic number described in the EAS, 0x0000754F;
p_LCDRegs->TCR = LCD_TM2S | LCD_TM1S | LCD_TM2En | LCD_TM1En |
LCD_TVBS(0x04) | LCD_THBS(0x05)| LCD_TSCS(0x03)|
LCD_TED;
p_LCDRegs->LCCR0 = (LCD_SDS | LCD_LDM | LCD_SFM | LCD_IUM |
LCD_CMS |LCD_EFM | LCD_PDD(0x01) | LCD_BM);
p_LCDRegs->LCCR1 = (LCD_PPL(639) | LCD_HSW(0x02) |
LCD_ELW(0x03) | LCD_BLW(0x03) );
//p_LCDRegs->LCCR2 = (LCD_LPP(479) | LCD_VSW(0x01) |
// LCD_EFW(0x00) | LCD_BFW(0x00) );
p_LCDRegs->LCCR2 = (LCD_LPP(239) | LCD_VSW(0x01) | // cqz 2009-2-23 16:35
LCD_EFW(0x00) | LCD_BFW(0x0) );
p_LCDRegs->LCCR3 = (LCD_PCD(PCD) | LCD_ACB(0xff) |
LCD_PCP | LCD_BPP(BPP) |
LCD_PDFOR(pXllpLCD->PixelDataFormat));
p_LCDRegs->LCCR4 = LCD_PAL_FOR(0);
if ( (p_LCDRegs->OVL1C1 & LCD_O1EN) || (p_LCDRegs->OVL2C1 & LCD_O2EN))
{
p_LCDRegs->LCCR4 = LCD_PAL_FOR(1);
}
}
break;
case VLFSDD320240: // 320x240x8 bpp passive monochrome matrix
{
//
// The actual equation requires that we take the ceiling of a floating point result.
// Rather than use floats, we'll calculate an approximation to the correct PCD value
// using integers.
//
PCD = (LCLK / (2 * VLFSDD320240_PCLOCK_FREQUENCY));
RETAILMSG(1,(TEXT("VL-FS-DD320240-01: LCLK=%d, L_PCLK=%d KHz, PCD=%d"r"n"), LCLK, VLFSDD320240_PCLOCK_FREQUENCY*10, PCD));
// Configure the TMED dithering engine
// Use the magic number described in the EAS, 0x00AA5500;
p_LCDRegs->TRGBR = LCD_TRS(0x00) | LCD_TGS(0x55) | LCD_TBS(0xAA);
// Use the magic number described in the EAS, 0x0000754F;
p_LCDRegs->TCR = LCD_TM2S | LCD_TM1S | LCD_TM2En | LCD_TM1En |
LCD_TVBS(0x04) | LCD_THBS(0x05) | LCD_TSCS(0x03) |
LCD_TED;
// Configure the LCD Controller Control Registers
p_LCDRegs->LCCR0 = (LCD_LDM | LCD_SFM | LCD_IUM | LCD_EFM |
LCD_CMS | LCD_QDM | LCD_BM | LCD_OUM );
p_LCDRegs->LCCR1 = (LCD_PPL(0x13F) | LCD_HSW(0x02) |
LCD_ELW(0x03) | LCD_BLW(0x3) );
p_LCDRegs->LCCR2 = (LCD_LPP(0xEF) | LCD_VSW(0x05) |
LCD_EFW(0x00) | LCD_BFW(0x0) );
p_LCDRegs->LCCR3 = (LCD_PCD(PCD) | LCD_BPP(BPP) | LCD_ACB(0x10) |
LCD_PCP | LCD_PDFOR(pXllpLCD->PixelDataFormat));
p_LCDRegs->LCCR4 = LCD_PAL_FOR(0);
if ( (p_LCDRegs->OVL1C1 & LCD_O1EN) || (p_LCDRegs->OVL2C1 & LCD_O2EN))
{
p_LCDRegs->LCCR4 = LCD_PAL_FOR(1);
}
}
break;
case LTM04C380K: // 640x480 16bpp active matrix
{
//
// The actual equation requires that we take the ceiling of a floating point result.
// Rather than use floats, we'll calculate an approximation to the correct PCD value
// using integers.
//
//PCD = (LCLK / (2 * LTM04C380K_PIXEL_CLOCK_FREQUENCY));
PCD = 1; //Modify by Terry for freq
// Configure the LCD Controller Control Registers
p_LCDRegs->LCCR0 = (LCD_LDM | LCD_SFM | LCD_IUM | LCD_EFM |
LCD_PAS | LCD_QDM | LCD_BM | LCD_OUM |
LCD_RDSTM | LCD_CMDIM | LCD_OUC | LCD_LDDALT);
p_LCDRegs->LCCR1 = (LCD_PPL(0x27FU) | LCD_HSW(0x3f) |
LCD_ELW(0x21) | LCD_BLW(0x50U) ); //Modufy by Terry@2005-2-5 LCD_BLW(0x9fU)
p_LCDRegs->LCCR2 = (LCD_LPP(0x1df) | LCD_VSW(0x0) | //Modufy by Terry@2005-2-23 LCD_VFW(0x02)
LCD_EFW(0x00) | LCD_BFW(0x20) ); //Modufy by Terry@2005-2-23 LCD_BFW(0x00)
p_LCDRegs->LCCR3 = (LCD_PCD(PCD) | LCD_BPP(BPP) | LCD_PCP |
LCD_PDFOR(pXllpLCD->PixelDataFormat));
p_LCDRegs->LCCR4 = LCD_PAL_FOR(0);
if ( (p_LCDRegs->OVL1C1 & LCD_O1EN) || (p_LCDRegs->OVL2C1 & LCD_O2EN))
{
p_LCDRegs->LCCR4 = LCD_PAL_FOR(1);
}
}
break;
case AU104: // 800X600 SVGA TFT
{//2009-2-26 10:03 Bruce
//
// The actual equation requires that we take the ceiling of a floating point result.
// Rather than use floats, we'll calculate an approximation to the correct PCD value
// using integers.
//
//PCD = (LCLK / (2 * LTM04C380K_PIXEL_CLOCK_FREQUENCY));
PCD = 1; //25MHz
// Configure the LCD Controller Control Registers
p_LCDRegs->LCCR0 = (LCD_LDM | LCD_SFM | LCD_IUM | LCD_EFM |
LCD_PAS | LCD_QDM | LCD_BM | LCD_OUM |
LCD_RDSTM | LCD_CMDIM | LCD_OUC | LCD_LDDALT);
p_LCDRegs->LCCR1 = (LCD_PPL(799) | LCD_HSW(0x04) |
LCD_ELW(0x17) | LCD_BLW(0x18) ); //Modufy by Terry@2005-2-5 LCD_BLW(0x9fU)
p_LCDRegs->LCCR2 = (LCD_LPP(599) | LCD_VSW(0x02) | //Modufy by Terry@2005-2-23 LCD_VFW(0x02)
LCD_EFW(0x01) | LCD_BFW(0x03) ); //Modufy by Terry@2005-2-23 LCD_BFW(0x00)
p_LCDRegs->LCCR3 = (LCD_PCD(PCD) | LCD_BPP(BPP) | LCD_PCP |
LCD_PDFOR(pXllpLCD->PixelDataFormat));
p_LCDRegs->LCCR4 = LCD_PAL_FOR(0);
if ( (p_LCDRegs->OVL1C1 & LCD_O1EN) || (p_LCDRegs->OVL2C1 & LCD_O2EN))
{
p_LCDRegs->LCCR4 = LCD_PAL_FOR(1);
}
}
break;
case LTM035A776C: // 240x320 16bpp active matrix
{
//
// The actual equation requires that we take the ceiling of a floating point result.
// Rather than use floats, we'll calculate an approximation to the correct PCD value
// using integers.
//
PCD = (LCLK / (2 * LTM035A776C_PIXEL_CLOCK_FREQUENCY));
// Configure the LCD Controller Control Registers
p_LCDRegs->LCCR0 = (LCD_LDM | LCD_SFM | LCD_IUM | LCD_EFM |
LCD_PAS | LCD_QDM | LCD_BM | LCD_OUM |
LCD_RDSTM | LCD_CMDIM | LCD_OUC | LCD_LDDALT);
p_LCDRegs->LCCR1 = (LCD_PPL(0xEF) | LCD_HSW(0x04) |
LCD_ELW(0x04) | LCD_BLW(0x05) );
p_LCDRegs->LCCR2 = (LCD_LPP(0x13f) | LCD_VSW(0x02) |
LCD_EFW(0x03) | LCD_BFW(0x02) );
p_LCDRegs->LCCR3 = (LCD_PCD(PCD) | LCD_BPP(BPP) | LCD_PCP | LCD_HSP |
LCD_PDFOR(pXllpLCD->PixelDataFormat));
p_LCDRegs->LCCR4 = LCD_PAL_FOR(0);
if ( (p_LCDRegs->OVL1C1 & LCD_O1EN) || (p_LCDRegs->OVL2C1 & LCD_O2EN))
{
p_LCDRegs->LCCR4 = LCD_PAL_FOR(1);
}
}
break;
case LM8V31: // 640x480 16bpp dual panel passive
{
//
// The actual equation requires that we take the ceiling of a floating point result.
// Rather than use floats, we'll calculate an approximation to the correct PCD value
// using integers.
//
PCD = (LCLK / (2 * LM8V31_PIXEL_CLOCK_FREQUENCY));
// Reconfigure the upper panel frame descriptors for dual panel operation by
// setting the DMA transfer length to half the size of the frame buffer
pXllpLCD->frameDescriptorCh0fd1->LDCMD = pXllpLCD->FrameBufferSize >> 1;
pXllpLCD->frameDescriptorCh0fd2->LDCMD = pXllpLCD->FrameBufferSize >> 1;
// Configure the lower panel frame descriptor for dual panel operation.
// Set the physical address of the frame descriptor
pXllpLCD->frameDescriptorCh1->FDADR = LCD_FDADR(pXllpLCD->_DMA_CHANNEL_1_FRAME_DESCRIPTOR_BASE_PHYSICAL);
// Set the physical address of the frame buffer
pXllpLCD->frameDescriptorCh1->FSADR = LCD_FSADR(pXllpLCD->_FRAME_BUFFER_BASE_PHYSICAL + pXllpLCD->CurrentPage*pXllpLCD->FrameBufferSize + (pXllpLCD->FrameBufferSize >> 1));
// Clear the frame ID
pXllpLCD->frameDescriptorCh1->FIDR = LCD_FIDR(0);
// Set the DMA transfer length to half the size of the frame buffer
pXllpLCD->frameDescriptorCh1->LDCMD = LCD_Len(pXllpLCD->FrameBufferSize >> 1);
// Store the physical address of this frame descriptor in the frame descriptor
pXllpLCD->frameDescriptorCh1->PHYSADDR = pXllpLCD->frameDescriptorCh1->FDADR;
// FBR1 is cleared and is not used in this implementation
p_LCDRegs->FBR1 = 0;
// Load the contents of FDADR1 with the physical address of this frame descriptor
p_LCDRegs->FDADR1 = pXllpLCD->frameDescriptorCh1->FDADR;
// Configure the TMED dithering engine
// Use the magic number described in the EAS, 0x00AA5500;
p_LCDRegs->TRGBR = LCD_TRS(0x00) | LCD_TGS(0x55) | LCD_TBS(0xAA);
// Use the magic number described in the EAS, 0x0000754F;
p_LCDRegs->TCR = LCD_TM2S | LCD_TM1S | LCD_TM2En | LCD_TM1En |
LCD_TVBS(0x04) | LCD_THBS(0x05) | LCD_TSCS(0x03) |
LCD_TED;
p_LCDRegs->LCCR0 = (LCD_SDS | LCD_LDM | LCD_SFM | LCD_IUM |
LCD_EFM | LCD_PDD(0x01) | LCD_BM |
LCD_RDSTM | LCD_CMDIM | LCD_OUC | LCD_LDDALT);
p_LCDRegs->LCCR1 = (LCD_PPL(0x27F) | LCD_HSW(0x02) |
LCD_ELW(0x03) | LCD_BLW(0x03) );
p_LCDRegs->LCCR2 = (LCD_LPP(0xef) | LCD_VSW(0x01) |
LCD_EFW(0x00) | LCD_BFW(0x00) );
p_LCDRegs->LCCR3 = (LCD_PCD(PCD) | LCD_ACB(0xff) |
LCD_PCP | LCD_BPP(BPP) |
LCD_PDFOR(pXllpLCD->PixelDataFormat));
p_LCDRegs->LCCR4 = LCD_PAL_FOR(0);
if ( (p_LCDRegs->OVL1C1 & LCD_O1EN) || (p_LCDRegs->OVL2C1 & LCD_O2EN))
{
p_LCDRegs->LCCR4 = LCD_PAL_FOR(1);
}
}
break;
case LQ64D341: // 176x220 active matrix Stinger display
{
//
// The actual equation requires that we take the ceiling of a floating point result.
// Rather than use floats, we'll calculate an approximation to the correct PCD value
// using integers.
//
PCD = (LCLK / (2 * LQ64D341_PIXEL_CLOCK_FREQUENCY));
p_LCDRegs->LCCR0 = ( LCD_LDM | LCD_SFM | LCD_IUM |
LCD_EFM | LCD_PAS | LCD_BM |
LCD_RDSTM | LCD_CMDIM | LCD_OUC | LCD_LDDALT);
p_LCDRegs->LCCR1 = ( LCD_PPL(0xAF) | LCD_HSW(0x02) |
LCD_ELW(0x7B) | LCD_BLW(0x03) );
p_LCDRegs->LCCR2 = ( LCD_LPP(0xdb) | LCD_VSW(0x01) |
LCD_EFW(0x02) | LCD_BFW(0x00) );
p_LCDRegs->LCCR3 = ( LCD_PCD(PCD) | LCD_BPP(BPP) |
LCD_VSP | LCD_HSP | LCD_PCP |
LCD_OEP | LCD_PDFOR(pXllpLCD->PixelDataFormat));
p_LCDRegs->LCCR4 = LCD_PAL_FOR(0);
if ( (p_LCDRegs->OVL1C1 & LCD_O1EN) || (p_LCDRegs->OVL2C1 & LCD_O2EN))
{
p_LCDRegs->LCCR4 = LCD_PAL_FOR(1);
}
}
break;
case LS022Q8DD06: // Sharp LS022Q8DD06 Sharp 240 x 320 for ZOAR
{
//
// The actual equation requires that we take the ceiling of a floating point result.
// Rather than use floats, we'll calculate an approximation to the correct PCD value
// using integers.
//
PCD = (LCLK / (2 * LS022Q8DD06_PIXEL_CLOCK_FREQUENCY));
// Configure the LCD Controller Control Registers
p_LCDRegs->LCCR0 = (LCD_LDM | LCD_SFM | LCD_IUM | LCD_EFM |
LCD_PAS | LCD_QDM | LCD_BM | LCD_OUM |
LCD_RDSTM | LCD_CMDIM | LCD_OUC | LCD_LDDALT);
p_LCDRegs->LCCR1 = (LCD_PPL(0xEF) | LCD_HSW(0x01) |
LCD_ELW(0x00) | LCD_BLW(0x07) );
p_LCDRegs->LCCR2 = (LCD_LPP(0x13f) | LCD_VSW(0x02) |
LCD_EFW(0x02) | LCD_BFW(0x00) );
p_LCDRegs->LCCR3 = (LCD_PCD(PCD) | LCD_BPP(BPP) | LCD_PCP |
LCD_PDFOR(pXllpLCD->PixelDataFormat));
p_LCDRegs->LCCR4 = LCD_PAL_FOR(0);
if ( (p_LCDRegs->OVL1C1 & LCD_O1EN) || (p_LCDRegs->OVL2C1 & LCD_O2EN))
{
p_LCDRegs->LCCR4 = LCD_PAL_FOR(1);
}
LockID = XllpLock(CKEN);
p_CLKRegs->cken = (p_CLKRegs->cken & XLLP_CLKEN_MASK) | CLK_SSP3;
XllpUnlock(LockID);
// Assert chip select on the LCD
LockID = XllpLock(GPCR2);
LockID2 = XllpLock(GPSR2);
p_GPIORegs->GPCR2 &= ~XLLP_GPIO_BIT_L_BIAS;
p_GPIORegs->GPSR2 |= XLLP_GPIO_BIT_L_BIAS;
XllpOstDelayMilliSeconds(p_OSTRegs, 1);
p_SSPRegs->sscr0 = 0x00C01030;
p_SSPRegs->sscr1 = 0x00008000;
p_SSPRegs->sspsp = 0x0025000C;
p_SSPRegs->sscr0 |= 0x8F;
// Wait for the operation to complete
while(p_SSPRegs->sssr & 0x10);
for (i = 0; i < sizeof(LS022Q8DD06_DATA_SET_1) >> 1; i+=2)
{
p_GPIORegs->GPCR2 &= ~XLLP_GPIO_BIT_L_BIAS;
p_GPIORegs->GPSR2 |= XLLP_GPIO_BIT_L_BIAS;
p_SSPRegs->ssdr = LS022Q8DD06_DATA_SET_1[i];
p_SSPRegs->ssdr = LS022Q8DD06_DATA_SET_1[i+1];
// Wait for the operation to complete
while(p_SSPRegs->sssr & 0x10);
XllpOstDelayMicroSeconds(p_OSTRegs, 50);
p_GPIORegs->GPSR2 &= ~XLLP_GPIO_BIT_L_BIAS;
p_GPIORegs->GPCR2 |= XLLP_GPIO_BIT_L_BIAS;
XllpOstDelayMilliSeconds(p_OSTRegs, 100);
}
for (i = 0; i < sizeof(LS022Q8DD06_DATA_SET_2) >> 1; i+=2)
{
p_GPIORegs->GPCR2 &= ~XLLP_GPIO_BIT_L_BIAS;
p_GPIORegs->GPSR2 |= XLLP_GPIO_BIT_L_BIAS;
p_SSPRegs->ssdr = LS022Q8DD06_DATA_SET_2[i];
p_SSPRegs->ssdr = LS022Q8DD06_DATA_SET_2[i+1];
// Wait for the operation to complete
while(p_SSPRegs->sssr & 0x10);
XllpOstDelayMicroSeconds(p_OSTRegs, 50);
p_GPIORegs->GPSR2 &= ~XLLP_GPIO_BIT_L_BIAS;
p_GPIORegs->GPCR2 |= XLLP_GPIO_BIT_L_BIAS;
XllpOstDelayMilliSeconds(p_OSTRegs, 100);
}
// De-assert chip select on the LCD
p_GPIORegs->GPSR2 &= ~XLLP_GPIO_BIT_L_BIAS;
p_GPIORegs->GPCR2 |= XLLP_GPIO_BIT_L_BIAS;
XllpUnlock(LockID);
XllpUnlock(LockID2);
}
break;
default:
{
}
break;
}
}
2.4
posted on 2009-07-03 10:41 常州市润邦电子科技 阅读(2375) 评论(1) 编辑 收藏 举报