diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 361bb5528bae..74c556be67e6 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -1247,12 +1247,22 @@ int dsi_display_set_power(struct drm_connector *connector, switch (power_mode) { case SDE_MODE_DPMS_LP1: + if (display->panel->power_mode == SDE_MODE_DPMS_LP2) { + if (dsi_display_set_ulp_load(display, false) < 0) + DSI_WARN("failed to set load for lp1 state\n"); + } rc = dsi_panel_set_lp1(display->panel); break; case SDE_MODE_DPMS_LP2: rc = dsi_panel_set_lp2(display->panel); + if (dsi_display_set_ulp_load(display, true) < 0) + DSI_WARN("failed to set load for lp2 state\n"); break; case SDE_MODE_DPMS_ON: + if (display->panel->power_mode == SDE_MODE_DPMS_LP2) { + if (dsi_display_set_ulp_load(display, false) < 0) + DSI_WARN("failed to set load for on state\n"); + } if ((display->panel->power_mode == SDE_MODE_DPMS_LP1) || (display->panel->power_mode == SDE_MODE_DPMS_LP2)) rc = dsi_panel_set_nolp(display->panel); @@ -3904,6 +3914,35 @@ int dsi_pre_clkon_cb(void *priv, return rc; } +int dsi_display_set_ulp_load(struct dsi_display *display, bool enable) +{ + int i, rc = 0; + struct dsi_display_ctrl *display_ctrl; + struct dsi_ctrl *ctrl; + struct dsi_panel *panel; + + display_for_each_ctrl(i, display) { + display_ctrl = &display->ctrl[i]; + if (!display_ctrl->ctrl) + continue; + ctrl = display_ctrl->ctrl; + + rc = dsi_pwr_config_vreg_opt_mode(&ctrl->pwr_info.host_pwr, enable); + if (rc) { + DSI_ERR("failed to set ctrl load\n"); + return rc; + } + } + + panel = display->panel; + rc = dsi_pwr_config_vreg_opt_mode(&panel->power_info, enable); + if (rc) { + DSI_ERR("failed to set panel load\n"); + return rc; + } + return rc; +} + static void __set_lane_map_v2(u8 *lane_map_v2, enum dsi_phy_data_lanes lane0, enum dsi_phy_data_lanes lane1, diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 7ac0c8ba8feb..2dc7bc7dd137 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -628,7 +628,7 @@ int dsi_pre_clkon_cb(void *priv, enum dsi_clk_type clk_type, * Return: error code. */ int dsi_display_unprepare(struct dsi_display *display); - +int dsi_display_set_ulp_load(struct dsi_display *display, bool enable); int dsi_display_set_tpg_state(struct dsi_display *display, bool enable); int dsi_display_clock_gate(struct dsi_display *display, bool enable); diff --git a/msm/dsi/dsi_pwr.c b/msm/dsi/dsi_pwr.c index 7b3f9e2c8541..44bb745ad275 100644 --- a/msm/dsi/dsi_pwr.c +++ b/msm/dsi/dsi_pwr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020,2021 The Linux Foundation. All rights reserved. */ #include @@ -65,6 +65,14 @@ static int dsi_pwr_parse_supply_node(struct dsi_parser_utils *utils, regs->vregs[i].disable_load = tmp; /* Optional values */ + rc = utils->read_u32(node, "qcom,supply-ulp-load", &tmp); + if (rc) { + DSI_DEBUG("ulp-load not specified\n"); + rc = 0; + } + regs->vregs[i].ulp_load = (!rc ? tmp : + regs->vregs[i].enable_load); + rc = utils->read_u32(node, "qcom,supply-off-min-voltage", &tmp); if (rc) { DSI_DEBUG("off-min-voltage not specified\n"); @@ -118,6 +126,30 @@ error: return rc; } +int dsi_pwr_config_vreg_opt_mode(struct dsi_regulator_info *regs, + bool enable) +{ + int i = 0, rc = 0; + struct dsi_vreg *vreg; + u32 mode; + + for (i = 0; i < regs->count; i++) { + vreg = ®s->vregs[i]; + mode = enable ? vreg->ulp_load : vreg->enable_load; + + DSI_DEBUG(" Setting optimum mode for %s load = %d\n", + vreg->vreg_name, mode); + + rc = regulator_set_load(vreg->vreg, mode); + if (rc < 0) { + DSI_ERR("Set opt mode failed for %s", + vreg->vreg_name); + return rc; + } + } + return rc; +} + /** * dsi_pwr_enable_vregs() - enable/disable regulators */ diff --git a/msm/dsi/dsi_pwr.h b/msm/dsi/dsi_pwr.h index fd9ef2c18d8b..8e808b63a2f8 100644 --- a/msm/dsi/dsi_pwr.h +++ b/msm/dsi/dsi_pwr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019,2021 The Linux Foundation. All rights reserved. */ #ifndef _DSI_PWR_H_ @@ -21,6 +21,7 @@ struct dsi_parser_utils; * @max_voltage: Maximum voltage in uV. * @enable_load: Load, in uA, when enabled. * @disable_load: Load, in uA, when disabled. + * @ulp_load: Load, in uA, when ulp is enabled. * @off_min_voltage: Minimum voltage in uV when regulator is disabled. * @pre_on_sleep: Sleep, in ms, before enabling the regulator. * @post_on_sleep: Sleep, in ms, after enabling the regulator. @@ -34,6 +35,7 @@ struct dsi_vreg { u32 max_voltage; u32 enable_load; u32 disable_load; + u32 ulp_load; u32 off_min_voltage; u32 pre_on_sleep; u32 post_on_sleep; @@ -103,4 +105,13 @@ int dsi_pwr_enable_regulator(struct dsi_regulator_info *regs, bool enable); int dsi_pwr_panel_regulator_mode_set(struct dsi_regulator_info *regs, const char *reg_name, int regulator_mode); + +/** + * dsi_pwr_config_vreg_opt_mode() + * set regulator load + * @regs: Pointer to set of regulators to enable or disable. + * @enable: enable ulp_load or disable + * return: error code in case of failure or 0 for success. + */ +int dsi_pwr_config_vreg_opt_mode(struct dsi_regulator_info *regs, bool enable); #endif /* _DSI_PWR_H_ */