Linux的LCD驱动源码分析报告及移植.docx
- 文档编号:5098205
- 上传时间:2022-12-13
- 格式:DOCX
- 页数:23
- 大小:706.07KB
Linux的LCD驱动源码分析报告及移植.docx
《Linux的LCD驱动源码分析报告及移植.docx》由会员分享,可在线阅读,更多相关《Linux的LCD驱动源码分析报告及移植.docx(23页珍藏版)》请在冰豆网上搜索。
Linux的LCD驱动源码分析报告及移植
Linux的LCD驱动源码分析及移植(三部曲)
第一部分:
基于ARM9处理器的linux-device)
1.与LCD控制器硬件相关的寄存器内容请参照三星S3C2440A技术手册中的第15章。
2. LCDController的平台设备定义如下(文件位于linux/arch/arm/plat-s3c24xx/devs.c):
1./* LCDController */
2.staticstructresources3c_lcd_resource[] = {
3. [0] = {
4. .start = S3C24XX_PA_LCD,
5. .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,
6. .flags = IORESOURCE_MEM,
7. },
8. [1] = {
9. .start = IRQ_LCD,
10. .end = IRQ_LCD,
11. .flags = IORESOURCE_IRQ,
12. }
13.};
14.staticu64s3c_device_lcd_dmamask = 0xffffffffUL;
15.structplatform_devices3c_device_lcd = {
16. .name = "s3c2410-lcd",
17. .id = -1,
18. .num_resources = ARRAY_SIZE(s3c_lcd_resource),
19. .resource = s3c_lcd_resource,
20. .dev = {
21. .dma_mask = &s3c_device_lcd_dmamask,
22. .coherent_dma_mask = 0xffffffffUL
23. }
24.};
25.EXPORT_SYMBOL(s3c_device_lcd);
平台设备的结构体定义为s3c_device_lcd,该设备在平台总线中的名字取为s3c2410-lcd,该平台设备申请的两个板级资源为以S3C24XX_PA_LCD为起始的IORESOURCE_MEM资源和一个定义为IRQ_LCD的IORESOURCE_IRQ资源。
其中,
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):
1.staticstructplatform_device *smdk2440_devices[] __initdata = {
2. &s3c_device_usb,
3. &s3c_device_lcd,
4. &s3c_device_wdt,
5. &s3c_device_i2c0,
6. &s3c_device_iis,
7. &s3c_device_rtc,
8.};
以上第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,
5. .boot_params = S3C2410_SDRAM_PA + 0x100,
6. .init_irq = s3c24xx_init_irq,
7. .map_io = smdk2440_map_io,
8. .init_machine = smdk2440_machine_init,
9. .timer = &s3c24xx_timer,
10.MACHINE_END
启动S3C2440机器,系统将通过“.init_machine = smdk2440_machine_init,”调用smdk2440_machine_init()函数。
4.2
1.staticvoid__initsmdk2440_machine_init(void)
2.{
3. s3c24xx_fb_set_platdata(&smdk2440_fb_info);
4. s3c_i2c0_set_platdata(NULL);
5. platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
6. smdk_machine_init();
7.}
在 smdk2440_machine_init函数中,通过“s3c24xx_fb_set_platdata(&smdk2440_fb_info);”将smdk2440_fb_info添加进平台设备的私有结构中。
4.3
1.void__inits3c24xx_fb_set_platdata(structs3c2410fb_mach_info *pd)
2.{
3. structs3c2410fb_mach_info *npd;
4. npd = kmalloc(sizeof(*npd), GFP_KERNEL);
5. if (npd) {
6. memcpy(npd, pd, sizeof(*npd));
7. s3c_device_ = npd;
8. } else {
9. printk(KERN_ERR "nomemoryforLCDplatformdata\n");
10. }
11.}
以上代码为smdk2440_fb_info结构的添加过程,其中“s3c_device_ = npd;”为核心实现部分。
4.4
1.staticstructs3c2410fb_mach_infosmdk2440_fb_info__initdata = {
2. .displays = &smdk2440_lcd_cfg,
3. .num_displays = 1,
4. .default_display = 0,
5.#if 0
6. /* currentlysetupbydownloader */
7. .gpccon = 0xaa940659,
8. .gpccon_mask = 0xffffffff,
9. .gpcup = 0x0000ffff,
10. .gpcup_mask = 0xffffffff,
11. .gpdcon = 0xaa84aaa0,
12. .gpdcon_mask = 0xffffffff,
13. .gpdup = 0x0000faff,
14. .gpdup_mask = 0xffffffff,
15.#endif
16. //.lpcsel = ((0xCE6) & ~7) | 1<<4,
17.};
以上为smdk2440_fb_info结构体定义。
在此需要注释掉源码中的“.lpcsel = ((0xCE6) & ~7) | 1<<4”!
本结构中的关键为“ .displays = &smdk2440_lcd_cfg,”,即LCD的硬件参数,需要根据具体的LCD屏幕来确定,小生使用的是天嵌3.5寸屏幕,所以该结构体的赋值如下:
4.5
1.staticstructs3c2410fb_displaysmdk2440_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. .width = 320,
9. .height = 240,
10. .pixclock = 80000, /* HCLK100MHz, divisor3 */
11. .xres = 320,
12. .yres = 240,
13. .bpp = 16,
14. .setclkval = 0x3,
15. .left_margin = 28, /* for HFPD*/
16. .right_margin = 24, /* for HBPD*/
17. .hsync_len = 42, /* for HSPW*/
18. .upper_margin = 6, /* for VFPD*/
19. .lower_margin = 2, /* for VBPD*/
20. .vsync_len = 12, /* for VSPW*/
21.};
以上位LCD屏幕硬件参数。
注:
a.本文旨在将与友善之臂开发板配套的的linux-
b.硬件平台:
天嵌科技TQ2440开发板(标配)
c.软件平台:
linux-
第二部分:
基于ARM9处理器的linux-driver)
5.LCD驱动模块的注册与注销:
2.int __inits3c2410fb_init(void)
3.{
4. int ret = platform_driver_register(&s3c2410fb_driver);
5. if (ret == 0)
6. ret = platform_driver_register(&s3c2412fb_driver);
7. returnret;
8.}
9.staticvoid__exits3c2410fb_cleanup(void)
10.{
11. platform_driver_unregister(&s3c2410fb_driver);
12. platform_driver_unregister(&s3c2412fb_driver);
13.}
14.module_init(s3c2410fb_init);
15.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.staticstructplatform_drivers3c2412fb_driver = {
12. .probe = s3c2412fb_probe,
13. .remove = s3c2410fb_remove,
14. .suspend = s3c2410fb_suspend,
15. .resume = s3c2410fb_resume,
16. .driver = {
17. .name = "s3c2412-lcd",
18. .owner = THIS_MODULE,
19. },
20.};
该结构定义了LCD驱动程序的名字:
"s3c2410-lcd",以及探测函数probe,移除函数remove,电源挂起函数suspend和电源恢复函数resume。
7.探测函数s3c2410fb_probe分析。
1.static int __inits3c2410fb_probe(structplatform_device *pdev)
2.{
3. returns3c24xxfb_probe(pdev, DRV_S3C2410);
4.}
5.static int __inits3c2412fb_probe(structplatform_device *pdev)
6.{
7. returns3c24xxfb_probe(pdev, DRV_S3C2412);
8.}
由此可见,真正的探测函数为s3c24xxfb_probe。
1.static int __inits3c24xxfb_probe(structplatform_device *pdev,
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. mach_info = pdev->dev.platform_data;
15. if (mach_info == NULL) {
16. dev_err(&pdev->dev,
17. "noplatformdataforlcd,cannotattach\n");
18. return -EINVAL;
19. }
20. if (mach_info->default_display >= mach_info->num_displays) {
21. dev_err(&pdev->dev, "defaultis%dbutonly%ddisplays\n",
22. mach_info->default_display, mach_info->num_displays);
23. return -EINVAL;
24. }
25. display = mach_info->displays + mach_info->default_display;
26. irq = platform_get_irq(pdev, 0);
27. if (irq < 0) {
28. dev_err(&pdev->dev, "noirqfordevice\n");
29. return -ENOENT;
30. }
31. fbinfo = framebuffer_alloc(sizeof(structs3c2410fb_info), &pdev->dev);
32. if (!
fbinfo)
33. return -ENOMEM;
34. platform_set_drvdata(pdev, fbinfo);
35. info = fbinfo->par;
36. info->dev = &pdev->dev;
37. info->drv_type = drv_type;
38. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
39. if (res == NULL) {
40. dev_err(&pdev->dev, "failedtogetmemoryregisters\n");
41. ret = -ENXIO;
42. gotodealloc_fb;
43. }
44. size = (res->end - res->start) + 1;
45. info->mem = request_mem_region(res->start, size, pdev->name);
46. if (info->mem == NULL) {
47. dev_err(&pdev->dev, "failedtogetmemoryregion\n");
48. ret = -ENOENT;
49. gotodealloc_fb;
50. }
51. info->io = ioremap(res->start, size);
52. if (info->io == NULL) {
53. dev_err(&pdev->dev, "ioremap()ofregistersfailed\n");
54. ret = -ENXIO;
55. gotorelease_mem;
56. }
57. info->irq_base = info->io + ((drv_type == DRV_S3C2412) ?
S3C2412_LCDINTBASE :
S3C2410_LCDINTBASE);
58. dprintk("devinit\n");
59. strcpy(fbinfo->fix.id, driver_name);
60. /* Stopthevideo */
61. lcdcon1 = readl(info->io + S3C2410_LCDCON1);
62. writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
63. fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
64. fbinfo->fix.type_aux = 0;
65. fbinfo->fix.xpanstep = 0;
66. fbinfo->fix.ypanstep = 0;
67. fbinfo->fix.ywrapstep = 0;
68. fbinfo->fix.accel = FB_ACCEL_NONE;
69. fbinfo->var.nonstd = 0;
70. fbinfo->var.activate = FB_ACTIVATE_NOW;
71. fbinfo->var.accel_flags = 0;
72. fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
73. fbinfo->fbops = &s3c2410fb_ops;
74. fbinfo->flags = FBINFO_FLAG_DEFAULT;
75. fbinfo->pseudo_palette = &info->pseudo_pal;
76. for (i = 0; i < 256; i++)
77. info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
78. ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info);
79. if (ret) {
80. dev_err(&pdev->dev, "cannotgetirq%d-err%d\n", irq, ret);
81. ret = -EBUSY;
82. gotorelease_regs;
83. }
84. info->clk = clk_get(NULL, "lcd");
85. if (!
info->clk || IS_ERR(info->clk)) {
86. printk(KERN_ERR "failedtogetlcdclock
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux LCD 驱动 源码 分析 报告 移植