diff options
| author | Jeykumar Sankaran <jsanka@codeaurora.org> | 2013-09-20 13:47:01 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:21:53 -0700 |
| commit | 29f66ae4688514f4af15fee4893ea3a54e76f32d (patch) | |
| tree | 0610df6f32afa75a6f67337657f37c30b29336cb | |
| parent | 6dedcd4fe530436d3c11a3144ddeab4b075d6b71 (diff) | |
mdss: dsi: Add support to partial update
Add support to send DCS commands to set the partial update region
of interest(ROI) size. These commands will set the column/row start and end
coordinates based on the ROI size.
Change-Id: I3418472d9d622150c3cd7571b0b1e7a3482f5597
Signed-off-by: Jeykumar Sankaran <jsanka@codeaurora.org>
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.c | 42 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.h | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_panel.c | 68 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c | 21 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 7 |
5 files changed, 138 insertions, 1 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index f1817675e989..24f09496599a 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -617,7 +617,7 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, - panel_data); + panel_data); if (!ctrl_pdata->panel_data.panel_info.dynamic_fps) { pr_err("%s: Dynamic fps not enabled for this panel\n", @@ -662,6 +662,43 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) return rc; } +static int mdss_dsi_ctl_partial_update(struct mdss_panel_data *pdata) +{ + int rc = -EINVAL; + u32 data; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; + + if (pdata == NULL) { + pr_err("%s: Invalid input data\n", __func__); + return -EINVAL; + } + + ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + + /* DSI_COMMAND_MODE_MDP_STREAM_CTRL */ + data = (((pdata->panel_info.roi_w * 3) + 1) << 16) | + (pdata->panel_info.mipi.vc << 8) | DTYPE_DCS_LWRITE; + MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x60, data); + MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x58, data); + + /* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */ + data = pdata->panel_info.roi_h << 16 | pdata->panel_info.roi_w; + MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x64, data); + MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data); + + if (ctrl_pdata->partial_update_fnc) + rc = ctrl_pdata->partial_update_fnc(pdata); + + if (rc) { + pr_err("%s: unable to initialize the panel\n", + __func__); + return rc; + } + + return rc; +} + static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, int event, void *arg) { @@ -729,6 +766,9 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, rc = mdss_dsi_blank(pdata); } break; + case MDSS_EVENT_ENABLE_PARTIAL_UPDATE: + rc = mdss_dsi_ctl_partial_update(pdata); + break; default: pr_debug("%s: unhandled event=%d\n", __func__, event); break; diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h index 619d6c83a172..64277c3fadc0 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.h +++ b/drivers/video/fbdev/msm/mdss_dsi.h @@ -315,6 +315,7 @@ struct mdss_dsi_ctrl_pdata { int ndx; /* panel_num */ int (*on) (struct mdss_panel_data *pdata); int (*off) (struct mdss_panel_data *pdata); + int (*partial_update_fnc) (struct mdss_panel_data *pdata); struct mdss_panel_data panel_data; unsigned char *ctrl_base; int reg_size; diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index c2b42ff9d2ef..99490c27f299 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -231,6 +231,61 @@ void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) } } +static char caset[] = {0x2a, 0x00, 0x00, 0x03, 0x00}; /* DTYPE_DCS_LWRITE */ +static char paset[] = {0x2b, 0x00, 0x00, 0x05, 0x00}; /* DTYPE_DCS_LWRITE */ + +static struct dsi_cmd_desc partial_update_enable_cmd[] = { + {{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(caset)}, caset}, + {{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(paset)}, paset}, +}; + +static int mdss_dsi_panel_partial_update(struct mdss_panel_data *pdata) +{ + struct mipi_panel_info *mipi; + struct mdss_dsi_ctrl_pdata *ctrl = NULL; + struct dcs_cmd_req cmdreq; + int rc = 0; + + if (pdata == NULL) { + pr_err("%s: Invalid input data\n", __func__); + return -EINVAL; + } + + ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + mipi = &pdata->panel_info.mipi; + + pr_debug("%s: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx); + + caset[1] = (((pdata->panel_info.roi_x) & 0xFF00) >> 8); + caset[2] = (((pdata->panel_info.roi_x) & 0xFF)); + caset[3] = (((pdata->panel_info.roi_x - 1 + pdata->panel_info.roi_w) + & 0xFF00) >> 8); + caset[4] = (((pdata->panel_info.roi_x - 1 + pdata->panel_info.roi_w) + & 0xFF)); + partial_update_enable_cmd[0].payload = caset; + + paset[1] = (((pdata->panel_info.roi_y) & 0xFF00) >> 8); + paset[2] = (((pdata->panel_info.roi_y) & 0xFF)); + paset[3] = (((pdata->panel_info.roi_y - 1 + pdata->panel_info.roi_h) + & 0xFF00) >> 8); + paset[4] = (((pdata->panel_info.roi_y - 1 + pdata->panel_info.roi_h) + & 0xFF)); + partial_update_enable_cmd[1].payload = paset; + + pr_debug("%s: enabling partial update\n", __func__); + memset(&cmdreq, 0, sizeof(cmdreq)); + cmdreq.cmds = partial_update_enable_cmd; + cmdreq.cmds_cnt = 2; + cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL; + cmdreq.rlen = 0; + cmdreq.cb = NULL; + + mdss_dsi_cmdlist_put(ctrl, &cmdreq); + + return rc; +} + static void mdss_dsi_panel_bl_ctrl(struct mdss_panel_data *pdata, u32 bl_level) { @@ -850,6 +905,7 @@ int mdss_dsi_panel_init(struct device_node *node, int rc = 0; static const char *panel_name; bool cont_splash_enabled; + bool partial_update_enabled; if (!node) { pr_err("%s: no panel node\n", __func__); @@ -886,6 +942,18 @@ int mdss_dsi_panel_init(struct device_node *node, ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 1; } + partial_update_enabled = of_property_read_bool(node, + "qcom,partial-update-enabled"); + if (partial_update_enabled) { + pr_info("%s: Partial update enabled.\n", __func__); + ctrl_pdata->panel_data.panel_info.partial_update_enabled = 1; + ctrl_pdata->partial_update_fnc = mdss_dsi_panel_partial_update; + } else { + pr_info("%s: Partial update disabled.\n", __func__); + ctrl_pdata->panel_data.panel_info.partial_update_enabled = 0; + ctrl_pdata->partial_update_fnc = NULL; + } + ctrl_pdata->on = mdss_dsi_panel_on; ctrl_pdata->off = mdss_dsi_panel_off; ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl; diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index 32d3bff1b2c8..fec73b3ac03e 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -431,10 +431,28 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) return rc; } +static int mdss_mdp_cmd_set_partial_roi(struct mdss_mdp_ctl *ctl, + struct mdss_mdp_img_rect *roi) +{ + int rc = 0; + if (roi->w && roi->h && + ctl->panel_data->panel_info.partial_update_enabled) { + ctl->panel_data->panel_info.roi_x = roi->x; + ctl->panel_data->panel_info.roi_y = roi->y; + ctl->panel_data->panel_info.roi_w = roi->w; + ctl->panel_data->panel_info.roi_h = roi->h; + + rc = mdss_mdp_ctl_intf_event(ctl, + MDSS_EVENT_ENABLE_PARTIAL_UPDATE, NULL); + } + return rc; +} + int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg) { struct mdss_mdp_cmd_ctx *ctx; unsigned long flags; + struct mdss_mdp_img_rect roi; int rc; ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data; @@ -453,6 +471,9 @@ int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg) WARN(rc, "intf %d panel on error (%d)\n", ctl->intf_num, rc); } + roi = (struct mdss_mdp_img_rect){0, 0, ctl->width, ctl->height}; + mdss_mdp_cmd_set_partial_roi(ctl, &roi); + /* * tx dcs command if had any */ diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index ee53139a30f3..82411153bb86 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -126,6 +126,7 @@ struct mdss_panel_recovery { - 0 clock disable - 1 clock enable * @MDSS_EVENT_DSI_CMDLIST_KOFF: acquire dsi_mdp_busy lock before kickoff. + * @MDSS_EVENT_ENABLE_PARTIAL_UPDATE: Event to update ROI of the panel. */ enum mdss_intf_events { MDSS_EVENT_RESET = 1, @@ -143,6 +144,7 @@ enum mdss_intf_events { MDSS_EVENT_FB_REGISTERED, MDSS_EVENT_PANEL_CLK_CTRL, MDSS_EVENT_DSI_CMDLIST_KOFF, + MDSS_EVENT_ENABLE_PARTIAL_UPDATE, }; struct lcd_panel_info { @@ -294,6 +296,10 @@ struct mdss_panel_info { u32 rst_seq[MDSS_DSI_RST_SEQ_LEN]; u32 rst_seq_len; u32 vic; /* video identification code */ + u32 roi_x; + u32 roi_y; + u32 roi_w; + u32 roi_h; int bklt_ctrl; /* backlight ctrl */ int pwm_pmic_gpio; int pwm_lpg_chan; @@ -304,6 +310,7 @@ struct mdss_panel_info { u32 mode_gpio_state; u32 cont_splash_enabled; + u32 partial_update_enabled; struct ion_handle *splash_ihdl; u32 panel_power_on; |
