Commit 29f034d7 authored by jilai wang's avatar jilai wang Committed by Rob Clark

drm/msm/mdp: Clear pending interrupt status before enable interrupt

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: default avatarJilai Wang <jilaiw@codeaurora.org>
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent 8089082f
...@@ -19,8 +19,11 @@ ...@@ -19,8 +19,11 @@
#include "msm_drv.h" #include "msm_drv.h"
#include "mdp4_kms.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_mdp4_kms(mdp_kms), REG_MDP4_INTR_CLEAR,
irqmask ^ (irqmask & old_irqmask));
mdp4_write(to_mdp4_kms(mdp_kms), REG_MDP4_INTR_ENABLE, 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) ...@@ -68,9 +71,10 @@ irqreturn_t mdp4_irq(struct msm_kms *kms)
struct drm_device *dev = mdp4_kms->dev; struct drm_device *dev = mdp4_kms->dev;
struct msm_drm_private *priv = dev->dev_private; struct msm_drm_private *priv = dev->dev_private;
unsigned int id; 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); mdp4_write(mdp4_kms, REG_MDP4_INTR_CLEAR, status);
VERB("status=%08x", status); VERB("status=%08x", status);
......
...@@ -167,7 +167,8 @@ static inline uint32_t mixercfg(uint32_t mixer_cfg, int mixer, ...@@ -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_disable(struct mdp4_kms *mdp4_kms);
int mdp4_enable(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); void mdp4_irq_preinstall(struct msm_kms *kms);
int mdp4_irq_postinstall(struct msm_kms *kms); int mdp4_irq_postinstall(struct msm_kms *kms);
void mdp4_irq_uninstall(struct msm_kms *kms); void mdp4_irq_uninstall(struct msm_kms *kms);
......
...@@ -21,8 +21,11 @@ ...@@ -21,8 +21,11 @@
#include "msm_drv.h" #include "msm_drv.h"
#include "mdp5_kms.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); 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) ...@@ -71,9 +74,10 @@ static void mdp5_irq_mdp(struct mdp_kms *mdp_kms)
struct drm_device *dev = mdp5_kms->dev; struct drm_device *dev = mdp5_kms->dev;
struct msm_drm_private *priv = dev->dev_private; struct msm_drm_private *priv = dev->dev_private;
unsigned int id; 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); mdp5_write(mdp5_kms, REG_MDP5_MDP_INTR_CLEAR(0), status);
VERB("status=%08x", status); VERB("status=%08x", status);
......
...@@ -186,7 +186,8 @@ static inline uint32_t lm2ppdone(int lm) ...@@ -186,7 +186,8 @@ static inline uint32_t lm2ppdone(int lm)
int mdp5_disable(struct mdp5_kms *mdp5_kms); int mdp5_disable(struct mdp5_kms *mdp5_kms);
int mdp5_enable(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); void mdp5_irq_preinstall(struct msm_kms *kms);
int mdp5_irq_postinstall(struct msm_kms *kms); int mdp5_irq_postinstall(struct msm_kms *kms);
void mdp5_irq_uninstall(struct msm_kms *kms); void mdp5_irq_uninstall(struct msm_kms *kms);
......
...@@ -39,7 +39,8 @@ static void update_irq(struct mdp_kms *mdp_kms) ...@@ -39,7 +39,8 @@ static void update_irq(struct mdp_kms *mdp_kms)
list_for_each_entry(irq, &mdp_kms->irq_list, node) list_for_each_entry(irq, &mdp_kms->irq_list, node)
irqmask |= irq->irqmask; 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 /* if an mdp_irq's irqmask has changed, such as when mdp5 crtc<->encoder
......
...@@ -30,7 +30,8 @@ struct mdp_kms; ...@@ -30,7 +30,8 @@ struct mdp_kms;
struct mdp_kms_funcs { struct mdp_kms_funcs {
struct msm_kms_funcs base; 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 { struct mdp_kms {
...@@ -42,6 +43,7 @@ struct mdp_kms { ...@@ -42,6 +43,7 @@ struct mdp_kms {
bool in_irq; bool in_irq;
struct list_head irq_list; /* list of mdp4_irq */ struct list_head irq_list; /* list of mdp4_irq */
uint32_t vblank_mask; /* irq bits set for userspace vblank */ 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) #define to_mdp_kms(x) container_of(x, struct mdp_kms, base)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment