從cimutils到核心-(5)一幀資料採集完成控制器響應中斷處理函式
(1)
static irqreturn_t jz_camera_irq_handler(int irq, void *data) {
if(status & CIM_STATE_DMA_EOF) { //硬體傳送這個EOF給控制器響應中斷
/* clear dma interrupt status */
temp = readl(pcdev->base + CIM_STATE);
temp &= (~CIM_STATE_DMA_EOF);
writel(temp, pcdev->base + CIM_STATE);
if(pcdev->active) { //active判斷,有資料
struct vb2_buffer *vb2 = &pcdev->active->vb2;
struct jz_buffer *buf = container_of(vb2, struct jz_buffer, vb2);
list_del_init(&buf->list);
v4l2_get_timestamp(&vb2->v4l2_buf.timestamp);
vb2->v4l2_buf.sequence = pcdev->sequence++;
vb2_buffer_done(vb2, VB2_BUF_STATE_DONE); //一幀資料採集完成,這個介面把採集完成的buffer從連結串列video_buffer_list加進done_list
/* start next dma frame. */
pcdev->active = list_entry(pcdev->video_buffer_list.next, struct jz_buffer, list);
}
void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
{
list_add_tail(&vb->done_entry, &q->done_list);
wake_up(&q->done_wq); //喚醒程序
}
(2)
應用層呼叫select後,呼叫我們控制器驅動的介面jz_camera_poll
static unsigned int jz_camera_poll(struct file *file, poll_table *pt)
{
struct soc_camera_device *icd = file->private_data;
return vb2_poll(&icd->vb2_vidq, file, pt);
}
unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
{
if (list_empty(&q->done_list))
poll_wait(file, &q->done_wq, wait); //done_list是空的話,poll_wait等待,等待中斷喚醒
}
總結:
把有資料的buffer[0]加進done_list連結串列後,應用層呼叫dqbuf就能從視訊快取佇列中取出資料