CMOS摄像头驱动分析-i2c驱动


文章目录

  • CMOS摄像头驱动分析-i2c驱动
  • 设备树内容
  • module_i2c_driver宏分析
  • ov2640_i2c_driver
    • ov2640_probe

设备树内容

ov2640: camera@0x30 {compatible = "ovti,ov2640";reg = <0x30>;status = "okay";pinctrl-names = "default";pinctrl-0 = <&pinctrl_csi1&csi_pwn_rst>;resetb = <&gpio1 2 GPIO_ACTIVE_LOW>;pwdn = <&gpio1 4 GPIO_ACTIVE_HIGH>;clocks = <&clks IMX6UL_CLK_CSI>;clock-names = "xvclk";port {camera_ep: endpoint {remote-endpoint = <&csi_ep>;bus-width = <8>;};};};

module_i2c_driver宏分析

// 注册i2c驱动程序

module_i2c_driver(ov2640_i2c_driver);

module_i2c_driver(ov2640_i2c_driver),可以分析出以下信息:
module_i2c_driver是一个宏,它可能是在编程中定义的一个宏,用于简化I2C驱动模块的注册。
ov2640_i2c_driver是一个I2C驱动的结构体或变量名。它可能定义了有关OV2640摄像头的I2C通信设置和功能的信息。
宏module_i2c_driver可能在内部执行一些操作,以便将ov2640_i2c_driver的I2C驱动注册到系统中。这通常涉及使用相关的函数和数据结构将驱动程序添加到I2C驱动程序列表中,并与I2C总线进行关联。
总的来说,module_i2c_driver(ov2640_i2c_driver)宏的作用是将ov2640_i2c_driver所定义的I2C驱动注册到系统中,以便系统能够正确识别和使用与OV2640摄像头相关的I2C通信功能。
module_i2c_driver原型

#define module_i2c_driver(__i2c_driver) \module_driver(__i2c_driver, i2c_add_driver, \i2c_del_driver)

根据您提供的代码宏定义,module_i2c_driver宏用于简化I2C驱动模块的注册和注销过程,并使用了module_driver宏。
该宏定义的详细分析如下:
module_i2c_driver是宏的名称。
__i2c_driver是一个传入的参数,表示要注册的I2C驱动程序。宏的具体实现包括以下步骤:
使用module_driver宏,传入__i2c_driver作为驱动参数,以及i2c_add_driver和i2c_del_driver作为注册和注销函数。
i2c_add_driver是用于将I2C驱动程序添加到系统中的函数。
i2c_del_driver是用于从系统中注销I2C驱动程序的函数。
通过使用module_i2c_driver宏,可以将注册和注销I2C驱动程序的过程简化为调用module_driver宏,并传入适当的参数。这样可以减少手动编写注册和注销函数的工作量,并提高代码的可读性和可维护性。
总结而言,module_i2c_driver宏的作用是将指定的I2C驱动程序注册到系统中,并在加载模块时调用注册函数,以及在卸载模块时调用注销函数。
module_i2c_driver的原型为module_driver,定义如下

#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);

module_driver宏用于简化驱动模块的注册和注销过程,并提供了模块的初始化和退出函数。
该宏定义的详细分析如下:
module_driver是宏的名称。
__driver是一个传入的参数,表示要注册的驱动程序。
__register是一个传入的参数,表示用于注册驱动的函数。
__unregister是一个传入的参数,表示用于注销驱动的函数。
…表示可变参数,用于传递额外的参数给注册和注销函数。
宏的具体实现包括以下步骤:
定义一个静态的初始化函数__driver##_init,该函数在模块初始化时被调用。
在__driver##_init函数中,调用__register函数来注册驱动程序,传递驱动程序结构体和额外的参数。
使用module_init宏将__driver##_init函数指定为模块的初始化函数,确保在加载模块时会调用该函数进行初始化。
定义一个静态的退出函数__driver##_exit,该函数在模块注销时被调用。
在__driver##_exit函数中,调用__unregister函数来注销驱动程序,传递驱动程序结构体和额外的参数。
使用module_exit宏将__driver##_exit函数指定为模块的退出函数,确保在卸载模块时会调用该函数进行注销。
通过使用module_driver宏,可以简化驱动模块的注册和注销过程,减少了手动编写初始化和退出函数的工作量,提高了代码的可读性和可维护性。

