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);
|
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
|
#ifdef CONFIG_FB_MSM_MDP303
|
||||||
/* vsync_isr_handler: Called from isr context*/
|
/* vsync_isr_handler: Called from isr context*/
|
||||||
static void vsync_isr_handler(void)
|
static void vsync_isr_handler(void)
|
||||||
|
@ -1806,6 +1778,7 @@ irqreturn_t mdp_isr(int irq, void *ptr)
|
||||||
struct mdp_hist_mgmt *mgmt = NULL;
|
struct mdp_hist_mgmt *mgmt = NULL;
|
||||||
char *base_addr;
|
char *base_addr;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
int vsync_isr;
|
||||||
/* Ensure all the register write are complete */
|
/* Ensure all the register write are complete */
|
||||||
mb();
|
mb();
|
||||||
|
|
||||||
|
@ -1825,8 +1798,23 @@ irqreturn_t mdp_isr(int irq, void *ptr)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/*Primary Vsync interrupt*/
|
/*Primary Vsync interrupt*/
|
||||||
if (mdp_interrupt & MDP_PRIM_RDPTR)
|
if (mdp_interrupt & MDP_PRIM_RDPTR) {
|
||||||
vsync_isr_handler();
|
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 */
|
/* DMA3 TV-Out Start */
|
||||||
if (mdp_interrupt & TV_OUT_DMA3_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) {
|
if (mdp_interrupt & LCDC_FRAME_START) {
|
||||||
dma = &dma2_data;
|
dma = &dma2_data;
|
||||||
spin_lock_irqsave(&mdp_spin_lock, flag);
|
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||||
|
vsync_isr = vsync_cntrl.vsync_irq_enabled;
|
||||||
/* let's disable LCDC interrupt */
|
/* let's disable LCDC interrupt */
|
||||||
if (dma->waiting) {
|
if (dma->waiting) {
|
||||||
dma->waiting = FALSE;
|
dma->waiting = FALSE;
|
||||||
complete(&dma->comp);
|
complete(&dma->comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vsync_cntrl.vsync_irq_enabled)
|
if (!vsync_isr) {
|
||||||
vsync_isr_handler();
|
|
||||||
|
|
||||||
if (!vsync_cntrl.vsync_irq_enabled && !(dma->waiting)) {
|
|
||||||
mdp_intr_mask &= ~LCDC_FRAME_START;
|
mdp_intr_mask &= ~LCDC_FRAME_START;
|
||||||
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
|
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
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 */
|
/* DMA2 LCD-Out Complete */
|
||||||
|
@ -2019,6 +2012,7 @@ static void mdp_drv_init(void)
|
||||||
atomic_set(&mdp_block_power_cnt[i], 0);
|
atomic_set(&mdp_block_power_cnt[i], 0);
|
||||||
}
|
}
|
||||||
INIT_WORK(&(vsync_cntrl.vsync_work), send_vsync_work);
|
INIT_WORK(&(vsync_cntrl.vsync_work), send_vsync_work);
|
||||||
|
init_completion(&vsync_cntrl.vsync_wait);
|
||||||
#ifdef MSM_FB_ENABLE_DBGFS
|
#ifdef MSM_FB_ENABLE_DBGFS
|
||||||
{
|
{
|
||||||
struct dentry *root;
|
struct dentry *root;
|
||||||
|
|
|
@ -96,6 +96,7 @@ struct vsync {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct work_struct vsync_work;
|
struct work_struct vsync_work;
|
||||||
int vsync_irq_enabled;
|
int vsync_irq_enabled;
|
||||||
|
struct completion vsync_wait;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct vsync vsync_cntrl;
|
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_vsync_ctrl(int enable);
|
||||||
void mdp_dma_video_vsync_ctrl(int enable);
|
void mdp_dma_video_vsync_ctrl(int enable);
|
||||||
void mdp_dma_lcdc_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
|
#ifdef MDP_HW_VSYNC
|
||||||
void vsync_clk_prepare_enable(void);
|
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)
|
void mdp_dma_vsync_ctrl(int enable)
|
||||||
{
|
{
|
||||||
|
unsigned long flag;
|
||||||
if (vsync_cntrl.vsync_irq_enabled == enable)
|
if (vsync_cntrl.vsync_irq_enabled == enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||||
vsync_cntrl.vsync_irq_enabled = enable;
|
vsync_cntrl.vsync_irq_enabled = enable;
|
||||||
|
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
|
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
|
||||||
MDP_OUTP(MDP_BASE + 0x021c, 0x10); /* read pointer */
|
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 {
|
} else {
|
||||||
mdp3_vsync_irq_disable(MDP_PRIM_RDPTR, MDP_VSYNC_TERM);
|
INIT_COMPLETION(vsync_cntrl.vsync_wait);
|
||||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
|
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)
|
void mdp_dma_video_vsync_ctrl(int enable)
|
||||||
{
|
{
|
||||||
|
unsigned long flag;
|
||||||
if (vsync_cntrl.vsync_irq_enabled == enable)
|
if (vsync_cntrl.vsync_irq_enabled == enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||||
vsync_cntrl.vsync_irq_enabled = enable;
|
vsync_cntrl.vsync_irq_enabled = enable;
|
||||||
|
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
|
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 {
|
} else {
|
||||||
mdp3_vsync_irq_disable(LCDC_FRAME_START, MDP_VSYNC_TERM);
|
INIT_COMPLETION(vsync_cntrl.vsync_wait);
|
||||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
|
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)
|
void mdp_dma_lcdc_vsync_ctrl(int enable)
|
||||||
{
|
{
|
||||||
|
unsigned long flag;
|
||||||
if (vsync_cntrl.vsync_irq_enabled == enable)
|
if (vsync_cntrl.vsync_irq_enabled == enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&mdp_spin_lock, flag);
|
||||||
vsync_cntrl.vsync_irq_enabled = enable;
|
vsync_cntrl.vsync_irq_enabled = enable;
|
||||||
|
spin_unlock_irqrestore(&mdp_spin_lock, flag);
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
|
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 {
|
} else {
|
||||||
mdp3_vsync_irq_disable(LCDC_FRAME_START, MDP_VSYNC_TERM);
|
INIT_COMPLETION(vsync_cntrl.vsync_wait);
|
||||||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
|
wait_for_completion(&vsync_cntrl.vsync_wait);
|
||||||
|
mdp_disable_irq(MDP_VSYNC_TERM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue