Merge "mdss: dsi: Add support to partial update"

This commit is contained in:
Linux Build Service Account 2013-10-03 23:16:43 -07:00 committed by Gerrit - the friendly Code Review server
commit 179b553f23
6 changed files with 141 additions and 2 deletions

View file

@ -279,7 +279,8 @@ Optional properties:
as below:
--> Reset GPIO value
--> Sleep value (in ms)
- qcom,partial-update-enabled: Boolean used to enable partial
panel update for command mode panels.
Note, if a given optional qcom,* binding is not present, then the driver will configure
the default values specified.
@ -378,5 +379,6 @@ Example:
qcom,mdss-tear-check-rd-ptr-trigger-intr = <1281>;
qcom,mdss-tear-check-frame-rate = <6000>;
qcom,mdss-dsi-reset-sequence = <1 2>, <0 10>, <1 10>;
qcom,partial-update-enabled;
};
};

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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
*/

View file

@ -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;