LCD驱动移植准备知识(一)

原文地址:linux-2.6.32内核LCD驱动移植 作者:charles413

参考资料:http://blog.chinaunix.net/uid-9688646-id-1998441.html 

http://blog.163.com/changchunxi@126/blog/static/111800823201212533243484/ 

主机:Windows 7旗舰版,VMware7.1.2,Fedora9

集成开发环境:Source Insight 3.5

编译环境:arm-linux-gcc 4.4.3

开发板:华中科技大学惠世科技S3C2440实验箱开发板,奇美4.3寸LCD(与TQ2440相似,参数见LR043JC211_V04.pdf)。

Uboot版本:u-boot-2009.11

Linux版本:linux-2.6.32.2

这里只讨论TFT LCD。

1.LCD驱动移植准备

Linux-2.6.32.2 内核已经支持S3C2440 的LCD 控制器驱动,在这里主要介绍一下LCD驱动移植时需要设置的参数。在移植LCD驱动时,我们需要根据LCD datasheet来设置相应的参数,这些参数包括:pixclock

left_marginright_marginupper_marginlower_marginhsync_lenvsync_len。

    各个参数的设置方法在内核目录树Documentation\fb\framebuffer.txt中都有介绍(其实最好的方法就是看文档,但开始可能由于对LCD参数不熟悉,又是全英文,看着比较困难,做完一遍再回头看就很清晰明了了),为了方便这里摘取我们需要的部分内容如下:

5. Video Mode Timings

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


A monitor draws an image on the screen by using an electron beam (3 electron

beams for color models, 1 electron beam for monochrome monitors). The front of

the screen is covered by a pattern of colored phosphors (pixels). If a phosphor

is hit by an electron, it emits a photon and thus becomes visible.


The electron beam draws horizontal lines (scanlines) from left to right, and

from the top to the bottom of the screen. By modifying the intensity of the

electron beam, pixels with various colors and intensities can be shown.


After each scanline the electron beam has to move back to the left side of the

screen and to the next line: this is called the horizontal retrace. After the

whole screen (frame) was painted, the beam moves back to the upper left corner:

this is called the vertical retrace. During both the horizontal and vertical

retrace, the electron beam is turned off (blanked).


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


If the screen resolution is 640x480, it will take


    640*35.242E-9 s = 22.555E-6 s


to paint the 640 (xres) pixels on one scanline. But the horizontal retrace

also takes time (e.g. 272 `pixels'), so a full scanline takes


    (640+272)*35.242E-9 s = 32.141E-6 s


We'll say that the horizontal scanrate is about 31 kHz:


    1/(32.141E-6 s) = 31.113E3 Hz


A full screen counts 480 (yres) lines, but we have to consider the vertical

retrace too (e.g. 49 `lines'). So a full screen will take


    (480+49)*32.141E-6 s = 17.002E-3 s


The vertical scanrate is about 59 Hz:


    1/(17.002E-3 s) = 58.815 Hz


This means the screen data is refreshed about 59 times per second. To have a

stable picture without visible flicker, VESA recommends a vertical scanrate of

at least 72 Hz. But the perceived flicker is very human dependent: some people

can use 50 Hz without any trouble, while I'll notice if it's less than 80 Hz.


Since the monitor doesn't know when a new scanline starts, the graphics board

will supply a synchronization pulse (horizontal sync or hsync) for each

scanline.  Similarly it supplies a synchronization pulse (vertical sync or

vsync) for each new frame. The position of the image on the screen is

influenced by the moments at which the synchronization pulses occur.


The following picture summarizes all timings. The horizontal retrace time is

the sum of the left margin, the right margin and the hsync length, while the

vertical retrace time is the sum of the upper margin, the lower margin and the

vsync length.


  +----------+---------------------------------------------+----------+-------+

  |          |                ↑                            |          |       |

  |          |                |upper_margin                |          |       |

  |          |                ↓                            |          |       |

  +----------###############################################----------+-------+

  |          #                ↑                            #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |   left   #                |                            #  right   | hsync |

  |  margin  #                |       xres                 #  margin  |  len  |

  |<-------->#<---------------+--------------------------->#<-------->|<----->|

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                |yres                        #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                |                            #          |       |

  |          #                ↓                            #          |       |

  +----------###############################################----------+-------+

  |          |                ↑                            |          |       |

  |          |                |lower_margin                |          |       |

  |          |                ↓                            |          |       |

  +----------+---------------------------------------------+----------+-------+

  |          |                ↑                            |          |       |

  |          |                |vsync_len                   |          |       |

  |          |                ↓                            |          |       |

  +----------+---------------------------------------------+----------+-------+

The frame buffer device expects all horizontal timings in number of dotclocks

(in picoseconds, 1E-12 s), and vertical timings in number of scanlines.



6. Converting XFree86 timing values info frame buffer device timings

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


An XFree86 mode line consists of the following fields:

 "800x600"     50      800  856  976 1040    600  637  643  666

 < name >     DCF       HR  SH1  SH2  HFL     VR  SV1  SV2  VFL


The frame buffer device uses the following fields:


  - pixclock: pixel clock in ps (pico seconds)

  - left_margin: time from sync to picture

  - right_margin: time from picture to sync

  - upper_margin: time from sync to picture

  - lower_margin: time from picture to sync

  - hsync_len: length of horizontal sync

  - vsync_len: length of vertical sync


1) Pixelclock:

   xfree: in MHz

   fb: in picoseconds (ps)


   pixclock = 1000000 / DCF