ov2640_i2c_driver

ov2640的i2c驱动程序

// 定义ov2640的i2c设备ID
static const struct i2c_device_id ov2640_id[] = {{ "ov2640", 0 }, // 设备名为ov2640,ID为0{ } // 结束符
};MODULE_DEVICE_TABLE(i2c, ov2640_id); // 将ov2640_id注册到i2c设备表中,以便内核能够自动加载驱动程序// 定义设备树匹配表
static const struct of_device_id ov2640_of_match[] = {{.compatible = "ovti,ov2640", }, // 匹配ovti,ov2640{}, // 结束符
};MODULE_DEVICE_TABLE(of, ov2640_of_match); // 将ov2640_of_match注册到设备树匹配表中,以便内核能够自动加载驱动程序// 定义ov2640的i2c驱动程序
static struct i2c_driver ov2640_i2c_driver = {.driver = {.name = "ov2640", // 驱动程序名为ov2640.of_match_table = of_match_ptr(ov2640_of_match), // 设置设备树匹配表},.probe    = ov2640_probe, // 设置探测函数.remove   = ov2640_remove, // 设置反初始化函数.id_table = ov2640_id, // 设置i2c设备ID
};

ov2640_probe

这个函数是用于初始化并探测OV2640摄像头的驱动程序。下面是对该函数的概括总结:
检查所使用的I2C适配器是否支持SMBUS功能,如果不支持则返回错误码。
分配内存并初始化ov2640_priv结构体。
获取摄像头的时钟,如果获取失败则返回延迟探测错误码。
检查是否存在soc_camera_subdev_desc结构体或设备树节点,如果都不存在则返回错误码。
如果不存在soc_camera_subdev_desc结构体,从设备树中获取OV2640的GPIO引脚并进行初始化。
初始化v4l2子设备,使用ov2640_subdev_ops作为操作函数。
初始化v4l2控制器,创建VFLIP和HFLIP控制器。
将控制器绑定到子设备的控制器处理器中。
如果控制器存在错误,则返回错误码。
进行视频探测,初始化摄像头的视频功能。
如果视频探测失败,则释放控制器并释放时钟,并返回错误码。
注册v4l2异步子设备。
如果注册失败,则释放探测的视频,并返回错误码。
打印OV2640已成功探测的消息。
返回0表示探测成功。
如果探测失败,将会在相应的错误标签处释放控制器和时钟,并返回相应的错误码。

static int ov2640_probe(struct i2c_client *client,const struct i2c_device_id *did)
{struct ov2640_priv    *priv;struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); // 获取soc_camera_subdev_descstruct i2c_adapter    *adapter = to_i2c_adapter(client->dev.parent); // 获取i2c_adapterint            ret;if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { // 如果i2c_adapter不支持SMBUSdev_err(&adapter->dev,"OV2640: I2C-Adapter doesn't support SMBUS\n"); // 打印错误信息return -EIO; // 返回-EIO}priv = devm_kzalloc(&client->dev, sizeof(struct ov2640_priv), GFP_KERNEL); // 分配内存if (!priv) { // 如果分配失败dev_err(&adapter->dev,"Failed to allocate memory for private data!\n"); // 打印错误信息return -ENOMEM; // 返回-ENOMEM}priv->clk = v4l2_clk_get(&client->dev, "xvclk"); // 获取时钟if (IS_ERR(priv->clk)) // 如果获取失败return -EPROBE_DEFER; // 返回-EPROBE_DEFERif (!ssdd && !client->dev.of_node) { // 如果soc_camera_subdev_desc不存在且设备树节点不存在dev_err(&client->dev, "Missing platform_data for driver\n"); // 打印错误信息ret = -EINVAL; // 返回-EINVALgoto err_clk; // 跳转到err_clk}//if (!ssdd) {ret = ov2640_probe_dt(client, priv); // 从设备树中获取ov2640的GPIO引脚并进行初始化if (ret) // 如果初始化失败goto err_clk; // 跳转到err_clk//}// 初始化v4l2子设备v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);// 初始化v4l2控制器v4l2_ctrl_handler_init(&priv->hdl, 2);// 添加vflip控制器v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,V4L2_CID_VFLIP, 0, 1, 1, 0);// 添加hflip控制器v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,V4L2_CID_HFLIP, 0, 1, 1, 0);// 设置子设备的控制器priv->subdev.ctrl_handler = &priv->hdl;// 如果控制器有错误,则返回错误if (priv->hdl.error) {ret = priv->hdl.error;goto err_clk;}// 进行视频探测ret = ov2640_video_probe(client);// 如果探测失败,则跳转到err_videoprobeif (ret < 0)goto err_videoprobe;// 注册v4l2异步子设备ret = v4l2_async_register_subdev(&priv->subdev);// 如果注册失败,则跳转到err_videoprobeif (ret < 0)goto err_videoprobe;// 打印信息dev_info(&adapter->dev, "OV2640 Probed\n");// 返回0return 0;// 如果探测失败,则释放控制器并释放时钟
err_videoprobe:v4l2_ctrl_handler_free(&priv->hdl);
err_clk:v4l2_clk_put(priv->clk);// 返回错误码return ret;
}

