S3C2440 Linux驱动移植——LCD

发布者:JoyfulSunflower最新更新时间:2017-09-23 来源: eefocus关键字:S3C2440  Linux驱动  移植  LCD 手机看文章 扫描二维码
随时随地手机看文章

PC主机:Ubuntu 10.4 和redhat 9.0

目标板:TQ2440开发板 Linux内核:2.6.30

屏幕型号:WXCAT35-TG3#001F 分辨率: 320X240


本文将介绍如何移植LCD设备。

在移植前,先配置下内核,将LCD设备编译进内核。


1.移植

移植LCD设置只须修改位于arch/arm/mach-s3c2440/mach-smdk2440.c中的两个结构体的数据。

1.1 s3c2410fb_display结构

修改后的内容如下:



  1. /* LCD driver info */  

  2.   

  3. static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {  

  4.   

  5.     .lcdcon5    = S3C2410_LCDCON5_FRM565 |  

  6.               S3C2410_LCDCON5_INVVLINE |  

  7.               S3C2410_LCDCON5_INVVFRAME |  

  8.               S3C2410_LCDCON5_PWREN |  

  9.               S3C2410_LCDCON5_HWSWP,  

  10.   

  11.     .type       = S3C2410_LCDCON1_TFT,  

  12.   

  13.     .width      = 320,//240,  

  14.     .height     = 240,//320,  

  15.   

  16.     .pixclock   = 156250,//166667, /* HCLK 60 MHz, divisor 10 */  

  17.     .xres       = 320,//240,  

  18.     .yres       = 240,//320,  

  19.     .bpp        = 16,  

  20.     .left_margin    = 20,  

  21.     .right_margin   = 38,//8,  

  22.     .hsync_len  = 30,//4,  

  23.     .upper_margin   = 15,//8,  

  24.     .lower_margin   = 12,//7,  

  25.     .vsync_len  = 3,//4,  

  26. };  


上面的参数是如何修改的呢?我们来看下。


type表示显示模式,这里为TFT模式。

width和height表示屏幕的分辨率,我的分辨率是320X240。

xres和yres分别等于width和height。

bpp表示所每个像素点位数,这里使用16位。

left_margin,right_margin,hsync_len,upper_margin,lower_margin,vsync_len这六个参数的值由LCD的手册给出。下图为LCD中的参数:


在这里,我给出上面6个参数和LCD手册中数据的对应关系:


       .left_margin    =            Hsync front porch        =    20

       .right_margin  =            Hsync back porch        =     38

       .hsync_len      =           Hsync pulse width        =     30

       .upper_margin       =      Vsync  back porch       =    15

       .lower_margin       =      Vsync front porch        =     12

       .vsync_len      =           Vsync pulse width        =     3

  

pixclock的值是用来计算CLKVAL的。在S3C2440的datasheet中,CLKVAL的计算公式为:

CLKVAL = HCLK / VCLK / 2 -1,而VCLK即为上面图中的Dclk,值为6.4MHz。


  1. /* s3c2410fb_activate_var 

  2.  * 

  3.  * activate (set) the controller from the given framebuffer 

  4.  * information 

  5.  */  

  6. static void s3c2410fb_activate_var(struct fb_info *info)  

  7. {  

  8.     struct s3c2410fb_info *fbi = info->par;  

  9.     void __iomem *regs = fbi->io;  

  10.     int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT; /*regs.lcdcon1在s3c2410fb_check_var设置*/  

  11.     struct fb_var_screeninfo *var = &info->var;  

  12.     int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock) / 2;  

  13.   

  14.     dprintk("%s: var->xres  = %d\n", __func__, var->xres);  

  15.     dprintk("%s: var->yres  = %d\n", __func__, var->yres);  

  16.     dprintk("%s: var->bpp   = %d\n", __func__, var->bits_per_pixel);  

  17.   

  18.     if (type == S3C2410_LCDCON1_TFT) {  

  19.         s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);/*根据var,计算出控制寄存器需要设置的值*/  

  20.         --clkdiv;  

  21.         if (clkdiv < 0)  

  22.             clkdiv = 0;  

  23.     } else {  

  24.         s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);  

  25.         if (clkdiv < 2)  

  26.             clkdiv = 2;  

  27.     }  

  28.   

  29.     fbi->regs.lcdcon1 |=  S3C2410_LCDCON1_CLKVAL(clkdiv);/*设置CLKVAL*/  

  30.   

  31.     /* write new registers */  

  32.   

  33.     dprintk("new register set:\n");  

  34.     dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);  

  35.     dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);  

  36.     dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);  

  37.     dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);  

  38.     dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);  

  39.     /*把计算好的值填入LCD控制器中*/  

  40.     writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID,     

  41.         regs + S3C2410_LCDCON1);                        /*仍然禁止LCD*/  

  42.     writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);  

  43.     writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);  

  44.     writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);  

  45.     writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);  

  46.   

  47.     /* set lcd address pointers */  

  48.     s3c2410fb_set_lcdaddr(info);                        /*设置LCD帧缓冲起始地址*/  

  49.   

  50.     fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID,  

  51.     writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1);   /*使能LCD*/  

  52. }  

  53. static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,  

  54.                       unsigned long pixclk)  

  55. {  

  56.     unsigned long clk = clk_get_rate(fbi->clk);         /*获取当前时钟频率(Hz)*/  

  57.     unsigned long long div;  

  58.   

  59.     /* pixclk is in picoseconds, our clock is in Hz 

  60.      * 

  61.      * Hz -> picoseconds is / 10^-12 

  62.      */  

  63.   

  64.     div = (unsigned long long)clk * pixclk;  

  65.     div >>= 12;            /* div / 2^12 */  

  66.     do_div(div, 625 * 625UL * 625); /* div / 5^12 */  

  67.   

  68.     dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div);  

  69.     return div;  

  70. }  

