summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/dsi/dsi_phy.c
diff options
context:
space:
mode:
authorHai Li <hali@codeaurora.org>2015-05-15 13:04:05 -0400
committerRob Clark <robdclark@gmail.com>2015-06-11 13:11:04 -0400
commit9d32c4989c858af12b333ae9a3c160a91ff43934 (patch)
treead5d91c6a4b2b91ca9d1e8e5a2c7742abe79a0ef /drivers/gpu/drm/msm/dsi/dsi_phy.c
parent825637b9c06cede2a742421b0ea6f24428099af3 (diff)
drm/msm/dsi: Enable PLL driver in MSM DSI
This change activates PLL driver for DSI to work with common clock framework. Signed-off-by: Hai Li <hali@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/dsi_phy.c')
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_phy.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c b/drivers/gpu/drm/msm/dsi/dsi_phy.c
index 4403f38bf220..2b1c8fdb10de 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c
@@ -34,10 +34,18 @@ struct dsi_dphy_timing {
};
struct msm_dsi_phy {
+ struct platform_device *pdev;
void __iomem *base;
void __iomem *reg_base;
int id;
+
+ struct clk *ahb_clk;
+
struct dsi_dphy_timing timing;
+ enum msm_dsi_phy_type type;
+
+ struct msm_dsi_pll *pll;
+
int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel,
const unsigned long bit_rate, const unsigned long esc_rate);
int (*disable)(struct msm_dsi_phy *phy);
@@ -284,6 +292,27 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
return 0;
}
+static int dsi_phy_enable_resource(struct msm_dsi_phy *phy)
+{
+ int ret;
+
+ pm_runtime_get_sync(&phy->pdev->dev);
+
+ ret = clk_prepare_enable(phy->ahb_clk);
+ if (ret) {
+ pr_err("%s: can't enable ahb clk, %d\n", __func__, ret);
+ pm_runtime_put_sync(&phy->pdev->dev);
+ }
+
+ return ret;
+}
+
+static void dsi_phy_disable_resource(struct msm_dsi_phy *phy)
+{
+ clk_disable_unprepare(phy->ahb_clk);
+ pm_runtime_put_sync(&phy->pdev->dev);
+}
+
#define dsi_phy_func_init(name) \
do { \
phy->enable = dsi_##name##_phy_enable; \
@@ -294,6 +323,7 @@ struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev,
enum msm_dsi_phy_type type, int id)
{
struct msm_dsi_phy *phy;
+ int ret;
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
@@ -320,11 +350,41 @@ struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev,
return NULL;
}
+ phy->type = type;
phy->id = id;
+ phy->pdev = pdev;
+
+ phy->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(phy->ahb_clk)) {
+ pr_err("%s: Unable to get ahb clk\n", __func__);
+ return NULL;
+ }
+
+ /* PLL init will call into clk_register which requires
+ * register access, so we need to enable power and ahb clock.
+ */
+ ret = dsi_phy_enable_resource(phy);
+ if (ret)
+ return NULL;
+
+ phy->pll = msm_dsi_pll_init(pdev, type, id);
+ if (!phy->pll)
+ pr_info("%s: pll init failed, need separate pll clk driver\n",
+ __func__);
+
+ dsi_phy_disable_resource(phy);
return phy;
}
+void msm_dsi_phy_destroy(struct msm_dsi_phy *phy)
+{
+ if (phy->pll) {
+ msm_dsi_pll_destroy(phy->pll);
+ phy->pll = NULL;
+ }
+}
+
int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,
const unsigned long bit_rate, const unsigned long esc_rate)
{
@@ -351,3 +411,11 @@ void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
*clk_post = phy->timing.clk_post;
}
+struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy)
+{
+ if (!phy)
+ return NULL;
+
+ return phy->pll;
+}
+