本文共 5223 字,大约阅读时间需要 17 分钟。
在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);#endifcsi_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这个函数需要的条件就是“产生硬件中断”。等待队列和工作队列的各自的优势在这里有所体现,我的博客有简述两者的区别。
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;
转载地址:http://ueuen.baihongyu.com/