微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > LCD驱动(输入子系统)

LCD驱动(输入子系统)

时间:11-21 来源:互联网 点击:

gpbdat = gpbcon+1;

gpccon = ioremap(0x56000020, 4);

gpdcon = ioremap(0x56000030, 4);

gpgcon = ioremap(0x56000060, 4);

*gpccon = 0xaaaaaaaa; //GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND

*gpdcon = 0xaaaaaaaa; // GPIO管脚用于VD[23:8]

*gpbcon &= ~(3); // GPB0设置为输出引脚

*gpbcon |= 1;

*gpbdat &= ~1; // 输出低电平

*gpgcon |= (3<8); //GPG4用作LCD_PWREN

// 3.2 根据LCD手册设置LCD控制器, 比如VCLK的频率等

lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));

// bit[17:8]: VCLK = HCLK / [(CLKVAL+1) x 2], LCD手册P14

* 10MHz(100ns) = 100MHz / [(CLKVAL+1) x 2]

* CLKVAL = 4

* bit[6:5]: 0b11, TFT LCD

* bit[4:1]: 0b1100, 16 bpp for TFT

* bit[0] : 0 = Disable the video output and the LCD control signal.

//

lcd_regs->lcdcon1 = (4<8) | (3<5) | (0x0c<1);

#if 1

// 垂直方向的时间参数

* bit[31:24]: VBPD, VSYNC之后再过多长时间才能发出第1行数据

* LCD手册 T0-T2-T1=4

* VBPD=3

* bit[23:14]: 多少行, 320, 所以LINEVAL=320-1=319

* bit[13:6] : VFPD, 发出最后一行数据之后,再过多长时间才发出VSYNC

* LCD手册T2-T5=322-320=2, 所以VFPD=2-1=1

* bit[5:0] : VSPW, VSYNC信号的脉冲宽度, LCD手册T1=1, 所以VSPW=1-1=0

//

lcd_regs->lcdcon2 = (3<24) | (319<14) | (1<6) | (0<0);

// 水平方向的时间参数

* bit[25:19]: HBPD, VSYNC之后再过多长时间才能发出第1行数据

* LCD手册 T6-T7-T8=17

* HBPD=16

* bit[18:8]: 多少列, 240, 所以HOZVAL=240-1=239

* bit[7:0] : HFPD, 发出最后一行里最后一个象素数据之后,再过多长时间才发出HSYNC

* LCD手册T8-T11=251-240=11, 所以HFPD=11-1=10

//

lcd_regs->lcdcon3 = (16<19) | (239<8) | (10<0);

// 水平方向的同步信号

* bit[7:0] : HSPW, HSYNC信号的脉冲宽度, LCD手册T7=5, 所以HSPW=5-1=4

//

lcd_regs->lcdcon4 = 4;

#else

lcd_regs->lcdcon2 = S3C2410_LCDCON2_VBPD(5) | \

S3C2410_LCDCON2_LINeval_r(319) | \

S3C2410_LCDCON2_VFPD(3) | \

S3C2410_LCDCON2_VSPW(1);

lcd_regs->lcdcon3 = S3C2410_LCDCON3_HBPD(10) | \

S3C2410_LCDCON3_HOZVAL(239) | \

S3C2410_LCDCON3_HFPD(1);

lcd_regs->lcdcon4 = S3C2410_LCDCON4_MVAL(13) | \

S3C2410_LCDCON4_HSPW(0);

#endif

// 信号的极性

* bit[11]: 1=565 format

* bit[10]: 0 = The video data is fetched at VCLK falling edge

* bit[9] : 1 = HSYNC信号要反转,即低电平有效

* bit[8] : 1 = VSYNC信号要反转,即低电平有效

* bit[6] : 0 = VDEN不用反转

* bit[3] : 0 = PWREN输出0

* bit[1] : 0 = BSWP

* bit[0] : 1 = HWSWP 2440手册P413

//

lcd_regs->lcdcon5 = (1<11) | (0<10) | (1<9) | (1<8) | (1<0);

// 3.3 分配显存(framebuffer), 并把地址告诉LCD控制器

s3c_lcd->screen_base = dma_alloc_writecombine(NULL, s3c_lcd->fix.smem_len, &s3c_lcd->fix.smem_start, GFP_KERNEL);

lcd_regs->lcdsaddr1 = (s3c_lcd->fix.smem_start >> 1) & ~(3<30);

lcd_regs->lcdsaddr2 = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len) >> 1) & 0x1fffff;

lcd_regs->lcdsaddr3 = (240*16/16); // 一行的长度(单位: 2字节)

//s3c_lcd->fix.smem_start = xxx; // 显存的物理地址

// 启动LCD

lcd_regs->lcdcon1 |= (1<0); // 使能LCD控制器

lcd_regs->lcdcon5 |= (1<3); // 使能LCD本身

*gpbdat |= 1; // 输出高电平, 使能背光

// 4. 注册

register_framebuffer(s3c_lcd);

return 0;

}

static void lcd_exit(void)

{

unregister_framebuffer(s3c_lcd);

lcd_regs->lcdcon1 &= ~(1<0); // 关闭LCD本身

*gpbdat &= ~1; // 关闭背光

dma_free_writecombine(NULL, s3c_lcd->fix.smem_len, s3c_lcd->screen_base, s3c_lcd->fix.smem_start);

iounmap(lcd_regs);

iounmap(gpbcon);

iounmap(gpccon);

iounmap(gpdcon);

iounmap(gpgcon);

framebuffer_release(s3c_lcd);

}

module_init(lcd_init);

module_exit(lcd_exit);

MODULE_LICENSE("GPL");

============================================================

解析:

LCD驱动程序

假设

app: open("/dev/fb0", ...) 主设备号: 29, 次设备号: 0

--------------------------------------------------------------

kernel:

fb_open

int fbidx = iminor(inode);

struct fb_info *info = = registered_fb[0];

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top