2) horizontal timings:

   left_margin = HFL - SH2

   right_margin = SH1 - HR

   hsync_len = SH2 - SH1


3) vertical timings:

   upper_margin = VFL - SV2

   lower_margin = SV1 - VR

   vsync_len = SV2 - SV1


Good examples for VESA timings can be found in the XFree86 source tree,

under "xc/programs/Xserver/hw/xfree86/doc/modeDB.txt".


这里介绍了如何计算LCD一帧图片的刷新频率,以及我们之前提到的那些参数的设置。我们可以找到Pixclock的计算方法:

pixclock = 1000000 / DCF

DCFDot Clk Frequency,单位是MHz,是扫描像素点的频率。计算出来的pixclock单位是ps

其他参数虽然给出了计算方法,但与我们的TFT LCD Datasheet中所给的的参数可能不太一致。下面对left_marginright_marginupper_marginlower_marginhsync_lenvsync_len这几个参数进行进一步讲解。

下图是典型的TFT LCD时序图(移植时以自己LCD相应的datasheet为准):

LCD驱动移植准备知识(一)_第1张图片

VBP(vertical back porch):表示在一帧图像开始时,垂直同步信号以后的无效的行数,对应驱动中的upper_margin

VFB(vertical front porch):表示在一帧图像结束后,垂直同步信号以前的无效的行数,对应驱动中的lower_margin

VSPW(vertical sync pulse width):表示垂直同步脉冲的宽度,用行数计算,对应驱动中的vsync_len

HBP(horizontal back porch):表示从水平同步信号开始到一行的有效数据开始之间的VCLK的个数,对应驱动中的left_margin

HFP(horizontal front porth):表示一行的有效数据结束到下一个水平同步信号开始之间的VCLK的个数,对应驱动中的right_margin

HSPW(horizontal sync pulse width):表示水平同步信号的宽度,用VCLK计算,对应驱动中的hsync_len

知道每个参数对应的值是什么意思后,查看我们所需移植的LCD Datasheet(LR043JC211_V04.pdf),参数和时序见下图:

LCD驱动移植准备知识(一)_第2张图片

LCD驱动移植准备知识(一)_第3张图片

根据所给参数可以计算出:

pixclock = 1000000 / DCLK = 1000000 / 9 = 111111

left_margin = Thb = 2

right_margin = Thf = 2

hsync_len = Thp = 41

upper_margin = Tvb = 2

lower_margin = Tvf = 2

vsync_len = Tvp = 10

xres = Thd = 480

Yres = Tvd = 272

2.内核中添加LCD驱动

在arch/arm/mach-s3c2440/mach-mini2440.c中添加如下代码:

点击(此处)折叠或打开

  1. static struct s3c2410fb_display mini2440_lcd_cfg __initdata = {
  2.     .lcdcon5 = S3C2410_LCDCON5_FRM565 |
  3.              S3C2410_LCDCON5_INVVLINE |
  4.              S3C2410_LCDCON5_INVVFRAME |
  5.              S3C2410_LCDCON5_PWREN |
  6.              S3C2410_LCDCON5_HWSWP,

  7.     .type = S3C2410_LCDCON1_TFT,

  8.     #if defined(CONFIG_FB_S3C2410_TFT480272)
  9.     .width = 480,
  10.     .height = 272,
  11.     .pixclock = 111111,
  12.     .xres = 480,
  13.     .yres = 272,
  14.     .bpp = 16,
  15.     .left_margin = 2,
  16.     .right_margin = 2,
  17.     .hsync_len = 41,
  18.     .upper_margin = 2,
  19.     .lower_margin = 2,
  20.     .vsync_len = 10,
  21.     #endif
  22. };
  23. static struct s3c2410fb_mach_info mini2440_fb_info __initdata = {
  24.     .displays = &mini2440_lcd_cfg,
  25.     .num_displays = 1,
  26.     .default_display = 0,

  27. #if 0
  28.     /* currently setup by downloader */
  29.     .gpccon = 0xaa940659,
  30.     .gpccon_mask = 0xffffffff,
  31.     .gpcup = 0x0000ffff,
  32.     .gpcup_mask = 0xffffffff,
  33.     .gpdcon = 0xaa84aaa0,
  34.     .gpdcon_mask = 0xffffffff,
  35.     .gpdup = 0x0000faff,
  36.     .gpdup_mask = 0xffffffff,

  37.     .default_display = 0,
  38.     .gpccon = 0xaa955699,
  39.     .gpccon_mask = 0xffc003cc,
  40.     .gpcup = 0x0000ffff,
  41.     .gpcup_mask = 0xffffffff,
  42.     .gpdcon = 0xaa95aaa1,
  43.     .gpdcon_mask = 0xffc0fff0,
  44.     .gpdup = 0x0000faff,
  45.     .gpdup_mask = 0xffffffff,
  46. #endif
  47.     .lpcsel = 0xf82,
  48. };

