1、驱动源码分析大致思路

(1)分析LCD驱动首先需要分析内核的帧缓冲子系统,因为LCD驱动就是按照帧缓冲子系统提供的注册接口来注册的;
(2)内核帧缓冲子系统参考博客:《Linux 帧缓冲子系统详解:LCD介绍、framebuffer驱动框架、LCD驱动源码分析》;
(3)先分析LCD驱动的加载和卸载;
(4)梳理清楚应用是如果调用到LCD驱动的;
(5)LCD驱动的源码大致分为两部分:一部分是Soc的LCD控制器,一方面是LCD本身,两者都是去查阅数据手册;
(6)LCD和Soc是通过gpio口连接的,分析LCD源码还涉及内核的gpio子系统,参考博客:《2.6.35内核的gpio子系统详解》;

2、应用层、帧缓冲子系统、LCD驱动三者的联系

(1)应用层通过操作设备节点"/dev/fbn"来操作LCD屏幕;
(2)应用层操作设备节点,首先是调用到帧缓冲子系统的struct file_operations操作方法;
(3)设备节点里包含主次设备号,帧缓冲系统先根据主次设备号找到对应注册过的驱动;
(4)最后调用驱动的struct fb_ops结构体里的方法;
补充:《应用程序操作LCD源码分析》;

3、LCD驱动的加载

static struct platform_driver s3cfb_driver = {.probe = s3cfb_probe,.remove = __devexit_p(s3cfb_remove),.driver = {.name = S3CFB_NAME,.owner = THIS_MODULE,},
};static int __init s3cfb_register(void)
{//向platform平台总线注册驱动platform_driver_register(&s3cfb_driver);return 0;
}
static void __exit s3cfb_unregister(void)
{//向platform平台总线卸载驱动platform_driver_unregister(&s3cfb_driver);
}module_init(s3cfb_register);
module_exit(s3cfb_unregister);

(1)LCD驱动是利用平台总线进行注册的,在内核启动时也会注册相应的LCD的平台设备,当驱动和设备匹配就会执行驱动的probe函数;
(2)平台总线相关知识参考博客:《内核platform总线详解:定义、注册、匹配、使用示例》;

4、LCD驱动的prob函数分析

