Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: ti: cal: fix wdma irq for metadata

CAL HW interrupts are inherently racy. If we get both start and end
interrupts, we don't know what has happened: did the DMA for a single
frame start and end, or did one frame end and a new frame start?

Usually for normal pixel frames we get the interrupts separately. If
we do get both, we have to guess. The assumption in the code is that the
active vertical area is larger than the blanking vertical area, and thus
it is more likely that we get the end of the old frame and the start of
a new frame.

However, for embedded data, which is only a few lines high, we always
get both interrupts. Here the assumption is that we get both for the
same frame.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>

authored by

Tomi Valkeinen and committed by
Mauro Carvalho Chehab
d91105e0 0872dc04

+27 -4
+27 -4
drivers/media/platform/ti/cal/cal.c
··· 717 717 718 718 static void cal_irq_handle_wdma(struct cal_ctx *ctx, bool start, bool end) 719 719 { 720 - if (end) 721 - cal_irq_wdma_end(ctx); 720 + /* 721 + * CAL HW interrupts are inherently racy. If we get both start and end 722 + * interrupts, we don't know what has happened: did the DMA for a single 723 + * frame start and end, or did one frame end and a new frame start? 724 + * 725 + * Usually for normal pixel frames we get the interrupts separately. If 726 + * we do get both, we have to guess. The assumption in the code below is 727 + * that the active vertical area is larger than the blanking vertical 728 + * area, and thus it is more likely that we get the end of the old frame 729 + * and the start of a new frame. 730 + * 731 + * However, for embedded data, which is only a few lines high, we always 732 + * get both interrupts. Here the assumption is that we get both for the 733 + * same frame. 734 + */ 735 + if (ctx->v_fmt.fmt.pix.height < 10) { 736 + if (start) 737 + cal_irq_wdma_start(ctx); 722 738 723 - if (start) 724 - cal_irq_wdma_start(ctx); 739 + if (end) 740 + cal_irq_wdma_end(ctx); 741 + } else { 742 + if (end) 743 + cal_irq_wdma_end(ctx); 744 + 745 + if (start) 746 + cal_irq_wdma_start(ctx); 747 + } 725 748 } 726 749 727 750 static irqreturn_t cal_irq(int irq_cal, void *data)