Pending interrupt status needs to be cleared before enable the
interrupt. Otherwise it's possible to get a pending interrupt instead
of an incoming interrupt.

Signed-off-by: Jilai Wang <jilaiw at codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c | 10 +++++++---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h |  3 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c | 10 +++++++---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h |  3 ++-
 drivers/gpu/drm/msm/mdp/mdp_kms.c       |  3 ++-
 drivers/gpu/drm/msm/mdp/mdp_kms.h       |  4 +++-
 6 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
index 7369ee7f..b6d491c 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
@@ -19,8 +19,11 @@
 #include "msm_drv.h"
 #include "mdp4_kms.h"

-void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask)
+void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
+               uint32_t old_irqmask)
 {
+       mdp4_write(to_mdp5_kms(mdp_kms), REG_MDP4_INTR_CLEAR,
+               irqmask ^ (irqmask & old_irqmask));
        mdp4_write(to_mdp4_kms(mdp_kms), REG_MDP4_INTR_ENABLE, irqmask);
 }

@@ -68,9 +71,10 @@ irqreturn_t mdp4_irq(struct msm_kms *kms)
        struct drm_device *dev = mdp4_kms->dev;
        struct msm_drm_private *priv = dev->dev_private;
        unsigned int id;
-       uint32_t status;
+       uint32_t status, enable;

-       status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS);
+       enable = mdp4_read(mdp4_kms, REG_MDP4_INTR_ENABLE);
+       status = mdp4_read(mdp4_kms, REG_MDP4_INTR_STATUS) & enable;
        mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, status);

        VERB("status=%08x", status);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h 
b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index 1aaedad..0cdf777 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -167,7 +167,8 @@ static inline uint32_t mixercfg(uint32_t mixer_cfg, int 
mixer,
 int mdp4_disable(struct mdp4_kms *mdp4_kms);
 int mdp4_enable(struct mdp4_kms *mdp4_kms);

-void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask);
+void mdp4_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
+               uint32_t old_irqmask);
 void mdp4_irq_preinstall(struct msm_kms *kms);
 int mdp4_irq_postinstall(struct msm_kms *kms);
 void mdp4_irq_uninstall(struct msm_kms *kms);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
index 33bd4c6..7115043 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
@@ -21,8 +21,11 @@
 #include "msm_drv.h"
 #include "mdp5_kms.h"

-void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask)
+void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
+               uint32_t old_irqmask)
 {
+       mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_MDP_INTR_CLEAR(0),
+               irqmask ^ (irqmask & old_irqmask));
        mdp5_write(to_mdp5_kms(mdp_kms), REG_MDP5_MDP_INTR_EN(0), irqmask);
 }

@@ -71,9 +74,10 @@ static void mdp5_irq_mdp(struct mdp_kms *mdp_kms)
        struct drm_device *dev = mdp5_kms->dev;
        struct msm_drm_private *priv = dev->dev_private;
        unsigned int id;
-       uint32_t status;
+       uint32_t status, enable;

-       status = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_STATUS(0));
+       enable = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_EN(0));
+       status = mdp5_read(mdp5_kms, REG_MDP5_MDP_INTR_STATUS(0)) & enable;
        mdp5_write(mdp5_kms, REG_MDP5_MDP_INTR_CLEAR(0), status);

        VERB("status=%08x", status);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h 
b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 8542b30..403a6f5 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -186,7 +186,8 @@ static inline uint32_t lm2ppdone(int lm)
 int mdp5_disable(struct mdp5_kms *mdp5_kms);
 int mdp5_enable(struct mdp5_kms *mdp5_kms);

-void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask);
+void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
+               uint32_t old_irqmask);
 void mdp5_irq_preinstall(struct msm_kms *kms);
 int mdp5_irq_postinstall(struct msm_kms *kms);
 void mdp5_irq_uninstall(struct msm_kms *kms);
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.c 
b/drivers/gpu/drm/msm/mdp/mdp_kms.c
index 1988c24..6428730 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.c
@@ -39,7 +39,8 @@ static void update_irq(struct mdp_kms *mdp_kms)
        list_for_each_entry(irq, &mdp_kms->irq_list, node)
                irqmask |= irq->irqmask;

-       mdp_kms->funcs->set_irqmask(mdp_kms, irqmask);
+       mdp_kms->funcs->set_irqmask(mdp_kms, irqmask, mdp_kms->cur_irq_mask);
+       mdp_kms->cur_irq_mask = irqmask;
 }

 /* if an mdp_irq's irqmask has changed, such as when mdp5 crtc<->encoder
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h 
b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 3db25df..39ead11 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -30,7 +30,8 @@ struct mdp_kms;

 struct mdp_kms_funcs {
        struct msm_kms_funcs base;
-       void (*set_irqmask)(struct mdp_kms *mdp_kms, uint32_t irqmask);
+       void (*set_irqmask)(struct mdp_kms *mdp_kms, uint32_t irqmask,
+               uint32_t old_irqmask);
 };

 struct mdp_kms {
@@ -42,6 +43,7 @@ struct mdp_kms {
        bool in_irq;
        struct list_head irq_list;    /* list of mdp4_irq */
        uint32_t vblank_mask;         /* irq bits set for userspace vblank */
+       uint32_t cur_irq_mask;        /* current irq mask */
 };
 #define to_mdp_kms(x) container_of(x, struct mdp_kms, base)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

Reply via email to