Skip to content

Commit

Permalink
drm/msm/mdp: Clear pending interrupt status before enable interrupt
Browse files Browse the repository at this point in the history
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@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
  • Loading branch information
jilai wang authored and Rob Clark committed Aug 15, 2015
1 parent 8089082 commit 29f034d
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 10 deletions.
10 changes: 7 additions & 3 deletions drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_mdp4_kms(mdp_kms), REG_MDP4_INTR_CLEAR,
irqmask ^ (irqmask & old_irqmask));
mdp4_write(to_mdp4_kms(mdp_kms), REG_MDP4_INTR_ENABLE, irqmask);
}

Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 7 additions & 3 deletions drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/msm/mdp/mdp_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/msm/mdp/mdp_kms.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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)

Expand Down

0 comments on commit 29f034d

Please sign in to comment.