diff --git a/drivers/media/video/msm_wfd/mdp-4-subdev.c b/drivers/media/video/msm_wfd/mdp-4-subdev.c index afb7239cbf19..3708c14fc5cf 100644 --- a/drivers/media/video/msm_wfd/mdp-4-subdev.c +++ b/drivers/media/video/msm_wfd/mdp-4-subdev.c @@ -24,7 +24,6 @@ struct mdp_instance { u32 width; bool secure; bool uses_iommu_split_domain; - struct switch_dev sdev; }; int mdp_init(struct v4l2_subdev *sd, u32 val) @@ -56,13 +55,7 @@ int mdp_open(struct v4l2_subdev *sd, void *arg) rc = -ENODEV; goto mdp_open_fail; } - inst->sdev.name = "wfd"; - /* Register wfd node to switch driver */ - rc = switch_dev_register(&inst->sdev); - if (rc) { - WFD_MSG_ERR("WFD switch registration failed\n"); - goto mdp_open_fail; - } + msm_fb_writeback_init(fbi); inst->mdp = fbi; inst->secure = mops->secure; @@ -92,8 +85,6 @@ int mdp_start(struct v4l2_subdev *sd, void *arg) rc = -ENODEV; goto exit; } - switch_set_state(&inst->sdev, true); - WFD_MSG_DBG("wfd state switched to %d\n", inst->sdev.state); } exit: return rc; @@ -110,8 +101,6 @@ int mdp_stop(struct v4l2_subdev *sd, void *arg) return rc; } fbi = (struct fb_info *)inst->mdp; - switch_set_state(&inst->sdev, false); - WFD_MSG_DBG("wfd state switched to %d\n", inst->sdev.state); } return 0; } @@ -122,8 +111,6 @@ int mdp_close(struct v4l2_subdev *sd, void *arg) if (inst) { fbi = (struct fb_info *)inst->mdp; msm_fb_writeback_terminate(fbi); - /* Unregister wfd node from switch driver */ - switch_dev_unregister(&inst->sdev); kfree(inst); } return 0; diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h index ea22a88f435f..3a2dd23b2c33 100644 --- a/drivers/video/msm/mdp4.h +++ b/drivers/video/msm/mdp4.h @@ -906,6 +906,7 @@ int mdp4_writeback_queue_buffer(struct fb_info *info, void mdp4_writeback_dma_stop(struct msm_fb_data_type *mfd); int mdp4_writeback_init(struct fb_info *info); int mdp4_writeback_terminate(struct fb_info *info); +int mdp4_writeback_set_mirroring_hint(struct fb_info *info, int hint); uint32_t mdp_block2base(uint32_t block); int mdp_hist_lut_config(struct mdp_hist_lut_data *data); diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c index 29e148bfd3e4..205febd958d1 100644 --- a/drivers/video/msm/mdp4_overlay_writeback.c +++ b/drivers/video/msm/mdp4_overlay_writeback.c @@ -224,6 +224,7 @@ int mdp4_overlay_writeback_off(struct platform_device *pdev) /* MDP_LAYERMIXER_WB_MUX_SEL to restore to default cfg*/ outpdw(MDP_BASE + 0x100F4, 0x0); mdp_clk_ctrl(0); + pr_debug("%s-:\n", __func__); return ret; } @@ -820,3 +821,23 @@ static void mdp4_wfd_queue_wakeup(struct msm_fb_data_type *mfd, mutex_unlock(&mfd->writeback_mutex); wake_up(&mfd->wait_q); } + +int mdp4_writeback_set_mirroring_hint(struct fb_info *info, int hint) +{ + struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + if (mfd->panel.type != WRITEBACK_PANEL) + return -ENOTSUPP; + + switch (hint) { + case MDP_WRITEBACK_MIRROR_ON: + case MDP_WRITEBACK_MIRROR_PAUSE: + case MDP_WRITEBACK_MIRROR_RESUME: + case MDP_WRITEBACK_MIRROR_OFF: + pr_info("wfd state switched to %d\n", hint); + switch_set_state(&mfd->writeback_sdev, hint); + return 0; + default: + return -EINVAL; + } +} diff --git a/drivers/video/msm/mdp4_wfd_writeback.c b/drivers/video/msm/mdp4_wfd_writeback.c index a8fdcc035ee2..7ec3dba261a1 100644 --- a/drivers/video/msm/mdp4_wfd_writeback.c +++ b/drivers/video/msm/mdp4_wfd_writeback.c @@ -75,6 +75,13 @@ static int writeback_probe(struct platform_device *pdev) platform_set_drvdata(mdp_dev, mfd); + mfd->writeback_sdev.name = "wfd"; + rc = switch_dev_register(&mfd->writeback_sdev); + if (rc) { + pr_err("Failed to setup switch dev for writeback panel"); + return rc; + } + rc = platform_device_add(mdp_dev); if (rc) { WRITEBACK_MSG_ERR("failed to add device"); @@ -84,8 +91,16 @@ static int writeback_probe(struct platform_device *pdev) return rc; } +static int writeback_remove(struct platform_device *pdev) +{ + struct msm_fb_data_type *mfd = platform_get_drvdata(pdev); + switch_dev_unregister(&mfd->writeback_sdev); + return 0; +} + static struct platform_driver writeback_driver = { .probe = writeback_probe, + .remove = writeback_remove, .driver = { .name = "writeback", }, diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c index 33975bd3a169..9fb82fccf790 100644 --- a/drivers/video/msm/msm_fb.c +++ b/drivers/video/msm/msm_fb.c @@ -3338,6 +3338,29 @@ static int msmfb_overlay_ioctl_writeback_terminate(struct fb_info *info) return mdp4_writeback_terminate(info); } +static int msmfb_overlay_ioctl_writeback_set_mirr_hint(struct fb_info * + info, void *argp) +{ + int ret = 0, hint; + + if (!info) { + ret = -EINVAL; + goto error; + } + + ret = copy_from_user(&hint, argp, sizeof(hint)); + if (ret) + goto error; + + ret = mdp4_writeback_set_mirroring_hint(info, hint); + if (ret) + goto error; +error: + if (ret) + pr_err("%s: ioctl failed\n", __func__); + return ret; +} + #else static int msmfb_overlay_ioctl_writeback_init(struct fb_info *info) { @@ -3370,6 +3393,12 @@ static int msmfb_overlay_ioctl_writeback_terminate(struct fb_info *info) { return -ENOTSUPP; } + +static int msmfb_overlay_ioctl_writeback_set_mirr_hint(struct fb_info * + info, void *argp) +{ + return -ENOTSUPP; +} #endif static int msmfb_overlay_3d_sbys(struct fb_info *info, unsigned long *argp) @@ -3750,6 +3779,10 @@ static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd, case MSMFB_WRITEBACK_TERMINATE: ret = msmfb_overlay_ioctl_writeback_terminate(info); break; + case MSMFB_WRITEBACK_SET_MIRRORING_HINT: + ret = msmfb_overlay_ioctl_writeback_set_mirr_hint( + info, argp); + break; #endif case MSMFB_VSYNC_CTRL: case MSMFB_OVERLAY_VSYNC_CTRL: diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h index 57fdef6a3e32..2f915b9a9ca6 100644 --- a/drivers/video/msm/msm_fb.h +++ b/drivers/video/msm/msm_fb.h @@ -37,7 +37,9 @@ #include #include #include +#include #include + #ifdef CONFIG_HAS_EARLYSUSPEND #include #endif @@ -178,6 +180,7 @@ struct msm_fb_data_type { struct list_head writeback_busy_queue; struct list_head writeback_free_queue; struct list_head writeback_register_queue; + struct switch_dev writeback_sdev; wait_queue_head_t wait_q; struct ion_client *iclient; unsigned long display_iova; diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h index eee85721f61c..c685fce3a952 100644 --- a/include/linux/msm_mdp.h +++ b/include/linux/msm_mdp.h @@ -73,6 +73,8 @@ #define MSMFB_BUFFER_SYNC _IOW(MSMFB_IOCTL_MAGIC, 162, struct mdp_buf_sync) #define MSMFB_DISPLAY_COMMIT _IOW(MSMFB_IOCTL_MAGIC, 164, \ struct mdp_display_commit) +#define MSMFB_WRITEBACK_SET_MIRRORING_HINT _IOW(MSMFB_IOCTL_MAGIC, 165, \ + unsigned int) #define MSMFB_METADATA_GET _IOW(MSMFB_IOCTL_MAGIC, 166, struct msmfb_metadata) #define FB_TYPE_3D_PANEL 0x10101010 @@ -574,6 +576,13 @@ enum { ROTATOR_SUBSYSTEM_ID, }; +enum { + MDP_WRITEBACK_MIRROR_OFF, + MDP_WRITEBACK_MIRROR_ON, + MDP_WRITEBACK_MIRROR_PAUSE, + MDP_WRITEBACK_MIRROR_RESUME, +}; + #ifdef __KERNEL__ /* get the framebuffer physical address information */