ov2640_remove
这个函数是用于从i2c_client中获取ov2640_priv结构体,并进行反初始化操作。下面是对该函数的概括总结:
从i2c_client中获取ov2640_priv结构体。
取消v4l2异步子设备的注册。
释放时钟资源。
取消v4l2子设备的注册。
释放控制器资源。
返回0表示反初始化成功。
该函数主要用于释放与OV2640摄像头驱动程序相关的资源,包括时钟、控制器和子设备的注册。
// 从i2c_client中获取ov2640_priv,并进行反初始化

static int ov2640_remove(struct i2c_client *client)
{struct ov2640_priv       *priv = to_ov2640(client); // 获取ov2640_privv4l2_async_unregister_subdev(&priv->subdev); // 取消v4l2异步子设备的注册v4l2_clk_put(priv->clk); // 释放时钟v4l2_device_unregister_subdev(&priv->subdev); // 取消v4l2子设备的注册v4l2_ctrl_handler_free(&priv->hdl); // 释放控制器return 0; // 返回0
}

如果文章对您有帮助,点赞

CMOS摄像头驱动分析-i2c驱动相关推荐

  1. 第三章 rt-thread设备驱动模型-i2c驱动

    rt-thread设备驱动模型-i2c驱动 1. 回顾 前面两章分别介绍了rt-thread设备驱动框架的实现原理,以及介绍了一个简单的看门狗驱动程序,用来加深对驱动框架的理解.看门狗驱动程序最终归纳 ...

  2. linux用户空间flash驱动,全面掌握Linux驱动框架——字符设备驱动、I2C驱动、总线设备驱动、NAND FLASH驱动...

    原标题:全面掌握Linux驱动框架--字符设备驱动.I2C驱动.总线设备驱动.NAND FLASH驱动 字符设备驱动 哈~ 这几天都在发图,通过这种方式,我们希望能帮大家梳理学过的知识,全局的掌握Li ...

  3. Linux驱动分析——I2C子系统

    stm32mp157  盘古开发板  Linux内核版本4.19 目录 1.朱有鹏老师视频笔记 2.I2C子系统的4个关键结构体 3.关键文件 4.i2c-core.c初步分析 ​4.1.smbus代 ...

  4. Exynos4412 IIC总线驱动开发(一)—— IIC 基础概念及驱动架构分析 (iic驱动框架,i2c驱动框架)...

    转载于 : http://blog.csdn.net/zqixiao_09/article/details/50917655 关于Exynos4412 IIC 裸机开发请看 :Exynos4412 裸 ...

  5. linux驱动:i2c驱动(二)

    3.驱动源码分析 IPNC_RDK_V3.8.0.1/Source/ti_tools/ipnc_psp_arago/kernel/sound/soc/codecs/tlv320aic3x.c 3.1 ...

  6. CMOS摄像头简单分析

    CMOS摄像头:ov7740摄像头模块 1.输出分辨率有:VGA(640*480) QVGA(240*320) CIF(352*288)或者更小的任意大小. 2.有效感光阵列:656*488 3.镜头 ...

  7. 《Linux驱动:I2C驱动看这一篇就够了》

    文章目录 一,前言 二,IIC驱动的体系架构 2.1 IIC核心 2.2 IIC适配器 2.2.1 适配器驱动资源的初始化和注册 2.2.2 IIC适配器里的通信方法 2.2.3 IIC适配器和IIC ...

  8. linux 触摸结构体,xboot-x4412ibox项目实战54-Linux触摸屏驱动之I2C驱动实验 - Powered by Discuz!...

    前面我们分析了linux触摸屏驱动的input子系统机制,本章节分析linux触摸屏驱动的i2c机制. 驱动源码路径: kernel/drivers/input/touchscreen/ft5x06_ ...

  9. linux驱动:i2c驱动(四)流程图之注册驱动

    二.i2c设备的驱动部分 1.i2c驱动i2c_driver 2.通过i2c_add_driver注册 2.注册过程中 比较i2c_device_id数组中各成员的id与i2c_client中的名字, ...

