aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/dsi/dsi_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/dsi/dsi_manager.c')
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c254
1 files changed, 160 insertions, 94 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 2bd8dad76105..921270ea6059 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)
@@ -119,6 +125,84 @@ static int dsi_mgr_host_register(int id)
119 return ret; 125 return ret;
120} 126}
121 127
128static int enable_phy(struct msm_dsi *msm_dsi, int src_pll_id,
129 struct msm_dsi_phy_shared_timings *shared_timings)
130{
131 struct msm_dsi_phy_clk_request clk_req;
132 int ret;
133
134 msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req);
135
136 ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, &clk_req);
137 msm_dsi_phy_get_shared_timings(msm_dsi->phy, shared_timings);
138
139 return ret;
140}
141
142static int
143dsi_mgr_phy_enable(int id,
144 struct msm_dsi_phy_shared_timings shared_timings[DSI_MAX])
145{
146 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
147 struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
148 struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
149 int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
150 int ret;
151
152 /* In case of dual DSI, some registers in PHY1 have been programmed
153 * during PLL0 clock's set_rate. The PHY1 reset called by host1 here
154 * will silently reset those PHY1 registers. Therefore we need to reset
155 * and enable both PHYs before any PLL clock operation.
156 */
157 if (IS_DUAL_DSI() && mdsi && sdsi) {
158 if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
159 msm_dsi_host_reset_phy(mdsi->host);
160 msm_dsi_host_reset_phy(sdsi->host);
161
162 ret = enable_phy(mdsi, src_pll_id,
163 &shared_timings[DSI_CLOCK_MASTER]);
164 if (ret)
165 return ret;
166 ret = enable_phy(sdsi, src_pll_id,
167 &shared_timings[DSI_CLOCK_SLAVE]);
168 if (ret) {
169 msm_dsi_phy_disable(mdsi->phy);
170 return ret;
171 }
172 }
173 } else {
174 msm_dsi_host_reset_phy(mdsi->host);
175 ret = enable_phy(msm_dsi, src_pll_id, &shared_timings[id]);
176 if (ret)
177 return ret;
178 }
179
180 msm_dsi->phy_enabled = true;
181
182 return 0;
183}
184
185static void dsi_mgr_phy_disable(int id)
186{
187 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
188 struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
189 struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
190
191 /* disable DSI phy
192 * In dual-dsi configuration, the phy should be disabled for the
193 * first controller only when the second controller is disabled.
194 */
195 msm_dsi->phy_enabled = false;
196 if (IS_DUAL_DSI() && mdsi && sdsi) {
197 if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
198 msm_dsi_phy_disable(sdsi->phy);
199 msm_dsi_phy_disable(mdsi->phy);
200 }
201 } else {
202 msm_dsi_phy_disable(msm_dsi->phy);
203 }
204}
205
122struct dsi_connector { 206struct dsi_connector {
123 struct drm_connector base; 207 struct drm_connector base;
124 int id; 208 int id;
@@ -168,6 +252,16 @@ static enum drm_connector_status dsi_mgr_connector_detect(
168 msm_dsi->panel = msm_dsi_host_get_panel( 252 msm_dsi->panel = msm_dsi_host_get_panel(
169 other_dsi->host, NULL); 253 other_dsi->host, NULL);
170 254
255
256 if (msm_dsi->panel && kms->funcs->set_encoder_mode) {
257 bool cmd_mode = !(msm_dsi->device_flags &
258 MIPI_DSI_MODE_VIDEO);
259 struct drm_encoder *encoder =
260 msm_dsi_get_encoder(msm_dsi);
261
262 kms->funcs->set_encoder_mode(kms, encoder, cmd_mode);
263 }
264
171 if (msm_dsi->panel && IS_DUAL_DSI()) 265 if (msm_dsi->panel && IS_DUAL_DSI())
172 drm_object_attach_property(&connector->base, 266 drm_object_attach_property(&connector->base,
173 connector->dev->mode_config.tile_property, 0); 267 connector->dev->mode_config.tile_property, 0);
@@ -344,22 +438,31 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
344 struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); 438 struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
345 struct mipi_dsi_host *host = msm_dsi->host; 439 struct mipi_dsi_host *host = msm_dsi->host;
346 struct drm_panel *panel = msm_dsi->panel; 440 struct drm_panel *panel = msm_dsi->panel;
441 struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX];
347 bool is_dual_dsi = IS_DUAL_DSI(); 442 bool is_dual_dsi = IS_DUAL_DSI();
348 int ret; 443 int ret;
349 444
350 DBG("id=%d", id); 445 DBG("id=%d", id);
351 if (!msm_dsi_device_connected(msm_dsi) || 446 if (!msm_dsi_device_connected(msm_dsi))
352 (is_dual_dsi && (DSI_1 == id)))
353 return; 447 return;
354 448
355 ret = msm_dsi_host_power_on(host); 449 ret = dsi_mgr_phy_enable(id, phy_shared_timings);
450 if (ret)
451 goto phy_en_fail;
452
453 /* Do nothing with the host if it is DSI 1 in case of dual DSI */
454 if (is_dual_dsi && (DSI_1 == id))
455 return;
456
457 ret = msm_dsi_host_power_on(host, &phy_shared_timings[id]);
356 if (ret) { 458 if (ret) {
357 pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); 459 pr_err("%s: power on host %d failed, %d\n", __func__, id, ret);
358 goto host_on_fail; 460 goto host_on_fail;
359 } 461 }
360 462
361 if (is_dual_dsi && msm_dsi1) { 463 if (is_dual_dsi && msm_dsi1) {
362 ret = msm_dsi_host_power_on(msm_dsi1->host); 464 ret = msm_dsi_host_power_on(msm_dsi1->host,
465 &phy_shared_timings[DSI_1]);
363 if (ret) { 466 if (ret) {
364 pr_err("%s: power on host1 failed, %d\n", 467 pr_err("%s: power on host1 failed, %d\n",
365 __func__, ret); 468 __func__, ret);
@@ -418,6 +521,8 @@ panel_prep_fail:
418host1_on_fail: 521host1_on_fail:
419 msm_dsi_host_power_off(host); 522 msm_dsi_host_power_off(host);
420host_on_fail: 523host_on_fail:
524 dsi_mgr_phy_disable(id);
525phy_en_fail:
421 return; 526 return;
422} 527}
423 528
@@ -443,10 +548,17 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
443 548
444 DBG("id=%d", id); 549 DBG("id=%d", id);
445 550
446 if (!msm_dsi_device_connected(msm_dsi) || 551 if (!msm_dsi_device_connected(msm_dsi))
447 (is_dual_dsi && (DSI_1 == id)))
448 return; 552 return;
449 553
554 /*
555 * Do nothing with the host if it is DSI 1 in case of dual DSI.
556 * It is safe to call dsi_mgr_phy_disable() here because a single PHY
557 * won't be diabled until both PHYs request disable.
558 */
559 if (is_dual_dsi && (DSI_1 == id))
560 goto disable_phy;
561
450 if (panel) { 562 if (panel) {
451 ret = drm_panel_disable(panel); 563 ret = drm_panel_disable(panel);
452 if (ret) 564 if (ret)
@@ -481,6 +593,9 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
481 pr_err("%s: host1 power off failed, %d\n", 593 pr_err("%s: host1 power off failed, %d\n",
482 __func__, ret); 594 __func__, ret);
483 } 595 }
596
597disable_phy:
598 dsi_mgr_phy_disable(id);
484} 599}
485 600
486static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge, 601static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
@@ -540,7 +655,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
540 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 655 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
541 struct drm_connector *connector = NULL; 656 struct drm_connector *connector = NULL;
542 struct dsi_connector *dsi_connector; 657 struct dsi_connector *dsi_connector;
543 int ret, i; 658 int ret;
544 659
545 dsi_connector = kzalloc(sizeof(*dsi_connector), GFP_KERNEL); 660 dsi_connector = kzalloc(sizeof(*dsi_connector), GFP_KERNEL);
546 if (!dsi_connector) 661 if (!dsi_connector)
@@ -566,9 +681,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
566 connector->interlace_allowed = 0; 681 connector->interlace_allowed = 0;
567 connector->doublescan_allowed = 0; 682 connector->doublescan_allowed = 0;
568 683
569 for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) 684 drm_mode_connector_attach_encoder(connector, msm_dsi->encoder);
570 drm_mode_connector_attach_encoder(connector,
571 msm_dsi->encoders[i]);
572 685
573 return connector; 686 return connector;
574} 687}
@@ -591,13 +704,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
591 704
592 dsi_bridge->id = id; 705 dsi_bridge->id = id;
593 706
594 /* 707 encoder = msm_dsi->encoder;
595 * HACK: we may not know the external DSI bridge device's mode
596 * flags here. We'll get to know them only when the device
597 * attaches to the dsi host. For now, assume the bridge supports
598 * DSI video mode
599 */
600 encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
601 708
602 bridge = &dsi_bridge->base; 709 bridge = &dsi_bridge->base;
603 bridge->funcs = &dsi_mgr_bridge_funcs; 710 bridge->funcs = &dsi_mgr_bridge_funcs;
@@ -628,13 +735,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
628 ext_bridge = msm_dsi->external_bridge = 735 ext_bridge = msm_dsi->external_bridge =
629 msm_dsi_host_get_bridge(msm_dsi->host); 736 msm_dsi_host_get_bridge(msm_dsi->host);
630 737
631 /* 738 encoder = msm_dsi->encoder;
632 * HACK: we may not know the external DSI bridge device's mode
633 * flags here. We'll get to know them only when the device
634 * attaches to the dsi host. For now, assume the bridge supports
635 * DSI video mode
636 */
637 encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
638 739
639 /* link the internal dsi bridge to the external bridge */ 740 /* link the internal dsi bridge to the external bridge */
640 drm_bridge_attach(encoder, ext_bridge, int_bridge); 741 drm_bridge_attach(encoder, ext_bridge, int_bridge);
@@ -662,68 +763,6 @@ void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge)
662{ 763{
663} 764}
664 765
665int msm_dsi_manager_phy_enable(int id,
666 const unsigned long bit_rate, const unsigned long esc_rate,
667 u32 *clk_pre, u32 *clk_post)
668{
669 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
670 struct msm_dsi_phy *phy = msm_dsi->phy;
671 int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
672 struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
673 int ret;
674
675 ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate);
676 if (ret)
677 return ret;
678
679 /*
680 * Reset DSI PHY silently changes its PLL registers to reset status,
681 * which will confuse clock driver and result in wrong output rate of
682 * link clocks. Restore PLL status if its PLL is being used as clock
683 * source.
684 */
685 if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER)) {
686 ret = msm_dsi_pll_restore_state(pll);
687 if (ret) {
688 pr_err("%s: failed to restore pll state\n", __func__);
689 msm_dsi_phy_disable(phy);
690 return ret;
691 }
692 }
693
694 msm_dsi->phy_enabled = true;
695 msm_dsi_phy_get_clk_pre_post(phy, clk_pre, clk_post);
696
697 return 0;
698}
699
700void msm_dsi_manager_phy_disable(int id)
701{
702 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
703 struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
704 struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
705 struct msm_dsi_phy *phy = msm_dsi->phy;
706 struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
707
708 /* Save PLL status if it is a clock source */
709 if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER))
710 msm_dsi_pll_save_state(pll);
711
712 /* disable DSI phy
713 * In dual-dsi configuration, the phy should be disabled for the
714 * first controller only when the second controller is disabled.
715 */
716 msm_dsi->phy_enabled = false;
717 if (IS_DUAL_DSI() && mdsi && sdsi) {
718 if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
719 msm_dsi_phy_disable(sdsi->phy);
720 msm_dsi_phy_disable(mdsi->phy);
721 }
722 } else {
723 msm_dsi_phy_disable(phy);
724 }
725}
726
727int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg) 766int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg)
728{ 767{
729 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 768 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
@@ -787,6 +826,33 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
787 return true; 826 return true;
788} 827}
789 828
829void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags)
830{
831 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
832 struct drm_device *dev = msm_dsi->dev;
833 struct msm_drm_private *priv;
834 struct msm_kms *kms;
835 struct drm_encoder *encoder;
836
837 /*
838 * drm_device pointer is assigned to msm_dsi only in the modeset_init
839 * path. If mipi_dsi_attach() happens in DSI driver's probe path
840 * (generally the case when we're connected to a drm_panel of the type
841 * mipi_dsi_device), this would be NULL. In such cases, try to set the
842 * encoder mode in the DSI connector's detect() op.
843 */
844 if (!dev)
845 return;
846
847 priv = dev->dev_private;
848 kms = priv->kms;
849 encoder = msm_dsi_get_encoder(msm_dsi);
850
851 if (encoder && kms->funcs->set_encoder_mode)
852 if (!(device_flags & MIPI_DSI_MODE_VIDEO))
853 kms->funcs->set_encoder_mode(kms, encoder, true);
854}
855
790int msm_dsi_manager_register(struct msm_dsi *msm_dsi) 856int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
791{ 857{
792 struct msm_dsi_manager *msm_dsim = &msm_dsim_glb; 858 struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
@@ -811,7 +877,7 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
811 goto fail; 877 goto fail;
812 } 878 }
813 879
814 ret = dsi_mgr_host_register(id); 880 ret = dsi_mgr_setup_components(id);
815 if (ret) { 881 if (ret) {
816 pr_err("%s: failed to register mipi dsi host for DSI %d\n", 882 pr_err("%s: failed to register mipi dsi host for DSI %d\n",
817 __func__, id); 883 __func__, id);