summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Salido-Moreno <adrianm@codeaurora.org>2014-01-07 17:29:20 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:26:13 -0700
commit0324446cc29c2b075edab7f3a88571af4d2b1ede (patch)
treefcc43665222f11a9a74635b13dcd5ce557093889
parent2688ad99c3c0fdc813a61df179fd84e7318d21e3 (diff)
msm: mdss: implement overlay prepare ioctl
Overlay prepare will allow a full frame with multiple overlays to be configured at once and perform frame level checks before being pushed to display. This function guarantees that if the call is successful, the frame can be displayed successfully on the screen when display commit is called. Change-Id: I276b6fe3e0a872a2e93170f3cea1002d3ce0dac9 Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c95
-rw-r--r--include/uapi/linux/msm_mdp.h20
2 files changed, 115 insertions, 0 deletions
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 763773b8b108..a61cf844e691 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2323,6 +2323,98 @@ static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd,
return ret;
}
+static int __handle_overlay_prepare(struct msm_fb_data_type *mfd,
+ struct mdp_overlay_list *ovlist,
+ struct mdp_overlay *overlays)
+{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_pipe *pipe;
+ struct mdp_overlay *req;
+ int ret = 0;
+ int i;
+ u32 new_reqs = 0;
+
+ ret = mutex_lock_interruptible(&mdp5_data->ov_lock);
+ if (ret)
+ return ret;
+
+ if (!mfd->panel_power_on) {
+ mutex_unlock(&mdp5_data->ov_lock);
+ return -EPERM;
+ }
+
+ pr_debug("prepare fb%d num_overlays=%d\n", mfd->index,
+ ovlist->num_overlays);
+
+ for (i = 0; i < ovlist->num_overlays; i++) {
+ req = overlays + i;
+
+ req->z_order += MDSS_MDP_STAGE_0;
+ ret = mdss_mdp_overlay_pipe_setup(mfd, req, &pipe);
+ req->z_order -= MDSS_MDP_STAGE_0;
+
+ if (IS_ERR_VALUE(ret))
+ goto validate_exit;
+
+ /* keep track of the new overlays to unset in case of errors */
+ if (pipe->play_cnt == 0)
+ new_reqs |= pipe->ndx;
+ }
+
+validate_exit:
+ if (IS_ERR_VALUE(ret))
+ mdss_mdp_overlay_release(mfd, new_reqs);
+ mutex_unlock(&mdp5_data->ov_lock);
+
+ ovlist->processed_overlays = i;
+
+ return ret;
+}
+
+static int __handle_ioctl_overlay_prepare(struct msm_fb_data_type *mfd,
+ void __user *argp)
+{
+ struct mdp_overlay_list ovlist;
+ struct mdp_overlay *overlays;
+ int i, ret;
+
+ if (copy_from_user(&ovlist, argp, sizeof(ovlist)))
+ return -EFAULT;
+
+ overlays = kmalloc(ovlist.num_overlays * sizeof(*overlays), GFP_KERNEL);
+ if (!overlays) {
+ pr_err("Unable to allocate memory for overlays\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < ovlist.num_overlays; i++) {
+ if (copy_from_user(overlays + i, ovlist.overlay_list[i],
+ sizeof(struct mdp_overlay))) {
+ ret = -EFAULT;
+ goto validate_exit;
+ }
+ }
+
+ ret = __handle_overlay_prepare(mfd, &ovlist, overlays);
+ if (!IS_ERR_VALUE(ret)) {
+ for (i = 0; i < ovlist.num_overlays; i++) {
+ if (copy_to_user(ovlist.overlay_list[i], overlays + i,
+ sizeof(struct mdp_overlay))) {
+ ret = -EFAULT;
+ goto validate_exit;
+ }
+ }
+ }
+
+ if (copy_to_user(argp, &ovlist, sizeof(ovlist)))
+ ret = -EFAULT;
+
+validate_exit:
+ kfree(overlays);
+
+ return ret;
+}
+
static int mdss_mdp_overlay_ioctl_handler(struct msm_fb_data_type *mfd,
u32 cmd, void __user *argp)
{
@@ -2446,6 +2538,9 @@ static int mdss_mdp_overlay_ioctl_handler(struct msm_fb_data_type *mfd,
if (!ret)
ret = copy_to_user(argp, &metadata, sizeof(metadata));
break;
+ case MSMFB_OVERLAY_PREPARE:
+ ret = __handle_ioctl_overlay_prepare(mfd, argp);
+ break;
default:
if (mfd->panel.type == WRITEBACK_PANEL)
ret = mdss_mdp_wb_ioctl_handler(mfd, cmd, argp);
diff --git a/include/uapi/linux/msm_mdp.h b/include/uapi/linux/msm_mdp.h
index 769daeb87320..683ca1111244 100644
--- a/include/uapi/linux/msm_mdp.h
+++ b/include/uapi/linux/msm_mdp.h
@@ -69,6 +69,8 @@
#define MSMFB_WRITEBACK_SET_MIRRORING_HINT _IOW(MSMFB_IOCTL_MAGIC, 167, \
unsigned int)
#define MSMFB_ASYNC_BLIT _IOW(MSMFB_IOCTL_MAGIC, 168, unsigned int)
+#define MSMFB_OVERLAY_PREPARE _IOWR(MSMFB_IOCTL_MAGIC, 169, \
+ struct mdp_overlay_list)
#define FB_TYPE_3D_PANEL 0x10101010
#define MDP_IMGTYPE2_START 0x10000
@@ -1026,6 +1028,24 @@ struct mdp_display_commit {
struct mdp_rect roi;
};
+/**
+ * struct mdp_overlay_list - argument for ioctl MSMFB_OVERLAY_PREPARE
+ * @num_overlays: Number of overlay layers as part of the frame.
+ * @overlay_list: Pointer to a list of overlay structures identifying
+ * the layers as part of the frame
+ * @flags: Flags can be used to extend behavior.
+ * @processed_overlays: Output parameter indicating how many pipes were
+ * successful. If there are no errors this number should
+ * match num_overlays. Otherwise it will indicate the last
+ * successful index for overlay that couldn't be set.
+ */
+struct mdp_overlay_list {
+ uint32_t num_overlays;
+ struct mdp_overlay **overlay_list;
+ uint32_t flags;
+ uint32_t processed_overlays;
+};
+
struct mdp_page_protection {
uint32_t page_protection;
};