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

Commit 797e0894 authored by Alan Kwong's avatar Alan Kwong
Browse files

drm/msm/dsi-staging: enable dsi idle to turn off phy



Phy can be turned off during idle period to conserve power.
Add idle mode support to turn off phy and reinitialize PLL
CSRs upon resume from idle.

Change-Id: If2c11a5a82c839f88b39c9d5d6da97888e4457ba
Signed-off-by: default avatarAlan Kwong <akwong@codeaurora.org>
parent fc9ce0e0
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -121,6 +121,11 @@ Optional properties:
					If ping pong split is enabled, this time should not be higher
					than two times the dsi link rate time.
					If the property is not specified, then the default value is 14000 us.
- qcom,panel-allow-phy-poweroff:	A boolean property indicates that panel allows to turn off the phy power
					supply during idle screen. A panel should be able to handle the dsi lanes
					in floating state(not LP00 or LP11) to turn on this property. Software
					turns off PHY pmic power supply, phy ldo and DSI Lane ldo during
					idle screen (footswitch control off) when this property is enabled.

[1] Documentation/devicetree/bindings/clocks/clock-bindings.txt
[2] Documentation/devicetree/bindings/graph.txt
@@ -229,4 +234,5 @@ Example:
		vddio-supply = <&pma8084_l12>;

		qcom,dsi-phy-regulator-ldo-mode;
		qcom,panel-allow-phy-poweroff;
	};
+33 −5
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@

#define MISR_BUFF_SIZE	256

#define MAX_NAME_SIZE	64

static DEFINE_MUTEX(dsi_display_list_lock);
static LIST_HEAD(dsi_display_list);
static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN];
@@ -687,6 +689,8 @@ static int dsi_display_debugfs_init(struct dsi_display *display)
{
	int rc = 0;
	struct dentry *dir, *dump_file, *misr_data;
	char name[MAX_NAME_SIZE];
	int i;

	dir = debugfs_create_dir(display->name, NULL);
	if (IS_ERR_OR_NULL(dir)) {
@@ -720,6 +724,24 @@ static int dsi_display_debugfs_init(struct dsi_display *display)
		goto error_remove_dir;
	}

	for (i = 0; i < display->ctrl_count; i++) {
		struct msm_dsi_phy *phy = display->ctrl[i].phy;

		if (!phy || !phy->name)
			continue;

		snprintf(name, ARRAY_SIZE(name),
				"%s_allow_phy_power_off", phy->name);
		dump_file = debugfs_create_bool(name, 0600, dir,
				&phy->allow_phy_power_off);
		if (IS_ERR_OR_NULL(dump_file)) {
			rc = PTR_ERR(dump_file);
			pr_err("[%s] debugfs create %s failed, rc=%d\n",
			       display->name, name, rc);
			goto error_remove_dir;
		}
	}

	display->root = dir;
	return rc;
error_remove_dir:
@@ -937,7 +959,7 @@ static int dsi_display_phy_enable(struct dsi_display *display);
/**
 * dsi_display_phy_idle_on() - enable DSI PHY while coming out of idle screen.
 * @dsi_display:         DSI display handle.
 * @enable:           enable/disable DSI PHY.
 * @mmss_clamp:          True if clamp is enabled.
 *
 * Return: error code.
 */
@@ -984,7 +1006,6 @@ static int dsi_display_phy_idle_on(struct dsi_display *display,
/**
 * dsi_display_phy_idle_off() - disable DSI PHY while going to idle screen.
 * @dsi_display:         DSI display handle.
 * @enable:           enable/disable DSI PHY.
 *
 * Return: error code.
 */
@@ -999,10 +1020,17 @@ static int dsi_display_phy_idle_off(struct dsi_display *display)
		return -EINVAL;
	}

	if (!display->panel->allow_phy_power_off) {
		pr_debug("panel doesn't support this feature\n");
	for (i = 0; i < display->ctrl_count; i++) {
		struct msm_dsi_phy *phy = display->ctrl[i].phy;

		if (!phy)
			continue;

		if (!phy->allow_phy_power_off) {
			pr_debug("phy doesn't support this feature\n");
			return 0;
		}
	}

	m_ctrl = &display->ctrl[display->cmd_master_idx];

+16 −0
Original line number Diff line number Diff line
@@ -290,6 +290,10 @@ static int dsi_phy_settings_init(struct platform_device *pdev,

	/* Actual timing values are dependent on panel */
	timing->count_per_lane = phy->ver_info->timing_cfg_count;

	phy->allow_phy_power_off = of_property_read_bool(pdev->dev.of_node,
			"qcom,panel-allow-phy-poweroff");

	return 0;
err:
	lane->count_per_lane = 0;
@@ -876,6 +880,8 @@ int dsi_phy_idle_ctrl(struct msm_dsi_phy *phy, bool enable)
		return -EINVAL;
	}

	pr_debug("[%s] enable=%d\n", phy->name, enable);

	mutex_lock(&phy->phy_lock);
	if (enable) {
		if (phy->hw.ops.phy_idle_on)
@@ -884,7 +890,17 @@ int dsi_phy_idle_ctrl(struct msm_dsi_phy *phy, bool enable)
		if (phy->hw.ops.regulator_enable)
			phy->hw.ops.regulator_enable(&phy->hw,
				&phy->cfg.regulators);

		if (phy->hw.ops.enable)
			phy->hw.ops.enable(&phy->hw, &phy->cfg);

		phy->dsi_phy_state = DSI_PHY_ENGINE_ON;
	} else {
		phy->dsi_phy_state = DSI_PHY_ENGINE_OFF;

		if (phy->hw.ops.disable)
			phy->hw.ops.disable(&phy->hw, &phy->cfg);

		if (phy->hw.ops.phy_idle_off)
			phy->hw.ops.phy_idle_off(&phy->hw);
	}
+3 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ enum phy_engine_state {
 * @mode:              Current mode.
 * @data_lanes:        Number of data lanes used.
 * @dst_format:        Destination format.
 * @allow_phy_power_off: True if PHY is allowed to power off when idle
 */
struct msm_dsi_phy {
	struct platform_device *pdev;
@@ -88,6 +89,8 @@ struct msm_dsi_phy {
	struct dsi_mode_info mode;
	enum dsi_data_lanes data_lanes;
	enum dsi_pixel_format dst_format;

	bool allow_phy_power_off;
};

/**