diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.c | 33 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 20 |
3 files changed, 41 insertions, 14 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index b122054b8322..0555ab42b375 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -184,14 +184,15 @@ u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp) static inline int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr) { struct mdss_hw *hw; + int rc = -ENODEV; spin_lock(&mdss_lock); hw = mdss_irq_handlers[hw_ndx]; - spin_unlock(&mdss_lock); if (hw) - return hw->irq_handler(irq, hw->ptr); + rc = hw->irq_handler(irq, hw->ptr); + spin_unlock(&mdss_lock); - return -ENODEV; + return rc; } static irqreturn_t mdss_irq_handler(int irq, void *ptr) @@ -204,8 +205,11 @@ static irqreturn_t mdss_irq_handler(int irq, void *ptr) mdata->irq_buzy = true; - if (intr & MDSS_INTR_MDP) + if (intr & MDSS_INTR_MDP) { + spin_lock(&mdp_lock); mdss_irq_dispatch(MDSS_HW_MDP, irq, ptr); + spin_unlock(&mdp_lock); + } if (intr & MDSS_INTR_DSI0) mdss_irq_dispatch(MDSS_HW_DSI0, irq, ptr); @@ -284,6 +288,7 @@ void mdss_disable_irq(struct mdss_hw *hw) } EXPORT_SYMBOL(mdss_disable_irq); +/* called from interrupt context */ void mdss_disable_irq_nosync(struct mdss_hw *hw) { u32 ndx_bit; @@ -296,7 +301,6 @@ void mdss_disable_irq_nosync(struct mdss_hw *hw) pr_debug("Disable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx, mdss_res->irq_ena, mdss_res->irq_mask); - spin_lock(&mdss_lock); if (!(mdss_res->irq_mask & ndx_bit)) { pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n", hw->hw_ndx, mdss_res->mdp_irq_mask, @@ -309,7 +313,6 @@ void mdss_disable_irq_nosync(struct mdss_hw *hw) disable_irq_nosync(mdss_res->irq); } } - spin_unlock(&mdss_lock); } EXPORT_SYMBOL(mdss_disable_irq_nosync); @@ -390,6 +393,21 @@ static inline u32 mdss_mdp_irq_mask(u32 intr_type, u32 intf_num) return 1 << (intr_type + intf_num); } +/* function assumes that mdp is clocked to access hw registers */ +void mdss_mdp_irq_clear(struct mdss_data_type *mdata, + u32 intr_type, u32 intf_num) +{ + unsigned long irq_flags; + u32 irq; + + irq = mdss_mdp_irq_mask(intr_type, intf_num); + + pr_debug("clearing mdp irq mask=%x\n", irq); + spin_lock_irqsave(&mdp_lock, irq_flags); + writel_relaxed(irq, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR); + spin_unlock_irqrestore(&mdp_lock, irq_flags); +} + int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num) { u32 irq; @@ -482,13 +500,13 @@ void mdss_mdp_hist_irq_disable(u32 irq) spin_unlock_irqrestore(&mdp_lock, irq_flags); } +/* called from interrupt context */ void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num) { u32 irq; irq = mdss_mdp_irq_mask(intr_type, intf_num); - spin_lock(&mdp_lock); if (!(mdss_res->mdp_irq_mask & irq)) { pr_warn("MDSS MDP IRQ-%x is NOT set, mask=%x\n", irq, mdss_res->mdp_irq_mask); @@ -500,7 +518,6 @@ void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num) (mdss_res->mdp_hist_irq_mask == 0)) mdss_disable_irq_nosync(&mdss_mdp_hw); } - spin_unlock(&mdp_lock); } static inline struct clk *mdss_mdp_get_clk(u32 clk_idx) diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index df5e5d300561..07b083a3a9f3 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -330,6 +330,8 @@ static inline u32 mdss_mdp_pingpong_read(struct mdss_mdp_mixer *mixer, u32 reg) irqreturn_t mdss_mdp_isr(int irq, void *ptr); int mdss_iommu_attach(struct mdss_data_type *mdata); int mdss_mdp_copy_splash_screen(struct mdss_panel_data *pdata); +void mdss_mdp_irq_clear(struct mdss_data_type *mdata, + u32 intr_type, u32 intf_num); int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num); void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num); int mdss_mdp_hist_irq_enable(u32 irq); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 8c57c8c569fb..0426784be46d 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -182,6 +182,9 @@ static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl) if (atomic_inc_return(&ctx->vsync_ref) == 1) mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num); + else + mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_INTF_VSYNC, + ctl->intf_num); } static inline void video_vsync_irq_disable(struct mdss_mdp_ctl *ctl) @@ -197,6 +200,7 @@ static int mdss_mdp_video_set_vsync_handler(struct mdss_mdp_ctl *ctl, { struct mdss_mdp_video_ctx *ctx; unsigned long flags; + int need_update; ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data; if (!ctx) { @@ -205,14 +209,18 @@ static int mdss_mdp_video_set_vsync_handler(struct mdss_mdp_ctl *ctl, } spin_lock_irqsave(&ctx->vsync_lock, flags); - if (!ctx->vsync_handler && vsync_handler) - video_vsync_irq_enable(ctl); - else if (ctx->vsync_handler && !vsync_handler) - video_vsync_irq_disable(ctl); - + need_update = (!ctx->vsync_handler && vsync_handler) || + (ctx->vsync_handler && !vsync_handler); ctx->vsync_handler = vsync_handler; spin_unlock_irqrestore(&ctx->vsync_lock, flags); + if (need_update) { + if (vsync_handler) + video_vsync_irq_enable(ctl); + else + video_vsync_irq_disable(ctl); + } + return 0; } @@ -335,8 +343,8 @@ static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg) if (!ctx->wait_pending) { ctx->wait_pending++; - INIT_COMPLETION(ctx->vsync_comp); video_vsync_irq_enable(ctl); + INIT_COMPLETION(ctx->vsync_comp); } else { WARN(1, "commit without wait! ctl=%d", ctl->num); } |
