关于qcom camera cpp driver 的buf分析笔记(msm8996)

关于qcom camera cpp driver 的buf分析笔记(msm8996)

tags : linux camera

CPP工作过程

其实cpp的工作过程就是一个伴随着buf流转的过程,这里节约时间,以最简便的方式把主线过程记录下来。

1 cpp_open_node()

主要做了两件事:1、初始化硬件,2、初始化mem。

  • cpp_init_hardware():设置一些硬件参数、时钟、注册中断以及buf管理接口:msm_cam_buf_mgr_register_ops()
  • cpp_init_mem() : 其实就是获取cpp_dev->iommu_hdl,这个东西是在msm_cam_smmu设备driver中统一管理的,vfe中有记录过这里。

2 VIDIOC_MSM_CPP_GET_INST_INFO32

user space获取cpp参数,具体是干什么结合android侧分析的时候再记录。

3 VIDIOC_SUBSCRIBE_EVENT

v4l2中的event系统,这里十之八九是订阅的V4L2_EVENT_CPP_FRAME_DONE事件……其实加个打印看一眼就可以确定了……

4 VIDIOC_MSM_CPP_IOMMU_ATTACH32 --> VIDIOC_MSM_CPP_IOMMU_ATTACH

int arm_iommu_attach_device(struct device *dev,
			    struct dma_iommu_mapping *mapping)
{
	int err;

	err = iommu_attach_device(mapping->domain, dev);
	if (err)
		return err;

	kref_get(&mapping->kref);
	dev->archdata.mapping = mapping;
	set_dma_ops(dev, &iommu_ops);

	pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev));
	return 0;
}

1、调用domain的attach
2、设置dev的iommu操作为:iommu_ops
关于这块在VFE中已经有记录。

5 VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO32 --> VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO

msm_cpp_subdev_ioctl 
{
……
    switch (cmd) {
    ……
        case VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO: {//198
        ……
        /* 从cpp_dev->buff_queue[i]中找到指定的buff queue */
            buff_queue_info = msm_cpp_get_buff_queue_entry(cpp_dev,
    				(k_stream_buff_info.identity >> 16) & 0xFFFF,
    				k_stream_buff_info.identity & 0xFFFF);
    
            /* 如果指定的buff queue不存在则添加这个buff queue */
    		if (buff_queue_info == NULL) {
                /* 从cpp_dev->buff_queue[i]中找到一个没用的buff queue */
    			rc = msm_cpp_add_buff_queue_entry(cpp_dev,
    				((k_stream_buff_info.identity >> 16) & 0xFFFF),
    				(k_stream_buff_info.identity & 0xFFFF));
                 ……
    		}
=           ……
    		if (VIDIOC_MSM_CPP_DELETE_STREAM_BUFF == cmd) {
    			……
    		} else {
    			for (j = 0; j < k_stream_buff_info.num_buffs; j++) {
    			   /* 逐条把每个buf info加入到该buff queue中,这里是用ion分配的buf */
    				msm_cpp_queue_buffer_info(cpp_dev,
    					buff_queue_info,
    					&k_stream_buff_info.buffer_info[j]);
    			}
    		}
    	}
    	……
    }
……
}

6 VIDIOC_MSM_CPP_SET_CLOCK32 --> VIDIOC_MSM_CPP_SET_CLOCK

设置时钟……

7 VIDIOC_MSM_CPP_CFG32

这里就是开始工作了,通过VIDIOC_MSM_CPP_CFG32给cpp喂一帧数据,然后cpp吐一帧数据。

static int msm_cpp_cfg_frame(struct cpp_device *cpp_dev,
	struct msm_cpp_frame_info_t *new_frame)
{
……
/* 把input buff的物理地址通过iommu映射给cpp的va,返回的phyaddr其实是cpp的va */
	in_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev,
		&new_frame->input_buffer_info,
		((new_frame->input_buffer_info.identity >> 16) & 0xFFFF),
		(new_frame->input_buffer_info.identity & 0xFFFF), &in_fd);
……
/* 把output buff的物理地址通过iommu映射给cpp的va,返回的phyaddr其实是cpp的va
 * output的buff在前面“VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO”时已经映射好了,这里直接读
 */
		out_phyaddr0 = msm_cpp_fetch_buffer_info(cpp_dev,
			&new_frame->output_buffer_info[0],
			((iden >> 16) & 0xFFFF),
			(iden & 0xFFFF),
			&new_frame->output_buffer_info[0].fd);
……
/* 把input buf 和 output buf的地址写给cpp,这里是把cpp所看到的va写下去了 */
	msm_cpp_update_frame_msg_phy_address(cpp_dev, new_frame,
		in_phyaddr, out_phyaddr0, out_phyaddr1,
		tnr_scratch_buffer0, tnr_scratch_buffer1);
……
}

8 cpp irq : IRQF_TRIGGER_RISING"

当cpp处理完一帧数据后,产生该中断,通知相关的模块来取数据。

msm_cpp_irq() --> tasklet_schedule(&cpp_dev->cpp_tasklet) --> msm_cpp_do_tasklet() --> msm_cpp_notify_frame_done() --> msm_enqueue(&cpp_dev->eventData_q, ...) --> v4l2_event_queue(V4L2_EVENT_CPP_FRAME_DONE)

通过v4l2 event机制通知订阅了V4L2_EVENT_CPP_FRAME_DONE消息的模块来取数据
VIDIOC_DQEVENT(89)

相关模块把数据读走
VIDIOC_MSM_CPP_GET_EVENTPAYLOAD32(193)


内存使用流程

关于msm8996平台下,cpp driver中buf的管理过程记录一下,除vfe模块外,vpe模块的管理模式也是这样。由于msm8996平台较老,从835平台开始这一块的变化就比较大,这里等有了新平台再对新平台进行分析。

先是整个buf相关的管理过程序列图:

stream buf sequence.jpg-506.2kB

这里cpp的input buf是vfe的Output buf,在其他情况下也可以不是。cpp的output buf是对cpp进行配置时通过VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO32来下发的,这点跟vfe模块一样,所有的输入输出buf都是有ion分配出来的。

这里output buf的index是由msm_vb2来决定的,vb2通过VIDIOC_REQBUFS进行设置的,而cpp的cpp_dev->buff_queue[i]->native_buff_head通过VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO32获取,这里cpp_dev中的buf管理有一个重要的作用就是cam_smmu_get_phy_addr()。get phy addr这个东西在VFE中已经记录过了,就是把这个ion分配的内存通过smmu映射到CPP的虚拟地址上面去,这里获取的所谓的phy addr其实就是cpp的虚拟地址。

至于android那边是如何管理这两个内存的,等研究过那部分代码后再单独记录,目前猜测应该都源自同一个ion分配的内存,并且两者要保持完全的一致。


这里记录一下关于msm vb2相关操作的来源

相关文件:msm.c

相关函数:

static int msm_probe(struct platform_device *pdev)
{
……
    msm_v4l2_dev->notify = msm_sd_notify;
    pvdev->vdev->v4l2_dev = msm_v4l2_dev;
……
}

相关文件:msm_generic_buf_mgr.c

相关函数:

static int32_t __init msm_buf_mngr_init(void)
{
……
    v4l2_subdev_notify(&msm_buf_mngr_dev->subdev.sd, MSM_SD_NOTIFY_REQ_CB,
    		&msm_buf_mngr_dev->vb2_ops);
……
}

这里的v4l2_subdev_notify最终就是调用的msm_sd_notify()

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值