[PATCH 05/10] drm/msm/dsi: Pass down use case to PHY
Archit Taneja
architt at codeaurora.org
Sat Jan 7 13:10:37 UTC 2017
From: Hai Li <hali at codeaurora.org>
For some new types of DSI PHY, more settings depend on
use cases controlled by DSI manager. This change allows
DSI manager to setup PHY with a use case.
Signed-off-by: Hai Li <hali at codeaurora.org>
Signed-off-by: Archit Taneja <architt at codeaurora.org>
---
drivers/gpu/drm/msm/dsi/dsi.h | 8 +++++++
drivers/gpu/drm/msm/dsi/dsi_manager.c | 43 ++++++++++++-----------------------
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 30 +++++++++++++++++++++++-
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 1 +
4 files changed, 52 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index f5e4ccf..d516fe2 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -37,6 +37,12 @@ enum msm_dsi_phy_type {
MSM_DSI_PHY_MAX
};
+enum msm_dsi_phy_usecase {
+ MSM_DSI_PHY_STANDALONE,
+ MSM_DSI_PHY_MASTER,
+ MSM_DSI_PHY_SLAVE,
+};
+
#define DSI_DEV_REGULATOR_MAX 8
#define DSI_BUS_CLK_MAX 4
@@ -180,6 +186,8 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy,
struct msm_dsi_phy_shared_timings *shared_timing);
struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy);
+void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy,
+ enum msm_dsi_phy_usecase uc);
#endif /* __DSI_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index ef186f1..fbd11dc 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -72,11 +72,12 @@ static int dsi_mgr_parse_dual_dsi(struct device_node *np, int id)
return 0;
}
-static int dsi_mgr_host_register(int id)
+static int dsi_mgr_setup_components(int id)
{
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
+ struct msm_dsi *clk_slave_dsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
struct msm_dsi_pll *src_pll;
int ret;
@@ -85,15 +86,16 @@ static int dsi_mgr_host_register(int id)
if (ret)
return ret;
+ msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE);
src_pll = msm_dsi_phy_get_pll(msm_dsi->phy);
ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll);
} else if (!other_dsi) {
ret = 0;
} else {
- struct msm_dsi *mdsi = IS_MASTER_DSI_LINK(id) ?
- msm_dsi : other_dsi;
- struct msm_dsi *sdsi = IS_MASTER_DSI_LINK(id) ?
- other_dsi : msm_dsi;
+ struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ?
+ msm_dsi : other_dsi;
+ struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ?
+ other_dsi : msm_dsi;
/* Register slave host first, so that slave DSI device
* has a chance to probe, and do not block the master
* DSI device's probe.
@@ -101,14 +103,18 @@ static int dsi_mgr_host_register(int id)
* because only master DSI device adds the panel to global
* panel list. The panel's device is the master DSI device.
*/
- ret = msm_dsi_host_register(sdsi->host, false);
+ ret = msm_dsi_host_register(slave_link_dsi->host, false);
if (ret)
return ret;
- ret = msm_dsi_host_register(mdsi->host, true);
+ ret = msm_dsi_host_register(master_link_dsi->host, true);
if (ret)
return ret;
/* PLL0 is to drive both 2 DSI link clocks in Dual DSI mode. */
+ msm_dsi_phy_set_usecase(clk_master_dsi->phy,
+ MSM_DSI_PHY_MASTER);
+ msm_dsi_phy_set_usecase(clk_slave_dsi->phy,
+ MSM_DSI_PHY_SLAVE);
src_pll = msm_dsi_phy_get_pll(clk_master_dsi->phy);
ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll);
if (ret)
@@ -656,28 +662,12 @@ int msm_dsi_manager_phy_enable(int id,
struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
struct msm_dsi_phy *phy = msm_dsi->phy;
int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
- struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
int ret;
ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate);
if (ret)
return ret;
- /*
- * Reset DSI PHY silently changes its PLL registers to reset status,
- * which will confuse clock driver and result in wrong output rate of
- * link clocks. Restore PLL status if its PLL is being used as clock
- * source.
- */
- if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER)) {
- ret = msm_dsi_pll_restore_state(pll);
- if (ret) {
- pr_err("%s: failed to restore pll state\n", __func__);
- msm_dsi_phy_disable(phy);
- return ret;
- }
- }
-
msm_dsi->phy_enabled = true;
msm_dsi_phy_get_shared_timings(phy, shared_timings);
@@ -690,11 +680,6 @@ void msm_dsi_manager_phy_disable(int id)
struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
struct msm_dsi_phy *phy = msm_dsi->phy;
- struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
-
- /* Save PLL status if it is a clock source */
- if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER))
- msm_dsi_pll_save_state(pll);
/* disable DSI phy
* In dual-dsi configuration, the phy should be disabled for the
@@ -810,7 +795,7 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
goto fail;
}
- ret = dsi_mgr_host_register(id);
+ ret = dsi_mgr_setup_components(id);
if (ret) {
pr_err("%s: failed to register mipi dsi host for DSI %d\n",
__func__, id);
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 51f7c66..425017a 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -451,7 +451,24 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
return ret;
}
- return 0;
+ /*
+ * Resetting DSI PHY silently changes its PLL registers to reset status,
+ * which will confuse clock driver and result in wrong output rate of
+ * link clocks. Restore PLL status if its PLL is being used as clock
+ * source.
+ */
+ if (phy->usecase != MSM_DSI_PHY_SLAVE) {
+ ret = msm_dsi_pll_restore_state(phy->pll);
+ if (ret) {
+ pr_err("%s: failed to restore pll state\n", __func__);
+ if (phy->cfg->ops.disable)
+ phy->cfg->ops.disable(phy);
+ dsi_phy_regulator_disable(phy);
+ return ret;
+ }
+ }
+
+ return ret;
}
void msm_dsi_phy_disable(struct msm_dsi_phy *phy)
@@ -459,6 +476,10 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy)
if (!phy || !phy->cfg->ops.disable)
return;
+ /* Save PLL status if it is a clock source */
+ if (phy->usecase != MSM_DSI_PHY_SLAVE)
+ msm_dsi_pll_save_state(phy->pll);
+
phy->cfg->ops.disable(phy);
dsi_phy_regulator_disable(phy);
@@ -479,3 +500,10 @@ struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy)
return phy->pll;
}
+void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy,
+ enum msm_dsi_phy_usecase uc)
+{
+ if (phy)
+ phy->usecase = uc;
+}
+
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 7399934..e105742 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -78,6 +78,7 @@ struct msm_dsi_phy {
struct msm_dsi_dphy_timing timing;
const struct msm_dsi_phy_cfg *cfg;
+ enum msm_dsi_phy_usecase usecase;
bool regulator_ldo_mode;
struct msm_dsi_pll *pll;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
More information about the dri-devel
mailing list