#define CTRL1_UNDERFLOW_IRQ (1 << 10)
#define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9)
#define CTRL1_VSYNC_EDGE_IRQ (1 << 8)
+#define CTRL1_IRQ_ENABLE_MASK (CTRL1_OVERFLOW_IRQ_EN | \
+ CTRL1_UNDERFLOW_IRQ_EN | \
+ CTRL1_CUR_FRAME_DONE_IRQ_EN | \
+ CTRL1_VSYNC_EDGE_IRQ_EN)
+#define CTRL1_IRQ_ENABLE_SHIFT 12
+#define CTRL1_IRQ_STATUS_MASK (CTRL1_OVERFLOW_IRQ | \
+ CTRL1_UNDERFLOW_IRQ | \
+ CTRL1_CUR_FRAME_DONE_IRQ | \
+ CTRL1_VSYNC_EDGE_IRQ)
+#define CTRL1_IRQ_STATUS_SHIFT 8
#define CTRL2_OUTSTANDING_REQS__REQ_16 (3 << 21)
static irqreturn_t mxsfb_irq_handler(int irq, void *dev_id)
{
struct mxsfb_info *host = dev_id;
- u32 status_lcd = readl(host->base + LCDC_CTRL1);
+ u32 ctrl1, enable, status, acked_status;
- if ((status_lcd & CTRL1_VSYNC_EDGE_IRQ) &&
- host->wait4vsync) {
+ ctrl1 = readl(host->base + LCDC_CTRL1);
+ enable = (ctrl1 & CTRL1_IRQ_ENABLE_MASK) >> CTRL1_IRQ_ENABLE_SHIFT;
+ status = (ctrl1 & CTRL1_IRQ_STATUS_MASK) >> CTRL1_IRQ_STATUS_SHIFT;
+ acked_status = (enable & status) << CTRL1_IRQ_STATUS_SHIFT;
+
+ if ((acked_status & CTRL1_VSYNC_EDGE_IRQ) && host->wait4vsync) {
writel(CTRL1_VSYNC_EDGE_IRQ_EN,
host->base + LCDC_CTRL1 + REG_CLR);
host->wait4vsync = 0;
complete(&host->vsync_complete);
}
- if (status_lcd & CTRL1_CUR_FRAME_DONE_IRQ) {
+ if (acked_status & CTRL1_CUR_FRAME_DONE_IRQ) {
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN,
host->base + LCDC_CTRL1 + REG_CLR);
up(&host->flip_sem);
}
- if (status_lcd & CTRL1_UNDERFLOW_IRQ) {
- writel(CTRL1_UNDERFLOW_IRQ,
- host->base + LCDC_CTRL1 + REG_CLR);
- }
+ if (acked_status & CTRL1_UNDERFLOW_IRQ)
+ writel(CTRL1_UNDERFLOW_IRQ, host->base + LCDC_CTRL1 + REG_CLR);
+
+ if (acked_status & CTRL1_OVERFLOW_IRQ)
+ writel(CTRL1_OVERFLOW_IRQ, host->base + LCDC_CTRL1 + REG_CLR);
- if (status_lcd & CTRL1_OVERFLOW_IRQ) {
- writel(CTRL1_OVERFLOW_IRQ,
- host->base + LCDC_CTRL1 + REG_CLR);
- }
return IRQ_HANDLED;
}