nano-pc-t1 4412 显示驱动分析

2024-02-12 11:48
文章标签 分析 显示 驱动 pc nano t1 4412

本文主要是介绍nano-pc-t1 4412 显示驱动分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 和其它内核代码类似。

     显示驱动的分析都是由 drivers/video/fbmem.c开始,fbmem.c是显示驱动的抽象,实际只是一个框架性的东西。

     fbmem_init 中实现了一个字符设备驱动,并创建了class,但是没有生成设备文件。

    这个字符设备驱动的file_operations里面的函数,实质上都是从struct fb_info *registered_fb[FB_MAX]   这个

    fb_info的结构体数组中去调用 fb_ops 这个结构体中函数指针。数组下标为次设备号。那么这个结构体是如何赋值的

     呢?

    fbmem.c里定义 register_framebuffer这个函数。真正的显示设备都是调用这个函数来给registered_fb这个数组赋值,

   然后再去创建设备文件。


2.  我们搜索register_framebuffer这个文件,有如下几处:

     drivers/gpu/drm/drm_fb_helper.c

     drivers/video/s3c-fb.c


3. 我们先来看看s3c-fb.c

    这个文件注册了一个平台总线设备驱动程序,在其probe函数中调用 register_framebuffer。

    那么这个驱动的probe的函数什么时候调用呢?

    接下来我们看一下内核中实现平台总线驱动代码,注意,平台总线驱动是内核实现的。


4. drivers/base/platform.c

    主要看platform_match这个函数,也就是平台总线设备驱动和平台总线设备是如何匹配的,知道了匹配规则,我们

    就知道如何去需找对应的平台设备了。

    先看这句话

    if (pdrv->id_table)
        return platform_match_id(pdrv->id_table, pdev) != NULL;

   return (strcmp(pdev->name, drv->name) == 0);

    如何平台总线设备驱动中有id_table的话,那么调用platform_match_id这个函数。

   我们再看一下platform_match_id函数做个什么。

   while (id->name[0]) {
        if (strcmp(pdev->name, id->name) == 0) {
            pdev->id_entry = id;
            return id;
        }
        id++;
    }

    很显然,就是拿平台总线设备的name去挨个比较平台总线设备驱动的id_table,匹配成功测返回id。

    如果没有匹配成功,则再去比较平台总线设备的名称和平台总线驱动的名称。也就是

   return (strcmp(pdev->name, drv->name) == 0);  这句。

   一旦匹配成功,那么内核会自动调用平台总线设备驱动的probe函数。


5.  那么接下来,我们就看看s3c-fb.c这个文件里实现的平台总线设备驱动程序的name和id_table

    static struct platform_driver s3c_fb_driver = {
    .probe        = s3c_fb_probe,
    .remove        = s3c_fb_remove,
    .id_table    = s3c_fb_driver_ids,
    .driver        = {
        .name    = "s3c-fb",
        .owner    = THIS_MODULE,
        .pm    = &s3cfb_pm_ops,
    },
};

static struct platform_device_id s3c_fb_driver_ids[] = {
    {
        .name        = "s3c-fb",
        .driver_data    = (unsigned long)&s3c_fb_data_64xx,
    }, {
        .name        = "s5pc100-fb",
        .driver_data    = (unsigned long)&s3c_fb_data_s5pc100,
    }, {
        .name        = "s5pv210-fb",
        .driver_data    = (unsigned long)&s3c_fb_data_s5pv210,
    }, {
        .name        = "exynos4-fb",
        .driver_data    = (unsigned long)&s3c_fb_data_exynos4,
    }, {
        .name        = "exynos5-fb",
        .driver_data    = (unsigned long)&s3c_fb_data_exynos5,
    }, {
        .name        = "s3c2443-fb",
        .driver_data    = (unsigned long)&s3c_fb_data_s3c2443,
    }, {
        .name        = "s5p64x0-fb",
        .driver_data    = (unsigned long)&s3c_fb_data_s5p64x0,
    },
    {},
};

  有了第4点的分析,我们可以搜索上面红字部分来查找对应的平台总线设备了。


