aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHai Li <hali@codeaurora.org>2016-09-15 05:14:22 -0400
committerRob Clark <robdclark@gmail.com>2017-02-06 11:28:45 -0500
commit57bf433893370c069a0c34842f35a3bb8aa130fc (patch)
treed4e5cf015190a3497cde2ddba9d316ee386068df
parentdceac340155b66b6c97cb802b03d4778dd82e9be (diff)
drm/msm/dsi: Pass down use case to PHY
For some new types of DSI PHY, more settings depend on use cases controlled by DSI manager. This change allows DSI manager to setup PHY with a use case. Signed-off-by: Hai Li <hali@codeaurora.org> Signed-off-by: Archit Taneja <architt@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h8
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c43
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c29
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h1
4 files changed, 51 insertions, 30 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index f5e4ccfc902d..d516fe296b78 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -37,6 +37,12 @@ enum msm_dsi_phy_type {
37 MSM_DSI_PHY_MAX 37 MSM_DSI_PHY_MAX
38}; 38};
39 39
40enum msm_dsi_phy_usecase {
41 MSM_DSI_PHY_STANDALONE,
42 MSM_DSI_PHY_MASTER,
43 MSM_DSI_PHY_SLAVE,
44};
45
40#define DSI_DEV_REGULATOR_MAX 8 46#define DSI_DEV_REGULATOR_MAX 8
41#define DSI_BUS_CLK_MAX 4 47#define DSI_BUS_CLK_MAX 4
42 48
@@ -180,6 +186,8 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy);
180void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy, 186void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy,
181 struct msm_dsi_phy_shared_timings *shared_timing); 187 struct msm_dsi_phy_shared_timings *shared_timing);
182struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy); 188struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy);
189void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy,
190 enum msm_dsi_phy_usecase uc);
183 191
184#endif /* __DSI_CONNECTOR_H__ */ 192#endif /* __DSI_CONNECTOR_H__ */
185 193
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 423afa66bd0f..c040830f5900 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -72,11 +72,12 @@ static int dsi_mgr_parse_dual_dsi(struct device_node *np, int id)
72 return 0; 72 return 0;
73} 73}
74 74
75static int dsi_mgr_host_register(int id) 75static int dsi_mgr_setup_components(int id)
76{ 76{
77 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 77 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
78 struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); 78 struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
79 struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER); 79 struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
80 struct msm_dsi *clk_slave_dsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
80 struct msm_dsi_pll *src_pll; 81 struct msm_dsi_pll *src_pll;
81 int ret; 82 int ret;
82 83
@@ -85,15 +86,16 @@ static int dsi_mgr_host_register(int id)
85 if (ret) 86 if (ret)
86 return ret; 87 return ret;
87 88
89 msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE);
88 src_pll = msm_dsi_phy_get_pll(msm_dsi->phy); 90 src_pll = msm_dsi_phy_get_pll(msm_dsi->phy);
89 ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll); 91 ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll);
90 } else if (!other_dsi) { 92 } else if (!other_dsi) {
91 ret = 0; 93 ret = 0;
92 } else { 94 } else {
93 struct msm_dsi *mdsi = IS_MASTER_DSI_LINK(id) ? 95 struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ?
94 msm_dsi : other_dsi; 96 msm_dsi : other_dsi;
95 struct msm_dsi *sdsi = IS_MASTER_DSI_LINK(id) ? 97 struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ?
96 other_dsi : msm_dsi; 98 other_dsi : msm_dsi;
97 /* Register slave host first, so that slave DSI device 99 /* Register slave host first, so that slave DSI device
98 * has a chance to probe, and do not block the master 100 * has a chance to probe, and do not block the master
99 * DSI device's probe. 101 * DSI device's probe.
@@ -101,14 +103,18 @@ static int dsi_mgr_host_register(int id)
101 * because only master DSI device adds the panel to global 103 * because only master DSI device adds the panel to global
102 * panel list. The panel's device is the master DSI device. 104 * panel list. The panel's device is the master DSI device.
103 */ 105 */
104 ret = msm_dsi_host_register(sdsi->host, false); 106 ret = msm_dsi_host_register(slave_link_dsi->host, false);
105 if (ret) 107 if (ret)
106 return ret; 108 return ret;
107 ret = msm_dsi_host_register(mdsi->host, true); 109 ret = msm_dsi_host_register(master_link_dsi->host, true);
108 if (ret) 110 if (ret)
109 return ret; 111 return ret;
110 112
111 /* PLL0 is to drive both 2 DSI link clocks in Dual DSI mode. */ 113 /* PLL0 is to drive both 2 DSI link clocks in Dual DSI mode. */
114 msm_dsi_phy_set_usecase(clk_master_dsi->phy,
115 MSM_DSI_PHY_MASTER);
116 msm_dsi_phy_set_usecase(clk_slave_dsi->phy,
117 MSM_DSI_PHY_SLAVE);
112 src_pll = msm_dsi_phy_get_pll(clk_master_dsi->phy); 118 src_pll = msm_dsi_phy_get_pll(clk_master_dsi->phy);
113 ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll); 119 ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll);
114 if (ret) 120 if (ret)
@@ -665,28 +671,12 @@ int msm_dsi_manager_phy_enable(int id,
665 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 671 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
666 struct msm_dsi_phy *phy = msm_dsi->phy; 672 struct msm_dsi_phy *phy = msm_dsi->phy;
667 int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id; 673 int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
668 struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
669 int ret; 674 int ret;
670 675
671 ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate); 676 ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate);
672 if (ret) 677 if (ret)
673 return ret; 678 return ret;
674 679
675 /*
676 * Reset DSI PHY silently changes its PLL registers to reset status,
677 * which will confuse clock driver and result in wrong output rate of
678 * link clocks. Restore PLL status if its PLL is being used as clock
679 * source.
680 */
681 if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER)) {
682 ret = msm_dsi_pll_restore_state(pll);
683 if (ret) {
684 pr_err("%s: failed to restore pll state\n", __func__);
685 msm_dsi_phy_disable(phy);
686 return ret;
687 }
688 }
689
690 msm_dsi->phy_enabled = true; 680 msm_dsi->phy_enabled = true;
691 msm_dsi_phy_get_shared_timings(phy, shared_timings); 681 msm_dsi_phy_get_shared_timings(phy, shared_timings);
692 682
@@ -699,11 +689,6 @@ void msm_dsi_manager_phy_disable(int id)
699 struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER); 689 struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
700 struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE); 690 struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
701 struct msm_dsi_phy *phy = msm_dsi->phy; 691 struct msm_dsi_phy *phy = msm_dsi->phy;
702 struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
703
704 /* Save PLL status if it is a clock source */
705 if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER))
706 msm_dsi_pll_save_state(pll);
707 692
708 /* disable DSI phy 693 /* disable DSI phy
709 * In dual-dsi configuration, the phy should be disabled for the 694 * In dual-dsi configuration, the phy should be disabled for the
@@ -834,7 +819,7 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
834 goto fail; 819 goto fail;
835 } 820 }
836 821
837 ret = dsi_mgr_host_register(id); 822 ret = dsi_mgr_setup_components(id);
838 if (ret) { 823 if (ret) {
839 pr_err("%s: failed to register mipi dsi host for DSI %d\n", 824 pr_err("%s: failed to register mipi dsi host for DSI %d\n",
840 __func__, id); 825 __func__, id);
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 51f7c66078d7..1021c1c572ca 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -451,7 +451,24 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
451 return ret; 451 return ret;
452 } 452 }
453 453
454 return 0; 454 /*
455 * Resetting DSI PHY silently changes its PLL registers to reset status,
456 * which will confuse clock driver and result in wrong output rate of
457 * link clocks. Restore PLL status if its PLL is being used as clock
458 * source.
459 */
460 if (phy->usecase != MSM_DSI_PHY_SLAVE) {
461 ret = msm_dsi_pll_restore_state(phy->pll);
462 if (ret) {
463 pr_err("%s: failed to restore pll state\n", __func__);
464 if (phy->cfg->ops.disable)
465 phy->cfg->ops.disable(phy);
466 dsi_phy_regulator_disable(phy);
467 return ret;
468 }
469 }
470
471 return ret;
455} 472}
456 473
457void msm_dsi_phy_disable(struct msm_dsi_phy *phy) 474void msm_dsi_phy_disable(struct msm_dsi_phy *phy)
@@ -459,6 +476,10 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy)
459 if (!phy || !phy->cfg->ops.disable) 476 if (!phy || !phy->cfg->ops.disable)
460 return; 477 return;
461 478
479 /* Save PLL status if it is a clock source */
480 if (phy->usecase != MSM_DSI_PHY_SLAVE)
481 msm_dsi_pll_save_state(phy->pll);
482
462 phy->cfg->ops.disable(phy); 483 phy->cfg->ops.disable(phy);
463 484
464 dsi_phy_regulator_disable(phy); 485 dsi_phy_regulator_disable(phy);
@@ -479,3 +500,9 @@ struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy)
479 return phy->pll; 500 return phy->pll;
480} 501}
481 502
503void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy,
504 enum msm_dsi_phy_usecase uc)
505{
506 if (phy)
507 phy->usecase = uc;
508}
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 7399934cec54..e1057423fd21 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -78,6 +78,7 @@ struct msm_dsi_phy {
78 struct msm_dsi_dphy_timing timing; 78 struct msm_dsi_dphy_timing timing;
79 const struct msm_dsi_phy_cfg *cfg; 79 const struct msm_dsi_phy_cfg *cfg;
80 80
81 enum msm_dsi_phy_usecase usecase;
81 bool regulator_ldo_mode; 82 bool regulator_ldo_mode;
82 83
83 struct msm_dsi_pll *pll; 84 struct msm_dsi_pll *pll;