diff options
author | Hai Li <hali@codeaurora.org> | 2015-05-15 13:04:05 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2015-06-11 13:11:04 -0400 |
commit | 9d32c4989c858af12b333ae9a3c160a91ff43934 (patch) | |
tree | ad5d91c6a4b2b91ca9d1e8e5a2c7742abe79a0ef | |
parent | 825637b9c06cede2a742421b0ea6f24428099af3 (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>
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi.h | 43 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_host.c | 60 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_manager.c | 79 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/dsi/dsi_phy.c | 68 |
5 files changed, 229 insertions, 35 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index ad50b80225f5..beb26dfca276 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c | |||
@@ -29,6 +29,12 @@ static void dsi_destroy(struct msm_dsi *msm_dsi) | |||
29 | return; | 29 | return; |
30 | 30 | ||
31 | msm_dsi_manager_unregister(msm_dsi); | 31 | msm_dsi_manager_unregister(msm_dsi); |
32 | |||
33 | if (msm_dsi->phy) { | ||
34 | msm_dsi_phy_destroy(msm_dsi->phy); | ||
35 | msm_dsi->phy = NULL; | ||
36 | } | ||
37 | |||
32 | if (msm_dsi->host) { | 38 | if (msm_dsi->host) { |
33 | msm_dsi_host_destroy(msm_dsi->host); | 39 | msm_dsi_host_destroy(msm_dsi->host); |
34 | msm_dsi->host = NULL; | 40 | msm_dsi->host = NULL; |
@@ -63,6 +69,14 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev) | |||
63 | if (ret) | 69 | if (ret) |
64 | goto fail; | 70 | goto fail; |
65 | 71 | ||
72 | /* Init dsi PHY */ | ||
73 | msm_dsi->phy = msm_dsi_phy_init(pdev, msm_dsi->phy_type, msm_dsi->id); | ||
74 | if (!msm_dsi->phy) { | ||
75 | ret = -ENXIO; | ||
76 | pr_err("%s: phy init failed\n", __func__); | ||
77 | goto fail; | ||
78 | } | ||
79 | |||
66 | /* Register to dsi manager */ | 80 | /* Register to dsi manager */ |
67 | ret = msm_dsi_manager_register(msm_dsi); | 81 | ret = msm_dsi_manager_register(msm_dsi); |
68 | if (ret) | 82 | if (ret) |
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 321964a6b27e..8022814f7914 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h | |||
@@ -38,6 +38,13 @@ | |||
38 | #define DSI_ENCODER_MASTER DSI_1 | 38 | #define DSI_ENCODER_MASTER DSI_1 |
39 | #define DSI_ENCODER_SLAVE DSI_0 | 39 | #define DSI_ENCODER_SLAVE DSI_0 |
40 | 40 | ||
41 | enum msm_dsi_phy_type { | ||
42 | MSM_DSI_PHY_UNKNOWN, | ||
43 | MSM_DSI_PHY_28NM_HPM, | ||
44 | MSM_DSI_PHY_28NM_LP, | ||
45 | MSM_DSI_PHY_MAX | ||
46 | }; | ||
47 | |||
41 | struct msm_dsi { | 48 | struct msm_dsi { |
42 | struct drm_device *dev; | 49 | struct drm_device *dev; |
43 | struct platform_device *pdev; | 50 | struct platform_device *pdev; |
@@ -49,6 +56,8 @@ struct msm_dsi { | |||
49 | struct msm_dsi_phy *phy; | 56 | struct msm_dsi_phy *phy; |
50 | struct drm_panel *panel; | 57 | struct drm_panel *panel; |
51 | unsigned long panel_flags; | 58 | unsigned long panel_flags; |
59 | |||
60 | enum msm_dsi_phy_type phy_type; | ||
52 | bool phy_enabled; | 61 | bool phy_enabled; |
53 | 62 | ||
54 | /* the encoders we are hooked to (outside of dsi block) */ | 63 | /* the encoders we are hooked to (outside of dsi block) */ |
@@ -73,6 +82,29 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi); | |||
73 | /* msm dsi */ | 82 | /* msm dsi */ |
74 | struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi); | 83 | struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi); |
75 | 84 | ||
85 | /* dsi pll */ | ||
86 | struct msm_dsi_pll; | ||
87 | #ifdef CONFIG_DRM_MSM_DSI_PLL | ||
88 | struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, | ||
89 | enum msm_dsi_phy_type type, int dsi_id); | ||
90 | void msm_dsi_pll_destroy(struct msm_dsi_pll *pll); | ||
91 | int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll, | ||
92 | struct clk **byte_clk_provider, struct clk **pixel_clk_provider); | ||
93 | #else | ||
94 | static inline struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, | ||
95 | enum msm_dsi_phy_type type, int id) { | ||
96 | return ERR_PTR(-ENODEV); | ||
97 | } | ||
98 | static inline void msm_dsi_pll_destroy(struct msm_dsi_pll *pll) | ||
99 | { | ||
100 | } | ||
101 | static inline int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll, | ||
102 | struct clk **byte_clk_provider, struct clk **pixel_clk_provider) | ||
103 | { | ||
104 | return -ENODEV; | ||
105 | } | ||
106 | #endif | ||
107 | |||
76 | /* dsi host */ | 108 | /* dsi host */ |
77 | int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host, | 109 | int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host, |
78 | const struct mipi_dsi_msg *msg); | 110 | const struct mipi_dsi_msg *msg); |
@@ -94,6 +126,8 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host, | |||
94 | unsigned long *panel_flags); | 126 | unsigned long *panel_flags); |
95 | int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer); | 127 | int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer); |
96 | void msm_dsi_host_unregister(struct mipi_dsi_host *host); | 128 | void msm_dsi_host_unregister(struct mipi_dsi_host *host); |
129 | int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, | ||
130 | struct msm_dsi_pll *src_pll); | ||
97 | void msm_dsi_host_destroy(struct mipi_dsi_host *host); | 131 | void msm_dsi_host_destroy(struct mipi_dsi_host *host); |
98 | int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, | 132 | int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, |
99 | struct drm_device *dev); | 133 | struct drm_device *dev); |
@@ -101,18 +135,15 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi); | |||
101 | 135 | ||
102 | /* dsi phy */ | 136 | /* dsi phy */ |
103 | struct msm_dsi_phy; | 137 | struct msm_dsi_phy; |
104 | enum msm_dsi_phy_type { | ||
105 | MSM_DSI_PHY_UNKNOWN, | ||
106 | MSM_DSI_PHY_28NM_HPM, | ||
107 | MSM_DSI_PHY_28NM_LP, | ||
108 | MSM_DSI_PHY_MAX | ||
109 | }; | ||
110 | struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev, | 138 | struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev, |
111 | enum msm_dsi_phy_type type, int id); | 139 | enum msm_dsi_phy_type type, int id); |
140 | void msm_dsi_phy_destroy(struct msm_dsi_phy *phy); | ||
112 | int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel, | 141 | int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel, |
113 | const unsigned long bit_rate, const unsigned long esc_rate); | 142 | const unsigned long bit_rate, const unsigned long esc_rate); |
114 | int msm_dsi_phy_disable(struct msm_dsi_phy *phy); | 143 | int msm_dsi_phy_disable(struct msm_dsi_phy *phy); |
115 | void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, | 144 | void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, |
116 | u32 *clk_pre, u32 *clk_post); | 145 | u32 *clk_pre, u32 *clk_post); |
146 | struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy); | ||
147 | |||
117 | #endif /* __DSI_CONNECTOR_H__ */ | 148 | #endif /* __DSI_CONNECTOR_H__ */ |
118 | 149 | ||
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index 8a246cfa5d19..43ea8a30c121 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c | |||
@@ -205,6 +205,9 @@ struct msm_dsi_host { | |||
205 | struct clk *byte_clk; | 205 | struct clk *byte_clk; |
206 | struct clk *esc_clk; | 206 | struct clk *esc_clk; |
207 | struct clk *pixel_clk; | 207 | struct clk *pixel_clk; |
208 | struct clk *byte_clk_src; | ||
209 | struct clk *pixel_clk_src; | ||
210 | |||
208 | u32 byte_clk_rate; | 211 | u32 byte_clk_rate; |
209 | 212 | ||
210 | struct gpio_desc *disp_en_gpio; | 213 | struct gpio_desc *disp_en_gpio; |
@@ -463,6 +466,22 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host) | |||
463 | goto exit; | 466 | goto exit; |
464 | } | 467 | } |
465 | 468 | ||
469 | msm_host->byte_clk_src = devm_clk_get(dev, "byte_clk_src"); | ||
470 | if (IS_ERR(msm_host->byte_clk_src)) { | ||
471 | ret = PTR_ERR(msm_host->byte_clk_src); | ||
472 | pr_err("%s: can't find byte_clk_src. ret=%d\n", __func__, ret); | ||
473 | msm_host->byte_clk_src = NULL; | ||
474 | goto exit; | ||
475 | } | ||
476 | |||
477 | msm_host->pixel_clk_src = devm_clk_get(dev, "pixel_clk_src"); | ||
478 | if (IS_ERR(msm_host->pixel_clk_src)) { | ||
479 | ret = PTR_ERR(msm_host->pixel_clk_src); | ||
480 | pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret); | ||
481 | msm_host->pixel_clk_src = NULL; | ||
482 | goto exit; | ||
483 | } | ||
484 | |||
466 | exit: | 485 | exit: |
467 | return ret; | 486 | return ret; |
468 | } | 487 | } |
@@ -1513,15 +1532,9 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) | |||
1513 | msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0); | 1532 | msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0); |
1514 | INIT_WORK(&msm_host->err_work, dsi_err_worker); | 1533 | INIT_WORK(&msm_host->err_work, dsi_err_worker); |
1515 | 1534 | ||
1516 | msm_dsi->phy = msm_dsi_phy_init(pdev, msm_host->cfg->phy_type, | ||
1517 | msm_host->id); | ||
1518 | if (!msm_dsi->phy) { | ||
1519 | ret = -EINVAL; | ||
1520 | pr_err("%s: phy init failed\n", __func__); | ||
1521 | goto fail; | ||
1522 | } | ||
1523 | msm_dsi->host = &msm_host->base; | 1535 | msm_dsi->host = &msm_host->base; |
1524 | msm_dsi->id = msm_host->id; | 1536 | msm_dsi->id = msm_host->id; |
1537 | msm_dsi->phy_type = msm_host->cfg->phy_type; | ||
1525 | 1538 | ||
1526 | DBG("Dsi Host %d initialized", msm_host->id); | 1539 | DBG("Dsi Host %d initialized", msm_host->id); |
1527 | return 0; | 1540 | return 0; |
@@ -1829,6 +1842,39 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 iova, u32 len) | |||
1829 | wmb(); | 1842 | wmb(); |
1830 | } | 1843 | } |
1831 | 1844 | ||
1845 | int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, | ||
1846 | struct msm_dsi_pll *src_pll) | ||
1847 | { | ||
1848 | struct msm_dsi_host *msm_host = to_msm_dsi_host(host); | ||
1849 | struct clk *byte_clk_provider, *pixel_clk_provider; | ||
1850 | int ret; | ||
1851 | |||
1852 | ret = msm_dsi_pll_get_clk_provider(src_pll, | ||
1853 | &byte_clk_provider, &pixel_clk_provider); | ||
1854 | if (ret) { | ||
1855 | pr_info("%s: can't get provider from pll, don't set parent\n", | ||
1856 | __func__); | ||
1857 | return 0; | ||
1858 | } | ||
1859 | |||
1860 | ret = clk_set_parent(msm_host->byte_clk_src, byte_clk_provider); | ||
1861 | if (ret) { | ||
1862 | pr_err("%s: can't set parent to byte_clk_src. ret=%d\n", | ||
1863 | __func__, ret); | ||
1864 | goto exit; | ||
1865 | } | ||
1866 | |||
1867 | ret = clk_set_parent(msm_host->pixel_clk_src, pixel_clk_provider); | ||
1868 | if (ret) { | ||
1869 | pr_err("%s: can't set parent to pixel_clk_src. ret=%d\n", | ||
1870 | __func__, ret); | ||
1871 | goto exit; | ||
1872 | } | ||
1873 | |||
1874 | exit: | ||
1875 | return ret; | ||
1876 | } | ||
1877 | |||
1832 | int msm_dsi_host_enable(struct mipi_dsi_host *host) | 1878 | int msm_dsi_host_enable(struct mipi_dsi_host *host) |
1833 | { | 1879 | { |
1834 | struct msm_dsi_host *msm_host = to_msm_dsi_host(host); | 1880 | struct msm_dsi_host *msm_host = to_msm_dsi_host(host); |
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 0a40f3c64e8b..87ac6612b6f8 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c | |||
@@ -60,6 +60,53 @@ static int dsi_mgr_parse_dual_panel(struct device_node *np, int id) | |||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | static int dsi_mgr_host_register(int id) | ||
64 | { | ||
65 | struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); | ||
66 | struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); | ||
67 | struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER); | ||
68 | struct msm_dsi_pll *src_pll; | ||
69 | int ret; | ||
70 | |||
71 | if (!IS_DUAL_PANEL()) { | ||
72 | ret = msm_dsi_host_register(msm_dsi->host, true); | ||
73 | if (ret) | ||
74 | return ret; | ||
75 | |||
76 | src_pll = msm_dsi_phy_get_pll(msm_dsi->phy); | ||
77 | ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll); | ||
78 | } else if (!other_dsi) { | ||
79 | ret = 0; | ||
80 | } else { | ||
81 | struct msm_dsi *mdsi = IS_MASTER_PANEL(id) ? | ||
82 | msm_dsi : other_dsi; | ||
83 | struct msm_dsi *sdsi = IS_MASTER_PANEL(id) ? | ||
84 | other_dsi : msm_dsi; | ||
85 | /* Register slave host first, so that slave DSI device | ||
86 | * has a chance to probe, and do not block the master | ||
87 | * DSI device's probe. | ||
88 | * Also, do not check defer for the slave host, | ||
89 | * because only master DSI device adds the panel to global | ||
90 | * panel list. The panel's device is the master DSI device. | ||
91 | */ | ||
92 | ret = msm_dsi_host_register(sdsi->host, false); | ||
93 | if (ret) | ||
94 | return ret; | ||
95 | ret = msm_dsi_host_register(mdsi->host, true); | ||
96 | if (ret) | ||
97 | return ret; | ||
98 | |||
99 | /* PLL0 is to drive both 2 DSI link clocks in Dual DSI mode. */ | ||
100 | src_pll = msm_dsi_phy_get_pll(clk_master_dsi->phy); | ||
101 | ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll); | ||
102 | if (ret) | ||
103 | return ret; | ||
104 | ret = msm_dsi_host_set_src_pll(other_dsi->host, src_pll); | ||
105 | } | ||
106 | |||
107 | return ret; | ||
108 | } | ||
109 | |||
63 | struct dsi_connector { | 110 | struct dsi_connector { |
64 | struct drm_connector base; | 111 | struct drm_connector base; |
65 | int id; | 112 | int id; |
@@ -652,7 +699,6 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi) | |||
652 | { | 699 | { |
653 | struct msm_dsi_manager *msm_dsim = &msm_dsim_glb; | 700 | struct msm_dsi_manager *msm_dsim = &msm_dsim_glb; |
654 | int id = msm_dsi->id; | 701 | int id = msm_dsi->id; |
655 | struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); | ||
656 | int ret; | 702 | int ret; |
657 | 703 | ||
658 | if (id > DSI_MAX) { | 704 | if (id > DSI_MAX) { |
@@ -670,31 +716,20 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi) | |||
670 | ret = dsi_mgr_parse_dual_panel(msm_dsi->pdev->dev.of_node, id); | 716 | ret = dsi_mgr_parse_dual_panel(msm_dsi->pdev->dev.of_node, id); |
671 | if (ret) { | 717 | if (ret) { |
672 | pr_err("%s: failed to parse dual panel info\n", __func__); | 718 | pr_err("%s: failed to parse dual panel info\n", __func__); |
673 | return ret; | 719 | goto fail; |
674 | } | 720 | } |
675 | 721 | ||
676 | if (!IS_DUAL_PANEL()) { | 722 | ret = dsi_mgr_host_register(id); |
677 | ret = msm_dsi_host_register(msm_dsi->host, true); | 723 | if (ret) { |
678 | } else if (!other_dsi) { | 724 | pr_err("%s: failed to register mipi dsi host for DSI %d\n", |
679 | return 0; | 725 | __func__, id); |
680 | } else { | 726 | goto fail; |
681 | struct msm_dsi *mdsi = IS_MASTER_PANEL(id) ? | ||
682 | msm_dsi : other_dsi; | ||
683 | struct msm_dsi *sdsi = IS_MASTER_PANEL(id) ? | ||
684 | other_dsi : msm_dsi; | ||
685 | /* Register slave host first, so that slave DSI device | ||
686 | * has a chance to probe, and do not block the master | ||
687 | * DSI device's probe. | ||
688 | * Also, do not check defer for the slave host, | ||
689 | * because only master DSI device adds the panel to global | ||
690 | * panel list. The panel's device is the master DSI device. | ||
691 | */ | ||
692 | ret = msm_dsi_host_register(sdsi->host, false); | ||
693 | if (ret) | ||
694 | return ret; | ||
695 | ret = msm_dsi_host_register(mdsi->host, true); | ||
696 | } | 727 | } |
697 | 728 | ||
729 | return 0; | ||
730 | |||
731 | fail: | ||
732 | msm_dsim->dsi[id] = NULL; | ||
698 | return ret; | 733 | return ret; |
699 | } | 734 | } |
700 | 735 | ||
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 { | |||
34 | }; | 34 | }; |
35 | 35 | ||
36 | struct msm_dsi_phy { | 36 | struct msm_dsi_phy { |
37 | struct platform_device *pdev; | ||
37 | void __iomem *base; | 38 | void __iomem *base; |
38 | void __iomem *reg_base; | 39 | void __iomem *reg_base; |
39 | int id; | 40 | int id; |
41 | |||
42 | struct clk *ahb_clk; | ||
43 | |||
40 | struct dsi_dphy_timing timing; | 44 | struct dsi_dphy_timing timing; |
45 | enum msm_dsi_phy_type type; | ||
46 | |||
47 | struct msm_dsi_pll *pll; | ||
48 | |||
41 | int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel, | 49 | int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel, |
42 | const unsigned long bit_rate, const unsigned long esc_rate); | 50 | const unsigned long bit_rate, const unsigned long esc_rate); |
43 | int (*disable)(struct msm_dsi_phy *phy); | 51 | int (*disable)(struct msm_dsi_phy *phy); |
@@ -284,6 +292,27 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy) | |||
284 | return 0; | 292 | return 0; |
285 | } | 293 | } |
286 | 294 | ||
295 | static int dsi_phy_enable_resource(struct msm_dsi_phy *phy) | ||
296 | { | ||
297 | int ret; | ||
298 | |||
299 | pm_runtime_get_sync(&phy->pdev->dev); | ||
300 | |||
301 | ret = clk_prepare_enable(phy->ahb_clk); | ||
302 | if (ret) { | ||
303 | pr_err("%s: can't enable ahb clk, %d\n", __func__, ret); | ||
304 | pm_runtime_put_sync(&phy->pdev->dev); | ||
305 | } | ||
306 | |||
307 | return ret; | ||
308 | } | ||
309 | |||
310 | static void dsi_phy_disable_resource(struct msm_dsi_phy *phy) | ||
311 | { | ||
312 | clk_disable_unprepare(phy->ahb_clk); | ||
313 | pm_runtime_put_sync(&phy->pdev->dev); | ||
314 | } | ||
315 | |||
287 | #define dsi_phy_func_init(name) \ | 316 | #define dsi_phy_func_init(name) \ |
288 | do { \ | 317 | do { \ |
289 | phy->enable = dsi_##name##_phy_enable; \ | 318 | phy->enable = dsi_##name##_phy_enable; \ |
@@ -294,6 +323,7 @@ struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev, | |||
294 | enum msm_dsi_phy_type type, int id) | 323 | enum msm_dsi_phy_type type, int id) |
295 | { | 324 | { |
296 | struct msm_dsi_phy *phy; | 325 | struct msm_dsi_phy *phy; |
326 | int ret; | ||
297 | 327 | ||
298 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); | 328 | phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); |
299 | if (!phy) | 329 | if (!phy) |
@@ -320,11 +350,41 @@ struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev, | |||
320 | return NULL; | 350 | return NULL; |
321 | } | 351 | } |
322 | 352 | ||
353 | phy->type = type; | ||
323 | phy->id = id; | 354 | phy->id = id; |
355 | phy->pdev = pdev; | ||
356 | |||
357 | phy->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk"); | ||
358 | if (IS_ERR(phy->ahb_clk)) { | ||
359 | pr_err("%s: Unable to get ahb clk\n", __func__); | ||
360 | return NULL; | ||
361 | } | ||
362 | |||
363 | /* PLL init will call into clk_register which requires | ||
364 | * register access, so we need to enable power and ahb clock. | ||
365 | */ | ||
366 | ret = dsi_phy_enable_resource(phy); | ||
367 | if (ret) | ||
368 | return NULL; | ||
369 | |||
370 | phy->pll = msm_dsi_pll_init(pdev, type, id); | ||
371 | if (!phy->pll) | ||
372 | pr_info("%s: pll init failed, need separate pll clk driver\n", | ||
373 | __func__); | ||
374 | |||
375 | dsi_phy_disable_resource(phy); | ||
324 | 376 | ||
325 | return phy; | 377 | return phy; |
326 | } | 378 | } |
327 | 379 | ||
380 | void msm_dsi_phy_destroy(struct msm_dsi_phy *phy) | ||
381 | { | ||
382 | if (phy->pll) { | ||
383 | msm_dsi_pll_destroy(phy->pll); | ||
384 | phy->pll = NULL; | ||
385 | } | ||
386 | } | ||
387 | |||
328 | int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel, | 388 | int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel, |
329 | const unsigned long bit_rate, const unsigned long esc_rate) | 389 | const unsigned long bit_rate, const unsigned long esc_rate) |
330 | { | 390 | { |
@@ -351,3 +411,11 @@ void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, | |||
351 | *clk_post = phy->timing.clk_post; | 411 | *clk_post = phy->timing.clk_post; |
352 | } | 412 | } |
353 | 413 | ||
414 | struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy) | ||
415 | { | ||
416 | if (!phy) | ||
417 | return NULL; | ||
418 | |||
419 | return phy->pll; | ||
420 | } | ||
421 | |||