mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm_fb: Handle vsync interrupt properly on MDP 3.03 targets
Handle enabling/disabling the vsync interrupt and mdp clock enabling/disabling in a better way on MDP 3.03 targets. This will avoid target crashes due to unclocked register access. CRs-fixed: 388751 Change-Id: I5c4a409772464ce7d06869374dcba5ad7e335955 Signed-off-by: Padmanabhan Komanduru <pkomandu@codeaurora.org> Signed-off-by: Siddhartha Agrawal <agrawals@codeaurora.org>
This commit is contained in:
parent
f72ca836e3
commit
a57b7f57a4
5 changed files with 66 additions and 46 deletions
|
@ -1321,34 +1321,6 @@ static void send_vsync_work(struct work_struct *work)
|
|||
kobject_uevent_env(&(vsync_cntrl.dev->kobj), KOBJ_CHANGE, envp);
|
||||
}
|
||||
|
||||
void mdp3_vsync_irq_enable(int intr, int term)
|
||||
{
|
||||
unsigned long flag;
|
||||
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
outp32(MDP_INTR_CLEAR, intr);
|
||||
mdp_intr_mask |= intr;
|
||||
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
|
||||
mdp_enable_irq(term);
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
}
|
||||
|
||||
void mdp3_vsync_irq_disable(int intr, int term)
|
||||
{
|
||||
unsigned long flag;
|
||||
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
/* required to synchronize between frame update and vsync
|
||||
* since both use the same LCDC_FRAME_START interrupt
|
||||
*/
|
||||
if (intr == LCDC_FRAME_START && dma2_data.waiting == FALSE) {
|
||||
mdp_intr_mask &= ~intr;
|
||||
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
|
||||
}
|
||||
mdp_disable_irq(term);
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FB_MSM_MDP303
|
||||
/* vsync_isr_handler: Called from isr context*/
|
||||
static void vsync_isr_handler(void)
|
||||
|
@ -1806,6 +1778,7 @@ irqreturn_t mdp_isr(int irq, void *ptr)
|
|||
struct mdp_hist_mgmt *mgmt = NULL;
|
||||
char *base_addr;
|
||||
int i, ret;
|
||||
int vsync_isr;
|
||||
/* Ensure all the register write are complete */
|
||||
mb();
|
||||
|
||||
|
@ -1825,8 +1798,23 @@ irqreturn_t mdp_isr(int irq, void *ptr)
|
|||
goto out;
|
||||
|
||||
/*Primary Vsync interrupt*/
|
||||
if (mdp_interrupt & MDP_PRIM_RDPTR)
|
||||
vsync_isr_handler();
|
||||
if (mdp_interrupt & MDP_PRIM_RDPTR) {
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
vsync_isr = vsync_cntrl.vsync_irq_enabled;
|
||||
if (!vsync_isr) {
|
||||
mdp_intr_mask &= ~MDP_PRIM_RDPTR;
|
||||
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
|
||||
}
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
|
||||
if (vsync_isr) {
|
||||
vsync_isr_handler();
|
||||
} else {
|
||||
mdp_pipe_ctrl(MDP_CMD_BLOCK,
|
||||
MDP_BLOCK_POWER_OFF, TRUE);
|
||||
complete(&vsync_cntrl.vsync_wait);
|
||||
}
|
||||
}
|
||||
|
||||
/* DMA3 TV-Out Start */
|
||||
if (mdp_interrupt & TV_OUT_DMA3_START) {
|
||||
|
@ -1874,21 +1862,26 @@ irqreturn_t mdp_isr(int irq, void *ptr)
|
|||
if (mdp_interrupt & LCDC_FRAME_START) {
|
||||
dma = &dma2_data;
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
vsync_isr = vsync_cntrl.vsync_irq_enabled;
|
||||
/* let's disable LCDC interrupt */
|
||||
if (dma->waiting) {
|
||||
dma->waiting = FALSE;
|
||||
complete(&dma->comp);
|
||||
}
|
||||
|
||||
if (vsync_cntrl.vsync_irq_enabled)
|
||||
vsync_isr_handler();
|
||||
|
||||
if (!vsync_cntrl.vsync_irq_enabled && !(dma->waiting)) {
|
||||
if (!vsync_isr) {
|
||||
mdp_intr_mask &= ~LCDC_FRAME_START;
|
||||
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
|
||||
if (vsync_isr) {
|
||||
vsync_isr_handler();
|
||||
} else {
|
||||
mdp_pipe_ctrl(MDP_CMD_BLOCK,
|
||||
MDP_BLOCK_POWER_OFF, TRUE);
|
||||
complete(&vsync_cntrl.vsync_wait);
|
||||
}
|
||||
}
|
||||
|
||||
/* DMA2 LCD-Out Complete */
|
||||
|
@ -2019,6 +2012,7 @@ static void mdp_drv_init(void)
|
|||
atomic_set(&mdp_block_power_cnt[i], 0);
|
||||
}
|
||||
INIT_WORK(&(vsync_cntrl.vsync_work), send_vsync_work);
|
||||
init_completion(&vsync_cntrl.vsync_wait);
|
||||
#ifdef MSM_FB_ENABLE_DBGFS
|
||||
{
|
||||
struct dentry *root;
|
||||
|
|
|
@ -96,6 +96,7 @@ struct vsync {
|
|||
struct device *dev;
|
||||
struct work_struct vsync_work;
|
||||
int vsync_irq_enabled;
|
||||
struct completion vsync_wait;
|
||||
};
|
||||
|
||||
extern struct vsync vsync_cntrl;
|
||||
|
@ -829,8 +830,6 @@ static inline int mdp_bus_scale_update_request(uint32_t index)
|
|||
void mdp_dma_vsync_ctrl(int enable);
|
||||
void mdp_dma_video_vsync_ctrl(int enable);
|
||||
void mdp_dma_lcdc_vsync_ctrl(int enable);
|
||||
void mdp3_vsync_irq_enable(int intr, int term);
|
||||
void mdp3_vsync_irq_disable(int intr, int term);
|
||||
|
||||
#ifdef MDP_HW_VSYNC
|
||||
void vsync_clk_prepare_enable(void);
|
||||
|
|
|
@ -514,18 +514,27 @@ void mdp_dma2_update(struct msm_fb_data_type *mfd)
|
|||
|
||||
void mdp_dma_vsync_ctrl(int enable)
|
||||
{
|
||||
unsigned long flag;
|
||||
if (vsync_cntrl.vsync_irq_enabled == enable)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
vsync_cntrl.vsync_irq_enabled = enable;
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
|
||||
if (enable) {
|
||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
|
||||
MDP_OUTP(MDP_BASE + 0x021c, 0x10); /* read pointer */
|
||||
mdp3_vsync_irq_enable(MDP_PRIM_RDPTR, MDP_VSYNC_TERM);
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
outp32(MDP_INTR_CLEAR, MDP_PRIM_RDPTR);
|
||||
mdp_intr_mask |= MDP_PRIM_RDPTR;
|
||||
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
|
||||
mdp_enable_irq(MDP_VSYNC_TERM);
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
} else {
|
||||
mdp3_vsync_irq_disable(MDP_PRIM_RDPTR, MDP_VSYNC_TERM);
|
||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
|
||||
INIT_COMPLETION(vsync_cntrl.vsync_wait);
|
||||
wait_for_completion(&vsync_cntrl.vsync_wait);
|
||||
mdp_disable_irq(MDP_VSYNC_TERM);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -249,17 +249,26 @@ int mdp_dsi_video_off(struct platform_device *pdev)
|
|||
|
||||
void mdp_dma_video_vsync_ctrl(int enable)
|
||||
{
|
||||
unsigned long flag;
|
||||
if (vsync_cntrl.vsync_irq_enabled == enable)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
vsync_cntrl.vsync_irq_enabled = enable;
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
|
||||
if (enable) {
|
||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
|
||||
mdp3_vsync_irq_enable(LCDC_FRAME_START, MDP_VSYNC_TERM);
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
outp32(MDP_INTR_CLEAR, LCDC_FRAME_START);
|
||||
mdp_intr_mask |= LCDC_FRAME_START;
|
||||
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
|
||||
mdp_enable_irq(MDP_VSYNC_TERM);
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
} else {
|
||||
mdp3_vsync_irq_disable(LCDC_FRAME_START, MDP_VSYNC_TERM);
|
||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
|
||||
INIT_COMPLETION(vsync_cntrl.vsync_wait);
|
||||
wait_for_completion(&vsync_cntrl.vsync_wait);
|
||||
mdp_disable_irq(MDP_VSYNC_TERM);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -330,17 +330,26 @@ int mdp_lcdc_off(struct platform_device *pdev)
|
|||
|
||||
void mdp_dma_lcdc_vsync_ctrl(int enable)
|
||||
{
|
||||
unsigned long flag;
|
||||
if (vsync_cntrl.vsync_irq_enabled == enable)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
vsync_cntrl.vsync_irq_enabled = enable;
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
|
||||
if (enable) {
|
||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
|
||||
mdp3_vsync_irq_enable(LCDC_FRAME_START, MDP_VSYNC_TERM);
|
||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||
outp32(MDP_INTR_CLEAR, LCDC_FRAME_START);
|
||||
mdp_intr_mask |= LCDC_FRAME_START;
|
||||
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
|
||||
mdp_enable_irq(MDP_VSYNC_TERM);
|
||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||
} else {
|
||||
mdp3_vsync_irq_disable(LCDC_FRAME_START, MDP_VSYNC_TERM);
|
||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
|
||||
INIT_COMPLETION(vsync_cntrl.vsync_wait);
|
||||
wait_for_completion(&vsync_cntrl.vsync_wait);
|
||||
mdp_disable_irq(MDP_VSYNC_TERM);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue