irqreturn_t mxr_irq_handler(int irq, void *dev_data) { struct mxr_device *mdev = dev_data; u32 val; spin_lock(&mdev->reg_slock); val = mxr_read(mdev, MXR_INT_STATUS); /* wake up process waiting for VSYNC */ if (val & MXR_INT_STATUS_VSYNC) { mdev->vsync_timestamp = ktime_get(); wake_up_interruptible_all(&mdev->vsync_wait); } /* clear interrupts. vsync is updated after write MXR_CFG_LAYER_UPDATE bit */ if (val & MXR_INT_CLEAR_VSYNC) mxr_write_mask(mdev, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); val = mxr_irq_underrun_handle(mdev, val); mxr_write(mdev, MXR_INT_STATUS, val); spin_unlock(&mdev->reg_slock); return IRQ_HANDLED; }
irqreturn_t mxr_irq_handler(int irq, void *dev_data) { struct mxr_device *mdev = dev_data; u32 i, val; spin_lock(&mdev->reg_slock); val = mxr_read(mdev, MXR_INT_STATUS); /* wake up process waiting for VSYNC */ if (val & MXR_INT_STATUS_VSYNC) { set_bit(MXR_EVENT_VSYNC, &mdev->event_flags); wake_up(&mdev->event_queue); } /* clear interrupts */ if (~val & MXR_INT_EN_VSYNC) { /* vsync interrupt use different bit for read and clear */ val &= ~MXR_INT_EN_VSYNC; val |= MXR_INT_CLEAR_VSYNC; } val = mxr_irq_underrun_handle(mdev, val); mxr_write(mdev, MXR_INT_STATUS, val); spin_unlock(&mdev->reg_slock); /* leave on non-vsync event */ if (~val & MXR_INT_CLEAR_VSYNC) return IRQ_HANDLED; for (i = 0; i < MXR_MAX_SUB_MIXERS; ++i) { #if defined(CONFIG_ARCH_EXYNOS4) mxr_irq_layer_handle(mdev->sub_mxr[i].layer[MXR_LAYER_VIDEO]); #endif mxr_irq_layer_handle(mdev->sub_mxr[i].layer[MXR_LAYER_GRP0]); mxr_irq_layer_handle(mdev->sub_mxr[i].layer[MXR_LAYER_GRP1]); } return IRQ_HANDLED; }