mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm: display: make pan display as a non-blocking call
Schedule a workqueue, do the current job in the workqueue handler. Block the second entry if the first one has not finished Change-Id: I9466c7795bd9d6765f468bf30f4021802d904c36 Signed-off-by: Ken Zhang <kenz@codeaurora.org> Conflicts: drivers/video/msm/msm_fb.c Signed-off-by: Naseer Ahmed <naseer@codeaurora.org>
This commit is contained in:
parent
e0501cd8dd
commit
c2f0fb04a0
2 changed files with 120 additions and 3 deletions
|
@ -113,6 +113,8 @@ static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);
|
|||
static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
|
||||
struct mdp_bl_scale_data *data);
|
||||
static void msm_fb_scale_bl(__u32 *bl_lvl);
|
||||
static void msm_fb_commit_wq_handler(struct work_struct *work);
|
||||
static int msm_fb_pan_idle(struct msm_fb_data_type *mfd);
|
||||
|
||||
#ifdef CONFIG_LGE_DISP_FBREAD
|
||||
static ssize_t msm_fb_read(struct fb_info *info, char __user *buf,
|
||||
|
@ -990,7 +992,7 @@ static void msm_fb_fillrect(struct fb_info *info,
|
|||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||
|
||||
msm_fb_pan_idle(mfd);
|
||||
cfb_fillrect(info, rect);
|
||||
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
|
||||
!mfd->sw_currently_refreshing) {
|
||||
|
@ -1011,6 +1013,7 @@ static void msm_fb_copyarea(struct fb_info *info,
|
|||
{
|
||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||
|
||||
msm_fb_pan_idle(mfd);
|
||||
cfb_copyarea(info, area);
|
||||
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
|
||||
!mfd->sw_currently_refreshing) {
|
||||
|
@ -1030,6 +1033,7 @@ static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image)
|
|||
{
|
||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||
|
||||
msm_fb_pan_idle(mfd);
|
||||
cfb_imageblit(info, image);
|
||||
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
|
||||
!mfd->sw_currently_refreshing) {
|
||||
|
@ -1055,6 +1059,7 @@ static int msm_fb_blank(int blank_mode, struct fb_info *info)
|
|||
event.data = &blank_mode;
|
||||
fb_notifier_call_chain(FB_EVENT_BLANK, &event);
|
||||
}
|
||||
msm_fb_pan_idle(mfd);
|
||||
return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
|
||||
}
|
||||
|
||||
|
@ -1081,6 +1086,7 @@ static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma)
|
|||
u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
|
||||
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
|
||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||
msm_fb_pan_idle(mfd);
|
||||
if (off >= len) {
|
||||
/* memory mapped io */
|
||||
off -= len;
|
||||
|
@ -1445,7 +1451,15 @@ static int msm_fb_register(struct msm_fb_data_type *mfd)
|
|||
mfd->msmfb_no_update_notify_timer.data = (unsigned long)mfd;
|
||||
init_completion(&mfd->msmfb_update_notify);
|
||||
init_completion(&mfd->msmfb_no_update_notify);
|
||||
|
||||
init_completion(&mfd->commit_comp);
|
||||
mutex_init(&mfd->sync_mutex);
|
||||
INIT_WORK(&mfd->commit_work, msm_fb_commit_wq_handler);
|
||||
mfd->msm_fb_backup = kzalloc(sizeof(struct msm_fb_backup_type),
|
||||
GFP_KERNEL);
|
||||
if (mfd->msm_fb_backup == 0) {
|
||||
pr_err("error: not enough memory!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
|
||||
fbram += fbram_offset;
|
||||
fbram_phys += fbram_offset;
|
||||
|
@ -1772,18 +1786,83 @@ int msm_fb_wait_for_fence(struct msm_fb_data_type *mfd)
|
|||
}
|
||||
int msm_fb_signal_timeline(struct msm_fb_data_type *mfd)
|
||||
{
|
||||
mutex_lock(&mfd->sync_mutex);
|
||||
if (mfd->timeline) {
|
||||
sw_sync_timeline_inc(mfd->timeline, 1);
|
||||
mfd->timeline_value++;
|
||||
}
|
||||
mfd->last_rel_fence = mfd->cur_rel_fence;
|
||||
mfd->cur_rel_fence = 0;
|
||||
mutex_unlock(&mfd->sync_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SEMAPHORE(msm_fb_pan_sem);
|
||||
static int msm_fb_pan_idle(struct msm_fb_data_type *mfd)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&mfd->sync_mutex);
|
||||
if (mfd->is_committing) {
|
||||
mutex_unlock(&mfd->sync_mutex);
|
||||
ret = wait_for_completion_timeout(&mfd->commit_comp,
|
||||
msecs_to_jiffies(WAIT_FENCE_TIMEOUT));
|
||||
if (ret <= 0)
|
||||
pr_err("%s wait for commit_comp timeout %d %d",
|
||||
__func__, ret, mfd->is_committing);
|
||||
} else {
|
||||
mutex_unlock(&mfd->sync_mutex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int msm_fb_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||
struct msm_fb_backup_type *fb_backup;
|
||||
int ret = 0;
|
||||
/*
|
||||
* If framebuffer is 2, io pen display is not allowed.
|
||||
*/
|
||||
if (bf_supported && info->node == 2) {
|
||||
pr_err("%s: no pan display for fb%d!",
|
||||
__func__, info->node);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (info->node != 0 || mfd->cont_splash_done) /* primary */
|
||||
if ((!mfd->op_enable) || (!mfd->panel_power_on))
|
||||
return -EPERM;
|
||||
|
||||
if (var->xoffset > (info->var.xres_virtual - info->var.xres))
|
||||
return -EINVAL;
|
||||
|
||||
if (var->yoffset > (info->var.yres_virtual - info->var.yres))
|
||||
return -EINVAL;
|
||||
msm_fb_pan_idle(mfd);
|
||||
|
||||
mutex_lock(&mfd->sync_mutex);
|
||||
|
||||
if (info->fix.xpanstep)
|
||||
info->var.xoffset =
|
||||
(var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
|
||||
|
||||
if (info->fix.ypanstep)
|
||||
info->var.yoffset =
|
||||
(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
|
||||
|
||||
fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
|
||||
memcpy(&fb_backup->info, info, sizeof(struct fb_info));
|
||||
memcpy(&fb_backup->var, var, sizeof(struct fb_var_screeninfo));
|
||||
mfd->is_committing = 1;
|
||||
INIT_COMPLETION(mfd->commit_comp);
|
||||
schedule_work(&mfd->commit_work);
|
||||
mutex_unlock(&mfd->sync_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_fb_pan_display_sub(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct mdp_dirty_region dirty;
|
||||
struct mdp_dirty_region *dirtyPtr = NULL;
|
||||
|
@ -1876,6 +1955,8 @@ static int msm_fb_pan_display(struct fb_var_screeninfo *var,
|
|||
|
||||
mdp_set_dma_pan_info(info, dirtyPtr,
|
||||
(var->activate == FB_ACTIVATE_VBL));
|
||||
/* async call */
|
||||
|
||||
mdp_dma_pan_update(info);
|
||||
msm_fb_signal_timeline(mfd);
|
||||
up(&msm_fb_pan_sem);
|
||||
|
@ -1897,10 +1978,30 @@ static int msm_fb_pan_display(struct fb_var_screeninfo *var,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void msm_fb_commit_wq_handler(struct work_struct *work)
|
||||
{
|
||||
struct msm_fb_data_type *mfd;
|
||||
struct fb_var_screeninfo *var;
|
||||
struct fb_info *info;
|
||||
struct msm_fb_backup_type *fb_backup;
|
||||
|
||||
mfd = container_of(work, struct msm_fb_data_type, commit_work);
|
||||
fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
|
||||
var = &fb_backup->var;
|
||||
info = &fb_backup->info;
|
||||
msm_fb_pan_display_sub(var, info);
|
||||
mutex_lock(&mfd->sync_mutex);
|
||||
mfd->is_committing = 0;
|
||||
complete_all(&mfd->commit_comp);
|
||||
mutex_unlock(&mfd->sync_mutex);
|
||||
|
||||
}
|
||||
|
||||
static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
{
|
||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||
|
||||
msm_fb_pan_idle(mfd);
|
||||
if (var->rotate != FB_ROTATE_UR)
|
||||
return -EINVAL;
|
||||
if (var->grayscale != info->var.grayscale)
|
||||
|
@ -2031,7 +2132,7 @@ static int msm_fb_set_par(struct fb_info *info)
|
|||
struct fb_var_screeninfo *var = &info->var;
|
||||
int old_imgType;
|
||||
int blank = 0;
|
||||
|
||||
msm_fb_pan_idle(mfd);
|
||||
old_imgType = mfd->fb_imgType;
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
|
@ -3431,6 +3532,7 @@ static int msmfb_handle_buf_sync_ioctl(struct msm_fb_data_type *mfd,
|
|||
pr_err("%s:copy_from_user failed", __func__);
|
||||
return ret;
|
||||
}
|
||||
mutex_lock(&mfd->sync_mutex);
|
||||
for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
|
||||
fence = sync_fence_fdget(acq_fen_fd[i]);
|
||||
if (fence == NULL) {
|
||||
|
@ -3471,6 +3573,7 @@ static int msmfb_handle_buf_sync_ioctl(struct msm_fb_data_type *mfd,
|
|||
goto buf_sync_err_2;
|
||||
}
|
||||
mfd->acq_fen_cnt = buf_sync->acq_fen_fd_cnt;
|
||||
mutex_unlock(&mfd->sync_mutex);
|
||||
return ret;
|
||||
buf_sync_err_2:
|
||||
sync_fence_put(mfd->cur_rel_fence);
|
||||
|
@ -3481,6 +3584,7 @@ buf_sync_err_1:
|
|||
for (i = 0; i < fence_cnt; i++)
|
||||
sync_fence_put(mfd->acq_fen[i]);
|
||||
mfd->acq_fen_cnt = 0;
|
||||
mutex_unlock(&mfd->sync_mutex);
|
||||
return ret;
|
||||
}
|
||||
static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
|
||||
|
@ -3502,6 +3606,7 @@ static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
|
|||
struct msmfb_mdp_pp mdp_pp;
|
||||
struct mdp_buf_sync buf_sync;
|
||||
int ret = 0;
|
||||
msm_fb_pan_idle(mfd);
|
||||
|
||||
switch (cmd) {
|
||||
#ifdef CONFIG_FB_MSM_OVERLAY
|
||||
|
|
|
@ -195,6 +195,18 @@ struct msm_fb_data_type {
|
|||
struct sync_fence *last_rel_fence;
|
||||
struct sw_sync_timeline *timeline;
|
||||
int timeline_value;
|
||||
u32 last_acq_fen_cnt;
|
||||
struct sync_fence *last_acq_fen[MDP_MAX_FENCE_FD];
|
||||
struct mutex sync_mutex;
|
||||
struct completion commit_comp;
|
||||
u32 is_committing;
|
||||
struct work_struct commit_work;
|
||||
void *msm_fb_backup;
|
||||
};
|
||||
struct msm_fb_backup_type {
|
||||
struct fb_info info;
|
||||
struct fb_var_screeninfo var;
|
||||
struct msm_fb_data_type mfd;
|
||||
};
|
||||
|
||||
struct dentry *msm_fb_get_debugfs_root(void);
|
||||
|
|
Loading…
Reference in a new issue