static irqreturn_t venc_isr(int irq, void *arg) { struct vpbe_display *disp_dev = (struct vpbe_display *)arg; struct vpbe_layer *layer; static unsigned last_event; unsigned event = 0; int fid; int i; if ((NULL == arg) || (NULL == disp_dev->dev[0])) return IRQ_HANDLED; if (venc_is_second_field(disp_dev)) event |= VENC_SECOND_FIELD; else event |= VENC_FIRST_FIELD; if (event == (last_event & ~VENC_END_OF_FRAME)) { event |= VENC_END_OF_FRAME; } else if (event == VENC_SECOND_FIELD) { event |= VENC_END_OF_FRAME; } last_event = event; for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { layer = disp_dev->dev[i]; if (!layer->started) continue; if (layer->layer_first_int) { layer->layer_first_int = 0; continue; } if ((V4L2_FIELD_NONE == layer->pix_fmt.field) && (event & VENC_END_OF_FRAME)) { vpbe_isr_even_field(disp_dev, layer); vpbe_isr_odd_field(disp_dev, layer); } else { layer->field_id ^= 1; if (event & VENC_FIRST_FIELD) fid = 0; else fid = 1; if (fid != layer->field_id) { layer->field_id = fid; continue; } if (0 == fid) vpbe_isr_even_field(disp_dev, layer); else vpbe_isr_odd_field(disp_dev, layer); } } return IRQ_HANDLED; }
/* interrupt service routine */ static irqreturn_t venc_isr(int irq, void *arg) { struct vpbe_display *disp_dev = (struct vpbe_display *)arg; struct vpbe_layer *layer; static unsigned last_event; unsigned event = 0; int fid; int i; if ((NULL == arg) || (NULL == disp_dev->dev[0])) return IRQ_HANDLED; if (venc_is_second_field(disp_dev)) event |= VENC_SECOND_FIELD; else event |= VENC_FIRST_FIELD; if (event == (last_event & ~VENC_END_OF_FRAME)) { /* * If the display is non-interlaced, then we need to flag the * end-of-frame event at every interrupt regardless of the * value of the FIDST bit. We can conclude that the display is * non-interlaced if the value of the FIDST bit is unchanged * from the previous interrupt. */ event |= VENC_END_OF_FRAME; } else if (event == VENC_SECOND_FIELD) { /* end-of-frame for interlaced display */ event |= VENC_END_OF_FRAME; } last_event = event; for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { layer = disp_dev->dev[i]; /* If streaming is started in this layer */ if (!layer->started) continue; if (layer->layer_first_int) { layer->layer_first_int = 0; continue; } /* Check the field format */ if ((V4L2_FIELD_NONE == layer->pix_fmt.field) && (event & VENC_END_OF_FRAME)) { /* Progressive mode */ vpbe_isr_even_field(disp_dev, layer); vpbe_isr_odd_field(disp_dev, layer); } else { /* Interlaced mode */ layer->field_id ^= 1; if (event & VENC_FIRST_FIELD) fid = 0; else fid = 1; /* * If field id does not match with store * field id */ if (fid != layer->field_id) { /* Make them in sync */ layer->field_id = fid; continue; } /* * device field id and local field id are * in sync. If this is even field */ if (0 == fid) vpbe_isr_even_field(disp_dev, layer); else /* odd field */ vpbe_isr_odd_field(disp_dev, layer); } } return IRQ_HANDLED; }