msmfb: display: support for overlay wait ioctl
this adds supports for overlay wait ioctl and it allows the
userapce start overlay play and HDMI and can call wait
later point of the time
Change-Id: I8000cc52a497861e0a5fdfe58c0c049219724ab6
Signed-off-by: Nagamalleswararao Ganji <nganji@codeaurora.org>
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index ef3092b..f60cb78 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -427,6 +427,10 @@
int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
int mdp4_overlay_unset(struct fb_info *info, int ndx);
+void mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe);
+int mdp4_overlay_play_wait(struct fb_info *info,
+ struct msmfb_overlay_data *req);
int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
struct file **pp_src_file, struct file **pp_src_plane1_file,
struct file **pp_src_plane2_file);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 1b2dec4..f865edf 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2262,6 +2262,29 @@
return ((row_num_w * row_num_h * tile_w * tile_h) + 8191) & ~8191;
}
+int mdp4_overlay_play_wait(struct fb_info *info, struct msmfb_overlay_data *req)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct mdp4_overlay_pipe *pipe;
+
+ if (mfd == NULL)
+ return -ENODEV;
+
+ if (!mfd->panel_power_on) /* suspended */
+ return -EPERM;
+
+ pipe = mdp4_overlay_ndx2pipe(req->id);
+
+ if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
+ return -EINTR;
+
+ mdp4_overlay_dtv_wait_for_ov(mfd, pipe);
+
+ mutex_unlock(&mfd->dma->ov_mutex);
+
+ return 0;
+}
+
int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
struct file **pp_src_file, struct file **pp_src_plane1_file,
struct file **pp_src_plane2_file)
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index a8ace6b..a9b32ab 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -334,7 +334,7 @@
mdp4_set_perf_level();
}
-static void mdp4_overlay_dtv_wait4_ov_done(struct msm_fb_data_type *mfd)
+static void mdp4_overlay_dtv_ov_start(struct msm_fb_data_type *mfd)
{
unsigned long flag;
@@ -347,6 +347,18 @@
mdp_intr_mask |= INTR_OVERLAY1_DONE;
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ mfd->ov_start = true;
+}
+
+static void mdp4_overlay_dtv_wait4_ov_done(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ u32 data = inpdw(MDP_BASE + DTV_BASE);
+
+ mfd->ov_start = false;
+
+ if (!(data & 0x1) || (pipe == NULL))
+ return;
wait_for_completion_killable(&dtv_pipe->comp);
mdp_disable_irq(MDP_OVERLAY1_TERM);
}
@@ -356,15 +368,28 @@
{
mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_overlay_dtv_ov_start(mfd);
+
if (pipe->flags & MDP_OV_PLAY_NOWAIT)
return;
- mdp4_overlay_dtv_wait4_ov_done(mfd);
+ mdp4_overlay_dtv_wait4_ov_done(mfd, pipe);
/* change mdp clk while mdp is idle` */
mdp4_set_perf_level();
}
+void mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ if (mfd->ov_end) {
+ mfd->ov_end = false;
+ return;
+ }
+ mdp4_overlay_dtv_wait4_ov_done(mfd, pipe);
+ mdp4_set_perf_level();
+}
+
void mdp4_external_vsync_dtv()
{
complete(&dtv_pipe->comp);
@@ -413,7 +438,6 @@
struct fb_info *fbi = mfd->fbi;
uint8 *buf;
int bpp;
- unsigned long flag;
struct mdp4_overlay_pipe *pipe;
if (!mfd->panel_power_on)
@@ -430,19 +454,12 @@
pipe = dtv_pipe;
pipe->srcp0_addr = (uint32) buf;
mdp4_overlay_rgb_setup(pipe);
- mdp4_overlay_reg_flush(pipe, 1); /* rgb2 and mixer1 */
- /* enable irq */
- spin_lock_irqsave(&mdp_spin_lock, flag);
- mdp_enable_irq(MDP_OVERLAY1_TERM);
- INIT_COMPLETION(dtv_pipe->comp);
- mfd->dma->waiting = TRUE;
- outp32(MDP_INTR_CLEAR, INTR_OVERLAY1_DONE);
- mdp_intr_mask |= INTR_OVERLAY1_DONE;
- outp32(MDP_INTR_ENABLE, mdp_intr_mask);
- spin_unlock_irqrestore(&mdp_spin_lock, flag);
- wait_for_completion_killable(&dtv_pipe->comp);
- mdp_disable_irq(MDP_OVERLAY1_TERM);
+ if (mfd->ov_start) {
+ mdp4_overlay_dtv_wait4_ov_done(mfd, pipe);
+ mfd->ov_end = true;
+ }
+ mdp4_overlay_dtv_ov_done_push(mfd, pipe);
mdp4_stat.kickoff_dtv++;
mutex_unlock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 94c38ff..b3d5573 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -2501,6 +2501,26 @@
return mdp4_overlay_unset(info, ndx);
}
+static int msmfb_overlay_play_wait(struct fb_info *info, unsigned long *argp)
+{
+ int ret;
+ struct msmfb_overlay_data req;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ if (mfd->overlay_play_enable == 0) /* nothing to do */
+ return 0;
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ pr_err("%s:msmfb_overlay_wait ioctl failed", __func__);
+ return ret;
+ }
+
+ ret = mdp4_overlay_play_wait(info, &req);
+
+ return ret;
+}
+
static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
{
int ret;
@@ -2764,6 +2784,11 @@
ret = msmfb_overlay_play_enable(info, argp);
up(&msm_fb_ioctl_ppp_sem);
break;
+ case MSMFB_OVERLAY_PLAY_WAIT:
+ down(&msm_fb_ioctl_ppp_sem);
+ ret = msmfb_overlay_play_wait(info, argp);
+ up(&msm_fb_ioctl_ppp_sem);
+ break;
case MSMFB_OVERLAY_BLT:
down(&msm_fb_ioctl_ppp_sem);
ret = msmfb_overlay_blt(info, argp);
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index bdf32eb..43802a2 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -150,6 +150,7 @@
struct timer_list msmfb_no_update_notify_timer;
struct completion msmfb_update_notify;
struct completion msmfb_no_update_notify;
+ u32 ov_start, ov_end;
};
struct dentry *msm_fb_get_debugfs_root(void);
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index a739761..ac18939 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -52,7 +52,8 @@
#define MSMFB_MIXER_INFO _IOWR(MSMFB_IOCTL_MAGIC, 148, \
struct msmfb_mixer_info_req)
-
+#define MSMFB_OVERLAY_PLAY_WAIT _IOWR(MSMFB_IOCTL_MAGIC, 149, \
+ struct msmfb_overlay_data)
#define FB_TYPE_3D_PANEL 0x10101010
#define MDP_IMGTYPE2_START 0x10000