summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h7
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c142
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c51
4 files changed, 107 insertions, 96 deletions
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index e016aab6629f..86df67cef584 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -1756,9 +1756,6 @@ int mdss_register_panel(struct mdss_panel_data *pdata)
if (mfd->key != MFD_KEY)
return -EINVAL;
- mfd->on_fnc = mdss_mdp_ctl_on;
- mfd->off_fnc = mdss_mdp_ctl_off;
-
rc = mdss_mdp_overlay_init(mfd);
if (rc)
pr_err("unable to init overlay\n");
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 3ae79af756b9..6bf691483b1e 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -291,8 +291,11 @@ int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl);
int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl);
int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl);
-int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd);
-int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd);
+struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
+ struct msm_fb_data_type *mfd);
+int mdss_mdp_ctl_destroy(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl);
int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg);
struct mdss_mdp_mixer *mdss_mdp_wb_mixer_alloc(int rotator);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index f4e43a40f570..81bec4d8bb0b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -386,41 +386,22 @@ int mdss_mdp_wb_mixer_destroy(struct mdss_mdp_mixer *mixer)
return 0;
}
-static int mdss_mdp_ctl_init(struct msm_fb_data_type *mfd)
+static int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
{
- struct mdss_mdp_ctl *ctl;
- struct mdss_panel_data *pdata;
u32 width, height;
- int ret = 0;
-
- if (!mfd)
- return -ENODEV;
+ int ret;
- pdata = dev_get_platdata(&mfd->pdev->dev);
- if (!pdata) {
- pr_err("no panel connected for fb%d\n", mfd->index);
+ if (!ctl || !ctl->panel_data) {
+ pr_err("invalid ctl handle\n");
return -ENODEV;
}
- width = pdata->panel_info.xres;
- height = pdata->panel_info.yres;
+ width = ctl->panel_data->panel_info.xres;
+ height = ctl->panel_data->panel_info.yres;
if (width > (2 * MAX_MIXER_WIDTH)) {
- pr_err("unsupported resolution\n");
- return -EINVAL;
- }
-
- if (!mfd->ctl) {
- ctl = mdss_mdp_ctl_alloc();
- if (!ctl) {
- pr_err("unable to allocate ctl\n");
- return -ENOMEM;
- }
- ctl->mfd = mfd;
- mfd->ctl = ctl;
- ctl->panel_data = pdata;
- } else {
- ctl = mfd->ctl;
+ pr_err("Unsupported panel resolution: %dx%d\n", width, height);
+ return -ENOTSUPP;
}
ctl->width = width;
@@ -432,7 +413,7 @@ static int mdss_mdp_ctl_init(struct msm_fb_data_type *mfd)
if (!ctl->mixer_left) {
pr_err("unable to allocate layer mixer\n");
ret = -ENOMEM;
- goto ctl_init_fail;
+ goto setup_fail;
}
}
@@ -450,7 +431,7 @@ static int mdss_mdp_ctl_init(struct msm_fb_data_type *mfd)
if (!ctl->mixer_right) {
pr_err("unable to allocate right mixer\n");
ret = -ENOMEM;
- goto ctl_init_fail;
+ goto setup_fail;
}
}
ctl->mixer_right->width = width;
@@ -460,6 +441,38 @@ static int mdss_mdp_ctl_init(struct msm_fb_data_type *mfd)
mdss_mdp_mixer_free(ctl->mixer_right);
}
+
+ if (ctl->mixer_right) {
+ ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
+ MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT;
+ } else {
+ ctl->opmode &= ~(MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
+ MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT);
+ }
+
+ return 0;
+setup_fail:
+ if (ctl->mixer_left)
+ mdss_mdp_mixer_free(ctl->mixer_left);
+ if (ctl->mixer_right)
+ mdss_mdp_mixer_free(ctl->mixer_right);
+ return ret;
+}
+
+struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
+ struct msm_fb_data_type *mfd)
+{
+ struct mdss_mdp_ctl *ctl;
+ int ret = 0;
+
+ ctl = mdss_mdp_ctl_alloc();
+ if (!ctl) {
+ pr_err("unable to allocate ctl\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ ctl->mfd = mfd;
+ ctl->panel_data = pdata;
+
switch (pdata->panel_info.type) {
case EDP_PANEL:
ctl->intf_num = MDSS_MDP_INTF0;
@@ -519,32 +532,19 @@ static int mdss_mdp_ctl_init(struct msm_fb_data_type *mfd)
mdss_mdp_dither_config(&dither, NULL);
}
- if (ctl->mixer_right) {
- ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
- MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT;
- }
-
+ return ctl;
ctl_init_fail:
- if (IS_ERR_VALUE(ret)) {
- if (ctl->mixer_left)
- mdss_mdp_mixer_free(ctl->mixer_left);
- if (ctl->mixer_right)
- mdss_mdp_mixer_free(ctl->mixer_right);
- mdss_mdp_ctl_free(ctl);
- mfd->ctl = NULL;
- }
+ mdss_mdp_ctl_free(ctl);
- return ret;
+ return ERR_PTR(ret);
}
-static int mdss_mdp_ctl_destroy(struct msm_fb_data_type *mfd)
+int mdss_mdp_ctl_destroy(struct mdss_mdp_ctl *ctl)
{
- struct mdss_mdp_ctl *ctl;
- if (!mfd || !mfd->ctl)
- return -ENODEV;
+ int rc;
- ctl = mfd->ctl;
- mfd->ctl = NULL;
+ rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CLOSE, NULL);
+ WARN(rc, "unable to close panel for intf=%d\n", ctl->intf_num);
if (ctl->mixer_left)
mdss_mdp_mixer_free(ctl->mixer_left);
@@ -571,25 +571,15 @@ int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg)
return 0;
}
-int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
+int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl)
{
- struct mdss_mdp_ctl *ctl;
struct mdss_mdp_mixer *mixer;
u32 outsize, temp, off;
int ret = 0;
- if (!mfd)
- return -ENODEV;
-
- if (mfd->key != MFD_KEY)
- return -EINVAL;
-
- if (mdss_mdp_ctl_init(mfd)) {
- pr_err("unable to initialize ctl\n");
- return -ENODEV;
- }
-
- ctl = mfd->ctl;
+ ret = mdss_mdp_ctl_setup(ctl);
+ if (ret)
+ return ret;
if (ctl->power_on) {
WARN(1, "already on!\n");
@@ -654,36 +644,20 @@ int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
start_fail:
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
mutex_unlock(&ctl->lock);
- if (ret)
- mdss_mdp_ctl_destroy(mfd);
return ret;
}
-int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd)
+int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl)
{
- struct mdss_mdp_ctl *ctl;
int ret = 0;
- if (!mfd)
- return -ENODEV;
-
- if (mfd->key != MFD_KEY)
- return -EINVAL;
-
- if (!mfd->ctl) {
- pr_err("ctl not initialized\n");
- return -ENODEV;
- }
-
- ctl = mfd->ctl;
-
if (!ctl->power_on) {
WARN(1, "already off!\n");
return 0;
}
- pr_debug("ctl_num=%d\n", mfd->ctl->num);
+ pr_debug("ctl_num=%d\n", ctl->num);
mutex_lock(&ctl->lock);
@@ -715,12 +689,6 @@ int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd)
mutex_unlock(&ctl->lock);
- if (!ret && !mfd->ref_cnt) {
- ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CLOSE, NULL);
- WARN(ret, "unable to close intf %d\n", ctl->intf_num);
- mdss_mdp_ctl_destroy(mfd);
- }
-
return ret;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 3956228c8d0a..ad905c5da9fc 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -1244,9 +1244,38 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd)
{
int rc;
- rc = mdss_mdp_ctl_on(mfd);
- if (rc == 0)
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (!mfd->ctl) {
+ struct mdss_mdp_ctl *ctl;
+ struct mdss_panel_data *pdata;
+
+ pdata = dev_get_platdata(&mfd->pdev->dev);
+ if (!pdata) {
+ pr_err("no panel connected for fb%d\n", mfd->index);
+ return -ENODEV;
+ }
+
+ ctl = mdss_mdp_ctl_init(pdata, mfd);
+ if (IS_ERR_OR_NULL(ctl)) {
+ pr_err("Unable to initialize ctl for fb%d\n",
+ mfd->index);
+ return PTR_ERR(ctl);
+ }
+ mfd->ctl = ctl;
+ }
+
+ rc = mdss_mdp_ctl_start(mfd->ctl);
+ if (rc == 0) {
atomic_inc(&ov_active_panels);
+ } else {
+ mdss_mdp_ctl_destroy(mfd->ctl);
+ mfd->ctl = NULL;
+ }
return rc;
}
@@ -1255,12 +1284,26 @@ static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd)
{
int rc;
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (!mfd->ctl) {
+ pr_err("ctl not initialized\n");
+ return -ENODEV;
+ }
+
mdss_mdp_overlay_release_all(mfd);
- rc = mdss_mdp_ctl_off(mfd);
+ rc = mdss_mdp_ctl_stop(mfd->ctl);
if (rc == 0) {
- if (!mfd->ref_cnt)
+ if (!mfd->ref_cnt) {
mfd->borderfill_enable = false;
+ mdss_mdp_ctl_destroy(mfd->ctl);
+ mfd->ctl = NULL;
+ }
if (atomic_dec_return(&ov_active_panels) == 0)
mdss_mdp_rotator_release_all();