diff options
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/phy/dsi_phy.c')
-rw-r--r-- | drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 161 |
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; +} |