在设备初始化函数中加入设置LCD初始化参数函数,如下:

点击(此处)折叠或打开

  1. static void __init mini2440_machine_init(void)
  2. {
  3.     s3c24xx_fb_set_platdata(&mini2440_fb_info);
  4.     s3c_i2c0_set_platdata(NULL);

  5.     s3c_device_nand.dev.platform_data = &mini2440_nand_info; 
  6.     platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));
  7.     //smdk_machine_init();
  8. }

drivers/video/Kconfig大概1930行加入添加内核配置选项:

点击(此处)折叠或打开

  1. config FB_S3C2410_DEBUG
  2.     bool "S3C2410 lcd debug messages"
  3.     depends on FB_S3C2410
  4.     help
  5.      Turn on debugging messages. Note that you can set/unset at run time
  6.      through sysfs

  7. choice
  8.     prompt "LCD select"
  9.     depends on FB_S3C2410
  10.     help
  11.      S3C24x0 LCD size select

  12.     config FB_S3C2410_TFT480272
  13.         boolean "4.2 inch TFT 480X272 LCD"
  14.         depends on FB_S3C2410
  15.         help
  16.          4.2 inch TFT 480X272 LCD 
  17. endchoice

  18. config FB_SM501
  19.     tristate "Silicon Motion SM501 framebuffer support"
  20.     depends on FB && MFD_SM501
  21.     select FB_CFB_FILLRECT
  22.     select FB_CFB_COPYAREA
  23.     select FB_CFB_IMAGEBLIT

3.配置内核

在命令行下,进入内核根目录,执行:

#make menuconfig,

Device Drivers  --->

    Graphics support  --->

        <*> Support for frame buffer devices  ---> 

    LCD select (4.2 inch TFT 480X272 LCD)  --->

(X) 4.2 inch TFT 480X272 LCD

    Console display driver support  --->

<*> Framebuffer Console support   //支持Framebuffer控制台

[*] Select compiled-in fonts  //选择字库,默认VGA 8x8 , VGA 8x16

[*]   VGA 8x8 font  

[*]   VGA 8x16 font 

    [*] Bootup logo  ---> 

[*]   Standard 224-color Linux logo  

按空格或者回车键选择我们需要的 LCD 型号,然后退出保存内核配置。在命令行执行:#make uImage
将会生成arch/arm/boot/uImage,把它烧写到开发板中,就可以看到熟悉的小企鹅出现在屏幕上了

4.修改Linux内核logo

Linux 系统启动时会出现一个小企鹅图像。大部分Linux 系统会有这个开机图片, 它对应的文件其实就是linux-2.6.32.2/drivers/video/logo/logo_linux_clut224.ppm该文件是一个特殊格式的图像文件,有很多方法可以把普通的图片转换为 logo 文件,最常用的就是netpbm 工具组。Fedora9光盘镜像中有netpbm软件包,可以在Fedora 9 i386 DVD/Packages/下找到,执行安装命令:

# rpm -ivh netpbm*.rpm

“netpbm”是一组命令行的工具,它可以转换很多格式的图片,在此以png 格式为例介绍一下如何把普通的PNG文件转换为我们需要的Linux LOGO 图片:

假定我们要转换的文件名为 logo_linux.png,首先将png 图片转成pnm

# pngtopnm logo_linux.png > logo_linux.pnm

然后将pnm 图片的颜色数限制在224

# pnmquant 224 logo_linux.pnm > logo_linux_clut224.pnm

最后将pnm 图片转换成我们需要的ppm

# pnmtoplainpnm logo_linux_clut224.pnm > logo_linux_clut224.ppm后用logo_linux_clut224.ppm 替换linux-2.6.32.2/drivers/video/logo 中对应的图像就可以了

你可能感兴趣的:(LCD驱动移植准备知识(一))