diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.c | 24 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_edp.c | 20 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.c | 30 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_hdmi_tx.c | 18 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 94 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 30 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 18 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_wb.c | 14 |
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); |
