summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/phy/dsi_phy.c')
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c161
1 files changed, 87 insertions, 74 deletions
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index e8c1a727179c..f0a2ddf96a4b 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -3,6 +3,7 @@
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*/
+#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "dsi_phy.h"
@@ -460,23 +461,6 @@ int msm_dsi_dphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing,
return 0;
}
-void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg,
- u32 bit_mask)
-{
- int phy_id = phy->id;
- u32 val;
-
- if ((phy_id >= DSI_MAX) || (pll_id >= DSI_MAX))
- return;
-
- val = dsi_phy_read(phy->base + reg);
-
- if (phy->cfg->src_pll_truthtable[phy_id][pll_id])
- dsi_phy_write(phy->base + reg, val | bit_mask);
- else
- dsi_phy_write(phy->base + reg, val & (~bit_mask));
-}
-
static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
{
struct regulator_bulk_data *s = phy->supplies;
@@ -637,24 +621,6 @@ static int dsi_phy_get_id(struct msm_dsi_phy *phy)
return -EINVAL;
}
-int msm_dsi_phy_init_common(struct msm_dsi_phy *phy)
-{
- struct platform_device *pdev = phy->pdev;
- int ret = 0;
-
- phy->reg_base = msm_ioremap(pdev, "dsi_phy_regulator",
- "DSI_PHY_REG");
- if (IS_ERR(phy->reg_base)) {
- DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy regulator base\n",
- __func__);
- ret = -ENOMEM;
- goto fail;
- }
-
-fail:
- return ret;
-}
-
static int dsi_phy_driver_probe(struct platform_device *pdev)
{
struct msm_dsi_phy *phy;
@@ -670,6 +636,14 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
if (!match)
return -ENODEV;
+ phy->provided_clocks = devm_kzalloc(dev,
+ struct_size(phy->provided_clocks, hws, NUM_PROVIDED_CLKS),
+ GFP_KERNEL);
+ if (!phy->provided_clocks)
+ return -ENOMEM;
+
+ phy->provided_clocks->num = NUM_PROVIDED_CLKS;
+
phy->cfg = match->data;
phy->pdev = pdev;
@@ -691,6 +665,31 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
goto fail;
}
+ phy->pll_base = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
+ if (IS_ERR(phy->pll_base)) {
+ DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (phy->cfg->has_phy_lane) {
+ phy->lane_base = msm_ioremap(pdev, "dsi_phy_lane", "DSI_PHY_LANE");
+ if (IS_ERR(phy->lane_base)) {
+ DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy lane base\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ if (phy->cfg->has_phy_regulator) {
+ phy->reg_base = msm_ioremap(pdev, "dsi_phy_regulator", "DSI_PHY_REG");
+ if (IS_ERR(phy->reg_base)) {
+ DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy regulator base\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
+ }
+
ret = dsi_phy_regulator_init(phy);
if (ret)
goto fail;
@@ -702,12 +701,6 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
goto fail;
}
- if (phy->cfg->ops.init) {
- ret = phy->cfg->ops.init(phy);
- if (ret)
- goto fail;
- }
-
/* PLL init will call into clk_register which requires
* register access, so we need to enable power and ahb clock.
*/
@@ -715,12 +708,21 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
if (ret)
goto fail;
- phy->pll = msm_dsi_pll_init(pdev, phy->cfg->type, phy->id);
- if (IS_ERR_OR_NULL(phy->pll)) {
- DRM_DEV_INFO(dev,
- "%s: pll init failed: %ld, need separate pll clk driver\n",
- __func__, PTR_ERR(phy->pll));
- phy->pll = NULL;
+ if (phy->cfg->ops.pll_init) {
+ ret = phy->cfg->ops.pll_init(phy);
+ if (ret) {
+ DRM_DEV_INFO(dev,
+ "%s: pll init failed: %d, need separate pll clk driver\n",
+ __func__, ret);
+ goto fail;
+ }
+ }
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+ phy->provided_clocks);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__, ret);
+ goto fail;
}
dsi_phy_disable_resource(phy);
@@ -733,23 +735,8 @@ fail:
return ret;
}
-static int dsi_phy_driver_remove(struct platform_device *pdev)
-{
- struct msm_dsi_phy *phy = platform_get_drvdata(pdev);
-
- if (phy && phy->pll) {
- msm_dsi_pll_destroy(phy->pll);
- phy->pll = NULL;
- }
-
- platform_set_drvdata(pdev, NULL);
-
- return 0;
-}
-
static struct platform_driver dsi_phy_platform_driver = {
.probe = dsi_phy_driver_probe,
- .remove = dsi_phy_driver_remove,
.driver = {
.name = "msm_dsi_phy",
.of_match_table = dsi_phy_dt_match,
@@ -766,7 +753,7 @@ void __exit msm_dsi_phy_driver_unregister(void)
platform_driver_unregister(&dsi_phy_platform_driver);
}
-int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
+int msm_dsi_phy_enable(struct msm_dsi_phy *phy,
struct msm_dsi_phy_clk_request *clk_req)
{
struct device *dev = &phy->pdev->dev;
@@ -789,7 +776,7 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
goto reg_en_fail;
}
- ret = phy->cfg->ops.enable(phy, src_pll_id, clk_req);
+ ret = phy->cfg->ops.enable(phy, clk_req);
if (ret) {
DRM_DEV_ERROR(dev, "%s: phy enable failed, %d\n", __func__, ret);
goto phy_en_fail;
@@ -802,9 +789,9 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
* source.
*/
if (phy->usecase != MSM_DSI_PHY_SLAVE) {
- ret = msm_dsi_pll_restore_state(phy->pll);
+ ret = msm_dsi_phy_pll_restore_state(phy);
if (ret) {
- DRM_DEV_ERROR(dev, "%s: failed to restore pll state, %d\n",
+ DRM_DEV_ERROR(dev, "%s: failed to restore phy state, %d\n",
__func__, ret);
goto pll_restor_fail;
}
@@ -841,17 +828,43 @@ void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy,
sizeof(*shared_timings));
}
-struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy)
-{
- if (!phy)
- return NULL;
-
- 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;
}
+
+int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy,
+ struct clk **byte_clk_provider, struct clk **pixel_clk_provider)
+{
+ if (byte_clk_provider)
+ *byte_clk_provider = phy->provided_clocks->hws[DSI_BYTE_PLL_CLK]->clk;
+ if (pixel_clk_provider)
+ *pixel_clk_provider = phy->provided_clocks->hws[DSI_PIXEL_PLL_CLK]->clk;
+
+ return -EINVAL;
+}
+
+void msm_dsi_phy_pll_save_state(struct msm_dsi_phy *phy)
+{
+ if (phy->cfg->ops.save_pll_state) {
+ phy->cfg->ops.save_pll_state(phy);
+ phy->state_saved = true;
+ }
+}
+
+int msm_dsi_phy_pll_restore_state(struct msm_dsi_phy *phy)
+{
+ int ret;
+
+ if (phy->cfg->ops.restore_pll_state && phy->state_saved) {
+ ret = phy->cfg->ops.restore_pll_state(phy);
+ if (ret)
+ return ret;
+
+ phy->state_saved = false;
+ }
+
+ return 0;
+}