首先pixclock作为参数传递给了s3c2410fb_calc_pixclk函数,当该函数执行完以后clkdiv  = clk x pixclk  / 10^12 / 2。


随后由于是采用TFT模式,将clkdiv-1。最后得:

clkdiv  = clk X pixclk  / 10^12 / 2 - 1,这里的clk即为HCLK,LCD模块使用HCLK作为时钟源。

为方便观察,将前面datasheet中的计算公式复制在此:CLKVAL = HCLK / VCLK / 2 -1。

我们可以看出1/VCLK = pixclk / 10^12,也就是说pixclk = 10^12 / VCLK。 我们已经知道VCLK=Dclk =6.4MHz,

因此,pixclk=156250。

其实在内核的参考文档中有这样一段话:

The speed at which the electron beam paints the pixels is determined by the
dotclock in the graphics board. For a dotclock of e.g. 28.37516 MHz (millions
of cycles per second), each pixel is 35242 ps (picoseconds) long:

    1/(28.37516E6 Hz) = 35.242E-9 s

也就是说VCLK的倒数,再乘10^12即为pixclk。picoseconds单位表示微微秒,即10^12。

最后一个参数lcdcon5,它是寄存器LCDCON5的配置信息。

S3C2410_LCDCON5_FRM565表示使用565格式。

S3C2410_LCDCON5_PWREN表示PWREN管脚输出信号使能。

S3C2410_LCDCON5_INVVLINE 和S3C2410_LCDCON5_INVVFRAME 表示反转VLINE/HSYNC和VFRAME/VSYNC两个信号线,这个可以通过对比LCD手册和S3C2440的datasheet来得出。

S3C2410_LCDCON5_HWSWP:由于使用小端模式,需设置半字交换。


1.2 s3c2410fb_mach_info结构


修改后的内容如下:


  1. static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {  

  2.     .displays   = &smdk2440_lcd_cfg,  

  3.     .num_displays   = 1,  

  4.     .default_display = 0,  

  5.   

  6. #if 0  

  7.     /* currently setup by downloader */  

  8.     .gpccon     = 0xaa940659,  

  9.     .gpccon_mask    = 0xffffffff,  

  10.     .gpcup      = 0x0000ffff,  

  11.     .gpcup_mask = 0xffffffff,  

  12.     .gpdcon     = 0xaa84aaa0,  

  13.     .gpdcon_mask    = 0xffffffff,  

  14.     .gpdup      = 0x0000faff,  

  15.     .gpdup_mask = 0xffffffff,  

  16. #endif  

  17. //no  

  18. //  .lpcsel     = ((0xCE6) & ~7) | 1<<4,  

  19. };  


做出的唯一修改就是:禁用lpsel,因为如果不是使用三星LPC3600/LCC3600 LCD,必须禁止LPC3600/LCC3600模式(写入0到TCONSEL)。


num_displays 表示有几个LCD设备。