6.  搜索"s3c-fb",找到了

   arch/arm/plat-samsung/devs.c这个文件

    搜索"exynos4-fb",找到了

    arch/arm/mach-exynos/common.c

      其它name,我们应该不用理会,都是其它soc名称。


   在devs.c里定义了

   struct platform_device s3c_device_fb = {
    .name        = "s3c-fb",
    .id        = -1,
    .num_resources    = ARRAY_SIZE(s3c_fb_resource),
    .resource    = s3c_fb_resource,
    .dev        = {
        .dma_mask        = &samsung_device_dma_mask,
        .coherent_dma_mask    = DMA_BIT_MASK(32),
    },
}; 

   在common.c里是这句 s5p_fb_setname(0,"exynos4-fb");

   展开实际是这样s5p_device_fimd0.name = name;

   struct platform_device s5p_device_fimd0 = {
    .name        = "s5p-fb",    这块被改为了 "exynos4-fb"
    .id        = 0,
    .num_resources    = ARRAY_SIZE(s5p_fimd0_resource),
    .resource    = s5p_fimd0_resource,
    .dev        = {
        .dma_mask        = &samsung_device_dma_mask,
        .coherent_dma_mask    = DMA_BIT_MASK(32),
    },
};

    从以上分析,实际定义了两个设备,"s3c-fb","exynos4-fb"。


7. 现在,找到了,平台总线的设备和驱动后,我们要做的主要事情就是去修改lcd的各种参数,主要是fb_info结构体

    的fb_var_screeninfo结构体,这里面记录了lcd的主要9个参数。

   行前肩,行后肩,行同步信号脉宽,帧前肩,帧后肩,帧同步信号脉宽,像素时钟频率,x轴像素点,y轴像素点。

    分析了s3c_fb.c文件后,发现是这句来赋值,fb_videomode_to_var(&fbinfo->var, &initmode);

    经过再次分析后,实际数据是来源于平台总线设备中,pd = pdev->dev.platform_data;


8.  那么我们再次回到devs.c这个文件,因为上面两个平台总线设备均定义在次文件中。

    但是查看s3c_device_fb和s5p_device_fimd0这两个平台设备结构体后,没有发现platform_data。那么一定是后面

   专门有赋值的地方。查找后,发现

   void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
{
    s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
             &s3c_device_fb);
}

void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
{
    s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
             &s5p_device_fimd0);
}

   经过搜索发现,s5p_fimd0_set_platdata在 下面文件中调用,

  arch/arm/mach-exynos/mach-nanopc-t1.c

   arch/arm/mach-exynos/mach-smdk4x12.c  这个文件应该没用

   s3c_fb_set_platdata没有被任何地方调用,那么s3c_device_fb这个设备应该没有用处,我认为应该去掉。


9. 接下来我们主要分析s5p_device_fimd0这个设备。

    在mach-nano-t1.c 这句 两句

    nanopc_fb_init_pdata(&nanopc_fb_pdata);

    s5p_fimd0_set_platdata(&nanopc_fb_pdata);

    实际真正的数据是在nanopc_fb_pdata中,并且在nanopc_fb_init_pdata中得到的值

    再看nanopc_fb_init_pdata这个函数,发现以下几句

    lcd = tiny4412_get_lcd();

     mode->left_margin    = lcd->timing.h_bp;
    mode->right_margin    = lcd->timing.h_fp;
    mode->upper_margin    = lcd->timing.v_bp;
    mode->lower_margin    = lcd->timing.v_fp;
    mode->hsync_len        = lcd->timing.h_sw;
    mode->vsync_len        = lcd->timing.v_sw;
    mode->xres            = lcd->width;
    mode->yres            = lcd->height;

    数据实际来源于tiny4412_get_lcd()。

    tiny4412_get_lcd定义在

    arch/arm/mach-exynos/tiny4412-lcds.c

     到此,我们终于找到各种屏的参数定义,并且还有hdmi参数的定义。

   
    待续

   

   

这篇关于nano-pc-t1 4412 显示驱动分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/702531

相关文章

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse

Redis中的AOF原理及分析

《Redis中的AOF原理及分析》Redis的AOF通过记录所有写操作命令实现持久化,支持always/everysec/no三种同步策略,重写机制优化文件体积,与RDB结合可平衡数据安全与恢复效率... 目录开篇:从日记本到AOF一、AOF的基本执行流程1. 命令执行与记录2. AOF重写机制二、AOF的

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

分析 Java Stream 的 peek使用实践与副作用处理方案

《分析JavaStream的peek使用实践与副作用处理方案》StreamAPI的peek操作是中间操作,用于观察元素但不终止流,其副作用风险包括线程安全、顺序混乱及性能问题,合理使用场景有限... 目录一、peek 操作的本质:有状态的中间操作二、副作用的定义与风险场景1. 并行流下的线程安全问题2. 顺

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

C#实现SHP文件读取与地图显示的完整教程

《C#实现SHP文件读取与地图显示的完整教程》在地理信息系统(GIS)开发中,SHP文件是一种常见的矢量数据格式,本文将详细介绍如何使用C#读取SHP文件并实现地图显示功能,包括坐标转换、图形渲染、平... 目录概述功能特点核心代码解析1. 文件读取与初始化2. 坐标转换3. 图形绘制4. 地图交互功能缩放

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按