diff --git a/drivers/media/platform/apple/avd/avd-drv.c b/drivers/media/platform/apple/avd/avd-drv.c index bf5bf96f4c62a..acbab4a2eb2be 100644 --- a/drivers/media/platform/apple/avd/avd-drv.c +++ b/drivers/media/platform/apple/avd/avd-drv.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -300,6 +301,25 @@ static irqreturn_t avd_irq_handler(int irq, void *data) if (!ctx) return IRQ_HANDLED; + /* + * Only pop a message the mailbox holds: popping an empty mailbox returns + * the previous message again. A stale post-processing "done" read that + * way finishes the frame early, the next frame starts while the PP is + * still busy, and its PP never completes, so the watchdog resets the + * decoder and the stream fails. The interrupt can also arrive just before + * its message is readable, so give the message a moment first. + */ + if (readl(avd->mbox + AVD_REG_MBOX1_STATUS) & AVD_MBOX1_STATUS_EMPTY) { + u32 mb; + + if (readl_poll_timeout_atomic(avd->mbox + AVD_REG_MBOX1_STATUS, mb, + !(mb & AVD_MBOX1_STATUS_EMPTY), 1, 10)) { + dev_dbg(avd->dev, "spurious interrupt, mailbox empty\n"); + writel(AVD_MBOX1_NOT_EMPTY, avd->mbox + AVD_REG_MBOX_IRQ_CLR); + return IRQ_HANDLED; + } + } + status = readl(avd->mbox + AVD_REG_MBOX1_RETRIEVE); writel(AVD_MBOX1_NOT_EMPTY, avd->mbox + AVD_REG_MBOX_IRQ_CLR); diff --git a/drivers/media/platform/apple/avd/avd-regs.h b/drivers/media/platform/apple/avd/avd-regs.h index 388f3e64895f5..ace0e4c48f40a 100644 --- a/drivers/media/platform/apple/avd/avd-regs.h +++ b/drivers/media/platform/apple/avd/avd-regs.h @@ -13,6 +13,8 @@ #define AVD_MBOX1_NOT_EMPTY BIT(3) #define AVD_REG_MBOX1_STATUS 0x5c +/* Read side: bits 8-11 write pointer, bits 12-15 read pointer, bit 17 empty. */ +#define AVD_MBOX1_STATUS_EMPTY BIT(17) #define AVD_REG_MBOX1_RETRIEVE 0x64 #define AVD_MBOX_ENABLE BIT(0)