aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c14
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h43
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c60
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c79
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_phy.c68
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
41enum 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
41struct msm_dsi { 48struct 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 */
74struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi); 83struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi);
75 84
85/* dsi pll */
86struct msm_dsi_pll;
87#ifdef CONFIG_DRM_MSM_DSI_PLL
88struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
89 enum msm_dsi_phy_type type, int dsi_id);
90void msm_dsi_pll_destroy(struct msm_dsi_pll *pll);
91int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
92 struct clk **byte_clk_provider, struct clk **pixel_clk_provider);
93#else
94static 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}
98static inline void msm_dsi_pll_destroy(struct msm_dsi_pll *pll)
99{
100}
101static 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 */
77int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host, 109int 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);
95int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer); 127int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);
96void msm_dsi_host_unregister(struct mipi_dsi_host *host); 128void msm_dsi_host_unregister(struct mipi_dsi_host *host);
129int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
130 struct msm_dsi_pll *src_pll);
97void msm_dsi_host_destroy(struct mipi_dsi_host *host); 131void msm_dsi_host_destroy(struct mipi_dsi_host *host);
98int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, 132int 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 */
103struct msm_dsi_phy; 137struct msm_dsi_phy;
104enum 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};
110struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev, 138struct 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);
140void msm_dsi_phy_destroy(struct msm_dsi_phy *phy);
112int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel, 141int 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);
114int msm_dsi_phy_disable(struct msm_dsi_phy *phy); 143int msm_dsi_phy_disable(struct msm_dsi_phy *phy);
115void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy, 144void 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);
146struct 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
466exit: 485exit:
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
1845int 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
1874exit:
1875 return ret;
1876}
1877
1832int msm_dsi_host_enable(struct mipi_dsi_host *host) 1878int 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
63static 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
63struct dsi_connector { 110struct 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
731fail:
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
36struct msm_dsi_phy { 36struct 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
295static 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
310static 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
380void 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
328int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel, 388int 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
414struct 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