Linux camera驱动(7) - 其它

中断

        在mxc_v4l2_capture.c中的mxc_v4l_open函数,里面有这样一个选择语句

if (strcmp(mxc_capture_inputs[cam->current_input].name,"CSI MEM") == 0) {
#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE)		
			err = csi_enc_select(cam);  
#endif
		} else if (strcmp(mxc_capture_inputs[cam->current_input].name,
				  "CSI IC MEM") == 0) {
#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE)
			err = prp_enc_select(cam);
#endif
csi_enc_select
    -->cam->enc_enable = csi_enc_enabling_tasks;
 
//通过stream_on开启数据收集时,申请中断(传入回调函数camera_callback)                 
mxc_streamon
    -->cam->enc_enable(cam)  //由上可知csi_enc_enabling_tasks
        -->ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, csi_enc_callback, 0, "Mxc Camera", cam); 
            -->csi_enc_callback  
                -->schedule_work(&cam->csi_work_struct)    //主动调度系统共享工作队列中的csi_work_struct进程  

        通过查看原理图可知,slave芯片有一个 INTRQ 引脚连接到了SOC端,该引脚的功能是:在有数据可用时触发中断请求。

INIT_WORK(&cam->csi_work_struct, csi_buf_work_func);

        这个地方我觉得用等待队列来实现也可以,但是呢,没必要,因为执行csi_buf_work_func这个函数需要的条件就是“产生硬件中断”。等待队列和工作队列的各自的优势在这里有所体现,我的博客《Linux 队列》有简述两者的区别。

附录

typedef struct _cam_data {
	struct semaphore busy_lock;		/*针对SMP的信号量*/
	int open_count;					/*open函数的引用计数,调用一次open函数,这个引用计数加1*/
	/* params lock for this camera */
	struct semaphore param_lock;	/*针对camera的信号量*/

	struct list_head ready_q;	/*三个工作队列之一,这个是应用程序VIDIOC_QBUF调用后,buffer所处的队列*/
	struct list_head done_q;	/*三个工作队列之一,这个是应用程序mxc_streamon调用后,buffer所处的队列*/
	struct list_head working_q;	/*三个工作队列之一,这个是应用程序VIDIOC_DQBUF调用后,buffer所处的队列*/
	int ping_pong_csi;			/*这个值一般取0或1,在CPMEM中buffer地址更新的过程中使用*/
	spinlock_t queue_int_lock;
	spinlock_t dqueue_int_lock;
	struct mxc_v4l_frame frame[FRAME_NUM];	/*这个数组是buffer的核心,应用程序申请的frame的信息都保存在这个数组*/
	struct mxc_v4l_frame dummy_frame;	/*虚假的frame,在CPMEM初始化时用这个frame的地址来填充*/
	wait_queue_head_t enc_queue;	/*译码buffer队列,一般在camera_callback函数中唤醒,在VIDIOC_DQBUF中进行等待,与下面的enc_counter一起使用*/
	int enc_counter;				/*执行完译码任务的buffer计数,译码队列的唤醒条件*/
	dma_addr_t rot_enc_bufs[2];		/*rot中需要使用两个buffer,其中buffer的物理地址存放在这个数组中*/
	void *rot_enc_bufs_vaddr[2];	/*虚拟地址存放在这个数组中*/
	int rot_enc_buf_size[2];		/*这两个buffer的大小分别存放在这个数组中*/
	enum v4l2_buf_type type;		/*buffer的类型*/

	/* still image capture *//*静态图片的一些信息*/
	wait_queue_head_t still_queue;	/*静态图片任务队列*/
	int still_counter;				/*静态图片任务计数*/
	dma_addr_t still_buf[2];		/*静态图片任务需要使用的两个buffer的地址存放在这个数组中*/
	void *still_buf_vaddr;
    
    /*overlay的一些信息,在网络领域指的是叠加的虚拟化技术模式*/
	struct v4l2_window win;
	struct v4l2_framebuffer v4l2_fb;
	dma_addr_t vf_bufs[2];
	void *vf_bufs_vaddr[2];
	int vf_bufs_size[2];
	dma_addr_t rot_vf_bufs[2];
	void *rot_vf_bufs_vaddr[2];
	int rot_vf_buf_size[2];
	bool overlay_active;
	int output;
	struct fb_info *overlay_fb;
	int fb_origin_std;
	struct work_struct csi_work_struct;

	/* v4l2 format *//*v4l2的一些格式信息*/
	struct v4l2_format v2f; /*这个结构体保存的是v4l2的格式信息,这些信息都通过VIDIOC_S_FMT宏最后设置好保存在里面的,包括width,height,bytesperline,sizeimage等参数*/
	struct v4l2_format input_fmt;	/* camera in *//*摄像头输入的格式*/
	bool bswapenable;
	int rotation;	/* for IPUv1 and IPUv3, this means encoder rotation */
	int vf_rotation; /* viewfinder rotation only for IPUv1 and IPUv3 */
	struct v4l2_mxc_offset offset;

	/* V4l2 control bit */ /*一些控制信息*/
	int bright;		/*亮度*/
	int hue;
	int contrast;	/*对比度*/
	int saturation;
	int red;
	int green;
	int blue;
	int ae_mode;

	/* standard */
	struct v4l2_streamparm streamparm;
	struct v4l2_standard standard;
	bool standard_autodetect;

	/* crop */ /*crop的一些信息*/
	struct v4l2_rect crop_bounds;	/*crop边界信息*/
	struct v4l2_rect crop_defrect;	/*crop默认矩形的信息*/
	struct v4l2_rect crop_current;	/*当前crop的信息*/

	/*以下这几个函数指针分为三种*/
	/*encoding相关的函数指针*/
	int (*enc_update_eba) (struct ipu_soc *ipu, dma_addr_t eba, /*更新cpmem中buffer地址的函数指针*/
			       int *bufferNum);
	int (*enc_enable) (void *private);							/*使能enc函数指针*/
	int (*enc_disable) (void *private);							/*关闭enc函数指针*/
	int (*enc_enable_csi) (void *private);						/*使能csi设备函数指针*/
	int (*enc_disable_csi) (void *private);						/*关闭csi设备函数指针*/
	void (*enc_callback) (u32 mask, void *dev);					/*中断处理函数指针*/
	/*viewfinder相关的函数指针,这几个函数都在mxc_v4l2_capture.c中的start_preview函数指定*/
	int (*vf_start_adc) (void *private);
	int (*vf_stop_adc) (void *private);
	int (*vf_start_sdc) (void *private);
	int (*vf_stop_sdc) (void *private);
	int (*vf_enable_csi) (void *private);
	int (*vf_disable_csi) (void *private);
	/*csi相关的函数指针*/
	int (*csi_start) (void *private);
	int (*csi_stop) (void *private);

	/* misc status flag *//*一些标记位*/
	bool overlay_on;	/*是否打开overlay的标记位*/
	bool capture_on;	/*是否打开capture的标记位,在streamon函数中置位*/
	int overlay_pid;
	int capture_pid;
	bool low_power;		/*用于标记这个设备是否处于低功耗状态,在resume函数中设置为false,在suspend函数设置位true,这个标记位与cam->power_queue队列一起使用*/
	wait_queue_head_t power_queue; /*在resume函数中根据low_power标志位来唤醒*/
	unsigned int ipu_id;	/*ipu ID*/
	unsigned int csi;		/*每个ipu可以拥有两个csi设备,用于区别哪一个csi设备,0或者1*/
	u8 mclk_source;
	bool mclk_on[2];	/* two mclk sources at most now */
	int current_input;	/*当前输入,在mxc_v4l2_capture.c中有一个mxc_capture_inputs[]数组,驱动程序会根据current_input这个数字作为 	下标从这个数组中索引*/

	/*csi相关的信息*/
	struct camera_sensor *cam_sensor;	/* old version */
	struct v4l2_int_device *all_sensors[MXC_SENSOR_NUM];
	struct v4l2_int_device *sensor;	/*有关摄像头的信息都保存在这个结构体中,它为一个slave子设备*/
	struct v4l2_int_device *self;	/*将cam->self结构体作为一个master主设备,cam->self->priv指向这个cam_data结构体*/
} cam_data;

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值