default_display表示这是第几个LCD设备。


2.  测试

在修改过上述两个数据结构之后,直接编译内核,然后下载到开发板上。

可以执行命令fbset,输出如下:

mode "320x240-58"

        # D: 6.400 MHz, H: 15.686 kHz, V: 58.097 Hz
        geometry 320 240 320 240 16
        timings 156250 20 38 15 12 30 3
        accel false
        rgba 5/11,6/5,5/0,0/0
endmode

上述中的数值都是我们设置的参数。

另外,可以通过下列测试程序进行测试:


  1. #include   

  2. #include   

  3. #include   

  4. #include   

  5. #include   

  6. //#include   

  7.   

  8. int main()  

  9. {  

  10.     int fd, retval, i;  

  11.     struct fb_var_screeninfo var;  

  12.     struct fb_fix_screeninfo fix;  

  13.     unsigned short *memstart;  

  14.   

  15.     fd = open("/dev/fb0", O_RDWR);  

  16.     if(fd < 0){  

  17.         printf("open /dev/fb0 failed\n");  

  18.         return -1;  

  19.     }  

  20.       

  21.     retval = ioctl(fd, FBIOGET_FSCREENINFO, &fix);  

  22.     if(retval < 0){  

  23.         printf("ioctl failed\n");  

  24.         return -1;  

  25.     }  

  26.   

  27.     printf("seme len= %d\n", fix.smem_len);  

  28.   

  29.     memstart = mmap(NULL, 240*320*2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  

  30.     if (memstart == MAP_FAILED){  

  31.         printf("mmap wrong\n");  

  32.     }  

  33.       

  34.     for(; ;){  

  35.     sleep(1);  

  36.     for(i = 0; i < (153600>>1); i++)  

  37.         *(memstart + i) = 0xf800;  

  38.     sleep(1);  

  39.     for(i = 0; i < (153600>>1); i++)  

  40.         *(memstart + i) = 0x0c00;  

  41.     }  

  42. }  

该测试程序是网上的,我只是稍微修改了下。


关键字:S3C2440  Linux驱动  移植  LCD 引用地址:S3C2440 Linux驱动移植——LCD

上一篇:S3C2440 Linux驱动移植——SPI
下一篇:S3C2440 Linux驱动移植——按键

推荐阅读最新更新时间:2024-03-16 15:38

车用LCD面板背光应用电源浪涌设计考量
  车用的DC电源由电源线提供,这条电源线连接了所有基于线路供电的电子模组、电池,以及由汽车引擎驱动的发电机。对于典型的12V或24V系统来说,我们通常看到的电源电压变化为±30%。因此,汽车应用中的所有电子模组都应该特别注意输入电压的变化。但是在电源浪涌期间,电源电压会大幅上升。在国际标準ISO7637-2中有pulse 2a和pulse 5a规範,并说明产生浪涌的一些塬因,pulse 2a所定义的浪涌是由线路和线束供电的电子模组中突然中断的电感电流所引起。pulse 5a所定义的浪涌是由以下情况所引起:当一个负载突降瞬态放电的电池被断开而且发电机同时又在利用残存在其电路的其他负载产生的充电电流时,激增发生并产生浪涌。   描述
[电源管理]
车用<font color='red'>LCD</font>面板背光应用电源浪涌设计考量
s3c2440裸机-内存控制器(三-2、norflash编程之适配访问时序)
前面我们了解了 norFlash的特性和原理 ,那么cpu是如何和nor进行通信的呢?下面开始详细介绍。 1.内存控制器适配norflash 如图是S3C2440的内存控制器的可编程访问周期读写时序,里面的时间参数要根据外部norflash的性能进行配置,这里先列出时间参数的含义: Tacs: Address set-up time before nGCSn(表示地址信号A发出多久后才能发出nGCS片选) Tcos: Chip selection set-up time before nOE(表示片选信号nGCS发出多久后才能发出读使能信号) Tacc:access cycle(数据访问周期) Tacp:page模式下的访问周
[单片机]
<font color='red'>s3c2440</font>裸机-内存控制器(三-2、norflash编程之适配访问时序)
u-boot-2016.09移植(8)-合并tq210-spl.bin与u-boot.bin
为了方便烧录,我们直接将u-boot.bin追加到tq210-spl.bin后面,组成一个文件。 修改Makefile,定义合并规则: combine: u-boot.bin spl/u-boot-spl.bin FORCE cp $(objtree)/spl/tq210-spl.bin $(objtree)/tmp.bin truncate $(objtree)/tmp.bin -c -s 16K cat $(objtree)/u-boot.bin $(objtree)/tmp.bin cp $(objtree)/tmp.bin $(objtree)/ky-uboot.bin chmod 777 k
[单片机]
u-boot-2016.09<font color='red'>移植</font>(8)-合并tq210-spl.bin与u-boot.bin
大尺寸TFT-LCD面板迎来新时代?Q2本土超日本
随着新世代线和更高世代线的投产,中国TFT- LCD供应商正在扩大生产计划。DisplaySearch最新报告Quarterly Large-Area Production Strategy Report指出,2011年第二季度中国大陆将有望在大尺寸TFT-LCD面板产量上超过日本。第一季度,中国大陆大尺寸TFT-LCD面板平均月产量为270万片,日本月产量为320万片,这些面板主要应用于上网本、平板电脑、笔记本电脑、显示器和电视机。但到第二季度,中国大陆平均月产量提高到340万片,而日本则减少到230万片;并且从2011年第三季度到2012年第一季度,中国大陆面板产量将持续超过日本。 “韩国一直是大尺寸TFT-LCD的
[家用电子]
大尺寸TFT-<font color='red'>LCD</font>面板迎来新时代?Q2本土超日本
S3c2440ARM异常与中断体系详解7---按键中断程序示例完善
首先main.c中 我们初始化中断控制器 初始化中断源 假设按键按键就会产生中断,CPU就会跳到start.S 执行 .text .global _start _start: b reset /*vector 0 一上电复位,是从0地址开始执行,跳到reset*/ ldr pc, und_addr /*vector 4 如果发生未定义指令异常,硬件就会在自动跳转0x04地址未定义指令异常处,执行do_und*/ ldr pc,swi_addr /* vector 8 : swi */ IRQ模式的话跳到0x00000018地方 .text .global _start _start: b rese
[单片机]
S3c2440ARM异常与中断体系详解7---按键中断程序示例完善
经济景气寒冬到 面板厂商关门是喜还是悲?
经济景气寒冬到,双D产业面板产业吹起减产、延后投资新产能,奇美电的8.5G投产已决定延后至2010年,近日友达 (2409)表示中科双子星7.5G拟延后投产,包括群创、彩晶、华映都有相关的减产、或延后设厂相关动作,面板五虎全数启动减产、节流动作。 由于景气急冻,烧钱行业双D受到最大的冲击,继DRAM之后,TFT-LCD采减产、延后投新产能,以减少资本支出,进行节流计划,以度寒冬。 奇美电原订8.5G在明第四季投产3万片,目前已决定延后至2010年,而奇美电明年的资本支因此,将由今年新台币1000亿元急冻至新台币500亿元,而因延后至2010年投产,再下缩至350亿元,创下近年来最低的资本支出。 友达在
[焦点新闻]
移植U-Boot.1.2.0到友善之臂S3C2440 (2)
8、在个文件中添加“CONFIG_S3C2440”,使得原来s3c2410的代码可以编译进来。 (1)/include/common.h文件的第454行: #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_LH7A40X) || defined(CONFIG_S3C2440) (2)/include/s3c24x0.h文件的第85、95、99、110、148、404行: #if defined(CONFIG_S3C2410) || defined (CONFIG_S3C2440) (3)/cpu/arm920t/s3c24x0/inte
[单片机]
小容量系统图形LCD的汉显解决方案
引言 在嵌入式系统应用中,人机界面的可操作性越来越为人们所重视,而用汉字来显示菜单是可操作性的前提;由于受到存储容量的限制,在汉字较多的情况下一般的解决方案是采用内建点阵字库的LCD模块,而这一类显示模块的使用灵活性却大受限制。本文从实际应用出发,介绍了一种在图形LCD中基于查表法的软件算法,可以在不影响显示灵活性的前提下最大化地节约系统存储资源。 查表法解决方案算法 在很多的人机界面中,虽然显示的汉字数量较多,但实际无重复的汉字数却较少,一个显示了2000个汉字菜单的系统中,用到的汉字却可能只有300个。这样看来,建立一个完整的国标字库很是浪费资源。 该算法在程序存储区建立两个表格,一张用来存储无重复汉字的点阵数据(WordLib
[电源管理]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved