typedef unsigned int U32;
volatile U32 FrameBuf[480][272];
/* 填充颜色 */
void paint_back(U32 c){
unsigned int i, j;
for(i = 100; i < 200; i++){
for(j = 100; j < 200; j++){
FrameBuf[i][j] = c;
}
}
}
void LCDDelay(int c){
int i;
for(; c != 0; c--){
for(i = 0; i < 10; i++);
}
}
static int lcd_open(struct inode *inode, struct file *file){
unsigned int clock_div, u32prediv, w55fa92_upll_clock;
ENTER();
/* reset IC */
#if 0
outpw(REG_AHBCLK, inpw(REG_AHBCLK) | VPOST_CKE | HCLK4_CKE);
outpw(REG_AHBIPRST, inpw(REG_AHBIPRST) | VPOST_RST);
LCDDelay(10);
outpw(REG_AHBIPRST, inpw(REG_AHBIPRST) & ~VPOST_RST);
#endif
outl((inl(REG_AHBCLK) | VPOST_CKE | HCLK4_CKE), REG_AHBCLK);
outl(inl(REG_AHBIPRST) | VPOST_RST, REG_AHBIPRST);
LCDDelay(10);
outl(inl(REG_AHBIPRST) & ~VPOST_RST, REG_AHBIPRST);
/* 时钟设置: DCLK 频率 -> 9MHz */
w55fa92_upll_clock = 162000;
clock_div = w55fa92_upll_clock / 9000;
u32prediv = 0;
clock_div--;
nvt_lock();
/* [2:0] 000 : LCD_SrcCLK / 1 */
outl((inl(REG_CLKDIV1) & ~VPOST_N0) | u32prediv, REG_CLKDIV1);
/* [15:8] VPOST_N = clock_div:
* ECLKvpost = LCD_SrcCLK / (VPOST_N + 1) */
outl((inl(REG_CLKDIV1) & ~VPOST_N1) | (clock_div << 8), REG_CLKDIV1);
/* [4:3] LCD_SrcCLK = UCLKOut */
outl((inl(REG_CLKDIV1) & ~VPOST_S) | (3 << 3), REG_CLKDIV1);
nvt_unlock();
/* 引脚设置 */
/* 使能时钟信号 */
outl((inl(REG_GPBFUN1) & ~MF_GPB15) | 0x20000000, REG_GPBFUN1);
/* 使能 LVDATA[15:0] -> GPC[15:0] */
outl(0x22222222, REG_GPCFUN0);
outl(0x22222222, REG_GPCFUN1);
/* 使能 LVDATA[17:16] -> GPE[1:0]*/
outl((inl(REG_GPEFUN1) & ~(MF_GPE0 + MF_GPE1)) | 0x22, REG_GPEFUN1);
/* 使能 LVDATA[23:18] -> GPB[12:7] */
outl((inl(REG_GPBFUN0) & ~MF_GPB7) | 0x20000000, REG_GPEFUN0);
outl((inl(REG_GPBFUN1) & 0xFFF00000) | 0x00022222, REG_GPEFUN1);
/* 使能 LCD_HS, LCD_VS, LCD_DE -> GPD[12:9] */
outl((inl(REG_GPDFUN1) & 0xFFFF000F) | 0x00002220, REG_GPDFUN1);
#if 0
outl((inl(REG_GPIOC_OMD) & 0xFFFF0000) | 0x0000FFFF, REG_GPIOC_OMD);
outl((inl(REG_GPIOE_OMD) & 0xFFFCFFFF) | 0x00030000, REG_GPIOE_OMD);
outl((inl(REG_GPIOB_OMD) & 0xFFFFFE7F) | 0x00000180, REG_GPIOB_OMD);
#endif
outl((inl(REG_GPIOC_PUEN) & 0xFFFF0000), REG_GPIOC_PUEN);
outl((inl(REG_GPIOE_PUEN) & 0xFFFCFFFF), REG_GPIOE_PUEN);
outl((inl(REG_GPIOB_PUEN) & 0xFFFFFE7F), REG_GPIOB_PUEN);
/* LCD image LCD interface */
outl((inl(REG_LCM_TVCtl) & ~TVCtl_LCDSrc) | (1 << 10), REG_LCM_TVCtl);
/* 配置 LCD 接口 */
/* [8] 使能 sync with TV */
outl(inl(REG_LCM_LCDCPrm) & ~LCDCPrm_LCDSynTv, REG_LCM_LCDCPrm);
/* [1:0] LCD type select:
* 0x00 High Resolution mode
* 0x01 Sync-type TFT LCD
* 0x10 Reserved
* 0x11 MPU-type LCD */
outl(inl(REG_LCM_LCDCPrm) & ~LCDCPrm_LCDTYPE, REG_LCM_LCDCPrm);
/* [21:20] 配置 LCD 并行 RGB 数据总线(高速模式下)
* 00 16pin, RGB565 output
* 01 18pin, RGB666 output
* 10 24pin, RGB888 output
* 11 Reserved*/
outl((inl(REG_LCM_LCDCCtl) & ~LCDCCtl_PRDB_SEL) | (0x2 << 20), REG_LCM_LCDCCtl);
/* [11:10] LCDSrc, [9:8] TVSrc: framebuffer
* 00 Reserved 01 Framebuffer
* 10 Register setting color 11 internal color bar
* NotchE;
* [0] enable TV encoder: 0-disable 1-enable
* [23:22]:00 NTSC;
* [15] TV output in D1 size: 0-640x480(VGA) 1-720x480(D1)
* [3] Interlace: 0-non-interlace 1-interlace
* ??? */
outl((inl(REG_LCM_TVCtl) & 0xFFFF30DA) | 0x00008529, REG_LCM_TVCtl);
/* 设置水平同步扫描时间线(unit: DCLK):
* 水平同步脉冲宽度 HSPW [31:24] .min 1,
* 前肩 HFPD [23:12] .min 2 .typ 8
* 后肩 HBPD [11:0] .min 8 .typ 43 */
outl(0x6302B008, REG_LCM_TCON1);
/* 设置垂直同步扫描时间线(unit: H):
* 水平同步脉冲宽度 HSPW [23:16] .min 1 .typ 10,
* 前肩 HFPD [15:8] .min 1 .typ 4
* 后肩 HBPD [7:0] .min 2 .typ 12 */
outl((inl(REG_LCM_TCON2) & 0xFF000000) | 0x000A040C, REG_LCM_TCON2);
/* 设置每行活跃数据的数量和每次面板显示的行数: 480x272
* [31:16] active data count per line: 480
* [15:0] lines per-panel: 272 */
outl(0x01E00110, REG_LCM_TCON3);
/* 设置桢缓冲的大小:
* [32:16] FB_X: 480 - 1
* [15:0] FB_Y: 272 - 1*/
outl(0x01DF010F, REG_LCM_FB_SIZE);
/* 信号极性,MPU 发出的是正脉冲,而 LCD 需要的是反的
* 根据芯片手册:取 VDEN HSYNC VSYNC DCLK 的极性 */
outl((inl(REG_LCM_TCON4) & 0xFFFFFFF0) | 0xE, REG_LCM_TCON4);
/* set TV control register and LCD to framebuffer, disable DAC*/
// outl((inl(REG_LCM_TVCtl) & 0xFFFFF0DA) | 0x00000510, REG_LCM_TVCtl);
/* 桢缓冲开始地址 */
// U32 FrameBuf = (U32)FrameBuf | 0X80000000;
outl(FrameBuf, REG_LCM_FSADDR);
/* 使能 LCD 控制器
* [16] endian select: 0- big endian 1- little endian
* [3:1] framebuffer data select:
* 000 RGB555 001 RGB565
* 010 RGB888(dummy,R,G,B) 011 RGB888(R,G,B,dummy)
* [0] LCD controler run: 0 disable 1 enable */
outl((inl(REG_LCM_LCDCCtl) & LCDCCtl_FBDS) | (2 << 1), REG_LCM_LCDCCtl);
outl((inl(REG_LCM_LCDCCtl) & LCDCCtl_YUVBL) | (1 << 16), REG_LCM_LCDCCtl);
outl((inl(REG_LCM_LCDCCtl) & LCDCCtl_LCDRUN) | 1, REG_LCM_LCDCCtl);
paint_back(0xCD5C5C);
outl((U32)FrameBuf, REG_LCM_FSADDR);
return 0;
}