From: "alice.yuan" <alice.yuan@xxxxxxx> When do 2592x1944 resolution capture, we found some times the "BIT_STATFF_INT" is abnormal, the stat fifo is not full, but still the DMA transfer done interrupts generate, at this time we will get broken frames. >From the reference manual of imx8mm, we know the STATFIFO full interrupt status, that indicates the number of data in the STATFIFO reaches the trigger level. It defined clearly about BIT_STATFF_INT, 0: STATFIFO is not full, 1: STATFIFO is full. So we should handler the abnormal interrupts when BIT_STATFF_INT is 0, the stat fifo is not full, we need to drop the broken frames, and recovery from the abnormal status. Signed-off-by: alice.yuan <alice.yuan@xxxxxxx> --- drivers/media/platform/nxp/imx7-media-csi.c | 25 ++++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c index 15049c6aab37..9012b155c2d7 100644 --- a/drivers/media/platform/nxp/imx7-media-csi.c +++ b/drivers/media/platform/nxp/imx7-media-csi.c @@ -249,6 +249,7 @@ struct imx7_csi { bool is_streaming; int buf_num; u32 frame_sequence; + int frame_skip; bool last_eof; struct completion last_eof_completion; @@ -686,6 +687,7 @@ static void imx7_csi_enable(struct imx7_csi *csi) imx7_csi_dmareq_rff_enable(csi); imx7_csi_hw_enable(csi); + csi->frame_skip = 0; if (csi->model == IMX7_CSI_IMX8MQ) imx7_csi_baseaddr_switch_on_second_frame(csi); } @@ -764,6 +766,12 @@ static irqreturn_t imx7_csi_irq_handler(int irq, void *data) imx7_csi_error_recovery(csi); } + if (!(status & BIT_STATFF_INT)) { + dev_warn(csi->dev, "Stat fifo is not full\n"); + imx7_csi_error_recovery(csi); + csi->frame_skip++; + } + if (status & BIT_ADDR_CH_ERR_INT) { imx7_csi_hw_disable(csi); @@ -790,14 +798,19 @@ static irqreturn_t imx7_csi_irq_handler(int irq, void *data) if ((status & BIT_DMA_TSF_DONE_FB1) || (status & BIT_DMA_TSF_DONE_FB2)) { - imx7_csi_vb2_buf_done(csi); - - if (csi->last_eof) { - complete(&csi->last_eof_completion); - csi->last_eof = false; + if (csi->frame_skip) { + dev_warn(csi->dev, "skip frame: %d\n", csi->frame_skip); + csi->frame_skip--; + goto out; + } else { + imx7_csi_vb2_buf_done(csi); + if (csi->last_eof) { + complete(&csi->last_eof_completion); + csi->last_eof = false; + } } } - +out: spin_unlock(&csi->irqlock); return IRQ_HANDLED; -- 2.37.1