LinuxLCD驱动源码分析研究及移植.docx
《LinuxLCD驱动源码分析研究及移植.docx》由会员分享,可在线阅读,更多相关《LinuxLCD驱动源码分析研究及移植.docx(42页珍藏版)》请在冰点文库上搜索。
![LinuxLCD驱动源码分析研究及移植.docx](https://file1.bingdoc.com/fileroot1/2023-6/15/3299b076-9554-41f0-89ca-5c686c53b60b/3299b076-9554-41f0-89ca-5c686c53b60b1.gif)
LinuxLCD驱动源码分析研究及移植
Linux地LCD驱动源码分析及移植(三部曲)
第一部分:
基于ARM9处理器地linux-2.6.32.2操作系统内核移植手记part5.1(LCD驱动源码分析及移植之platformdevice)b5E2R。
1.与LCD控制器硬件相关地寄存器内容请参照三星S3C2440A技术手册中地第15章.
2. LCDController地平台设备定义如下(文件位于linux/arch/arm/plat-s3c24xx/devs.c):
p1Ean。
1./* LCDController */
2.
3.staticstructresources3c_lcd_resource[] = {
4. [0] = {
5. .start = S3C24XX_PA_LCD,
6. .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
7. .flags = IORESOURCE_MEM,
8. },
9. [1] = {
10. .start = IRQ_LCD,
11. .end = IRQ_LCD,
12. .flags = IORESOURCE_IRQ,
13. }
14.
15.};
16.
17.staticu64s3c_device_lcd_dmamask = 0xffffffffUL;
18.
19.structplatform_devices3c_device_lcd = {
20. .name = "s3c2410-lcd",
21. .id = -1,
22. .num_resources = ARRAY_SIZE(s3c_lcd_resource),
23. .resource = s3c_lcd_resource,
24. .dev = {
25. .dma_mask = &s3c_device_lcd_dmamask,
26. .coherent_dma_mask = 0xffffffffUL
27. }
28.};
29.
30.EXPORT_SYMBOL(s3c_device_lcd);
平台设备地结构体定义为s3c_device_lcd,该设备在平台总线中地名字取为s3c2410-lcd,该平台设备申请地两个板级资源为以S3C24XX_PA_LCD为起始地IORESOURCE_MEM资源和一个定义为IRQ_LCD地IORESOURCE_IRQ资源.DXDiT。
其中,
1.#defineS3C24XX_PA_LCDS3C2410_PA_LCD
1./* LCDcontroller */
2.#defineS3C2410_PA_LCD (0x4D000000)
3.#defineS3C24XX_SZ_LCD SZ_1M
0x4D000000为LCDCON1寄存器地地址.
3.LCDController地平台设备地注册如下(文件位于linux/arch/arm/mach-s3c2440/mach-smdk2440.c):
RTCrp。
1.staticstructplatform_device *smdk2440_devices[] __initdata = {5PCzV。
2. &s3c_device_usb,
3.
4. &s3c_device_lcd,
5.
6. &s3c_device_wdt,
7. &s3c_device_i2c0,
8. &s3c_device_iis,
9. &s3c_device_rtc,
10.};
以上第4行代码将lcd平台设备注册进内核.
4.在系统初始化时将smdk2440_fb_info结构体添加进平台设备地私有结构中.具体流程如下:
4.1
1.MACHINE_START(S3C2440, "SMDK2440")
2. /* Maintainer:
BenDooks */
3. .phys_io = S3C2410_PA_UART,
4. .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,jLBHr。
5. .boot_params = S3C2410_SDRAM_PA + 0x100,
6.
7. .init_irq = s3c24xx_init_irq,
8. .map_io = smdk2440_map_io,
9. .init_machine = smdk2440_machine_init,
10. .timer = &s3c24xx_timer,
11.MACHINE_END
启动S3C2440机器,系统将通过“.init_machine = smdk2440_machine_init,”调用smdk2440_machine_init()函数.xHAQX。
4.2
1.staticvoid__initsmdk2440_machine_init(void)
2.{
3. s3c24xx_fb_set_platdata(&smdk2440_fb_info);
4. s3c_i2c0_set_platdata(NULL);
5.
6. platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));LDAYt。
7. smdk_machine_init();
8.}
在 smdk2440_machine_init函数中,通过“s3c24xx_fb_set_platdata(&smdk2440_fb_info);”将smdk2440_fb_info添加进平台设备地私有结构中.Zzz6Z。
4.3
1.void__inits3c24xx_fb_set_platdata(structs3c2410fb_mach_info *pd)dvzfv。
2.{
3. structs3c2410fb_mach_info *npd;
4.
5. npd = kmalloc(sizeof(*npd), GFP_KERNEL);
6. if (npd) {
7. memcpy(npd, pd, sizeof(*npd));
8. s3c_device_lcd.dev.platform_data = npd;
9. } else {
10. printk(KERN_ERR "nomemoryforLCDplatformdata\n");rqyn1。
11. }
12.}
以上代码为smdk2440_fb_info结构地添加过程,其中“s3c_device_lcd.dev.platform_data = npd;”为核心实现部分.Emxvx。
4.4
1.staticstructs3c2410fb_mach_infosmdk2440_fb_info__initdata = {SixE2。
2. .displays = &smdk2440_lcd_cfg,
3. .num_displays = 1,
4. .default_display = 0,
5.
6.#if 0
7. /* currentlysetupbydownloader */
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.
18. //.lpcsel = ((0xCE6) & ~7) | 1<<4,
19.};
以上为smdk2440_fb_info结构体定义.在此需要注释掉源码中地“.lpcsel = ((0xCE6) & ~7) | 1<<4”!
本结构中地关键为“ .displays = &smdk2440_lcd_cfg,”,即LCD地硬件参数,需要根据具体地LCD屏幕来确定,小生使用地是天嵌3.5寸屏幕,所以该结构体地赋值如下:
6ewMy。
4.5
1.staticstructs3c2410fb_displaysmdk2440_lcd_cfg__initdata = {kavU4。
2.
3. .lcdcon5 = S3C2410_LCDCON5_FRM565 |
4. S3C2410_LCDCON5_INVVLINE |
5. S3C2410_LCDCON5_INVVFRAME |
6. S3C2410_LCDCON5_PWREN |
7. S3C2410_LCDCON5_HWSWP,
8.
9. .type = S3C2410_LCDCON1_TFT,
10.
11. .width = 320,
12. .height = 240,
13.
14. .pixclock = 80000, /* HCLK100MHz, divisor3 */y6v3A。
15. .xres = 320,
16. .yres = 240,
17. .bpp = 16,
18.
19. .setclkval = 0x3,
20. .left_margin = 28, /* for HFPD*/
21. .right_margin = 24, /* for HBPD*/
22. .hsync_len = 42, /* for HSPW*/
23. .upper_margin = 6, /* for VFPD*/
24. .lower_margin = 2, /* for VBPD*/
25. .vsync_len = 12, /* for VSPW*/
26.
27.};
以上位LCD屏幕硬件参数.
注:
a.本文旨在将与友善之臂开发板配套地地linux-2.6.32.2内核移植到天嵌科技地TQ2440开发板上.M2ub6。
b.硬件平台:
天嵌科技TQ2440开发板(标配)
c.软件平台:
linux-2.6.32.2内核源码
第二部分:
基于ARM9处理器地linux-2.6.32.2操作系统内核移植手记part5.2(LCD驱动源码分析及移植之platformdriver) 0YujC。
5.LCD驱动模块地注册与注销:
2.int __inits3c2410fb_init(void)
3.{
4. int ret = platform_driver_register(&s3c2410fb_driver);eUts8。
5.
6. if (ret == 0)
7. ret = platform_driver_register(&s3c2412fb_driver);
8.
9. returnret;
10.}
11.
12.staticvoid__exits3c2410fb_cleanup(void)
13.{
14. platform_driver_unregister(&s3c2410fb_driver);
15. platform_driver_unregister(&s3c2412fb_driver);
16.}
17.
18.module_init(s3c2410fb_init);
19.module_exit(s3c2410fb_cleanup);
注册与注销模块由module_init宏与module_exit宏指定.
6.LCD平台设备驱动s3c2410fb_driver.
1.staticstructplatform_drivers3c2410fb_driver = {
2. .probe = s3c2410fb_probe,
3. .remove = s3c2410fb_remove,
4. .suspend = s3c2410fb_suspend,
5. .resume = s3c2410fb_resume,
6. .driver = {
7. .name = "s3c2410-lcd",
8. .owner = THIS_MODULE,
9. },
10.};
11.
12.staticstructplatform_drivers3c2412fb_driver = {
13. .probe = s3c2412fb_probe,
14. .remove = s3c2410fb_remove,
15. .suspend = s3c2410fb_suspend,
16. .resume = s3c2410fb_resume,
17. .driver = {
18. .name = "s3c2412-lcd",
19. .owner = THIS_MODULE,
20. },
21.};
该结构定义了LCD驱动程序地名字:
"s3c2410-lcd",以及探测函数probe,移除函数remove,电源挂起函数suspend和电源恢复函数resume.sQsAE。
7.探测函数s3c2410fb_probe分析.
1.static int __inits3c2410fb_probe(structplatform_device *pdev)GMsIa。
2.{
3. returns3c24xxfb_probe(pdev, DRV_S3C2410);
4.}
5.
6.static int __inits3c2412fb_probe(structplatform_device *pdev)TIrRG。
7.{
8. returns3c24xxfb_probe(pdev, DRV_S3C2412);
9.}
由此可见,真正地探测函数为s3c24xxfb_probe.
1.static int __inits3c24xxfb_probe(structplatform_device *pdev,7EqZc。
2. enums3c_drv_typedrv_type)
3.{
4. structs3c2410fb_info *info;
5. structs3c2410fb_display *display;
6. structfb_info *fbinfo;
7. structs3c2410fb_mach_info *mach_info;
8. structresource *res;
9. int ret;
10. int irq;
11. int i;
12. int size;
13. u32lcdcon1;
14.
15. mach_info = pdev->dev.platform_data;
16. if (mach_info == NULL) {
17. dev_err(&pdev->dev,
18. "noplatformdataforlcd,cannotattach\n");
19. return -EINVAL;
20. }
21.
22. if (mach_info->default_display >= mach_info->num_displays) {lzq7I。
23. dev_err(&pdev->dev, "defaultis%dbutonly%ddisplays\n",zvpge。
24. mach_info->default_display, mach_info->num_displays);NrpoJ。
25. return -EINVAL;
26. }
27.
28. display = mach_info->displays + mach_info->default_display;1nowf。
29.
30. irq = platform_get_irq(pdev, 0);
31. if (irq < 0) {
32. dev_err(&pdev->dev, "noirqfordevice\n");
33. return -ENOENT;
34. }
35.
36. fbinfo = framebuffer_alloc(sizeof(structs3c2410fb_info), &pdev->dev);fjnFL。
37. if (!
fbinfo)
38. return -ENOMEM;
39.
40. platform_set_drvdata(pdev, fbinfo);
41.
42. info = fbinfo->par;
43. info->dev = &pdev->dev;
44. info->drv_type = drv_type;
45.
46. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);tfnNh。
47. if (res == NULL) {
48. dev_err(&pdev->dev, "failedtogetmemoryregisters\n");HbmVN。
49. ret = -ENXIO;
50. gotodealloc_fb;
51. }
52.
53. size = (res->end - res->start) + 1;
54. info->mem = request_mem_region(res->start, size, pdev->name);V7l4j。
55. if (info->mem == NULL) {
56. dev_err(&pdev->dev, "failedtogetmemoryregion\n");83lcP。
57. ret = -ENOENT;
58. gotodealloc_fb;
59. }
60.
61. info->io = ioremap(res->start, size);
62. if (info->io == NULL) {
63. dev_err(&pdev->dev, "ioremap()ofregistersfailed\n");mZkkl。
64. ret = -ENXIO;
65. gotorelease_mem;
66. }
67.
68. info->irq_base = info->io + ((drv_type == DRV_S3C2412) ?
S3C2412_LCDINTBASE :
S3C2410_LCDINTBASE);AVktR。
69.
70. dprintk("devinit\n");
71.
72. strcpy(fbinfo->fix.id, driver_name);
73.
74. /* Stopthevideo */
75. lcdcon1 = readl(info->io + S3C2410_LCDCON1);
76. writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);ORjBn。
77.
78. fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
79. fbinfo->fix.type_aux = 0;
80. fbinfo->fix.xpanstep = 0;
81. fbinfo->fix.ypanstep = 0;
82. fbinfo->fix.ywrapstep = 0;
83. fbinfo->fix.accel = FB_ACCEL_NONE;
84.
85. fbinfo->var.nonstd = 0;
86. fbinfo->var.activate = FB_ACTIVATE_NOW;
87. fbinfo->var.accel_flags = 0;
88. fbinfo->var.vmode = FB_VMODE_NONINTER