高通Android camera驱动框架

1、camera kernel驱动

高通的kernel中,将camera分为两部分:video和camera两部分

1.1、camera video部分

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;

}


1.2、camera sensor部分

根据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_
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值