1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
4 */
5
6 #include "drm/drm_bridge_connector.h"
7
8 #include "msm_kms.h"
9 #include "dsi.h"
10
11 #define DSI_CLOCK_MASTER DSI_0
12 #define DSI_CLOCK_SLAVE DSI_1
13
14 #define DSI_LEFT DSI_0
15 #define DSI_RIGHT DSI_1
16
17 /* According to the current drm framework sequence, take the encoder of
18 * DSI_1 as master encoder
19 */
20 #define DSI_ENCODER_MASTER DSI_1
21 #define DSI_ENCODER_SLAVE DSI_0
22
23 struct msm_dsi_manager {
24 struct msm_dsi *dsi[DSI_MAX];
25
26 bool is_bonded_dsi;
27 bool is_sync_needed;
28 int master_dsi_link_id;
29 };
30
31 static struct msm_dsi_manager msm_dsim_glb;
32
33 #define IS_BONDED_DSI() (msm_dsim_glb.is_bonded_dsi)
34 #define IS_SYNC_NEEDED() (msm_dsim_glb.is_sync_needed)
35 #define IS_MASTER_DSI_LINK(id) (msm_dsim_glb.master_dsi_link_id == id)
36
dsi_mgr_get_dsi(int id)37 static inline struct msm_dsi *dsi_mgr_get_dsi(int id)
38 {
39 return msm_dsim_glb.dsi[id];
40 }
41
dsi_mgr_get_other_dsi(int id)42 static inline struct msm_dsi *dsi_mgr_get_other_dsi(int id)
43 {
44 return msm_dsim_glb.dsi[(id + 1) % DSI_MAX];
45 }
46
dsi_mgr_parse_of(struct device_node * np,int id)47 static int dsi_mgr_parse_of(struct device_node *np, int id)
48 {
49 struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
50
51 /* We assume 2 dsi nodes have the same information of bonded dsi and
52 * sync-mode, and only one node specifies master in case of bonded mode.
53 */
54 if (!msm_dsim->is_bonded_dsi)
55 msm_dsim->is_bonded_dsi = of_property_read_bool(np, "qcom,dual-dsi-mode");
56
57 if (msm_dsim->is_bonded_dsi) {
58 if (of_property_read_bool(np, "qcom,master-dsi"))
59 msm_dsim->master_dsi_link_id = id;
60 if (!msm_dsim->is_sync_needed)
61 msm_dsim->is_sync_needed = of_property_read_bool(
62 np, "qcom,sync-dual-dsi");
63 }
64
65 return 0;
66 }
67
dsi_mgr_setup_components(int id)68 static int dsi_mgr_setup_components(int id)
69 {
70 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
71 struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
72 struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
73 struct msm_dsi *clk_slave_dsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
74 int ret;
75
76 if (!IS_BONDED_DSI()) {
77 /*
78 * Set the usecase before calling msm_dsi_host_register(), which would
79 * already program the PLL source mux based on a default usecase.
80 */
81 msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE);
82 msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy);
83
84 ret = msm_dsi_host_register(msm_dsi->host);
85 if (ret)
86 return ret;
87 } else if (other_dsi) {
88 struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ?
89 msm_dsi : other_dsi;
90 struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ?
91 other_dsi : msm_dsi;
92
93 /*
94 * PLL0 is to drive both DSI link clocks in bonded DSI mode.
95 *
96 * Set the usecase before calling msm_dsi_host_register(), which would
97 * already program the PLL source mux based on a default usecase.
98 */
99 msm_dsi_phy_set_usecase(clk_master_dsi->phy,
100 MSM_DSI_PHY_MASTER);
101 msm_dsi_phy_set_usecase(clk_slave_dsi->phy,
102 MSM_DSI_PHY_SLAVE);
103 msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy);
104 msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy);
105
106 /* Register slave host first, so that slave DSI device
107 * has a chance to probe, and do not block the master
108 * DSI device's probe.
109 * Also, do not check defer for the slave host,
110 * because only master DSI device adds the panel to global
111 * panel list. The panel's device is the master DSI device.
112 */
113 ret = msm_dsi_host_register(slave_link_dsi->host);
114 if (ret)
115 return ret;
116 ret = msm_dsi_host_register(master_link_dsi->host);
117 if (ret)
118 return ret;
119 }
120
121 return 0;
122 }
123
enable_phy(struct msm_dsi * msm_dsi,struct msm_dsi_phy_shared_timings * shared_timings)124 static int enable_phy(struct msm_dsi *msm_dsi,
125 struct msm_dsi_phy_shared_timings *shared_timings)
126 {
127 struct msm_dsi_phy_clk_request clk_req;
128 bool is_bonded_dsi = IS_BONDED_DSI();
129
130 msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_bonded_dsi);
131
132 return msm_dsi_phy_enable(msm_dsi->phy, &clk_req, shared_timings);
133 }
134
135 static int
dsi_mgr_phy_enable(int id,struct msm_dsi_phy_shared_timings shared_timings[DSI_MAX])136 dsi_mgr_phy_enable(int id,
137 struct msm_dsi_phy_shared_timings shared_timings[DSI_MAX])
138 {
139 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
140 struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
141 struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
142 int ret;
143
144 /* In case of bonded DSI, some registers in PHY1 have been programmed
145 * during PLL0 clock's set_rate. The PHY1 reset called by host1 here
146 * will silently reset those PHY1 registers. Therefore we need to reset
147 * and enable both PHYs before any PLL clock operation.
148 */
149 if (IS_BONDED_DSI() && mdsi && sdsi) {
150 if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
151 msm_dsi_host_reset_phy(mdsi->host);
152 msm_dsi_host_reset_phy(sdsi->host);
153
154 ret = enable_phy(mdsi,
155 &shared_timings[DSI_CLOCK_MASTER]);
156 if (ret)
157 return ret;
158 ret = enable_phy(sdsi,
159 &shared_timings[DSI_CLOCK_SLAVE]);
160 if (ret) {
161 msm_dsi_phy_disable(mdsi->phy);
162 return ret;
163 }
164 }
165 } else {
166 msm_dsi_host_reset_phy(msm_dsi->host);
167 ret = enable_phy(msm_dsi, &shared_timings[id]);
168 if (ret)
169 return ret;
170 }
171
172 msm_dsi->phy_enabled = true;
173
174 return 0;
175 }
176
dsi_mgr_phy_disable(int id)177 static void dsi_mgr_phy_disable(int id)
178 {
179 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
180 struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
181 struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
182
183 /* disable DSI phy
184 * In bonded dsi configuration, the phy should be disabled for the
185 * first controller only when the second controller is disabled.
186 */
187 msm_dsi->phy_enabled = false;
188 if (IS_BONDED_DSI() && mdsi && sdsi) {
189 if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
190 msm_dsi_phy_disable(sdsi->phy);
191 msm_dsi_phy_disable(mdsi->phy);
192 }
193 } else {
194 msm_dsi_phy_disable(msm_dsi->phy);
195 }
196 }
197
198 struct dsi_bridge {
199 struct drm_bridge base;
200 int id;
201 };
202
203 #define to_dsi_bridge(x) container_of(x, struct dsi_bridge, base)
204
dsi_mgr_bridge_get_id(struct drm_bridge * bridge)205 static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge)
206 {
207 struct dsi_bridge *dsi_bridge = to_dsi_bridge(bridge);
208 return dsi_bridge->id;
209 }
210
dsi_mgr_bridge_power_on(struct drm_bridge * bridge)211 static int dsi_mgr_bridge_power_on(struct drm_bridge *bridge)
212 {
213 int id = dsi_mgr_bridge_get_id(bridge);
214 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
215 struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
216 struct mipi_dsi_host *host = msm_dsi->host;
217 struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX];
218 bool is_bonded_dsi = IS_BONDED_DSI();
219 int ret;
220
221 DBG("id=%d", id);
222
223 ret = dsi_mgr_phy_enable(id, phy_shared_timings);
224 if (ret)
225 goto phy_en_fail;
226
227 ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_bonded_dsi, msm_dsi->phy);
228 if (ret) {
229 pr_err("%s: power on host %d failed, %d\n", __func__, id, ret);
230 goto host_on_fail;
231 }
232
233 if (is_bonded_dsi && msm_dsi1) {
234 ret = msm_dsi_host_power_on(msm_dsi1->host,
235 &phy_shared_timings[DSI_1], is_bonded_dsi, msm_dsi1->phy);
236 if (ret) {
237 pr_err("%s: power on host1 failed, %d\n",
238 __func__, ret);
239 goto host1_on_fail;
240 }
241 }
242
243 /*
244 * Enable before preparing the panel, disable after unpreparing, so
245 * that the panel can communicate over the DSI link.
246 */
247 msm_dsi_host_enable_irq(host);
248 if (is_bonded_dsi && msm_dsi1)
249 msm_dsi_host_enable_irq(msm_dsi1->host);
250
251 return 0;
252
253 host1_on_fail:
254 msm_dsi_host_power_off(host);
255 host_on_fail:
256 dsi_mgr_phy_disable(id);
257 phy_en_fail:
258 return ret;
259 }
260
dsi_mgr_bridge_power_off(struct drm_bridge * bridge)261 static void dsi_mgr_bridge_power_off(struct drm_bridge *bridge)
262 {
263 int id = dsi_mgr_bridge_get_id(bridge);
264 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
265 struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
266 struct mipi_dsi_host *host = msm_dsi->host;
267 bool is_bonded_dsi = IS_BONDED_DSI();
268
269 msm_dsi_host_disable_irq(host);
270 if (is_bonded_dsi && msm_dsi1) {
271 msm_dsi_host_disable_irq(msm_dsi1->host);
272 msm_dsi_host_power_off(msm_dsi1->host);
273 }
274 msm_dsi_host_power_off(host);
275 dsi_mgr_phy_disable(id);
276 }
277
dsi_mgr_bridge_pre_enable(struct drm_bridge * bridge)278 static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
279 {
280 int id = dsi_mgr_bridge_get_id(bridge);
281 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
282 struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
283 struct mipi_dsi_host *host = msm_dsi->host;
284 bool is_bonded_dsi = IS_BONDED_DSI();
285 int ret;
286
287 DBG("id=%d", id);
288
289 /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
290 if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
291 return;
292
293 ret = dsi_mgr_bridge_power_on(bridge);
294 if (ret) {
295 dev_err(&msm_dsi->pdev->dev, "Power on failed: %d\n", ret);
296 return;
297 }
298
299 ret = msm_dsi_host_enable(host);
300 if (ret) {
301 pr_err("%s: enable host %d failed, %d\n", __func__, id, ret);
302 goto host_en_fail;
303 }
304
305 if (is_bonded_dsi && msm_dsi1) {
306 ret = msm_dsi_host_enable(msm_dsi1->host);
307 if (ret) {
308 pr_err("%s: enable host1 failed, %d\n", __func__, ret);
309 goto host1_en_fail;
310 }
311 }
312
313 return;
314
315 host1_en_fail:
316 msm_dsi_host_disable(host);
317 host_en_fail:
318 dsi_mgr_bridge_power_off(bridge);
319 }
320
msm_dsi_manager_tpg_enable(void)321 void msm_dsi_manager_tpg_enable(void)
322 {
323 struct msm_dsi *m_dsi = dsi_mgr_get_dsi(DSI_0);
324 struct msm_dsi *s_dsi = dsi_mgr_get_dsi(DSI_1);
325
326 /* if dual dsi, trigger tpg on master first then slave */
327 if (m_dsi) {
328 msm_dsi_host_test_pattern_en(m_dsi->host);
329 if (IS_BONDED_DSI() && s_dsi)
330 msm_dsi_host_test_pattern_en(s_dsi->host);
331 }
332 }
333
dsi_mgr_bridge_post_disable(struct drm_bridge * bridge)334 static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
335 {
336 int id = dsi_mgr_bridge_get_id(bridge);
337 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
338 struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
339 struct mipi_dsi_host *host = msm_dsi->host;
340 bool is_bonded_dsi = IS_BONDED_DSI();
341 int ret;
342
343 DBG("id=%d", id);
344
345 /*
346 * Do nothing with the host if it is slave-DSI in case of bonded DSI.
347 * It is safe to call dsi_mgr_phy_disable() here because a single PHY
348 * won't be diabled until both PHYs request disable.
349 */
350 if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
351 goto disable_phy;
352
353 ret = msm_dsi_host_disable(host);
354 if (ret)
355 pr_err("%s: host %d disable failed, %d\n", __func__, id, ret);
356
357 if (is_bonded_dsi && msm_dsi1) {
358 ret = msm_dsi_host_disable(msm_dsi1->host);
359 if (ret)
360 pr_err("%s: host1 disable failed, %d\n", __func__, ret);
361 }
362
363 msm_dsi_host_disable_irq(host);
364 if (is_bonded_dsi && msm_dsi1)
365 msm_dsi_host_disable_irq(msm_dsi1->host);
366
367 /* Save PHY status if it is a clock source */
368 msm_dsi_phy_pll_save_state(msm_dsi->phy);
369
370 ret = msm_dsi_host_power_off(host);
371 if (ret)
372 pr_err("%s: host %d power off failed,%d\n", __func__, id, ret);
373
374 if (is_bonded_dsi && msm_dsi1) {
375 ret = msm_dsi_host_power_off(msm_dsi1->host);
376 if (ret)
377 pr_err("%s: host1 power off failed, %d\n",
378 __func__, ret);
379 }
380
381 disable_phy:
382 dsi_mgr_phy_disable(id);
383 }
384
dsi_mgr_bridge_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted_mode)385 static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
386 const struct drm_display_mode *mode,
387 const struct drm_display_mode *adjusted_mode)
388 {
389 int id = dsi_mgr_bridge_get_id(bridge);
390 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
391 struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
392 struct mipi_dsi_host *host = msm_dsi->host;
393 bool is_bonded_dsi = IS_BONDED_DSI();
394
395 DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
396
397 if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
398 return;
399
400 msm_dsi_host_set_display_mode(host, adjusted_mode);
401 if (is_bonded_dsi && other_dsi)
402 msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
403 }
404
dsi_mgr_bridge_mode_valid(struct drm_bridge * bridge,const struct drm_display_info * info,const struct drm_display_mode * mode)405 static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge *bridge,
406 const struct drm_display_info *info,
407 const struct drm_display_mode *mode)
408 {
409 int id = dsi_mgr_bridge_get_id(bridge);
410 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
411 struct mipi_dsi_host *host = msm_dsi->host;
412 struct platform_device *pdev = msm_dsi->pdev;
413 struct dev_pm_opp *opp;
414 unsigned long byte_clk_rate;
415
416 byte_clk_rate = dsi_byte_clk_get_rate(host, IS_BONDED_DSI(), mode);
417
418 opp = dev_pm_opp_find_freq_ceil(&pdev->dev, &byte_clk_rate);
419 if (!IS_ERR(opp)) {
420 dev_pm_opp_put(opp);
421 } else if (PTR_ERR(opp) == -ERANGE) {
422 /*
423 * An empty table is created by devm_pm_opp_set_clkname() even
424 * if there is none. Thus find_freq_ceil will still return
425 * -ERANGE in such case.
426 */
427 if (dev_pm_opp_get_opp_count(&pdev->dev) != 0)
428 return MODE_CLOCK_RANGE;
429 } else {
430 return MODE_ERROR;
431 }
432
433 return msm_dsi_host_check_dsc(host, mode);
434 }
435
dsi_mgr_bridge_attach(struct drm_bridge * bridge,enum drm_bridge_attach_flags flags)436 static int dsi_mgr_bridge_attach(struct drm_bridge *bridge,
437 enum drm_bridge_attach_flags flags)
438 {
439 int id = dsi_mgr_bridge_get_id(bridge);
440 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
441
442 return drm_bridge_attach(bridge->encoder, msm_dsi->next_bridge,
443 bridge, flags);
444 }
445
446 static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = {
447 .attach = dsi_mgr_bridge_attach,
448 .pre_enable = dsi_mgr_bridge_pre_enable,
449 .post_disable = dsi_mgr_bridge_post_disable,
450 .mode_set = dsi_mgr_bridge_mode_set,
451 .mode_valid = dsi_mgr_bridge_mode_valid,
452 };
453
454 /* initialize bridge */
msm_dsi_manager_connector_init(struct msm_dsi * msm_dsi,struct drm_encoder * encoder)455 int msm_dsi_manager_connector_init(struct msm_dsi *msm_dsi,
456 struct drm_encoder *encoder)
457 {
458 struct drm_device *dev = msm_dsi->dev;
459 struct drm_bridge *bridge;
460 struct dsi_bridge *dsi_bridge;
461 struct drm_connector *connector;
462 int ret;
463
464 dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
465 sizeof(*dsi_bridge), GFP_KERNEL);
466 if (!dsi_bridge)
467 return -ENOMEM;
468
469 dsi_bridge->id = msm_dsi->id;
470
471 bridge = &dsi_bridge->base;
472 bridge->funcs = &dsi_mgr_bridge_funcs;
473
474 ret = devm_drm_bridge_add(msm_dsi->dev->dev, bridge);
475 if (ret)
476 return ret;
477
478 ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
479 if (ret)
480 return ret;
481
482 connector = drm_bridge_connector_init(dev, encoder);
483 if (IS_ERR(connector)) {
484 DRM_ERROR("Unable to create bridge connector\n");
485 return PTR_ERR(connector);
486 }
487
488 ret = drm_connector_attach_encoder(connector, encoder);
489 if (ret < 0)
490 return ret;
491
492 return 0;
493 }
494
msm_dsi_manager_cmd_xfer(int id,const struct mipi_dsi_msg * msg)495 int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg)
496 {
497 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
498 struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
499 struct mipi_dsi_host *host = msm_dsi->host;
500 bool is_read = (msg->rx_buf && msg->rx_len);
501 bool need_sync = (IS_SYNC_NEEDED() && !is_read);
502 int ret;
503
504 if (!msg->tx_buf || !msg->tx_len)
505 return 0;
506
507 /* In bonded master case, panel requires the same commands sent to
508 * both DSI links. Host issues the command trigger to both links
509 * when DSI_1 calls the cmd transfer function, no matter it happens
510 * before or after DSI_0 cmd transfer.
511 */
512 if (need_sync && (id == DSI_0))
513 return is_read ? msg->rx_len : msg->tx_len;
514
515 if (need_sync && msm_dsi0) {
516 ret = msm_dsi_host_xfer_prepare(msm_dsi0->host, msg);
517 if (ret) {
518 pr_err("%s: failed to prepare non-trigger host, %d\n",
519 __func__, ret);
520 return ret;
521 }
522 }
523 ret = msm_dsi_host_xfer_prepare(host, msg);
524 if (ret) {
525 pr_err("%s: failed to prepare host, %d\n", __func__, ret);
526 goto restore_host0;
527 }
528
529 ret = is_read ? msm_dsi_host_cmd_rx(host, msg) :
530 msm_dsi_host_cmd_tx(host, msg);
531
532 msm_dsi_host_xfer_restore(host, msg);
533
534 restore_host0:
535 if (need_sync && msm_dsi0)
536 msm_dsi_host_xfer_restore(msm_dsi0->host, msg);
537
538 return ret;
539 }
540
msm_dsi_manager_cmd_xfer_trigger(int id,u32 dma_base,u32 len)541 bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
542 {
543 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
544 struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
545 struct mipi_dsi_host *host = msm_dsi->host;
546
547 if (IS_SYNC_NEEDED() && (id == DSI_0))
548 return false;
549
550 if (IS_SYNC_NEEDED() && msm_dsi0)
551 msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, dma_base, len);
552
553 msm_dsi_host_cmd_xfer_commit(host, dma_base, len);
554
555 return true;
556 }
557
msm_dsi_manager_register(struct msm_dsi * msm_dsi)558 int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
559 {
560 struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
561 int id = msm_dsi->id;
562 int ret;
563
564 if (id >= DSI_MAX) {
565 pr_err("%s: invalid id %d\n", __func__, id);
566 return -EINVAL;
567 }
568
569 if (msm_dsim->dsi[id]) {
570 pr_err("%s: dsi%d already registered\n", __func__, id);
571 return -EBUSY;
572 }
573
574 msm_dsim->dsi[id] = msm_dsi;
575
576 ret = dsi_mgr_parse_of(msm_dsi->pdev->dev.of_node, id);
577 if (ret) {
578 pr_err("%s: failed to parse OF DSI info\n", __func__);
579 goto fail;
580 }
581
582 ret = dsi_mgr_setup_components(id);
583 if (ret) {
584 pr_err("%s: failed to register mipi dsi host for DSI %d: %d\n",
585 __func__, id, ret);
586 goto fail;
587 }
588
589 return 0;
590
591 fail:
592 msm_dsim->dsi[id] = NULL;
593 return ret;
594 }
595
msm_dsi_manager_unregister(struct msm_dsi * msm_dsi)596 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi)
597 {
598 struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
599
600 if (msm_dsi->host)
601 msm_dsi_host_unregister(msm_dsi->host);
602
603 if (msm_dsi->id >= 0)
604 msm_dsim->dsi[msm_dsi->id] = NULL;
605 }
606
msm_dsi_is_bonded_dsi(struct msm_dsi * msm_dsi)607 bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi)
608 {
609 return IS_BONDED_DSI();
610 }
611
msm_dsi_is_master_dsi(struct msm_dsi * msm_dsi)612 bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi)
613 {
614 return IS_MASTER_DSI_LINK(msm_dsi->id);
615 }
616
msm_dsi_get_te_source(struct msm_dsi * msm_dsi)617 const char *msm_dsi_get_te_source(struct msm_dsi *msm_dsi)
618 {
619 return msm_dsi->te_source;
620 }
621