赞
踩
高通的kernel中,将camera分为两部分:video和camera两部分
video部分与userspace进行交互,sensor是有camera厂商定义的寄存器配置部分,主要完成相关寄存器参数的配置。
主要文件路径:kernel\msm-4.4\arch\arm\boot\dts\qcom\sdm660-camera.dtsi
kernel\msm-4.4\drivers\media\platform\msm\camera_v2\msm.c
qcom,msm-cam@ca00000 {
compatible = "qcom,msm-cam";
reg = <0xca00000 0x4000>;
reg-names = "msm-cam";
status = "ok";
bus-vectors = "suspend", "svs", "nominal", "turbo";
qcom,bus-votes = <0 150000000 320000000 320000000>;
qcom,gpu-limit = <700000000>;
};
static const struct of_device_id msm_dt_match[] = {
{.compatible = “qcom,msm-cam”},
{}
};
MODULE_DEVICE_TABLE(of, msm_dt_match);static struct platform_driver msm_driver = {
.probe = msm_probe,
.driver = {
.name = “msm”,
.owner = THIS_MODULE,
.of_match_table = msm_dt_match,
},
};static int __init msm_init(void)
{
return platform_driver_register(&msm_driver);
}
如上:这就是一个简单的platform框架的驱动设备文件,主要提供camera平台的电器参数。
在platform_drv中的probe()才是我们重点关注的,大胆猜测一下:不就是注册video设备到内核的video链表中吗?
msm_v4l2_dev该函数就是驱动的重点分析对象:如下,构造一个msm_v4l2_dev数据,并且调用v4l2_device_register()来将的v4l2部分注册进系统的video链表,调用video_register_device()来注册video部分。
static struct v4l2_device *msm_v4l2_dev; // 初始化一个 v4l2_device 类型的结构体 static int msm_probe(struct platform_device *pdev) { struct msm_video_device *pvdev = NULL; static struct dentry *cam_debugfs_root; // 1. 初始化一个 v4l2_device 类型的结构体,并分配好结构体内存 msm_v4l2_dev = kzalloc(sizeof(*msm_v4l2_dev), GFP_KERNEL); pvdev = kzalloc(sizeof(struct msm_video_device), GFP_KERNEL); // 2. 分配 video_device 结构体内存 pvdev->vdev = video_device_alloc(); // ---> kzalloc(sizeof(struct video_device), GFP_KERNEL); // 3. 分配 media_device 结构体内存 msm_v4l2_dev->mdev = kzalloc(sizeof(struct media_device), GFP_KERNEL); strlcpy(msm_v4l2_dev->mdev->model, MSM_CONFIGURATION_NAME, sizeof(msm_v4l2_dev->mdev->model)); // msm_config msm_v4l2_dev->mdev->dev = &(pdev->dev); // 4. 注册 media_device , 使用的 v4l2 rc = media_device_register(msm_v4l2_dev->mdev); pvdev->vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; // V4L pvdev->vdev->entity.group_id = QCAMERA_VNODE_GROUP_ID; // #define QCAMERA_VNODE_GROUP_ID 2 msm_v4l2_dev->notify = msm_sd_notify; // 用于发现对应的 subdev pvdev->vdev->v4l2_dev = msm_v4l2_dev; // 5. 设置父设备为 pdev->dev (也就是 qcom,msm-cam 的设备信息) rc = v4l2_device_register(&(pdev->dev), pvdev->vdev->v4l2_dev); // 6. 注册 video_device设备 strlcpy(pvdev->vdev->name, "msm-config", sizeof(pvdev->vdev->name)); pvdev->vdev->release = video_device_release; pvdev->vdev->fops = &msm_fops; // 配置 video_device 的字符设备操作函数 pvdev->vdev->ioctl_ops = &g_msm_ioctl_ops; // 配置 v4l2 IOCTRL pvdev->vdev->minor = -1; pvdev->vdev->vfl_type = VFL_TYPE_GRABBER; rc = video_register_device(pvdev->vdev, VFL_TYPE_GRABBER, -1); // 7. 将当前 msm_video_device 结构体设为私有数据 video_set_drvdata(pvdev->vdev, pvdev); // 8. 分配 msm_queue_head 结构体内存 msm_session_q = kzalloc(sizeof(*msm_session_q), GFP_KERNEL); msm_init_queue(msm_session_q); // 9. 创建 camera 调试目录 cam_debugfs_root = debugfs_create_dir(MSM_CAM_LOGSYNC_FILE_BASEDIR, NULL); rc = cam_ahb_clk_init(pdev); of_property_read_u32(pdev->dev.of_node, "qcom,gpu-limit", &gpu_limit); goto probe_end; }
根据dts中camera sensor属性可知、节点为 compatible = "qcom,camera";
所以对饮的驱动路径为:kernel\msm-4.4\drivers\media\platform\msm\camera_v2\sensor\msm_sensor_driver.c
static const struct of_device_id msm_sensor_driver_dt_match[] = { {.compatible = "qcom,camera"}, {} }; MODULE_DEVICE_TABLE(of, msm_sensor_driver_dt_match); static struct platform_driver msm_sensor_platform_driver = { .probe = msm_sensor_driver_platform_probe, .driver = { .name = "qcom,camera", .owner = THIS_MODULE, .of_match_table = msm_sensor_driver_dt_match, }, .remove = msm_sensor_platform_remove, }; static struct i2c_driver msm_sensor_driver_i2c = { .id_table = i2c_id, .probe = msm_sensor_driver_i2c_probe, .remove = msm_sensor_driver_i2c_remove, .driver = { .name = SENSOR_DRIVER_I2C, }, }; static int __init msm_sensor_driver_init(void) { rc = platform_driver_register(&msm_sensor_platform_driver); rc = i2c_add_driver(&msm_sensor_driver_i2c); return rc; }
依旧还是一个platform_driver设备类型,重点关注probe函数
代码路径:kernel\msm-4.4\drivers\media\platform\msm\camera_v2\sensor\msm_sensor_driver.c
static int32_t msm_sensor_driver_platform_probe(struct platform_device *pdev) { int32_t rc = 0; struct msm_sensor_ctrl_t *s_ctrl = NULL; // 1. 创建并分配 msm_sensor_ctrl_t 结构体内存。 /* Create sensor control structure */ s_ctrl = kzalloc(sizeof(*s_ctrl), GFP_KERNEL); platform_set_drvdata(pdev, s_ctrl); // 2. 将sensor device type 初始化为 MSM_CAMERA_PLATFORM_DEVICE /* Initialize sensor device type */ s_ctrl->sensor_device_type = MSM_CAMERA_PLATFORM_DEVICE; s_ctrl->of_node = pdev->dev.of_node; /*fill in platform device*/ s_ctrl->pdev = pdev; // 3. 解析 节点为 compatible = "qcom,camera"; 的 dts 内容 rc = msm_sensor_driver_parse(s_ctrl); // 4. 解析dts 中配置的camera clk 信息 // 解析 clock-names = "cam_src_clk", "cam_clk"; // 解析 qcom,clock-rates = <24000000 0>; /* Get clocks information */ rc = msm_camera_get_clk_info(s_ctrl->pdev, &s_ctrl->sensordata->power_info.clk_info, &s_ctrl->sensordata->power_info.clk_ptr, &s_ctrl->sensordata->power_info.clk_info_size); /* Fill platform device id*/ pdev->id = s_ctrl->id; /* Fill device in power info */ s_ctrl->sensordata->power_info.dev = &pdev->dev; return rc; }
dts的属性解析:
static int32_t msm_sensor_driver_parse(struct msm_sensor_ctrl_t *s_ctrl){
/* Allocate memory for sensor_i2c_client */
s_ctrl->sensor_i2c_client = kzalloc(sizeof(*s_ctrl->sensor_i2c_client), GFP_KERNEL);
/* Parse dt information and store in sensor control structure */
rc = msm_sensor_driver_get_dt_data(s_ctrl); // 解析Camera DTS 节点,详见 Chapter 3.2
/* Initilize v4l2 subdev info */
s_ctrl->sensor_v4l2_subdev_info = msm_sensor_driver_subdev_info;
s_ctrl->sensor_v4l2_subdev_info_size =ARRAY_SIZE(msm_sensor_driver_subdev_info);
/* Initialize default parameters */
rc = msm_sensor_init_
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。