summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c24
-rw-r--r--drivers/video/fbdev/msm/mdss_edp.c20
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c30
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c18
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c94
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c30
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h18
-rw-r--r--drivers/video/fbdev/msm/mdss_wb.c14
9 files changed, 172 insertions, 77 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 09c810b52ca2..c22666f82c9b 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -327,6 +327,26 @@ static int mdss_dsi_on(struct mdss_panel_data *pdata)
return ret;
}
+static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
+ int event, void *arg)
+{
+ int rc = 0;
+
+ pr_debug("%s: event=%d\n", __func__, event);
+ switch (event) {
+ case MDSS_EVENT_UNBLANK:
+ rc = mdss_dsi_on(pdata);
+ break;
+ case MDSS_EVENT_BLANK:
+ rc = mdss_dsi_ctrl_unprepare(pdata);
+ break;
+ case MDSS_EVENT_TIMEGEN_OFF:
+ rc = mdss_dsi_off(pdata);
+ break;
+ }
+ return rc;
+}
+
static int mdss_dsi_resource_initialized;
static int mdss_dsi_probe(struct platform_device *pdev)
@@ -476,9 +496,7 @@ int dsi_panel_device_register(struct platform_device *pdev,
if (!ctrl_pdata)
return -ENOMEM;
- (ctrl_pdata->panel_data).on = mdss_dsi_on;
- (ctrl_pdata->panel_data).off = mdss_dsi_off;
- (ctrl_pdata->panel_data).intf_unprepare = mdss_dsi_ctrl_unprepare;
+ ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;
memcpy(&((ctrl_pdata->panel_data).panel_info),
&(panel_data->panel_info),
sizeof(struct mdss_panel_info));
diff --git a/drivers/video/fbdev/msm/mdss_edp.c b/drivers/video/fbdev/msm/mdss_edp.c
index 3006a6ed9d9e..9f2e4f48c407 100644
--- a/drivers/video/fbdev/msm/mdss_edp.c
+++ b/drivers/video/fbdev/msm/mdss_edp.c
@@ -353,6 +353,23 @@ int mdss_edp_off(struct mdss_panel_data *pdata)
return ret;
}
+static int mdss_edp_event_handler(struct mdss_panel_data *pdata,
+ int event, void *arg)
+{
+ int rc = 0;
+
+ pr_debug("%s: event=%d\n", __func__, event);
+ switch (event) {
+ case MDSS_EVENT_UNBLANK:
+ rc = mdss_edp_on(pdata);
+ break;
+ case MDSS_EVENT_TIMEGEN_OFF:
+ rc = mdss_edp_off(pdata);
+ break;
+ }
+ return rc;
+}
+
/*
* Converts from EDID struct to mdss_panel_info
*/
@@ -413,8 +430,7 @@ static int mdss_edp_device_register(struct mdss_edp_drv_pdata *edp_drv)
edp_drv->panel_data.panel_info.bl_min = 1;
edp_drv->panel_data.panel_info.bl_max = 255;
- edp_drv->panel_data.on = mdss_edp_on;
- edp_drv->panel_data.off = mdss_edp_off;
+ edp_drv->panel_data.event_handler = mdss_edp_event_handler;
edp_drv->panel_data.set_backlight = mdss_edp_set_backlight;
ret = mdss_register_panel(&edp_drv->panel_data);
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index ccbb80b391ca..eb70aebaa090 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -325,6 +325,24 @@ static int mdss_fb_remove(struct platform_device *pdev)
return 0;
}
+static inline int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd, int e)
+{
+ struct mdss_panel_data *pdata;
+
+ pdata = dev_get_platdata(&mfd->pdev->dev);
+ if (!pdata) {
+ pr_err("no panel connected\n");
+ return -ENODEV;
+ }
+
+ pr_debug("sending event=%d for fb%d\n", e, mfd->index);
+
+ if (pdata->event_handler)
+ return pdata->event_handler(pdata, e, NULL);
+
+ return 0;
+}
+
static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd)
{
int ret = 0;
@@ -334,6 +352,12 @@ static int mdss_fb_suspend_sub(struct msm_fb_data_type *mfd)
pr_debug("mdss_fb suspend index=%d\n", mfd->index);
+ ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_SUSPEND);
+ if (ret) {
+ pr_warn("unable to suspend fb%d (%d)\n", mfd->index, ret);
+ return ret;
+ }
+
mfd->suspend.op_enable = mfd->op_enable;
mfd->suspend.panel_power_on = mfd->panel_power_on;
@@ -359,6 +383,12 @@ static int mdss_fb_resume_sub(struct msm_fb_data_type *mfd)
pr_debug("mdss_fb resume index=%d\n", mfd->index);
+ ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_RESUME);
+ if (ret) {
+ pr_warn("unable to resume fb%d (%d)\n", mfd->index, ret);
+ return ret;
+ }
+
/* resume state var recover */
mfd->op_enable = mfd->suspend.op_enable;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index 0828fb418932..85a7de5b1496 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -2020,6 +2020,21 @@ fail_no_hdmi:
return rc;
} /* hdmi_tx_dev_init */
+static int hdmi_tx_event_handler(struct mdss_panel_data *panel_data,
+ int event, void *arg)
+{
+ int rc = 0;
+ switch (event) {
+ case MDSS_EVENT_UNBLANK:
+ rc = hdmi_tx_power_on(panel_data);
+ break;
+ case MDSS_EVENT_TIMEGEN_OFF:
+ rc = hdmi_tx_power_off(panel_data);
+ break;
+ }
+ return rc;
+}
+
static int hdmi_tx_register_panel(struct hdmi_tx_ctrl *hdmi_ctrl)
{
int rc = 0;
@@ -2029,8 +2044,7 @@ static int hdmi_tx_register_panel(struct hdmi_tx_ctrl *hdmi_ctrl)
return -EINVAL;
}
- hdmi_ctrl->panel_data.on = hdmi_tx_power_on;
- hdmi_ctrl->panel_data.off = hdmi_tx_power_off;
+ hdmi_ctrl->panel_data.event_handler = hdmi_tx_event_handler;
hdmi_ctrl->video_resolution = DEFAULT_VIDEO_RESOLUTION;
rc = hdmi_tx_init_panel_info(hdmi_ctrl->video_resolution,
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index ff173461c2ed..ffacc5d38450 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -291,6 +291,7 @@ int mdss_mdp_writeback_start(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);
+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);
int mdss_mdp_wb_mixer_destroy(struct mdss_mdp_mixer *mixer);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 04773199b0f2..5bd432a22d39 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -68,6 +68,11 @@ static int mdss_mdp_ctl_perf_commit(u32 flags)
bus_ab_quota = bus_ab_quota << MDSS_MDP_BUS_FACTOR_SHIFT;
bus_ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR(bus_ib_quota);
bus_ib_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT;
+
+ if ((bus_ib_quota == 0) && (clk_rate > 0)) {
+ /* allocate min bw for panel cmds if mdp is active */
+ bus_ib_quota = SZ_16M;
+ }
mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota);
}
if (flags & MDSS_MDP_PERF_UPDATE_CLK) {
@@ -531,9 +536,28 @@ static int mdss_mdp_ctl_destroy(struct msm_fb_data_type *mfd)
return 0;
}
-int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
+int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg)
{
struct mdss_panel_data *pdata;
+ if (!ctl || !ctl->mfd)
+ return -ENODEV;
+
+ pdata = dev_get_platdata(&ctl->mfd->pdev->dev);
+ if (!pdata) {
+ pr_err("no panel connected\n");
+ return -ENODEV;
+ }
+
+ pr_debug("sending ctl=%d event=%d\n", ctl->num, event);
+
+ if (pdata->event_handler)
+ return pdata->event_handler(pdata, event, arg);
+
+ return 0;
+}
+
+int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
+{
struct mdss_mdp_ctl *ctl;
struct mdss_mdp_mixer *mixer;
u32 outsize, temp, off;
@@ -545,12 +569,6 @@ int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
if (mfd->key != MFD_KEY)
return -EINVAL;
- pdata = dev_get_platdata(&mfd->pdev->dev);
- if (!pdata) {
- pr_err("no panel connected\n");
- return -ENODEV;
- }
-
if (mdss_mdp_ctl_init(mfd)) {
pr_err("unable to initialize ctl\n");
return -ENODEV;
@@ -568,6 +586,12 @@ int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
ctl->power_on = true;
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
@@ -579,17 +603,6 @@ int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
goto start_fail;
}
- /* request bus bandwidth for panel commands */
- ctl->clk_rate = MDP_CLK_DEFAULT_RATE;
- ctl->bus_ib_quota = SZ_1M;
- mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
-
- ret = pdata->on(pdata);
- if (ret) {
- pr_err("panel power on failed ctl=%d\n", ctl->num);
- goto panel_fail;
- }
-
pr_debug("ctl_num=%d\n", ctl->num);
mixer = ctl->mixer_left;
@@ -617,23 +630,18 @@ int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd)
MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_OUT_SIZE, outsize);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0);
}
-panel_fail:
- if (ret && ctl->stop_fnc)
- ctl->stop_fnc(ctl);
+
start_fail:
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
mutex_unlock(&ctl->lock);
- if (ret) {
+ if (ret)
mdss_mdp_ctl_destroy(mfd);
- mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
- }
return ret;
}
int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd)
{
- struct mdss_panel_data *pdata;
struct mdss_mdp_ctl *ctl;
int ret = 0;
@@ -648,12 +656,6 @@ int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd)
return -ENODEV;
}
- pdata = dev_get_platdata(&mfd->pdev->dev);
- if (!pdata) {
- pr_err("no panel connected\n");
- return -ENODEV;
- }
-
ctl = mfd->ctl;
if (!ctl->power_on) {
@@ -665,41 +667,33 @@ int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd)
mdss_mdp_overlay_release_all(mfd);
- /* request bus bandwidth for panel commands */
- ctl->bus_ib_quota = SZ_1M;
- mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
-
mutex_lock(&ctl->lock);
- ctl->power_on = false;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- if (pdata->intf_unprepare)
- ret = pdata->intf_unprepare(pdata);
-
- if (ret)
- pr_err("%s: intf_unprepare failed\n", __func__);
-
if (ctl->stop_fnc)
ret = ctl->stop_fnc(ctl);
else
pr_warn("no stop func for ctl=%d\n", ctl->num);
- if (ret)
+ if (ret) {
pr_warn("error powering off intf ctl=%d\n", ctl->num);
-
- ret = pdata->off(pdata);
+ } else {
+ ctl->power_on = false;
+ ctl->play_cnt = 0;
+ ctl->clk_rate = 0;
+ mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
+ }
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
- ctl->play_cnt = 0;
-
- mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
-
mutex_unlock(&ctl->lock);
- if (!mfd->ref_cnt)
+ 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_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index 097ef3888b74..64216aae500e 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -201,7 +201,7 @@ static int mdss_mdp_video_set_vsync_handler(struct mdss_mdp_ctl *ctl,
static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_video_ctx *ctx;
- int off;
+ int rc, off;
pr_debug("stop ctl=%d\n", ctl->num);
@@ -211,16 +211,27 @@ static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl)
return -ENODEV;
}
- if (ctx->vsync_handler)
- mdss_mdp_video_set_vsync_handler(ctl, NULL);
-
if (ctx->timegen_en) {
+ rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_BLANK, NULL);
+ if (rc == -EBUSY) {
+ pr_debug("intf #%d busy don't turn off\n",
+ ctl->intf_num);
+ return rc;
+ }
+ WARN(rc, "intf %d blank error (%d)\n", ctl->intf_num, rc);
+
off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
ctx->timegen_en = false;
+
+ rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_TIMEGEN_OFF, NULL);
+ WARN(rc, "intf %d timegen off error (%d)\n", ctl->intf_num, rc);
}
+ if (ctx->vsync_handler)
+ mdss_mdp_video_set_vsync_handler(ctl, NULL);
+
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
NULL, NULL);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
@@ -288,6 +299,7 @@ static int mdss_mdp_video_prepare(struct mdss_mdp_ctl *ctl, void *arg)
static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
{
struct mdss_mdp_video_ctx *ctx;
+ int rc;
pr_debug("kickoff ctl=%d\n", ctl->num);
@@ -306,15 +318,23 @@ static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
if (!ctx->timegen_en) {
int off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
+ rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_UNBLANK, NULL);
+ WARN(rc, "intf %d unblank error (%d)\n", ctl->intf_num, rc);
+
pr_debug("enabling timing gen for intf=%d\n", ctl->intf_num);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);
- ctx->timegen_en = true;
wmb();
}
wait_for_completion(&ctx->vsync_comp);
+
+ if (!ctx->timegen_en) {
+ ctx->timegen_en = true;
+ rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_TIMEGEN_ON, NULL);
+ WARN(rc, "intf %d timegen on error (%d)\n", ctl->intf_num, rc);
+ }
if (!ctx->vsync_handler)
mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
mutex_unlock(&ctx->vsync_lock);
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 102aaffbd693..34f19f63027b 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -55,6 +55,17 @@ enum {
MAX_PHYS_TARGET_NUM,
};
+enum mdss_intf_events {
+ MDSS_EVENT_RESET,
+ MDSS_EVENT_UNBLANK,
+ MDSS_EVENT_TIMEGEN_ON,
+ MDSS_EVENT_BLANK,
+ MDSS_EVENT_TIMEGEN_OFF,
+ MDSS_EVENT_CLOSE,
+ MDSS_EVENT_SUSPEND,
+ MDSS_EVENT_RESUME,
+};
+
/* panel info type */
struct lcd_panel_info {
u32 vsync_enable;
@@ -178,14 +189,11 @@ struct mdss_panel_info {
struct mdss_panel_data {
struct mdss_panel_info panel_info;
- void (*set_backlight) (struct mdss_panel_data *pdata,
- u32 bl_level);
- int (*intf_unprepare) (struct mdss_panel_data *pdata);
+ void (*set_backlight) (struct mdss_panel_data *pdata, u32 bl_level);
unsigned char *mmss_cc_base;
/* function entry chain */
- int (*on) (struct mdss_panel_data *pdata);
- int (*off) (struct mdss_panel_data *pdata);
+ int (*event_handler) (struct mdss_panel_data *pdata, int e, void *arg);
};
int mdss_register_panel(struct mdss_panel_data *pdata);
diff --git a/drivers/video/fbdev/msm/mdss_wb.c b/drivers/video/fbdev/msm/mdss_wb.c
index 287d1f9a6ee7..7352ea6f9bd0 100644
--- a/drivers/video/fbdev/msm/mdss_wb.c
+++ b/drivers/video/fbdev/msm/mdss_wb.c
@@ -26,15 +26,10 @@
#include "mdss_panel.h"
-static int mdss_wb_on(struct mdss_panel_data *pdata)
+static int mdss_wb_event_handler(struct mdss_panel_data *pdata,
+ int event, void *arg)
{
- pr_debug("%s\n", __func__);
- return 0;
-}
-
-static int mdss_wb_off(struct mdss_panel_data *pdata)
-{
- pr_debug("%s\n", __func__);
+ pr_debug("%s: event=%d\n", __func__, event);
return 0;
}
@@ -76,8 +71,7 @@ static int mdss_wb_probe(struct platform_device *pdev)
pdata->panel_info.pdest = DISPLAY_3;
pdata->panel_info.out_format = MDP_Y_CBCR_H2V2_VENUS;
- pdata->on = mdss_wb_on;
- pdata->off = mdss_wb_off;
+ pdata->event_handler = mdss_wb_event_handler;
pdev->dev.platform_data = pdata;
rc = mdss_register_panel(pdata);