drm/msm/dsi-staging: fix few validation checks in ulps
Fix few validations related to Ultra-Low Power State in phy.
Move target specific register checks to appropriate phy
version file.
Change-Id: Idb85434ab11c7975eb2505ba1acaaf2d71198542
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
index 976be99..26032a1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
@@ -167,6 +167,8 @@
dsi_phy_hw_v3_0_ulps_exit;
phy->ops.ulps_ops.get_lanes_in_ulps =
dsi_phy_hw_v3_0_get_lanes_in_ulps;
+ phy->ops.ulps_ops.is_lanes_in_ulps =
+ dsi_phy_hw_v3_0_is_lanes_in_ulps;
phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0;
}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index 4a6a934..cec2736 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -97,6 +97,7 @@
void dsi_phy_hw_v3_0_ulps_exit(struct dsi_phy_hw *phy,
struct dsi_phy_cfg *cfg, u32 lanes);
u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy);
+bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes);
int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
u32 *timing_val, u32 size);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 2c5bd76..106511c 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -260,7 +260,8 @@
return rc;
}
- rc = dsi_phy_set_ulps(m_ctrl->phy, &display->config, enable);
+ rc = dsi_phy_set_ulps(m_ctrl->phy, &display->config, enable,
+ display->clamp_enabled);
if (rc) {
pr_err("Ulps PHY state change(%d) failed\n", enable);
return rc;
@@ -278,7 +279,8 @@
return rc;
}
- rc = dsi_phy_set_ulps(ctrl->phy, &display->config, enable);
+ rc = dsi_phy_set_ulps(ctrl->phy, &display->config, enable,
+ display->clamp_enabled);
if (rc) {
pr_err("Ulps PHY state change(%d) failed\n", enable);
return rc;
@@ -1365,8 +1367,7 @@
/*
* Enable DSI clamps only if entering idle power collapse.
*/
- if (dsi_panel_initialized(display->panel) &&
- dsi_panel_ulps_feature_enabled(display->panel)) {
+ if (dsi_panel_initialized(display->panel)) {
dsi_display_phy_idle_off(display);
rc = dsi_display_set_clamp(display, true);
if (rc)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index bda9c2d..8b759f4 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -2490,7 +2490,6 @@
panel->name, rc);
goto error;
}
- panel->panel_initialized = false;
error:
mutex_unlock(&panel->panel_lock);
return rc;
@@ -2536,6 +2535,8 @@
panel->name, rc);
goto error;
}
+ panel->panel_initialized = false;
+
error:
mutex_unlock(&panel->panel_lock);
return rc;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
index 96a98bd..f140842 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
@@ -669,7 +669,7 @@
}
static int dsi_phy_enable_ulps(struct msm_dsi_phy *phy,
- struct dsi_host_config *config)
+ struct dsi_host_config *config, bool clamp_enabled)
{
int rc = 0;
u32 lanes = 0;
@@ -679,17 +679,25 @@
lanes = config->common_config.data_lanes;
lanes |= DSI_CLOCK_LANE;
- rc = phy->hw.ops.ulps_ops.wait_for_lane_idle(&phy->hw, lanes);
- if (rc) {
- pr_err("lanes not entering idle, skip ULPS\n");
- return rc;
+ /*
+ * If DSI clamps are enabled, it means that the DSI lanes are
+ * already in idle state. Checking for lanes to be in idle state
+ * should be skipped during ULPS entry programming while coming
+ * out of idle screen.
+ */
+ if (!clamp_enabled) {
+ rc = phy->hw.ops.ulps_ops.wait_for_lane_idle(&phy->hw, lanes);
+ if (rc) {
+ pr_err("lanes not entering idle, skip ULPS\n");
+ return rc;
+ }
}
phy->hw.ops.ulps_ops.ulps_request(&phy->hw, &phy->cfg, lanes);
ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw);
- if ((lanes & ulps_lanes) != lanes) {
+ if (!phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) {
pr_err("Failed to enter ULPS, request=0x%x, actual=0x%x\n",
lanes, ulps_lanes);
rc = -EIO;
@@ -701,7 +709,6 @@
static int dsi_phy_disable_ulps(struct msm_dsi_phy *phy,
struct dsi_host_config *config)
{
- int rc = 0;
u32 ulps_lanes, lanes = 0;
if (config->panel_mode == DSI_OP_CMD_MODE)
@@ -710,25 +717,27 @@
ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw);
- if ((lanes & ulps_lanes) != lanes)
- pr_err("Mismatch between lanes in ULPS\n");
-
- lanes &= ulps_lanes;
+ if (!phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) {
+ pr_err("Mismatch in ULPS: lanes:%d, ulps_lanes:%d\n",
+ lanes, ulps_lanes);
+ return -EIO;
+ }
phy->hw.ops.ulps_ops.ulps_exit(&phy->hw, &phy->cfg, lanes);
ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw);
- if (ulps_lanes & lanes) {
+
+ if (phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) {
pr_err("Lanes (0x%x) stuck in ULPS\n", ulps_lanes);
- rc = -EIO;
+ return -EIO;
}
- return rc;
+ return 0;
}
int dsi_phy_set_ulps(struct msm_dsi_phy *phy, struct dsi_host_config *config,
- bool enable)
+ bool enable, bool clamp_enabled)
{
int rc = 0;
@@ -738,7 +747,10 @@
}
if (!phy->hw.ops.ulps_ops.ulps_request ||
- !phy->hw.ops.ulps_ops.ulps_exit) {
+ !phy->hw.ops.ulps_ops.ulps_exit ||
+ !phy->hw.ops.ulps_ops.get_lanes_in_ulps ||
+ !phy->hw.ops.ulps_ops.is_lanes_in_ulps ||
+ !phy->hw.ops.ulps_ops.wait_for_lane_idle) {
pr_debug("DSI PHY ULPS ops not present\n");
return 0;
}
@@ -746,7 +758,7 @@
mutex_lock(&phy->phy_lock);
if (enable)
- rc = dsi_phy_enable_ulps(phy, config);
+ rc = dsi_phy_enable_ulps(phy, config, clamp_enabled);
else
rc = dsi_phy_disable_ulps(phy, config);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
index 4a64855..e721486 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
@@ -182,11 +182,12 @@
* @phy: DSI PHY handle
* @config: DSi host configuration information.
* @enable: Enable/Disable
+ * @clamp_enabled: mmss_clamp enabled/disabled
*
* Return: error code.
*/
int dsi_phy_set_ulps(struct msm_dsi_phy *phy, struct dsi_host_config *config,
- bool enable);
+ bool enable, bool clamp_enabled);
/**
* dsi_phy_clk_cb_register() - Register PHY clock control callback
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
index daaa78a..51c2f46 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
@@ -143,15 +143,22 @@
* @phy: Pointer to DSI PHY hardware instance.
*
* Returns an ORed list of lanes (enum dsi_data_lanes) that are in ULPS
- * state. If 0 is returned, all the lanes are active.
+ * state.
*
* Return: List of lanes in ULPS state.
*/
u32 (*get_lanes_in_ulps)(struct dsi_phy_hw *phy);
+
+ /**
+ * is_lanes_in_ulps() - checks if the given lanes are in ulps
+ * @lanes: lanes to be checked.
+ * @ulps_lanes: lanes in ulps currenly.
+ *
+ * Return: true if all the given lanes are in ulps; false otherwise.
+ */
+ bool (*is_lanes_in_ulps)(u32 ulps, u32 ulps_lanes);
};
-
-
/**
* struct dsi_phy_hw_ops - Operations for DSI PHY hardware.
* @regulator_enable: Enable PHY regulators.
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c
index 96f5c19..489666e 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c
@@ -419,6 +419,14 @@
return lanes;
}
+bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes)
+{
+ if (lanes & ulps_lanes)
+ return false;
+
+ return true;
+}
+
int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
u32 *timing_val, u32 size)
{