Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7a86c39 authored by Sachin Bhayare's avatar Sachin Bhayare Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: io_util: Add support to configure regulator opt mode



For certain usecases, it may be possible to lower the current load
requested for a particular regulator. For example, during static
display if the DSI lanes are in ULPS mode, it is possible that the
load on the panel regulators can be lowered. To support such usecases,
add a new API to the io_util library to configure optimum mode for a
power module.

Change-Id: Ie31ef9a67d321fd89767ba2c7f92d6f3b4ae7e7e
Signed-off-by: default avatarSachin Bhayare <sachin.bhayare@codeaurora.org>
parent f5be93c4
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -516,6 +516,8 @@ Additional properties added to the second level nodes that represent timings pro
Note, if a given optional qcom,* binding is not present, then the driver will configure
the default values specified.

Note, all the "qcom,supply-*" properties have their definitions in mdss-dsi-txt.

Example:
&mdss_mdp {
	dsi_sim_vid: qcom,mdss_dsi_sim_video {
@@ -705,6 +707,7 @@ Example:
				qcom,supply-max-voltage = <2800000>;
				qcom,supply-enable-load = <100000>;
				qcom,supply-disable-load = <100>;
				qcom,supply-ulp-load = <100>;
				qcom,supply-pre-on-sleep = <0>;
				qcom,supply-post-on-sleep = <0>;
				qcom,supply-pre-off-sleep = <0>;
@@ -718,6 +721,7 @@ Example:
				qcom,supply-max-voltage = <1800000>;
				qcom,supply-enable-load = <100000>;
				qcom,supply-disable-load = <100>;
				qcom,supply-ulp-load = <100>;
				qcom,supply-pre-on-sleep = <0>;
				qcom,supply-post-on-sleep = <0>;
				qcom,supply-pre-off-sleep = <0>;
+4 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ Optional properties:
					-- qcom,supply-max-voltage: maximum voltage level (uV)
					-- qcom,supply-enable-load: load drawn (uA) from enabled supply
					-- qcom,supply-disable-load: load drawn (uA) from disabled supply
					-- qcom,supply-ulp-load: load drawn (uA) from supply in ultra-low power mode
					-- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on
					-- qcom,supply-post-on-sleep: time to sleep (ms) after turning on
					-- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off
@@ -164,6 +165,7 @@ Example:
				qcom,supply-max-voltage = <0>;
				qcom,supply-enable-load = <0>;
				qcom,supply-disable-load = <0>;
				qcom,supply-ulp-load = <0>;
				qcom,supply-pre-on-sleep = <0>;
				qcom,supply-post-on-sleep = <0>;
				qcom,supply-pre-off-sleep = <0>;
@@ -182,6 +184,7 @@ Example:
				qcom,supply-max-voltage = <1800000>;
				qcom,supply-enable-load = <100000>;
				qcom,supply-disable-load = <100>;
				qcom,supply-ulp-load = <100>;
				qcom,supply-pre-on-sleep = <0>;
				qcom,supply-post-on-sleep = <20>;
				qcom,supply-pre-off-sleep = <0>;
@@ -200,6 +203,7 @@ Example:
				qcom,supply-max-voltage = <1200000>;
				qcom,supply-enable-load = <100000>;
				qcom,supply-disable-load = <100>;
				qcom,supply-ulp-load = <1000>;
				qcom,supply-pre-on-sleep = <0>;
				qcom,supply-post-on-sleep = <20>;
				qcom,supply-pre-off-sleep = <0>;
+22 −13
Original line number Diff line number Diff line
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -218,7 +218,7 @@ static int mdss_pll_util_parse_dt_supply(struct platform_device *pdev,
			pr_err(": error reading enable load. rc=%d\n", rc);
			goto error;
		}
		mp->vreg_config[i].enable_load = tmp;
		mp->vreg_config[i].load[DSS_REG_MODE_ENABLE] = tmp;

		rc = of_property_read_u32(supply_node,
					"qcom,supply-disable-load", &tmp);
@@ -226,7 +226,15 @@ static int mdss_pll_util_parse_dt_supply(struct platform_device *pdev,
			pr_err(": error reading disable load. rc=%d\n", rc);
			goto error;
		}
		mp->vreg_config[i].disable_load = tmp;
		mp->vreg_config[i].load[DSS_REG_MODE_DISABLE] = tmp;

		rc = of_property_read_u32(supply_node,
					"qcom,supply-ulp-load", &tmp);
		if (rc)
			pr_warn(": error reading ulp load. rc=%d\n", rc);

		mp->vreg_config[i].load[DSS_REG_MODE_ULP] = (!rc ? tmp :
			mp->vreg_config[i].load[DSS_REG_MODE_ENABLE]);

		rc = of_property_read_u32(supply_node,
					"qcom,supply-pre-on-sleep", &tmp);
@@ -260,12 +268,13 @@ static int mdss_pll_util_parse_dt_supply(struct platform_device *pdev,

		mp->vreg_config[i].post_off_sleep = (!rc ? tmp : 0);

		pr_debug("%s min=%d, max=%d, enable=%d, disable=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
		pr_debug("%s min=%d, max=%d, enable=%d, disable=%d, ulp=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
			mp->vreg_config[i].vreg_name,
			mp->vreg_config[i].min_voltage,
			mp->vreg_config[i].max_voltage,
					mp->vreg_config[i].enable_load,
					mp->vreg_config[i].disable_load,
			mp->vreg_config[i].load[DSS_REG_MODE_ENABLE],
			mp->vreg_config[i].load[DSS_REG_MODE_DISABLE],
			mp->vreg_config[i].load[DSS_REG_MODE_ULP],
			mp->vreg_config[i].pre_on_sleep,
			mp->vreg_config[i].post_on_sleep,
			mp->vreg_config[i].pre_off_sleep,
+17 −6
Original line number Diff line number Diff line
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -334,7 +334,7 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev,
				__func__, rc);
			goto error;
		}
		mp->vreg_config[i].enable_load = tmp;
		mp->vreg_config[i].load[DSS_REG_MODE_ENABLE] = tmp;

		/* disable-load */
		rc = of_property_read_u32(supply_node,
@@ -344,7 +344,17 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev,
				__func__, rc);
			goto error;
		}
		mp->vreg_config[i].disable_load = tmp;
		mp->vreg_config[i].load[DSS_REG_MODE_DISABLE] = tmp;

		/* ulp-load */
		rc = of_property_read_u32(supply_node,
			"qcom,supply-ulp-load", &tmp);
		if (rc)
			pr_warn("%s: error reading ulp load. rc=%d\n",
				__func__, rc);

		mp->vreg_config[i].load[DSS_REG_MODE_ULP] = (!rc ? tmp :
			mp->vreg_config[i].load[DSS_REG_MODE_ENABLE]);

		/* pre-sleep */
		rc = of_property_read_u32(supply_node,
@@ -388,13 +398,14 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev,
			mp->vreg_config[i].post_off_sleep = tmp;
		}

		pr_debug("%s: %s min=%d, max=%d, enable=%d, disable=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
		pr_debug("%s: %s min=%d, max=%d, enable=%d, disable=%d, ulp=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
			__func__,
			mp->vreg_config[i].vreg_name,
			mp->vreg_config[i].min_voltage,
			mp->vreg_config[i].max_voltage,
			mp->vreg_config[i].enable_load,
			mp->vreg_config[i].disable_load,
			mp->vreg_config[i].load[DSS_REG_MODE_ENABLE]
			mp->vreg_config[i].load[DSS_REG_MODE_DISABLE]
			mp->vreg_config[i].load[DSS_REG_MODE_ULP]
			mp->vreg_config[i].pre_on_sleep,
			mp->vreg_config[i].post_on_sleep,
			mp->vreg_config[i].pre_off_sleep,
+95 −11
Original line number Diff line number Diff line
@@ -354,11 +354,62 @@ static int mdss_dsi_panel_power_lp(struct mdss_panel_data *pdata, int enable)
	return 0;
}

static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
static int mdss_dsi_panel_power_ulp(struct mdss_panel_data *pdata,
					int enable)
{
	int ret = 0, i;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	u32 mode = enable ? DSS_REG_MODE_ULP : DSS_REG_MODE_ENABLE;
	struct dsi_shared_data *sdata;

	pr_debug("%s: +\n", __func__);
	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);
	sdata = ctrl_pdata->shared_data;

	for (i = 0; i < DSI_MAX_PM; i++) {
		/*
		 * Core power module need to be controlled along with
		 * DSI core clocks.
		 */
		if (DSI_CORE_PM == i)
			continue;
		if (DSI_PANEL_PM == i)
			ret = msm_dss_config_vreg_opt_mode(
				ctrl_pdata->panel_power_data.vreg_config,
				ctrl_pdata->panel_power_data.num_vreg, mode);
		else
			ret = msm_dss_config_vreg_opt_mode(
				sdata->power_data[i].vreg_config,
				sdata->power_data[i].num_vreg, mode);
		if (ret) {
			pr_err("%s: failed to config ulp opt mode for %s.rc=%d\n",
				__func__, __mdss_dsi_pm_name(i), ret);
			break;
		}
	}

	if (ret) {
		mode = enable ? DSS_REG_MODE_ENABLE : DSS_REG_MODE_ULP;
		for (; i >= 0; i--)
			msm_dss_config_vreg_opt_mode(
				ctrl_pdata->power_data[i].vreg_config,
				ctrl_pdata->power_data[i].num_vreg, mode);
	}
	return ret;
}

int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
	int power_state)
{
	int ret;
	struct mdss_panel_info *pinfo;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
@@ -366,7 +417,8 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
	}

	pinfo = &pdata->panel_info;
	pr_debug("%s: cur_power_state=%d req_power_state=%d\n", __func__,
	pr_debug("%pS-->%s: cur_power_state=%d req_power_state=%d\n",
		__builtin_return_address(0), __func__,
		pinfo->panel_power_state, power_state);

	if (pinfo->panel_power_state == power_state) {
@@ -374,6 +426,9 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
		return 0;
	}

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);

	/*
	 * If a dynamic mode switch is pending, the regulators should not
	 * be turned off or on.
@@ -386,14 +441,31 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,
		ret = mdss_dsi_panel_power_off(pdata);
		break;
	case MDSS_PANEL_POWER_ON:
		if (mdss_dsi_is_panel_on_lp(pdata))
		if (mdss_dsi_is_panel_on_ulp(pdata)) {
			ret = mdss_dsi_panel_power_ulp(pdata, false);
			goto end;
		} else if (mdss_dsi_is_panel_on_lp(pdata)) {
			ret = mdss_dsi_panel_power_lp(pdata, false);
		else
			goto end;
		} else {
			ret = mdss_dsi_panel_power_on(pdata);
		}
		break;
	case MDSS_PANEL_POWER_LP1:
	case MDSS_PANEL_POWER_LP2:
		if (mdss_dsi_is_panel_on_ulp(pdata))
			ret = mdss_dsi_panel_power_ulp(pdata, false);
		else
			ret = mdss_dsi_panel_power_lp(pdata, true);
		/*
		 * temp workaround until framework issues pertaining to LP2
		 * power state transitions are fixed. For now, we internally
		 * transition to LP2 state whenever core power is turned off
		 * in LP1 state
		 */
		break;
	case MDSS_PANEL_POWER_LP2:
		if (!ctrl_pdata->core_power)
			ret = mdss_dsi_panel_power_ulp(pdata, true);
		break;
	default:
		pr_err("%s: unknown panel power state requested (%d)\n",
@@ -403,7 +475,7 @@ static int mdss_dsi_panel_power_ctrl(struct mdss_panel_data *pdata,

	if (!ret)
		pinfo->panel_power_state = power_state;

end:
	return ret;
}

@@ -513,7 +585,7 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev,
				__func__, rc);
			goto error;
		}
		mp->vreg_config[i].enable_load = tmp;
		mp->vreg_config[i].load[DSS_REG_MODE_ENABLE] = tmp;

		/* disable-load */
		rc = of_property_read_u32(supply_node,
@@ -523,7 +595,18 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev,
				__func__, rc);
			goto error;
		}
		mp->vreg_config[i].disable_load = tmp;
		mp->vreg_config[i].load[DSS_REG_MODE_DISABLE] = tmp;

		/* ulp-load */
		rc = of_property_read_u32(supply_node,
			"qcom,supply-ulp-load", &tmp);
		if (rc) {
			pr_warn("%s: error reading ulp load. rc=%d\n",
				__func__, rc);
			rc = 0;
		}
		mp->vreg_config[i].load[DSS_REG_MODE_ULP] = (!rc ? tmp :
			mp->vreg_config[i].load[DSS_REG_MODE_ENABLE]);

		/* pre-sleep */
		rc = of_property_read_u32(supply_node,
@@ -567,13 +650,14 @@ static int mdss_dsi_get_dt_vreg_data(struct device *dev,
			mp->vreg_config[i].post_off_sleep = tmp;
		}

		pr_debug("%s: %s min=%d, max=%d, enable=%d, disable=%d, preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
		pr_debug("%s: %s min=%d, max=%d, enable=%d, disable=%d, ulp_load=%d preonsleep=%d, postonsleep=%d, preoffsleep=%d, postoffsleep=%d\n",
			__func__,
			mp->vreg_config[i].vreg_name,
			mp->vreg_config[i].min_voltage,
			mp->vreg_config[i].max_voltage,
			mp->vreg_config[i].enable_load,
			mp->vreg_config[i].disable_load,
			mp->vreg_config[i].load[DSS_REG_MODE_ENABLE],
			mp->vreg_config[i].load[DSS_REG_MODE_DISABLE],
			mp->vreg_config[i].load[DSS_REG_MODE_ULP],
			mp->vreg_config[i].pre_on_sleep,
			mp->vreg_config[i].post_on_sleep,
			mp->vreg_config[i].pre_off_sleep,
Loading