/** * vpif_channel_isr : ISR handler for vpif capture * @irq: irq number * @dev_id: dev_id ptr * * It changes status of the captured buffer, takes next buffer from the queue * and sets its address in VPIF registers */ static irqreturn_t vpif_channel_isr(int irq, void *dev_id) { struct vpif_device *dev = &vpif_obj; struct common_obj *common; struct channel_obj *ch; enum v4l2_field field; int channel_id = 0; int fid = -1, i; channel_id = *(int *)(dev_id); ch = dev->dev[channel_id]; field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field; for (i = 0; i < VPIF_NUMBER_OF_OBJECTS; i++) { common = &ch->common[i]; /* skip If streaming is not started in this channel */ if (0 == common->started) continue; /* Check the field format */ if (1 == ch->vpifparams.std_info.frm_fmt) { /* Progressive mode */ if (list_empty(&common->dma_queue)) continue; if (!channel_first_int[i][channel_id]) vpif_process_buffer_complete(common); channel_first_int[i][channel_id] = 0; vpif_schedule_next_buffer(common); channel_first_int[i][channel_id] = 0; } else { /** * Interlaced mode. If it is first interrupt, ignore * it */ if (channel_first_int[i][channel_id]) { channel_first_int[i][channel_id] = 0; continue; } if (0 == i) { ch->field_id ^= 1; /* Get field id from VPIF registers */ fid = vpif_channel_getfid(ch->channel_id); if (fid != ch->field_id) { /** * If field id does not match stored * field id, make them in sync */ if (0 == fid) ch->field_id = fid; return IRQ_HANDLED; } } /* device field id and local field id are in sync */ if (0 == fid) { /* this is even field */ if (common->cur_frm == common->next_frm) continue; /* mark the current buffer as done */ vpif_process_buffer_complete(common); } else if (1 == fid) { /* odd field */ if (list_empty(&common->dma_queue) || (common->cur_frm != common->next_frm)) continue; vpif_schedule_next_buffer(common); } } } return IRQ_HANDLED; }
static irqreturn_t vpif_channel_isr(int irq, void *dev_id) { struct vpif_device *dev = &vpif_obj; struct common_obj *common; struct channel_obj *ch; enum v4l2_field field; int channel_id = 0; int fid = -1, i; channel_id = *(int *)(dev_id); ch = dev->dev[channel_id]; field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field; for (i = 0; i < VPIF_NUMBER_OF_OBJECTS; i++) { common = &ch->common[i]; if (0 == common->started) continue; if (1 == ch->vpifparams.std_info.frm_fmt) { if (list_empty(&common->dma_queue)) continue; if (!channel_first_int[i][channel_id]) vpif_process_buffer_complete(common); channel_first_int[i][channel_id] = 0; vpif_schedule_next_buffer(common); channel_first_int[i][channel_id] = 0; } else { if (channel_first_int[i][channel_id]) { channel_first_int[i][channel_id] = 0; continue; } if (0 == i) { ch->field_id ^= 1; fid = vpif_channel_getfid(ch->channel_id); if (fid != ch->field_id) { if (0 == fid) ch->field_id = fid; return IRQ_HANDLED; } } if (0 == fid) { if (common->cur_frm == common->next_frm) continue; vpif_process_buffer_complete(common); } else if (1 == fid) { if (list_empty(&common->dma_queue) || (common->cur_frm != common->next_frm)) continue; vpif_schedule_next_buffer(common); } } } return IRQ_HANDLED; }