diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index d871ba0d5bcd..dcb08e054124 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -885,6 +885,11 @@ int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl) if (dsi_panel_set_hbm_backlight(panel, &bl_lvl)) return 0; + if(panel->lhbm_config.enable) { + panel->lhbm_config.dbv_level = bl_lvl; + DSI_INFO("backlight type:%d dbv lvl:%d\n", bl->type, bl_lvl); + } + DSI_DEBUG("backlight type:%d lvl:%d\n", bl->type, bl_lvl); switch (bl->type) { case DSI_BACKLIGHT_WLED: @@ -1054,10 +1059,89 @@ end: return rc; }; +static int dsi_panel_set_local_hbm_param(struct dsi_panel *panel, + struct msm_param_info *param_info, + struct dsi_panel_lhbm_config *lhbm_config) +{ + int rc = 0, count = 0, i; + int alpha = 0; + u8 *payload; + struct panel_param_val_map *param_map; + struct panel_param_val_map *param_map_state; + struct panel_param *panel_param; + struct dsi_cmd_desc *cmds; + + + panel_param = &panel->param_cmds[param_info->param_idx]; + if (!panel_param) { + DSI_ERR("%s: invalid panel_param.\n", __func__); + return -EINVAL; + } + + param_map = panel_param->val_map; + + mutex_lock(&panel->panel_lock); + + if (param_info->value >= panel_param->val_max) + param_info->value = panel_param->val_max - 1; + + if (panel_param->value == param_info->value) + { + rc = 0; + goto end; + } else { + param_map = panel->param_cmds[param_info->param_idx].val_map; + param_map_state = ¶m_map[param_info->value]; + if (!param_map_state->cmds || !param_map_state->cmds->cmds) { + DSI_ERR("Invalid cmds or cmds->cmds\n"); + rc = -EINVAL; + goto end; + } + + cmds = param_map_state->cmds->cmds; + count = param_map_state->cmds->count; + + for (i =0; i < count; i++) { + payload = (u8 *)cmds->msg.tx_buf; + if(param_info->value == HBM_FOD_ON_STATE && + payload[0] == lhbm_config->alpha_reg) { + if(lhbm_config->dbv_level >lhbm_config->alpha_size) { + DSI_ERR("unsupport dbv level %d on local hbm\n", lhbm_config->dbv_level); + rc = -EINVAL; + goto end; + } + + alpha = lhbm_config->alpha[lhbm_config->dbv_level]; + payload[1] = (alpha&0xff00)>>8; + payload[2] = alpha&0xff; + DSI_INFO("%s: alpha [%x]=%x%x\n", + __func__, payload[0], payload[1], payload[2]); + rc = 0; + goto end; + } else if(param_info->value == HBM_OFF_STATE && + payload[0] == 0x51) { + payload[1] = (lhbm_config->dbv_level&0xff00)>>8; + payload[2] = lhbm_config->dbv_level&0xff; + DSI_INFO("%s: restore backlight level=%d\n", + __func__, lhbm_config->dbv_level); + rc = 0; + goto end; + } + cmds++; + } + } + +end: + mutex_unlock(&panel->panel_lock); + return rc; +}; + static int dsi_panel_set_hbm(struct dsi_panel *panel, struct msm_param_info *param_info) { int rc = 0; + u32 bl_lvl; + struct dsi_panel_lhbm_config *lhbm_config = &panel->lhbm_config; pr_info("Set HBM to (%d)\n", param_info->value); @@ -1084,11 +1168,19 @@ static int dsi_panel_set_hbm(struct dsi_panel *panel, rc = -EINVAL; } } else { + if(lhbm_config->enable && param_info->value != HBM_ON_STATE) { + dsi_panel_set_local_hbm_param(panel, param_info, lhbm_config); + } + rc = dsi_panel_send_param_cmd(panel, param_info); if (rc < 0) { DSI_ERR("%s: failed to send param cmds. ret=%d\n", __func__, rc); } else { - rc = dsi_panel_set_backlight(panel, HBM_BRIGHTNESS(param_info->value)); + if(lhbm_config->enable) + bl_lvl = lhbm_config->dbv_level; + else + bl_lvl = HBM_BRIGHTNESS(param_info->value); + rc = dsi_panel_set_backlight(panel, bl_lvl); if (rc) DSI_ERR("unable to set backlight\n"); } @@ -4085,6 +4177,66 @@ error: return rc; } +static int dsi_panel_parse_local_hbm_config(struct dsi_panel *panel) +{ + int rc = 0; + u32 size; + struct dsi_panel_lhbm_config *lhbm_config; + struct dsi_parser_utils *utils = &panel->utils; + + lhbm_config = &panel->lhbm_config; + lhbm_config->enable = utils->read_bool(utils->data, + "qcom,mdss-dsi-panel-local-hbm-enabled"); + + if (lhbm_config->enable) { + rc = utils->read_u32(utils->data, + "qcom,mdss-dsi-panel-local-hbm-alpha-size", + &(lhbm_config->alpha_size)); + if (rc) { + DSI_ERR("%s:%d, Unable to read local hbm alpha size, rc:%u\n", + __func__, __LINE__, rc); + lhbm_config->enable = false; + return rc; + } + + size = lhbm_config->alpha_size * sizeof(u32); + + lhbm_config->alpha = kzalloc(size, GFP_KERNEL); + if (!lhbm_config->alpha) { + rc = -ENOMEM; + DSI_ERR("%s:%d, no memory for local hbm alpha table, rc:%u\n", + __func__, __LINE__, rc); + lhbm_config->enable = false; + return rc; + } + + rc = utils->read_u32_array(utils->data, + "qcom,mdss-dsi-panel-local-hbm-alpha-table", + lhbm_config->alpha, + lhbm_config->alpha_size); + if (rc) { + DSI_ERR("%s:%d, Unable to read local hbm alpha table,rc:%u\n", + __func__, __LINE__, rc); + lhbm_config->enable = false; + return rc; + } + + rc = utils->read_u32(utils->data, + "qcom,mdss-dsi-panel-local-hbm-alpha-register", + &(lhbm_config->alpha_reg)); + if (rc) { + DSI_ERR("%s:%d, Unable to read local hbm register, rc:%u\n", + __func__, __LINE__, rc); + lhbm_config->enable = false; + return rc; + } + } else { + DSI_INFO("%s:%d, no local hbm config\n", + __func__, __LINE__); + } + return 0; +} + static void dsi_panel_update_util(struct dsi_panel *panel, struct device_node *parser_node) { @@ -4446,6 +4598,10 @@ struct dsi_panel *dsi_panel_get(struct device *parent, if (rc) DSI_DEBUG("failed to parse esd config, rc=%d\n", rc); + rc = dsi_panel_parse_local_hbm_config(panel); + if (rc) + DSI_DEBUG("failed to parse local hbm config, rc=%d\n", rc); + rc = dsi_panel_vreg_get(panel); if (rc) { DSI_ERR("[%s] failed to get panel regulators, rc=%d\n", diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index e98564ed5321..26066cd5ca80 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -223,6 +223,14 @@ struct dsi_panel_spr_info { enum msm_display_spr_pack_type pack_type; }; +struct dsi_panel_lhbm_config { + bool enable; + u32 dbv_level; + u32 alpha_reg; + u32 alpha_size; + u32 *alpha; +}; + enum panel_idx { MAIN_IDX = 0, SEC_INX, @@ -327,6 +335,8 @@ struct dsi_panel { struct drm_panel_hdr_properties hdr_props; struct drm_panel_esd_config esd_config; + struct dsi_panel_lhbm_config lhbm_config; + struct dsi_parser_utils utils; bool lp11_init;