📄 s3c2410disp.cpp
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 2001. Samsung Electronics, co. ltd All rights reserved.
Module Name:
Abstract:
This file implements the S3C2410 LCD function
rev:
2002.4.4 : First S3C2410 version (kwangyoon LEE, kwangyoon@samsung.com)
2002.1.31 : CE.NET port (kwangyoon LEE, kwangyoon@samsung.com)
Notes:
--*/
#include "precomp.h"
#ifdef CLEARTYPE
#include <ctblt.h>
#endif
#include <aablt.h>
DWORD gdwLCDVirtualFrameBase;
/**********************************************************************************************************
Description: There are five places in this file modified from display driver
in SMDK2410 BSP for using Chrontel Chip, these modified places
have been marked with following:
CHANGE(1)
CHANGE(2)
CHANGE(3)
CHANGE(4)
CHANGE(5)
Modified: 2007-5-15 By JUNFENG WANG
2007-6-25 By JUNFENG WANG
***********************************************************************************************************/
//****************************************** CHANGE(1) BEGIN *********************************************//
I2C g_i2c(CH7025_ADDR); //I2C object to operate IIC
UART g_uart; //UART object to operate UART
CHIP_TYPE g_ChipType=CHIP_NUMBER; //Chrontel Chip type flap variable
//Gate of IIC test:
//#define IIC_TEST_MODE
//CH7023/CH7024 timing define: //clkdiv, HA, HFP, FBP, HW, VA, VFP, VBP, VW
TIMING CH7023_OUTPUT_TIMING = { 6, 320, 54, 40, 10, 240, 20, 20, 5}; //320x240
//CH7025 mode timing define: //clkdiv, HA, HFP(HO),HBP, HW, VA, VFP(VO),VBP, VW
TIMING CH7025_OUTPUT_TIMING = { 6, 240, 9, 9, 7, 320, 3, 3, 5};// Local LCD screen
//******************************************* CHANGE(1) END **********************************************//
INSTANTIATE_GPE_ZONES(0x3,"MGDI Driver","unused1","unused2") // Start with errors and warnings
static GPE *gGPE = (GPE*)NULL;
static ulong gBitMasks[] = { 0xF800, 0x07E0, 0x001F }; // 565 MODE
static TCHAR gszBaseInstance[256] = _T("Drivers\\Display\\S3C2410\\CONFIG");
#define dim(x) (sizeof(x) / sizeof(x[0]))
// This prototype avoids problems exporting from .lib
BOOL APIENTRY GPEEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA *data,
PENGCALLBACKS engineCallbacks);
// GWES will invoke this routine once prior to making any other calls into the driver.
// This routine needs to save its instance path information and return TRUE. If it
// returns FALSE, GWES will abort the display initialization.
BOOL APIENTRY
DisplayInit(LPCTSTR pszInstance, DWORD dwNumMonitors)
{
DWORD dwStatus;
HKEY hkDisplay;
BOOL fOk = FALSE;
RETAILMSG(0, (_T("SALCD2: display instance '%s', num monitors %d\r\n"),
pszInstance != NULL ? pszInstance : _T("<NULL>"), dwNumMonitors));
if(pszInstance != NULL) {
_tcsncpy(gszBaseInstance, pszInstance, dim(gszBaseInstance));
}
// sanity check the path by making sure it exists
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, gszBaseInstance, 0, 0, &hkDisplay);
if(dwStatus == ERROR_SUCCESS) {
RegCloseKey(hkDisplay);
fOk = TRUE;
} else {
RETAILMSG(0, (_T("SALCD2: DisplayInit: can't open '%s'\r\n"), gszBaseInstance));
}
return fOk;
}
BOOL APIENTRY DrvEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA *data,
PENGCALLBACKS engineCallbacks)
{
BOOL fOk = FALSE;
// make sure we know where our registry configuration is
if(gszBaseInstance[0] != 0) {
fOk = GPEEnableDriver(engineVersion, cj, data, engineCallbacks);
}
return fOk;
}
//
// Main entry point for a GPE-compliant driver
//
GPE *GetGPE(void)
{
if (!gGPE)
{
gGPE = new S3C2410DISP();
}
return gGPE;
}
WORD TempBuffer[241][320];
S3C2410DISP::S3C2410DISP (void)
{
RETAILMSG(0, (TEXT("++S3C2410DISP::S3C2410DISP\r\n")));
//****************************************** CHANGE(2) BEGIN *********************************************//
g_ChipType=FindChrontelChip();
switch(g_ChipType)
{
case CHIP_CH7023:
RETAILMSG(1,(_T("Find CH7023 Chip on Board!!!\r\n")));
Set2410LCDReg(&CH7023_OUTPUT_TIMING);
m_nScreenWidth = CH7023_OUTPUT_TIMING.ha;
m_nScreenHeight = CH7023_OUTPUT_TIMING.va;
RETAILMSG(1,(_T("m_nScreenWidth=%d,m_nScreenHeight=%d\r\n"),m_nScreenWidth,m_nScreenHeight));
break;
case CHIP_CH7025:
RETAILMSG(1,(_T("Find CH7025 Chip on Board!!!\r\n")));
Set2410LCDReg(&CH7025_OUTPUT_TIMING);
m_nScreenWidth = CH7025_OUTPUT_TIMING.ha;
m_nScreenHeight = CH7025_OUTPUT_TIMING.va;
RETAILMSG(1,(_T("m_nScreenWidth=%d,m_nScreenHeight=%d\r\n"),m_nScreenWidth,m_nScreenHeight));
break;
default:
RETAILMSG(1,(_T("No chip connect,only choose mode for Ch7025...\n")));
m_nScreenWidth = 240;
m_nScreenHeight = 320;
RETAILMSG(1,(_T("m_nScreenWidth=%d,m_nScreenHeight=%d\r\n"),m_nScreenWidth,m_nScreenHeight));
break;
}
//******************************************* CHANGE(2) END **********************************************//
// setup up display mode related constants
m_colorDepth = 16;
m_cbScanLineLength = m_nScreenWidth * 2;
m_FrameBufferSize = m_nScreenHeight * m_cbScanLineLength;
// memory map register access window, frame buffer, and program LCD controller
InitializeHardware();
#ifdef ROTATE
m_iRotate = 0;
SetRotateParms();
#endif //ROTATE
// setup ModeInfo structure
m_ModeInfo.modeId = 0;
m_ModeInfo.width = m_nScreenWidth;
m_ModeInfo.height = m_nScreenHeight;
m_ModeInfo.Bpp = m_colorDepth;
m_ModeInfo.format = gpe16Bpp;
m_ModeInfo.frequency = 60; // ?
m_pMode = &m_ModeInfo;
// allocate primary display surface
#ifdef ROTATE
m_pPrimarySurface = new GPESurfRotate(m_nScreenWidthSave, m_nScreenHeightSave, (void*)(m_VirtualFrameBuffer), m_cbScanLineLength, m_ModeInfo.format);
#else
m_pPrimarySurface = new GPESurf(m_nScreenWidth, m_nScreenHeight, (void*)(m_VirtualFrameBuffer), m_cbScanLineLength, m_ModeInfo.format);
#endif //!ROTATE
memset ((void*)m_pPrimarySurface->Buffer(), 0x0, m_FrameBufferSize);
// init cursor related vars
m_CursorVisible = FALSE;
m_CursorDisabled = TRUE;
m_CursorForcedOff = FALSE;
memset (&m_CursorRect, 0x0, sizeof(m_CursorRect));
m_CursorBackingStore = NULL;
m_CursorXorShape = NULL;
m_CursorAndShape = NULL;
#ifdef CLEARTYPE
HKEY hKey;
DWORD dwValue;
ULONG ulGamma = DEFAULT_CT_GAMMA;
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE,szGamma,0, NULL,0,0,0,&hKey,&dwValue))
{
if (dwValue == REG_OPENED_EXISTING_KEY)
{
DWORD dwType = REG_DWORD;
DWORD dwSize = sizeof(LONG);
if (ERROR_SUCCESS == RegQueryValueEx(hKey,szGammaValue,0,&dwType,(BYTE *)&dwValue,&dwSize))
{
ulGamma = dwValue;
}
}
else if (dwValue == REG_CREATED_NEW_KEY )
{
RegSetValueEx(hKey,szGammaValue,0,REG_DWORD,(BYTE *)&ulGamma,sizeof(DWORD));
}
RegCloseKey(hKey);
}
SetClearTypeBltGamma(ulGamma);
SetClearTypeBltMasks(gBitMasks[0], gBitMasks[1], gBitMasks[2]);
#endif //CLEARTYPE
//****************************************** CHANGE(3) BEGIN *********************************************//
//Test IIC read and write ( EPPROM and CHIP)
#ifdef IIC_TEST_MODE
for(int i=0;i<26;i++)
g_uart.SendByte('A'+i);
g_uart.GetKey();
RETAILMSG(1,(_T("Now to test the I2C read and write...\n\rChoices:\r\n")));
RETAILMSG(1,(_T("r(R):read 8 byte from 0x00 to 0x07...\r\n")));
RETAILMSG(1,(_T("w(W):write 8 byte from 0x00 to 0x07 with index...\r\n")));
RETAILMSG(1,(_T("m(M):change the slave address...\r\n")));
RETAILMSG(1,(_T("q(Q):quit..\r\n")));
UCHAR cValue,fQuit;
int j,k;
fQuit=0;
while(1)
{
if(fQuit)
break;
RETAILMSG(1,(_T("Please press the key as you want to do...\r\n")));
switch(g_uart.GetKey())
{
case 'q':
case 'Q':
fQuit=1;
break;
case 'r':
case 'R':
for(j=0;j<8;j++)
{
g_i2c.GetReg((UCHAR)j,&cValue);
RETAILMSG(1,(_T("READ:reg[0x%.2x]=0x%.2x\r\n"),j,cValue));
}
break;
case 'w':
case 'W':
for(k=0;k<8;k++)
{
g_i2c.SetReg((UCHAR)k,(UCHAR*)&k);
RETAILMSG(1,(_T("WRITE:reg[0x%.2x]=0x%.2x\r\n"),k,k));
}
break;
case 'm':
case 'M':
RETAILMSG(1,(_T("Please select one slave address:\r\n")));
RETAILMSG(1,(_T("a(A):0xA0 b(B):0xEC\r\n")));
switch(g_uart.GetKey())
{
case 'a':
case 'A':
g_i2c.SetChipAddr((UCHAR)0xA0);
break;
case 'b':
case 'B':
g_i2c.SetChipAddr((UCHAR)0xEC);
break;
default:
RETAILMSG(1,(_T("you input is invalid,nothing has been done!\r\n")));
break;
}
break;
default:
RETAILMSG(1,(_T("invalid! please input again...\r\n")));
break;
}
}
RETAILMSG(1,(_T("test end...\r\n")));
#endif
//I2C test end
//Now to initialize the chrontel chip
RETAILMSG(1,(_T("\r\nNow to initialize the Chrontel Chip...\n\n")));
InitChrontelChip(g_ChipType);
//******************************************* CHANGE(3) END **********************************************//
RETAILMSG(0, (TEXT("--S3C2410DISP::S3C2410DISP\r\n")));
}
//****************************************** CHANGE(4) BEGIN *********************************************//
//Define 4 member functions: Get2410LCDReg(), Set2410LCDReg(), DelayNS() and CleanBuffer():
void S3C2410DISP::Get2410LCDReg(PTIMING tm)
{
switch(g_ChipType)
{
case CHIP_CH7023:
*tm=CH7023_OUTPUT_TIMING;
break;
case CHIP_CH7025:
*tm=CH7025_OUTPUT_TIMING;
break;
default:
break;
}
}
void S3C2410DISP::Set2410LCDReg(PTIMING tm)
{
// Check parameter:
RETAILMSG(1,(_T("\nCheck timing------\nclkdiv=%d\ntm.ha=%d\rtm.va=%d\ntm.hfp=%d\rtm.vfp=%d\ntm.hw=%d\rtm.vw=%d\ntm.hbp=%d\rtm.vbp=%d\r\n"),
tm->clkdiv,tm->ha,tm->va,tm->hfp,tm->vfp,tm->hw,tm->vw,tm->hbp,tm->vbp));
RETAILMSG(1,(_T("Set2410LCDReg invoked\n\r")));
volatile S3C2410_IOPreg *s2410IOP = (volatile S3C2410_IOPreg *)IOP_BASE; //defined in s2410.h
volatile S3C2410_LCDreg *s2410LCD = (volatile S3C2410_LCDreg *)LCD_BASE; //defined in s2410.h
//turn off the LCD controller
s2410LCD->rLCDCON1 &= 0xFFFFFFFE;
// Assume that the LCD port not initialized,so setup LCD port ...
s2410IOP->rGPCUP = 0xFFFFFFFF;
s2410IOP->rGPCCON = 0xAAAAAAAA;
s2410IOP->rGPDUP = 0xFFFFFFFF;
s2410IOP->rGPDCON = 0xAAAAAAAA;
s2410IOP->rGPGCON &= ~(3 << 8); /* Set LCD_PWREN as output */
s2410IOP->rGPGCON |= (1 << 8);
//initialize...
s2410LCD->rLCDCON1 &= 0xFFFFFFFE;
//reset the start buffer address
s2410LCD->rLCDSADDR1=0x00000000;
s2410LCD->rLCDSADDR2=0x00000000;
s2410LCD->rLCDSADDR3=0x00000000;
//set:
// assume LCD control not initialized,so set LCD controller registers
s2410LCD->rLCDCON1= (tm->clkdiv << 8) |
(0 << 7) |
(3 << 5) |
(12 << 1) |
(0 << 0) ;
// TFT LCD panel,16bpp TFT,ENVID=off
s2410LCD->rLCDCON2= ((tm->vbp-1) <<24) |
((tm->va-1) <<14) |
((tm->vfp-1) << 6) |
((tm->vw-1) << 0) ;
s2410LCD->rLCDCON3= ((tm->hbp-1) <<19) |
((tm->ha-1) << 8) |
((tm->hfp-1) << 0) ;
s2410LCD->rLCDCON4= (13 << 8) |
((tm->hw-1) << 0) ;
s2410LCD->rLCDCON5= (1 <<11) |
(0 << 9) |
(0 << 8) |
(0 << 3) |
(1 << 0) ; //FRM5:6:5,HSYNC and VSYNC are inverted
s2410LCD->rLCDSADDR1=((FRAMEBUF_DMA_BASE>>22)<<21)|M5D(FRAMEBUF_DMA_BASE>>1);
s2410LCD->rLCDSADDR2=M5D( (FRAMEBUF_DMA_BASE+((tm->ha)*(tm->va)*2))>>1 );
s2410LCD->rLCDSADDR3=(0<<11)|(tm->ha);
s2410LCD->rLCDINTMSK|=(3); // MASK LCD Sub Interrupt
s2410LCD->rLPCSEL&=(~7); // Disable LPC3600
s2410LCD->rTPAL=0; // Disable Temp Palette
DelayNS(5000);
s2410LCD->rTPAL = 0x0;
s2410LCD->rLCDCON1 |= 1; // Enable lcd ouput
}
void S3C2410DISP::CleanBuffer(LPVOID buf)
{
memset(buf,0,FRAMEBUF_SIZE);
}
void S3C2410DISP::DelayNS(unsigned int dly)
{
unsigned int i;
for(; dly>0; dly--)
for(i=0; i<50000; i++);
}
//******************************************* CHANGE(4) END **********************************************//
void S3C2410DISP::InitializeHardware (void)
{
WORD *ptr;
DWORD index;
HKEY hkDisplay = NULL;
DWORD dwLCDPhysicalFrameBase;
DWORD dwStatus, dwType, dwSize;
RETAILMSG(0, (_T("++S3C2410DISP::InitializeHardware\r\n")));
// open the registry key and read our configuration
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, gszBaseInstance, 0, 0, &hkDisplay);
dwType = REG_DWORD;
if(dwStatus == ERROR_SUCCESS && dwType == REG_DWORD) {
dwSize = sizeof(DWORD);
dwStatus = RegQueryValueEx(hkDisplay, _T("LCDVirtualFrameBase"), NULL, &dwType,
(LPBYTE) &gdwLCDVirtualFrameBase, &dwSize);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -