summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandan Uddaraju <chandanu@codeaurora.org>2013-01-24 14:33:19 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:14:21 -0700
commit0a547f9587bf86c4018ad4055592f0d9d77e56bf (patch)
tree188aeac05b306121f2ab88c6e91b196296564ace
parent2b0b211563d29d53c6f53831c9fe81b300f7a55b (diff)
msm: mdss: enable split display in mdp
Allow a second panel to be registered to a single frame buffer, the image from frame buffer would then be displayed across the two panels. Change-Id: I2bc78741ed8408bedfa563cd312c4e628045bfae Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org> Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org>
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c46
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c266
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_hwio.h4
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c11
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h2
7 files changed, 273 insertions, 61 deletions
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index dc983bbacb62..c18206b8ff3d 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -261,6 +261,8 @@ static int mdss_fb_probe(struct platform_device *pdev)
mfd->fb_imgType = MDP_RGBA_8888;
mfd->pdev = pdev;
+ if (pdata->next)
+ mfd->split_display = true;
mutex_init(&mfd->lock);
@@ -886,13 +888,15 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd)
return ret;
}
+ var->xres = panel_info->xres;
+ if (mfd->split_display)
+ var->xres *= 2;
+
fix->type = panel_info->is_3d_panel;
- fix->line_length = mdss_fb_line_length(mfd->index, panel_info->xres,
- bpp);
+ fix->line_length = mdss_fb_line_length(mfd->index, var->xres, bpp);
- var->xres = panel_info->xres;
var->yres = panel_info->yres;
- var->xres_virtual = panel_info->xres;
+ var->xres_virtual = var->xres;
var->yres_virtual = panel_info->yres * mfd->fb_page;
var->bits_per_pixel = bpp * 8; /* FrameBuffer color depth */
var->upper_margin = panel_info->lcdc.v_back_porch;
@@ -1735,6 +1739,36 @@ struct fb_info *msm_fb_get_writeback_fb(void)
}
EXPORT_SYMBOL(msm_fb_get_writeback_fb);
+static int mdss_fb_register_extra_panel(struct platform_device *pdev,
+ struct mdss_panel_data *pdata)
+{
+ struct mdss_panel_data *fb_pdata;
+
+ fb_pdata = dev_get_platdata(&pdev->dev);
+ if (!fb_pdata) {
+ pr_err("framebuffer device %s contains invalid panel data\n",
+ dev_name(&pdev->dev));
+ return -EINVAL;
+ }
+
+ if (fb_pdata->next) {
+ pr_err("split panel already setup for framebuffer device %s\n",
+ dev_name(&pdev->dev));
+ return -EEXIST;
+ }
+
+ if ((fb_pdata->panel_info.type != MIPI_VIDEO_PANEL) ||
+ (pdata->panel_info.type != MIPI_VIDEO_PANEL)) {
+ pr_err("Split panel not supported for panel type %d\n",
+ pdata->panel_info.type);
+ return -EINVAL;
+ }
+
+ fb_pdata->next = pdata;
+
+ return 0;
+}
+
int mdss_register_panel(struct platform_device *pdev,
struct mdss_panel_data *pdata)
{
@@ -1762,9 +1796,7 @@ int mdss_register_panel(struct platform_device *pdev,
fb_pdev = of_find_device_by_node(node);
if (fb_pdev) {
- pr_warn("frame buffer device already exists for %s\n",
- node->full_name);
- rc = -EPERM;
+ rc = mdss_fb_register_extra_panel(fb_pdev, pdata);
} else {
pr_info("adding framebuffer device %s\n", dev_name(&pdev->dev));
fb_pdev = of_platform_device_create(node, NULL,
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index a3b1ac323ddf..8ad8665fdcfb 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. 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
@@ -60,6 +60,7 @@ struct msm_fb_data_type {
struct panel_id panel;
struct mdss_panel_info *panel_info;
+ int split_display;
u32 dest;
struct fb_info *fbi;
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 6bf691483b1e..4a2bec98d07c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -293,6 +293,8 @@ int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl);
struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
struct msm_fb_data_type *mfd);
+int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
+ struct mdss_panel_data *pdata);
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);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 81bec4d8bb0b..be7ee4ebd67e 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -386,20 +386,45 @@ int mdss_mdp_wb_mixer_destroy(struct mdss_mdp_mixer *mixer)
return 0;
}
+static inline int mdss_mdp_set_split_ctl(struct mdss_mdp_ctl *ctl,
+ struct mdss_mdp_ctl *split_ctl)
+{
+ if (!ctl || !split_ctl)
+ return -ENODEV;
+
+ /* setup split ctl mixer as right mixer of original ctl so that
+ * original ctl can work the same way as dual pipe solution */
+ ctl->mixer_right = split_ctl->mixer_left;
+
+ return 0;
+}
+
+static inline struct mdss_mdp_ctl *mdss_mdp_get_split_ctl(
+ struct mdss_mdp_ctl *ctl)
+{
+ if (ctl && ctl->mixer_right && (ctl->mixer_right->ctl != ctl))
+ return ctl->mixer_right->ctl;
+
+ return NULL;
+}
+
static int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
{
+ struct mdss_mdp_ctl *split_ctl;
u32 width, height;
- int ret;
if (!ctl || !ctl->panel_data) {
pr_err("invalid ctl handle\n");
return -ENODEV;
}
+ split_ctl = mdss_mdp_get_split_ctl(ctl);
+
width = ctl->panel_data->panel_info.xres;
height = ctl->panel_data->panel_info.yres;
- if (width > (2 * MAX_MIXER_WIDTH)) {
+ if ((split_ctl && (width > MAX_MIXER_WIDTH)) ||
+ (width > (2 * MAX_MIXER_WIDTH))) {
pr_err("Unsupported panel resolution: %dx%d\n", width, height);
return -ENOTSUPP;
}
@@ -412,8 +437,7 @@ static int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
if (!ctl->mixer_left) {
pr_err("unable to allocate layer mixer\n");
- ret = -ENOMEM;
- goto setup_fail;
+ return -ENOMEM;
}
}
@@ -424,14 +448,20 @@ static int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
ctl->mixer_left->height = height;
ctl->mixer_left->ctl = ctl;
+ if (split_ctl) {
+ pr_debug("split display detected\n");
+ return 0;
+ }
+
if (width < ctl->width) {
if (ctl->mixer_right == NULL) {
ctl->mixer_right =
mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
if (!ctl->mixer_right) {
pr_err("unable to allocate right mixer\n");
- ret = -ENOMEM;
- goto setup_fail;
+ if (ctl->mixer_left)
+ mdss_mdp_mixer_free(ctl->mixer_left);
+ return -ENOMEM;
}
}
ctl->mixer_right->width = width;
@@ -441,7 +471,6 @@ static int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
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;
@@ -451,12 +480,6 @@ static int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
}
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,
@@ -539,17 +562,109 @@ ctl_init_fail:
return ERR_PTR(ret);
}
+int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
+ struct mdss_panel_data *pdata)
+{
+ struct mdss_mdp_ctl *sctl;
+ struct mdss_mdp_mixer *mixer;
+
+ if (!ctl || !pdata)
+ return -ENODEV;
+
+ if (pdata->panel_info.xres > MAX_MIXER_WIDTH) {
+ pr_err("Unsupported second panel resolution: %dx%d\n",
+ pdata->panel_info.xres, pdata->panel_info.yres);
+ return -ENOTSUPP;
+ }
+
+ if (ctl->mixer_right) {
+ pr_err("right mixer already setup for ctl=%d\n", ctl->num);
+ return -EPERM;
+ }
+
+ sctl = mdss_mdp_ctl_init(pdata, ctl->mfd);
+ if (!sctl) {
+ pr_err("unable to setup split display\n");
+ return -ENODEV;
+ }
+
+ sctl->width = pdata->panel_info.xres;
+ sctl->height = pdata->panel_info.yres;
+
+ ctl->mixer_left = mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+ if (!ctl->mixer_left) {
+ pr_err("unable to allocate layer mixer\n");
+ mdss_mdp_ctl_destroy(sctl);
+ return -ENOMEM;
+ }
+ ctl->mixer_left->ctl = ctl;
+
+ mixer = mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+ if (!mixer) {
+ pr_err("unable to allocate layer mixer\n");
+ mdss_mdp_ctl_destroy(sctl);
+ return -ENOMEM;
+ }
+
+ mixer->width = sctl->width;
+ mixer->height = sctl->height;
+ mixer->ctl = sctl;
+ sctl->mixer_left = mixer;
+
+ return mdss_mdp_set_split_ctl(ctl, sctl);
+}
+
+static void mdss_mdp_ctl_split_display_enable(int enable,
+ struct mdss_mdp_ctl *main_ctl, struct mdss_mdp_ctl *slave_ctl)
+{
+ u32 upper = 0, lower = 0;
+
+ pr_debug("split main ctl=%d intf=%d slave ctl=%d intf=%d\n",
+ main_ctl->num, main_ctl->intf_num,
+ slave_ctl->num, slave_ctl->intf_num);
+ if (enable) {
+ if (main_ctl->opmode & MDSS_MDP_CTL_OP_CMD_MODE) {
+ upper |= BIT(1);
+ lower |= BIT(1);
+
+ /* interface controlling sw trigger */
+ if (main_ctl->intf_num == MDSS_MDP_INTF2)
+ upper |= BIT(4);
+ else
+ upper |= BIT(8);
+ } else { /* video mode */
+ if (main_ctl->intf_num == MDSS_MDP_INTF2)
+ lower |= BIT(4);
+ else
+ lower |= BIT(8);
+ }
+ }
+ MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTRL, upper);
+ MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTRL, lower);
+ MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SPLIT_DISPLAY_EN, enable);
+}
+
+
int mdss_mdp_ctl_destroy(struct mdss_mdp_ctl *ctl)
{
+ struct mdss_mdp_ctl *sctl;
int rc;
rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CLOSE, NULL);
WARN(rc, "unable to close panel for intf=%d\n", ctl->intf_num);
+ sctl = mdss_mdp_get_split_ctl(ctl);
+ if (sctl) {
+ pr_debug("destroying split display ctl=%d\n", sctl->num);
+ if (sctl->mixer_left)
+ mdss_mdp_mixer_free(sctl->mixer_left);
+ mdss_mdp_ctl_free(sctl);
+ } else if (ctl->mixer_right) {
+ mdss_mdp_mixer_free(ctl->mixer_right);
+ }
+
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);
return 0;
@@ -558,6 +673,8 @@ int mdss_mdp_ctl_destroy(struct mdss_mdp_ctl *ctl)
int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg)
{
struct mdss_panel_data *pdata;
+ int rc = 0;
+
if (!ctl || !ctl->panel_data)
return -ENODEV;
@@ -565,41 +682,21 @@ int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg)
pr_debug("sending ctl=%d event=%d\n", ctl->num, event);
- if (pdata->event_handler)
- return pdata->event_handler(pdata, event, arg);
+ do {
+ if (pdata->event_handler)
+ rc = pdata->event_handler(pdata, event, arg);
+ pdata = pdata->next;
+ } while (rc == 0 && pdata);
- return 0;
+ return rc;
}
-int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl)
+static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_mixer *mixer;
u32 outsize, temp, off;
int ret = 0;
- ret = mdss_mdp_ctl_setup(ctl);
- if (ret)
- return ret;
-
- if (ctl->power_on) {
- WARN(1, "already on!\n");
- return 0;
- }
-
- mutex_lock(&ctl->lock);
-
- ctl->power_on = true;
- ctl->bus_ab_quota = 0;
- ctl->bus_ib_quota = 0;
- ctl->clk_rate = 0;
-
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_RESET, NULL);
- if (ret) {
- pr_err("panel power on failed ctl=%d\n", ctl->num);
- goto start_fail;
- }
-
if (ctl->start_fnc)
ret = ctl->start_fnc(ctl);
else
@@ -608,7 +705,7 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl)
if (ret) {
pr_err("unable to start intf\n");
- goto start_fail;
+ return ret;
}
pr_debug("ctl_num=%d\n", ctl->num);
@@ -631,17 +728,59 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl)
off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, outsize);
- if (ctl->mixer_right) {
- mixer = ctl->mixer_right;
- mdss_mdp_pp_resume(mixer->num);
- mixer->params_changed++;
- outsize = (mixer->height << 16) | mixer->width;
- off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
- MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, outsize);
- mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0);
+ return ret;
+}
+
+int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl)
+{
+ struct mdss_mdp_ctl *sctl;
+ int ret = 0;
+
+ ret = mdss_mdp_ctl_setup(ctl);
+ if (ret)
+ return ret;
+
+ if (ctl->power_on) {
+ WARN(1, "already on!\n");
+ return 0;
+ }
+
+ sctl = mdss_mdp_get_split_ctl(ctl);
+
+ mutex_lock(&ctl->lock);
+
+ ctl->power_on = true;
+ ctl->bus_ab_quota = 0;
+ ctl->bus_ib_quota = 0;
+ ctl->clk_rate = 0;
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+ ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_RESET, NULL);
+ if (ret) {
+ pr_err("panel power on failed ctl=%d\n", ctl->num);
+ return ret;
+ }
+
+ ret = mdss_mdp_ctl_start_sub(ctl);
+ if (ret == 0) {
+ if (sctl) { /* split display is available */
+ ret = mdss_mdp_ctl_start_sub(sctl);
+ if (!ret)
+ mdss_mdp_ctl_split_display_enable(1, ctl, sctl);
+ } else if (ctl->mixer_right) {
+ struct mdss_mdp_mixer *mixer = ctl->mixer_right;
+ u32 out, off;
+
+ mdss_mdp_pp_resume(mixer->num);
+ mixer->params_changed++;
+ out = (mixer->height << 16) | mixer->width;
+ off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
+ MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, out);
+ mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0);
+ }
}
-start_fail:
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
mutex_unlock(&ctl->lock);
@@ -650,6 +789,7 @@ start_fail:
int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl)
{
+ struct mdss_mdp_ctl *sctl;
int ret = 0;
if (!ctl->power_on) {
@@ -657,6 +797,8 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl)
return 0;
}
+ sctl = mdss_mdp_get_split_ctl(ctl);
+
pr_debug("ctl_num=%d\n", ctl->num);
mutex_lock(&ctl->lock);
@@ -668,6 +810,12 @@ int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl)
else
pr_warn("no stop func for ctl=%d\n", ctl->num);
+ if (sctl && sctl->stop_fnc) {
+ ret = sctl->stop_fnc(sctl);
+
+ mdss_mdp_ctl_split_display_enable(0, ctl, sctl);
+ }
+
if (ret) {
pr_warn("error powering off intf ctl=%d\n", ctl->num);
} else {
@@ -912,6 +1060,7 @@ static int mdss_mdp_mixer_update(struct mdss_mdp_mixer *mixer)
int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
{
+ struct mdss_mdp_ctl *sctl = NULL;
int mixer1_changed, mixer2_changed;
int ret = 0;
int perf_update = MDSS_MDP_PERF_UPDATE_SKIP;
@@ -933,6 +1082,8 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
return 0;
}
+ sctl = mdss_mdp_get_split_ctl(ctl);
+
mixer1_changed = (ctl->mixer_left && ctl->mixer_left->params_changed);
mixer2_changed = (ctl->mixer_right && ctl->mixer_right->params_changed);
@@ -957,11 +1108,22 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg)
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_TOP, ctl->opmode);
ctl->flush_bits |= BIT(17); /* CTL */
+
+ if (sctl) {
+ mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_TOP,
+ sctl->opmode);
+ sctl->flush_bits |= BIT(17);
+ }
}
/* postprocessing setup, including dspp */
mdss_mdp_pp_setup(ctl);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
+ if (sctl) {
+ mdss_mdp_pp_setup(sctl);
+ mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH,
+ sctl->flush_bits);
+ }
wmb();
ctl->flush_bits = 0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
index d2b2eab96d6f..dd0d998aee11 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
@@ -34,6 +34,10 @@
#define MDSS_MDP_REG_HIST_INTR_STATUS 0x00120
#define MDSS_MDP_REG_HIST_INTR_CLEAR 0x00124
+#define MDSS_MDP_REG_SPLIT_DISPLAY_EN 0x003F4
+#define MDSS_MDP_REG_SPLIT_DISPLAY_UPPER_PIPE_CTRL 0x003F8
+#define MDSS_MDP_REG_SPLIT_DISPLAY_LOWER_PIPE_CTRL 0x004F0
+
#define MDSS_INTF_DSI 0x1
#define MDSS_INTF_HDMI 0x3
#define MDSS_INTF_LCDC 0x5
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index ad905c5da9fc..97e84d4d6525 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -863,7 +863,7 @@ static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
return;
}
- if (fbi->var.xres > MAX_MIXER_WIDTH) {
+ if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe,
MDSS_MDP_MIXER_MUX_RIGHT);
if (ret) {
@@ -1266,6 +1266,15 @@ static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd)
mfd->index);
return PTR_ERR(ctl);
}
+
+ if (mfd->split_display && pdata->next) {
+ /* enable split display */
+ rc = mdss_mdp_ctl_split_display_setup(ctl, pdata->next);
+ if (rc) {
+ mdss_mdp_ctl_destroy(ctl);
+ return rc;
+ }
+ }
mfd->ctl = ctl;
}
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 1682e7635085..40131eb79780 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -196,6 +196,8 @@ struct mdss_panel_data {
/* function entry chain */
int (*event_handler) (struct mdss_panel_data *pdata, int e, void *arg);
+
+ struct mdss_panel_data *next;
};
int mdss_register_panel(struct platform_device *pdev,