最新文章

  1. gsmake —— golang版gradle
  2. GIT常用的基础命令
  3. svm 支持向量机 回归 预测_机器学习:简单理解支持向量机SVM
  4. 抖音提示需要转换为mp4_如何将MP4文件转换为MP3格式?万兴优转帮你轻松完成转换...
  5. Event/window.Event属性和方法
  6. WPF: 使用CommandManager.InvalidateRequerySuggested手动更新Command状态
  7. 开源项目几点心得,Java架构必会几大技术点
  8. 【三维深度学习】多视角立体视觉 MVSNet代码解读
  9. 动态规划——环形子数组的最大和(Leetcode 918)
  10. 解决to_hdf() 报错ImportError: Missing optional dependency ‘tables‘. Use pip or conda to install tables.
  11. c语言界面飞机图形代码,求个用最简单的的代码来实现图形界面…
  12. linux修改参数命令,linux chfn命令参数及用法详解(linux修改用户资料命令)
  13. Oracle 视图、序列、索引、游标、触发器、事务
  14. 给大楼装上转动外壳减少风力作用
  15. Shopee2022届校园招聘提前批笔试
  16. java socket监听_Java -socket接口(监听)
  17. Oracle 基本语句语法
  18. what is VC维
  19. spring boot 集成druid数据库连接池,并打印sql
  20. 数据结构和算法 数论 水仙花数

热门文章

  1. SpringBoot(模板Thymeleaf)
  2. 【JQuery框架】JQuery对象和JS对象的区别和转换
  3. c语言获取PCI信息,C语言-遍历pci设备
  4. 从Visual Studio看微软20年技术变迁
  5. win7计算机评分达到7分,话说怎么才能让cpu得到7.6分?win7评分
  6. 2021西门子比赛东北赛区一等奖WINCC画面
  7. 中国“超级工程”震惊世界 打造四大领域“国家名片”
  8. 月夜_飘云羽逸_新浪博客
  9. 4-20ma转 0-5V
  10. Firefox地址栏收藏星星图标被移除后如何恢复