mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm_fb: display: wake up system around vsync
To avoid frame drops due to power collapse, wake up cpu right before vsync. Conflicts: drivers/video/msm/mdp.c drivers/video/msm/msm_fb.h Change-Id: I63385eb329ae5e74cbac5256823fd3a213e0a0e1 Signed-off-by: Ken Zhang <kenz@codeaurora.org> Signed-off-by: Huaibin Yang <huaibiny@codeaurora.org>
This commit is contained in:
parent
69b8f54698
commit
82c6b4cdd7
8 changed files with 64 additions and 4 deletions
|
@ -35,6 +35,7 @@
|
|||
#include <asm/mach-types.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <mach/event_timer.h>
|
||||
#include <mach/clk.h>
|
||||
#include "mdp.h"
|
||||
#include "msm_fb.h"
|
||||
|
@ -1405,15 +1406,15 @@ int mdp_ppp_pipe_wait(void)
|
|||
if (wait == TRUE) {
|
||||
ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
|
||||
5 * HZ);
|
||||
|
||||
if (!ret)
|
||||
printk(KERN_ERR "%s: Timed out waiting for the MDP.\n",
|
||||
__func__);
|
||||
__func__);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_VSYNC_GAP 4
|
||||
#define DEFAULT_FRAME_RATE 60
|
||||
|
||||
u32 mdp_get_panel_framerate(struct msm_fb_data_type *mfd)
|
||||
|
@ -1447,6 +1448,53 @@ u32 mdp_get_panel_framerate(struct msm_fb_data_type *mfd)
|
|||
return frame_rate;
|
||||
}
|
||||
|
||||
static int mdp_diff_to_next_vsync(ktime_t cur_time,
|
||||
ktime_t last_vsync, u32 vsync_period)
|
||||
{
|
||||
int diff_from_last, diff_to_next;
|
||||
/*
|
||||
* Get interval beween last vsync and current time
|
||||
* Current time = CPU programming MDP for next Vsync
|
||||
*/
|
||||
diff_from_last =
|
||||
(ktime_to_us(ktime_sub(cur_time, last_vsync)));
|
||||
diff_from_last /= USEC_PER_MSEC;
|
||||
/*
|
||||
* If the last Vsync occurred too long ago, skip programming
|
||||
* the timer
|
||||
*/
|
||||
if (diff_from_last < (vsync_period * MAX_VSYNC_GAP)) {
|
||||
if (diff_from_last > vsync_period)
|
||||
diff_to_next =
|
||||
(diff_from_last - vsync_period) % vsync_period;
|
||||
else
|
||||
diff_to_next = vsync_period - diff_from_last;
|
||||
} else {
|
||||
/* mark it out of range */
|
||||
diff_to_next = vsync_period + 1;
|
||||
}
|
||||
return diff_to_next;
|
||||
}
|
||||
|
||||
void mdp_update_pm(struct msm_fb_data_type *mfd, ktime_t pre_vsync)
|
||||
{
|
||||
u32 vsync_period;
|
||||
int diff_to_next;
|
||||
ktime_t cur_time, wakeup_time;
|
||||
|
||||
if (!mfd->cpu_pm_hdl)
|
||||
return;
|
||||
vsync_period = mfd->panel_info.frame_interval;
|
||||
cur_time = ktime_get();
|
||||
diff_to_next = mdp_diff_to_next_vsync(cur_time,
|
||||
pre_vsync,
|
||||
vsync_period);
|
||||
if (diff_to_next > vsync_period)
|
||||
return;
|
||||
wakeup_time = ktime_add_ns(cur_time, diff_to_next * NSEC_PER_MSEC);
|
||||
activate_event_timer(mfd->cpu_pm_hdl, wakeup_time);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(mdp_lock);
|
||||
static int mdp_irq_mask;
|
||||
static int mdp_irq_enabled;
|
||||
|
@ -2508,6 +2556,7 @@ static int mdp_probe(struct platform_device *pdev)
|
|||
int rc;
|
||||
resource_size_t size ;
|
||||
unsigned long flag;
|
||||
u32 frame_rate;
|
||||
#ifdef CONFIG_FB_MSM_MDP40
|
||||
int intf, if_no;
|
||||
#endif
|
||||
|
@ -2910,6 +2959,11 @@ static int mdp_probe(struct platform_device *pdev)
|
|||
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
|
||||
}
|
||||
|
||||
frame_rate = mdp_get_panel_framerate(mfd);
|
||||
if (frame_rate) {
|
||||
mfd->panel_info.frame_interval = 1000 / frame_rate;
|
||||
mfd->cpu_pm_hdl = add_event_timer(NULL, (void *)mfd);
|
||||
}
|
||||
mdp_clk_ctrl(0);
|
||||
|
||||
#ifdef CONFIG_MSM_BUS_SCALING
|
||||
|
|
|
@ -911,6 +911,7 @@ int mdp_ppp_v4l2_overlay_clear(void);
|
|||
int mdp_ppp_v4l2_overlay_play(struct fb_info *info,
|
||||
unsigned long srcp0_addr, unsigned long srcp0_size,
|
||||
unsigned long srcp1_addr, unsigned long srcp1_size);
|
||||
void mdp_update_pm(struct msm_fb_data_type *mfd, ktime_t pre_vsync);
|
||||
|
||||
u32 mdp_get_panel_framerate(struct msm_fb_data_type *mfd);
|
||||
|
||||
|
|
|
@ -184,6 +184,8 @@ void mdp4_atv_overlay(struct msm_fb_data_type *mfd)
|
|||
} else {
|
||||
pipe->srcp0_addr = (uint32)(buf + buf_offset);
|
||||
}
|
||||
mdp_update_pm(mfd, vsync_ctrl_db[0].vsync_time);
|
||||
|
||||
mdp4_overlay_mdp_perf_req(pipe, mfd);
|
||||
mdp4_overlay_mdp_perf_upd(mfd, 1);
|
||||
mdp4_overlay_rgb_setup(pipe);
|
||||
|
|
|
@ -1132,6 +1132,7 @@ void mdp4_dsi_video_overlay(struct msm_fb_data_type *mfd)
|
|||
mdp4_dsi_video_pipe_queue(0, pipe);
|
||||
}
|
||||
|
||||
mdp_update_pm(mfd, vsync_ctrl_db[0].vsync_time);
|
||||
mdp4_overlay_mdp_perf_upd(mfd, 1);
|
||||
|
||||
cnt = mdp4_dsi_video_pipe_commit(cndx, 0);
|
||||
|
|
|
@ -1068,6 +1068,7 @@ void mdp4_dtv_overlay(struct msm_fb_data_type *mfd)
|
|||
pipe->srcp0_addr = (uint32)mfd->ibuf.buf;
|
||||
mdp4_dtv_pipe_queue(0, pipe);
|
||||
}
|
||||
mdp_update_pm(mfd, vsync_ctrl_db[0].vsync_time);
|
||||
|
||||
mdp4_overlay_mdp_perf_upd(mfd, 1);
|
||||
mdp4_dtv_pipe_commit(0, 0);
|
||||
|
|
|
@ -971,6 +971,7 @@ void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd)
|
|||
|
||||
mdp4_lcdc_pipe_queue(0, pipe);
|
||||
}
|
||||
mdp_update_pm(mfd, vsync_ctrl_db[0].vsync_time);
|
||||
|
||||
mdp4_overlay_mdp_perf_upd(mfd, 1);
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include <linux/fb.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/msm_mdp.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
|
@ -191,6 +190,7 @@ struct msm_fb_data_type {
|
|||
u32 writeback_state;
|
||||
bool writeback_active_cnt;
|
||||
int cont_splash_done;
|
||||
void *cpu_pm_hdl;
|
||||
u32 acq_fen_cnt;
|
||||
struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
|
||||
int cur_rel_fen_fd;
|
||||
|
|
|
@ -169,7 +169,7 @@ struct msm_panel_info {
|
|||
__u32 frame_count;
|
||||
__u32 is_3d_panel;
|
||||
__u32 frame_rate;
|
||||
|
||||
__u32 frame_interval;
|
||||
|
||||
struct mddi_panel_info mddi;
|
||||
struct lcd_panel_info lcd;
|
||||
|
|
Loading…
Reference in a new issue