static int __devinit s3cfb_probe(struct platform_device *pdev)
{struct s3c_platform_fb *pdata;struct s3cfb_global *fbdev;struct resource *res;int i, j, ret = 0;//分配s3cfb_global结构体大小的内存fbdev = kzalloc(sizeof(struct s3cfb_global), GFP_KERNEL);if (!fbdev) {dev_err(&pdev->dev, "failed to allocate for ""global fb structure\n");ret = -ENOMEM;goto err_global;}//保存设备结构体fbdev->dev = &pdev->dev;//电流整流:和电源管理有关,实现低功耗fbdev->regulator = regulator_get(&pdev->dev, "pd");if (!fbdev->regulator) {dev_err(fbdev->dev, "failed to get regulator\n");ret = -EINVAL;goto err_regulator;}ret = regulator_enable(fbdev->regulator);if (ret < 0) {dev_err(fbdev->dev, "failed to enable regulator\n");ret = -EINVAL;goto err_regulator;}//获取platform设备传过来的私有数据pdata = to_fb_plat(&pdev->dev);if (!pdata) {dev_err(fbdev->dev, "failed to get platform data\n");ret = -EINVAL;goto err_pdata;}fbdev->lcd = (struct s3cfb_lcd *)pdata->lcd;//设置LCD相关的引脚if (pdata->cfg_gpio)pdata->cfg_gpio(pdev);//打开LCD的时钟if (pdata->clk_on)pdata->clk_on(pdev, &fbdev->clock);//获取设备IORESOURCE_MEM类的资源res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (!res) {dev_err(fbdev->dev, "failed to get io memory region\n");ret = -EINVAL;goto err_io;}/***************动态映射*****************///向内核申请地址资源res = request_mem_region(res->start,res->end - res->start + 1, pdev->name);if (!res) {dev_err(fbdev->dev, "failed to request io memory region\n");ret = -EINVAL;goto err_io;}//IO地址动态映射fbdev->regs = ioremap(res->start, res->end - res->start + 1);if (!fbdev->regs) {dev_err(fbdev->dev, "failed to remap io region\n");ret = -EINVAL;goto err_mem;}//开启相关中断,是设置的LCD控制器的寄存器s3cfb_set_vsync_interrupt(fbdev, 1);s3cfb_set_global_interrupt(fbdev, 1);//根据设备传过来的数据,设置LCD控制器s3cfb_init_global(fbdev);//构建struct fb_info结构体if (s3cfb_alloc_framebuffer(fbdev)) {ret = -ENOMEM;goto err_alloc;}//将struct fb_info结构体注册到帧缓冲子系统中if (s3cfb_register_framebuffer(fbdev)) {ret = -EINVAL;goto err_register;}//设置LCD控制器的时钟s3cfb_set_clock(fbdev);//打开默认的显示屏s3cfb_set_window(fbdev, pdata->default_win, 1);//打开屏幕的显示功能,到现在才允许视频输出到屏幕s3cfb_display_on(fbdev);//申请中断号fbdev->irq = platform_get_irq(pdev, 0);if (request_irq(fbdev->irq, s3cfb_irq_frame, IRQF_SHARED,pdev->name, fbdev)) {dev_err(fbdev->dev, "request_irq failed\n");ret = -EINVAL;goto err_irq;}#ifdef CONFIG_FB_S3C_LCD_INITif (pdata->backlight_on)pdata->backlight_on(pdev);if (!bootloaderfb && pdata->reset_lcd)pdata->reset_lcd(pdev);
#endif//和电源管理有关
#ifdef CONFIG_HAS_EARLYSUSPENDfbdev->early_suspend.suspend = s3cfb_early_suspend;fbdev->early_suspend.resume = s3cfb_late_resume;fbdev->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;register_early_suspend(&fbdev->early_suspend);
#endif//给设备创建属性文件ret = device_create_file(&(pdev->dev), &dev_attr_win_power);if (ret < 0)dev_err(fbdev->dev, "failed to add sysfs entries\n");dev_info(fbdev->dev, "registered successfully\n");//这是显示内核开机的logo
#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)if (fb_prepare_logo( fbdev->fb[pdata->default_win], FB_ROTATE_UR)) {printk("Start display and show logo\n");/* Start display and show logo on boot */fb_set_cmap(&fbdev->fb[pdata->default_win]->cmap, fbdev->fb[pdata->default_win]);fb_show_logo(fbdev->fb[pdata->default_win], FB_ROTATE_UR);}
#endifmdelay(100);//点亮屏幕的背光if (pdata->backlight_on)pdata->backlight_on(pdev);return 0;err_irq:s3cfb_display_off(fbdev);s3cfb_set_window(fbdev, pdata->default_win, 0);for (i = pdata->default_win;i < pdata->nr_wins + pdata->default_win; i++) {j = i % pdata->nr_wins;unregister_framebuffer(fbdev->fb[j]);}
err_register:for (i = 0; i < pdata->nr_wins; i++) {if (i == pdata->default_win)s3cfb_unmap_default_video_memory(fbdev->fb[i]);framebuffer_release(fbdev->fb[i]);}kfree(fbdev->fb);err_alloc:iounmap(fbdev->regs);err_mem:release_mem_region(res->start,res->end - res->start + 1);err_io:pdata->clk_off(pdev, &fbdev->clock);err_pdata:regulator_disable(fbdev->regulator);err_regulator:kfree(fbdev);err_global:return ret;
}

(1)解析出平台设备传过来的数据;
(2)设置LCD相关的gpio引脚,设置好时钟;
(3)对LCD相关的寄存器地址进行动态映射;
(4)根据平台设备传过来的数据,设置Soc的LCD控制器相关寄存器;
(5)构建struct fb_info结构体,最重要的是struct fb_ops结构体,这是LCD屏幕的具体硬件操作方法,然后注册到帧缓冲子系统中;
(6)打开默认的显示屏。一个LCD可以对应对个虚拟屏幕;
(7)给设备创建属性文件,设备属于"graphics"类,在"/sys/class/graphics"目录下可以看到;
(8)显示内核的启动logo,打开屏幕的背光,真正显示出启动logo;

