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,
|
static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
|
||||||
struct mdp_bl_scale_data *data);
|
struct mdp_bl_scale_data *data);
|
||||||
static void msm_fb_scale_bl(__u32 *bl_lvl);
|
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
|
#ifdef CONFIG_LGE_DISP_FBREAD
|
||||||
static ssize_t msm_fb_read(struct fb_info *info, char __user *buf,
|
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)
|
const struct fb_fillrect *rect)
|
||||||
{
|
{
|
||||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||||
|
msm_fb_pan_idle(mfd);
|
||||||
cfb_fillrect(info, rect);
|
cfb_fillrect(info, rect);
|
||||||
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
|
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
|
||||||
!mfd->sw_currently_refreshing) {
|
!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;
|
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||||
|
|
||||||
|
msm_fb_pan_idle(mfd);
|
||||||
cfb_copyarea(info, area);
|
cfb_copyarea(info, area);
|
||||||
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
|
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
|
||||||
!mfd->sw_currently_refreshing) {
|
!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;
|
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||||
|
|
||||||
|
msm_fb_pan_idle(mfd);
|
||||||
cfb_imageblit(info, image);
|
cfb_imageblit(info, image);
|
||||||
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
|
if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
|
||||||
!mfd->sw_currently_refreshing) {
|
!mfd->sw_currently_refreshing) {
|
||||||
|
@ -1055,6 +1059,7 @@ static int msm_fb_blank(int blank_mode, struct fb_info *info)
|
||||||
event.data = &blank_mode;
|
event.data = &blank_mode;
|
||||||
fb_notifier_call_chain(FB_EVENT_BLANK, &event);
|
fb_notifier_call_chain(FB_EVENT_BLANK, &event);
|
||||||
}
|
}
|
||||||
|
msm_fb_pan_idle(mfd);
|
||||||
return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
|
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);
|
u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
|
||||||
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
|
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
|
||||||
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||||
|
msm_fb_pan_idle(mfd);
|
||||||
if (off >= len) {
|
if (off >= len) {
|
||||||
/* memory mapped io */
|
/* memory mapped io */
|
||||||
off -= len;
|
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;
|
mfd->msmfb_no_update_notify_timer.data = (unsigned long)mfd;
|
||||||
init_completion(&mfd->msmfb_update_notify);
|
init_completion(&mfd->msmfb_update_notify);
|
||||||
init_completion(&mfd->msmfb_no_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_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
|
||||||
fbram += fbram_offset;
|
fbram += fbram_offset;
|
||||||
fbram_phys += 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)
|
int msm_fb_signal_timeline(struct msm_fb_data_type *mfd)
|
||||||
{
|
{
|
||||||
|
mutex_lock(&mfd->sync_mutex);
|
||||||
if (mfd->timeline) {
|
if (mfd->timeline) {
|
||||||
sw_sync_timeline_inc(mfd->timeline, 1);
|
sw_sync_timeline_inc(mfd->timeline, 1);
|
||||||
mfd->timeline_value++;
|
mfd->timeline_value++;
|
||||||
}
|
}
|
||||||
mfd->last_rel_fence = mfd->cur_rel_fence;
|
mfd->last_rel_fence = mfd->cur_rel_fence;
|
||||||
mfd->cur_rel_fence = 0;
|
mfd->cur_rel_fence = 0;
|
||||||
|
mutex_unlock(&mfd->sync_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_SEMAPHORE(msm_fb_pan_sem);
|
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,
|
static int msm_fb_pan_display(struct fb_var_screeninfo *var,
|
||||||
struct fb_info *info)
|
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 dirty;
|
||||||
struct mdp_dirty_region *dirtyPtr = NULL;
|
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,
|
mdp_set_dma_pan_info(info, dirtyPtr,
|
||||||
(var->activate == FB_ACTIVATE_VBL));
|
(var->activate == FB_ACTIVATE_VBL));
|
||||||
|
/* async call */
|
||||||
|
|
||||||
mdp_dma_pan_update(info);
|
mdp_dma_pan_update(info);
|
||||||
msm_fb_signal_timeline(mfd);
|
msm_fb_signal_timeline(mfd);
|
||||||
up(&msm_fb_pan_sem);
|
up(&msm_fb_pan_sem);
|
||||||
|
@ -1897,10 +1978,30 @@ static int msm_fb_pan_display(struct fb_var_screeninfo *var,
|
||||||
return 0;
|
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)
|
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;
|
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||||||
|
|
||||||
|
msm_fb_pan_idle(mfd);
|
||||||
if (var->rotate != FB_ROTATE_UR)
|
if (var->rotate != FB_ROTATE_UR)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (var->grayscale != info->var.grayscale)
|
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;
|
struct fb_var_screeninfo *var = &info->var;
|
||||||
int old_imgType;
|
int old_imgType;
|
||||||
int blank = 0;
|
int blank = 0;
|
||||||
|
msm_fb_pan_idle(mfd);
|
||||||
old_imgType = mfd->fb_imgType;
|
old_imgType = mfd->fb_imgType;
|
||||||
switch (var->bits_per_pixel) {
|
switch (var->bits_per_pixel) {
|
||||||
case 16:
|
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__);
|
pr_err("%s:copy_from_user failed", __func__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
mutex_lock(&mfd->sync_mutex);
|
||||||
for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
|
for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
|
||||||
fence = sync_fence_fdget(acq_fen_fd[i]);
|
fence = sync_fence_fdget(acq_fen_fd[i]);
|
||||||
if (fence == NULL) {
|
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;
|
goto buf_sync_err_2;
|
||||||
}
|
}
|
||||||
mfd->acq_fen_cnt = buf_sync->acq_fen_fd_cnt;
|
mfd->acq_fen_cnt = buf_sync->acq_fen_fd_cnt;
|
||||||
|
mutex_unlock(&mfd->sync_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
buf_sync_err_2:
|
buf_sync_err_2:
|
||||||
sync_fence_put(mfd->cur_rel_fence);
|
sync_fence_put(mfd->cur_rel_fence);
|
||||||
|
@ -3481,6 +3584,7 @@ buf_sync_err_1:
|
||||||
for (i = 0; i < fence_cnt; i++)
|
for (i = 0; i < fence_cnt; i++)
|
||||||
sync_fence_put(mfd->acq_fen[i]);
|
sync_fence_put(mfd->acq_fen[i]);
|
||||||
mfd->acq_fen_cnt = 0;
|
mfd->acq_fen_cnt = 0;
|
||||||
|
mutex_unlock(&mfd->sync_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
|
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 msmfb_mdp_pp mdp_pp;
|
||||||
struct mdp_buf_sync buf_sync;
|
struct mdp_buf_sync buf_sync;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
msm_fb_pan_idle(mfd);
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
#ifdef CONFIG_FB_MSM_OVERLAY
|
#ifdef CONFIG_FB_MSM_OVERLAY
|
||||||
|
|
|
@ -195,6 +195,18 @@ struct msm_fb_data_type {
|
||||||
struct sync_fence *last_rel_fence;
|
struct sync_fence *last_rel_fence;
|
||||||
struct sw_sync_timeline *timeline;
|
struct sw_sync_timeline *timeline;
|
||||||
int timeline_value;
|
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);
|
struct dentry *msm_fb_get_debugfs_root(void);
|
||||||
|
|
Loading…
Reference in a new issue