LCD驱动源码分析(s3cfb.c)相关推荐

  1. (转)Linux设备驱动之HID驱动 源码分析

    //Linux设备驱动之HID驱动 源码分析 http://blog.chinaunix.net/uid-20543183-id-1930836.html HID是Human Interface De ...

  2. 【内核配置】六、修改内核自带的的LCD驱动源码并编译进内核 | 烧写到Mini2440__TD35 完整攻略...

    主   机:VMWare--Ubuntu-16.04.2-x64-100ask 开发板:Mini2440--256M NandFlash, 2M NorFlash, 64M SDRAM, LCD-TD ...

  3. 通用USB设备驱动源码分析

    通用USB设备驱动源码分析 Author:aaron 前段时间写了篇<qualcomm usb modem驱动小结>的文章, 描述了自己如何为高通的一个usb modem设备写驱动的过程, ...

  4. linux网卡驱动源码分析(一)

    linux网卡驱动源码分析(一) linux struct linux内核 网络 descriptor resources 转自http://blog.csdn.net/ustc_dylan/arti ...

  5. linux打印源码,Linux打印机驱动源码分析.pdf

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbsplinux/Unix相关 Linux打印机驱动源码分析.pdf1 ...

  6. hisi3516dv300芯片基于hwmon驱动框架的温度获取驱动源码分析

    1.内核hwmon驱动框架 参考博客:<内核hwmon驱动框架详解以及海思芯片温度驱动分析>: 2.驱动实现的效果 /sys/devices/virtual/hwmon/hwmon0 # ...

  7. 字符设备驱动基础篇1——简单的驱动源码分析

    以下内容源于朱有鹏嵌入式课程的学习,如有侵权,请告知删除. 参考资料:http://www.cnblogs.com/biaohc/p/6575074.html module_test.c代码 #inc ...

  8. 我的内核学习笔记10:Intel GPIO驱动源码分析

    本文对Intel e3800的GPIO驱动源码进行分析. 一.概述 1.1 内核配置 Intel e3800的GPIO在Linux内核中使用的驱动名为gpio_ich(为了行文方便,将对应的设备称为& ...

  9. java mysql 源码分析_JAVA JDBC(MySQL)驱动源码分析

    JAVA连接数据库是其众多功能中的一部分,主要有两种方式连接DataBase: 一种是采用JDBC-ODBC桥,另一种则是称之为纯驱动连接DataBase,第一种方式在大型项目中基本上不再使用,本系列 ...

最新文章

  1. Django 实现分库
  2. hashCode之一--两个对象值相同,有相同的hash code
  3. 日常生活 -- 开博一周年
  4. AtCoder Beginner Contest 215 G - Colorful Candies 2
  5. 数据库 流量切分_私域流量之社群运营技巧,社群运营技巧解析
  6. 英语本科 国外跨计算机,跨专业考研需具备哪些条件,如英语,计算机的过级情况...
  7. docker安装mysql redis_使用docker安装mysql和redis
  8. java 职业规划_java个人职业生涯规划范文
  9. 【郑州校区】BOS v2.0物流管理平台整体概述
  10. C++ Qt QComboBox使用教程
  11. 计算机上fn按键,fn键设置方法
  12. 没学历可以学IT吗?
  13. 【laravel-admin】权限管理与实现原理
  14. win10电脑怎么清理电脑内存
  15. 拓嘉启远电商:为什么拼多多商品会掉资源位
  16. 极路由+花生壳内网版配置
  17. linux下常用alias
  18. 关联规则 置信度定义
  19. 异常图标导致转码失败
  20. 最新2022财报,亚信科技稳步转型

热门文章

  1. 布袋除尘器过滤风速多少_布袋除尘器过滤风速的选择!
  2. 校园网限速引起网络知识:网络配置ipconfig /release ipconfig /renew
  3. AtCoder Beginner Contest 153 题解
  4. FFmpeg动效实践与探索(文字方框的同步展开及收缩)
  5. 【层级多标签文本分类】HFT-CNN: Learning Hierarchical Category Structure for Multi-label Short Text Categorizati
  6. A - The Fool HDU - 6555
  7. c语言表示时间的程序,C语言显示“当前时间”小程序
  8. redis集群批量删除指定的key
  9. RPC论文翻译(Implementing Remote Procedure Calls)
  10. 【转】怎样有效的一心多用?