1 /* 2 * Copyright (c) 2015, The Linux Foundation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 and 6 * only version 2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14 #include "msm_kms.h" 15 #include "dsi.h" 16 17 struct msm_dsi_manager { 18 struct msm_dsi *dsi[DSI_MAX]; 19 20 bool is_dual_panel; 21 bool is_sync_needed; 22 int master_panel_id; 23 }; 24 25 static struct msm_dsi_manager msm_dsim_glb; 26 27 #define IS_DUAL_PANEL() (msm_dsim_glb.is_dual_panel) 28 #define IS_SYNC_NEEDED() (msm_dsim_glb.is_sync_needed) 29 #define IS_MASTER_PANEL(id) (msm_dsim_glb.master_panel_id == id) 30 31 static inline struct msm_dsi *dsi_mgr_get_dsi(int id) 32 { 33 return msm_dsim_glb.dsi[id]; 34 } 35 36 static inline struct msm_dsi *dsi_mgr_get_other_dsi(int id) 37 { 38 return msm_dsim_glb.dsi[(id + 1) % DSI_MAX]; 39 } 40 41 static int dsi_mgr_parse_dual_panel(struct device_node *np, int id) 42 { 43 struct msm_dsi_manager *msm_dsim = &msm_dsim_glb; 44 45 /* We assume 2 dsi nodes have the same information of dual-panel and 46 * sync-mode, and only one node specifies master in case of dual mode. 47 */ 48 if (!msm_dsim->is_dual_panel) 49 msm_dsim->is_dual_panel = of_property_read_bool( 50 np, "qcom,dual-panel-mode"); 51 52 if (msm_dsim->is_dual_panel) { 53 if (of_property_read_bool(np, "qcom,master-panel")) 54 msm_dsim->master_panel_id = id; 55 if (!msm_dsim->is_sync_needed) 56 msm_dsim->is_sync_needed = of_property_read_bool( 57 np, "qcom,sync-dual-panel"); 58 } 59 60 return 0; 61 } 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 110 struct dsi_connector { 111 struct drm_connector base; 112 int id; 113 }; 114 115 struct dsi_bridge { 116 struct drm_bridge base; 117 int id; 118 }; 119 120 #define to_dsi_connector(x) container_of(x, struct dsi_connector, base) 121 #define to_dsi_bridge(x) container_of(x, struct dsi_bridge, base) 122 123 static inline int dsi_mgr_connector_get_id(struct drm_connector *connector) 124 { 125 struct dsi_connector *dsi_connector = to_dsi_connector(connector); 126 return dsi_connector->id; 127 } 128 129 static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge) 130 { 131 struct dsi_bridge *dsi_bridge = to_dsi_bridge(bridge); 132 return dsi_bridge->id; 133 } 134 135 static enum drm_connector_status dsi_mgr_connector_detect( 136 struct drm_connector *connector, bool force) 137 { 138 int id = dsi_mgr_connector_get_id(connector); 139 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 140 struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); 141 struct msm_drm_private *priv = connector->dev->dev_private; 142 struct msm_kms *kms = priv->kms; 143 144 DBG("id=%d", id); 145 if (!msm_dsi->panel) { 146 msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host, 147 &msm_dsi->panel_flags); 148 149 /* There is only 1 panel in the global panel list 150 * for dual panel mode. Therefore slave dsi should get 151 * the drm_panel instance from master dsi, and 152 * keep using the panel flags got from the current DSI link. 153 */ 154 if (!msm_dsi->panel && IS_DUAL_PANEL() && 155 !IS_MASTER_PANEL(id) && other_dsi) 156 msm_dsi->panel = msm_dsi_host_get_panel( 157 other_dsi->host, NULL); 158 159 if (msm_dsi->panel && IS_DUAL_PANEL()) 160 drm_object_attach_property(&connector->base, 161 connector->dev->mode_config.tile_property, 0); 162 163 /* Set split display info to kms once dual panel is connected 164 * to both hosts 165 */ 166 if (msm_dsi->panel && IS_DUAL_PANEL() && 167 other_dsi && other_dsi->panel) { 168 bool cmd_mode = !(msm_dsi->panel_flags & 169 MIPI_DSI_MODE_VIDEO); 170 struct drm_encoder *encoder = msm_dsi_get_encoder( 171 dsi_mgr_get_dsi(DSI_ENCODER_MASTER)); 172 struct drm_encoder *slave_enc = msm_dsi_get_encoder( 173 dsi_mgr_get_dsi(DSI_ENCODER_SLAVE)); 174 175 if (kms->funcs->set_split_display) 176 kms->funcs->set_split_display(kms, encoder, 177 slave_enc, cmd_mode); 178 else 179 pr_err("mdp does not support dual panel\n"); 180 } 181 } 182 183 return msm_dsi->panel ? connector_status_connected : 184 connector_status_disconnected; 185 } 186 187 static void dsi_mgr_connector_destroy(struct drm_connector *connector) 188 { 189 DBG(""); 190 drm_connector_unregister(connector); 191 drm_connector_cleanup(connector); 192 } 193 194 static void dsi_dual_connector_fix_modes(struct drm_connector *connector) 195 { 196 struct drm_display_mode *mode, *m; 197 198 /* Only support left-right mode */ 199 list_for_each_entry_safe(mode, m, &connector->probed_modes, head) { 200 mode->clock >>= 1; 201 mode->hdisplay >>= 1; 202 mode->hsync_start >>= 1; 203 mode->hsync_end >>= 1; 204 mode->htotal >>= 1; 205 drm_mode_set_name(mode); 206 } 207 } 208 209 static int dsi_dual_connector_tile_init( 210 struct drm_connector *connector, int id) 211 { 212 struct drm_display_mode *mode; 213 /* Fake topology id */ 214 char topo_id[8] = {'M', 'S', 'M', 'D', 'U', 'D', 'S', 'I'}; 215 216 if (connector->tile_group) { 217 DBG("Tile property has been initialized"); 218 return 0; 219 } 220 221 /* Use the first mode only for now */ 222 mode = list_first_entry(&connector->probed_modes, 223 struct drm_display_mode, 224 head); 225 if (!mode) 226 return -EINVAL; 227 228 connector->tile_group = drm_mode_get_tile_group( 229 connector->dev, topo_id); 230 if (!connector->tile_group) 231 connector->tile_group = drm_mode_create_tile_group( 232 connector->dev, topo_id); 233 if (!connector->tile_group) { 234 pr_err("%s: failed to create tile group\n", __func__); 235 return -ENOMEM; 236 } 237 238 connector->has_tile = true; 239 connector->tile_is_single_monitor = true; 240 241 /* mode has been fixed */ 242 connector->tile_h_size = mode->hdisplay; 243 connector->tile_v_size = mode->vdisplay; 244 245 /* Only support left-right mode */ 246 connector->num_h_tile = 2; 247 connector->num_v_tile = 1; 248 249 connector->tile_v_loc = 0; 250 connector->tile_h_loc = (id == DSI_RIGHT) ? 1 : 0; 251 252 return 0; 253 } 254 255 static int dsi_mgr_connector_get_modes(struct drm_connector *connector) 256 { 257 int id = dsi_mgr_connector_get_id(connector); 258 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 259 struct drm_panel *panel = msm_dsi->panel; 260 int ret, num; 261 262 if (!panel) 263 return 0; 264 265 /* Since we have 2 connectors, but only 1 drm_panel in dual DSI mode, 266 * panel should not attach to any connector. 267 * Only temporarily attach panel to the current connector here, 268 * to let panel set mode to this connector. 269 */ 270 drm_panel_attach(panel, connector); 271 num = drm_panel_get_modes(panel); 272 drm_panel_detach(panel); 273 if (!num) 274 return 0; 275 276 if (IS_DUAL_PANEL()) { 277 /* report half resolution to user */ 278 dsi_dual_connector_fix_modes(connector); 279 ret = dsi_dual_connector_tile_init(connector, id); 280 if (ret) 281 return ret; 282 ret = drm_mode_connector_set_tile_property(connector); 283 if (ret) { 284 pr_err("%s: set tile property failed, %d\n", 285 __func__, ret); 286 return ret; 287 } 288 } 289 290 return num; 291 } 292 293 static int dsi_mgr_connector_mode_valid(struct drm_connector *connector, 294 struct drm_display_mode *mode) 295 { 296 int id = dsi_mgr_connector_get_id(connector); 297 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 298 struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi); 299 struct msm_drm_private *priv = connector->dev->dev_private; 300 struct msm_kms *kms = priv->kms; 301 long actual, requested; 302 303 DBG(""); 304 requested = 1000 * mode->clock; 305 actual = kms->funcs->round_pixclk(kms, requested, encoder); 306 307 DBG("requested=%ld, actual=%ld", requested, actual); 308 if (actual != requested) 309 return MODE_CLOCK_RANGE; 310 311 return MODE_OK; 312 } 313 314 static struct drm_encoder * 315 dsi_mgr_connector_best_encoder(struct drm_connector *connector) 316 { 317 int id = dsi_mgr_connector_get_id(connector); 318 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 319 320 DBG(""); 321 return msm_dsi_get_encoder(msm_dsi); 322 } 323 324 static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) 325 { 326 int id = dsi_mgr_bridge_get_id(bridge); 327 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 328 struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); 329 struct mipi_dsi_host *host = msm_dsi->host; 330 struct drm_panel *panel = msm_dsi->panel; 331 bool is_dual_panel = IS_DUAL_PANEL(); 332 int ret; 333 334 DBG("id=%d", id); 335 if (!panel || (is_dual_panel && (DSI_1 == id))) 336 return; 337 338 ret = msm_dsi_host_power_on(host); 339 if (ret) { 340 pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); 341 goto host_on_fail; 342 } 343 344 if (is_dual_panel && msm_dsi1) { 345 ret = msm_dsi_host_power_on(msm_dsi1->host); 346 if (ret) { 347 pr_err("%s: power on host1 failed, %d\n", 348 __func__, ret); 349 goto host1_on_fail; 350 } 351 } 352 353 /* Always call panel functions once, because even for dual panels, 354 * there is only one drm_panel instance. 355 */ 356 ret = drm_panel_prepare(panel); 357 if (ret) { 358 pr_err("%s: prepare panel %d failed, %d\n", __func__, id, ret); 359 goto panel_prep_fail; 360 } 361 362 ret = msm_dsi_host_enable(host); 363 if (ret) { 364 pr_err("%s: enable host %d failed, %d\n", __func__, id, ret); 365 goto host_en_fail; 366 } 367 368 if (is_dual_panel && msm_dsi1) { 369 ret = msm_dsi_host_enable(msm_dsi1->host); 370 if (ret) { 371 pr_err("%s: enable host1 failed, %d\n", __func__, ret); 372 goto host1_en_fail; 373 } 374 } 375 376 ret = drm_panel_enable(panel); 377 if (ret) { 378 pr_err("%s: enable panel %d failed, %d\n", __func__, id, ret); 379 goto panel_en_fail; 380 } 381 382 return; 383 384 panel_en_fail: 385 if (is_dual_panel && msm_dsi1) 386 msm_dsi_host_disable(msm_dsi1->host); 387 host1_en_fail: 388 msm_dsi_host_disable(host); 389 host_en_fail: 390 drm_panel_unprepare(panel); 391 panel_prep_fail: 392 if (is_dual_panel && msm_dsi1) 393 msm_dsi_host_power_off(msm_dsi1->host); 394 host1_on_fail: 395 msm_dsi_host_power_off(host); 396 host_on_fail: 397 return; 398 } 399 400 static void dsi_mgr_bridge_enable(struct drm_bridge *bridge) 401 { 402 DBG(""); 403 } 404 405 static void dsi_mgr_bridge_disable(struct drm_bridge *bridge) 406 { 407 DBG(""); 408 } 409 410 static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge) 411 { 412 int id = dsi_mgr_bridge_get_id(bridge); 413 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 414 struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1); 415 struct mipi_dsi_host *host = msm_dsi->host; 416 struct drm_panel *panel = msm_dsi->panel; 417 bool is_dual_panel = IS_DUAL_PANEL(); 418 int ret; 419 420 DBG("id=%d", id); 421 422 if (!panel || (is_dual_panel && (DSI_1 == id))) 423 return; 424 425 ret = drm_panel_disable(panel); 426 if (ret) 427 pr_err("%s: Panel %d OFF failed, %d\n", __func__, id, ret); 428 429 ret = msm_dsi_host_disable(host); 430 if (ret) 431 pr_err("%s: host %d disable failed, %d\n", __func__, id, ret); 432 433 if (is_dual_panel && msm_dsi1) { 434 ret = msm_dsi_host_disable(msm_dsi1->host); 435 if (ret) 436 pr_err("%s: host1 disable failed, %d\n", __func__, ret); 437 } 438 439 ret = drm_panel_unprepare(panel); 440 if (ret) 441 pr_err("%s: Panel %d unprepare failed,%d\n", __func__, id, ret); 442 443 ret = msm_dsi_host_power_off(host); 444 if (ret) 445 pr_err("%s: host %d power off failed,%d\n", __func__, id, ret); 446 447 if (is_dual_panel && msm_dsi1) { 448 ret = msm_dsi_host_power_off(msm_dsi1->host); 449 if (ret) 450 pr_err("%s: host1 power off failed, %d\n", 451 __func__, ret); 452 } 453 } 454 455 static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge, 456 struct drm_display_mode *mode, 457 struct drm_display_mode *adjusted_mode) 458 { 459 int id = dsi_mgr_bridge_get_id(bridge); 460 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 461 struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id); 462 struct mipi_dsi_host *host = msm_dsi->host; 463 bool is_dual_panel = IS_DUAL_PANEL(); 464 465 DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", 466 mode->base.id, mode->name, 467 mode->vrefresh, mode->clock, 468 mode->hdisplay, mode->hsync_start, 469 mode->hsync_end, mode->htotal, 470 mode->vdisplay, mode->vsync_start, 471 mode->vsync_end, mode->vtotal, 472 mode->type, mode->flags); 473 474 if (is_dual_panel && (DSI_1 == id)) 475 return; 476 477 msm_dsi_host_set_display_mode(host, adjusted_mode); 478 if (is_dual_panel && other_dsi) 479 msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode); 480 } 481 482 static const struct drm_connector_funcs dsi_mgr_connector_funcs = { 483 .dpms = drm_atomic_helper_connector_dpms, 484 .detect = dsi_mgr_connector_detect, 485 .fill_modes = drm_helper_probe_single_connector_modes, 486 .destroy = dsi_mgr_connector_destroy, 487 .reset = drm_atomic_helper_connector_reset, 488 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 489 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 490 }; 491 492 static const struct drm_connector_helper_funcs dsi_mgr_conn_helper_funcs = { 493 .get_modes = dsi_mgr_connector_get_modes, 494 .mode_valid = dsi_mgr_connector_mode_valid, 495 .best_encoder = dsi_mgr_connector_best_encoder, 496 }; 497 498 static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = { 499 .pre_enable = dsi_mgr_bridge_pre_enable, 500 .enable = dsi_mgr_bridge_enable, 501 .disable = dsi_mgr_bridge_disable, 502 .post_disable = dsi_mgr_bridge_post_disable, 503 .mode_set = dsi_mgr_bridge_mode_set, 504 }; 505 506 /* initialize connector */ 507 struct drm_connector *msm_dsi_manager_connector_init(u8 id) 508 { 509 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 510 struct drm_connector *connector = NULL; 511 struct dsi_connector *dsi_connector; 512 int ret, i; 513 514 dsi_connector = devm_kzalloc(msm_dsi->dev->dev, 515 sizeof(*dsi_connector), GFP_KERNEL); 516 if (!dsi_connector) { 517 ret = -ENOMEM; 518 goto fail; 519 } 520 521 dsi_connector->id = id; 522 523 connector = &dsi_connector->base; 524 525 ret = drm_connector_init(msm_dsi->dev, connector, 526 &dsi_mgr_connector_funcs, DRM_MODE_CONNECTOR_DSI); 527 if (ret) 528 goto fail; 529 530 drm_connector_helper_add(connector, &dsi_mgr_conn_helper_funcs); 531 532 /* Enable HPD to let hpd event is handled 533 * when panel is attached to the host. 534 */ 535 connector->polled = DRM_CONNECTOR_POLL_HPD; 536 537 /* Display driver doesn't support interlace now. */ 538 connector->interlace_allowed = 0; 539 connector->doublescan_allowed = 0; 540 541 ret = drm_connector_register(connector); 542 if (ret) 543 goto fail; 544 545 for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) 546 drm_mode_connector_attach_encoder(connector, 547 msm_dsi->encoders[i]); 548 549 return connector; 550 551 fail: 552 if (connector) 553 dsi_mgr_connector_destroy(connector); 554 555 return ERR_PTR(ret); 556 } 557 558 /* initialize bridge */ 559 struct drm_bridge *msm_dsi_manager_bridge_init(u8 id) 560 { 561 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 562 struct drm_bridge *bridge = NULL; 563 struct dsi_bridge *dsi_bridge; 564 int ret; 565 566 dsi_bridge = devm_kzalloc(msm_dsi->dev->dev, 567 sizeof(*dsi_bridge), GFP_KERNEL); 568 if (!dsi_bridge) { 569 ret = -ENOMEM; 570 goto fail; 571 } 572 573 dsi_bridge->id = id; 574 575 bridge = &dsi_bridge->base; 576 bridge->funcs = &dsi_mgr_bridge_funcs; 577 578 ret = drm_bridge_attach(msm_dsi->dev, bridge); 579 if (ret) 580 goto fail; 581 582 return bridge; 583 584 fail: 585 if (bridge) 586 msm_dsi_manager_bridge_destroy(bridge); 587 588 return ERR_PTR(ret); 589 } 590 591 void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge) 592 { 593 } 594 595 int msm_dsi_manager_phy_enable(int id, 596 const unsigned long bit_rate, const unsigned long esc_rate, 597 u32 *clk_pre, u32 *clk_post) 598 { 599 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 600 struct msm_dsi_phy *phy = msm_dsi->phy; 601 int ret; 602 603 ret = msm_dsi_phy_enable(phy, IS_DUAL_PANEL(), bit_rate, esc_rate); 604 if (ret) 605 return ret; 606 607 msm_dsi->phy_enabled = true; 608 msm_dsi_phy_get_clk_pre_post(phy, clk_pre, clk_post); 609 610 return 0; 611 } 612 613 void msm_dsi_manager_phy_disable(int id) 614 { 615 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 616 struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER); 617 struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE); 618 struct msm_dsi_phy *phy = msm_dsi->phy; 619 620 /* disable DSI phy 621 * In dual-dsi configuration, the phy should be disabled for the 622 * first controller only when the second controller is disabled. 623 */ 624 msm_dsi->phy_enabled = false; 625 if (IS_DUAL_PANEL() && mdsi && sdsi) { 626 if (!mdsi->phy_enabled && !sdsi->phy_enabled) { 627 msm_dsi_phy_disable(sdsi->phy); 628 msm_dsi_phy_disable(mdsi->phy); 629 } 630 } else { 631 msm_dsi_phy_disable(phy); 632 } 633 } 634 635 int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg) 636 { 637 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 638 struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0); 639 struct mipi_dsi_host *host = msm_dsi->host; 640 bool is_read = (msg->rx_buf && msg->rx_len); 641 bool need_sync = (IS_SYNC_NEEDED() && !is_read); 642 int ret; 643 644 if (!msg->tx_buf || !msg->tx_len) 645 return 0; 646 647 /* In dual master case, panel requires the same commands sent to 648 * both DSI links. Host issues the command trigger to both links 649 * when DSI_1 calls the cmd transfer function, no matter it happens 650 * before or after DSI_0 cmd transfer. 651 */ 652 if (need_sync && (id == DSI_0)) 653 return is_read ? msg->rx_len : msg->tx_len; 654 655 if (need_sync && msm_dsi0) { 656 ret = msm_dsi_host_xfer_prepare(msm_dsi0->host, msg); 657 if (ret) { 658 pr_err("%s: failed to prepare non-trigger host, %d\n", 659 __func__, ret); 660 return ret; 661 } 662 } 663 ret = msm_dsi_host_xfer_prepare(host, msg); 664 if (ret) { 665 pr_err("%s: failed to prepare host, %d\n", __func__, ret); 666 goto restore_host0; 667 } 668 669 ret = is_read ? msm_dsi_host_cmd_rx(host, msg) : 670 msm_dsi_host_cmd_tx(host, msg); 671 672 msm_dsi_host_xfer_restore(host, msg); 673 674 restore_host0: 675 if (need_sync && msm_dsi0) 676 msm_dsi_host_xfer_restore(msm_dsi0->host, msg); 677 678 return ret; 679 } 680 681 bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len) 682 { 683 struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); 684 struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0); 685 struct mipi_dsi_host *host = msm_dsi->host; 686 687 if (IS_SYNC_NEEDED() && (id == DSI_0)) 688 return false; 689 690 if (IS_SYNC_NEEDED() && msm_dsi0) 691 msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, iova, len); 692 693 msm_dsi_host_cmd_xfer_commit(host, iova, len); 694 695 return true; 696 } 697 698 int msm_dsi_manager_register(struct msm_dsi *msm_dsi) 699 { 700 struct msm_dsi_manager *msm_dsim = &msm_dsim_glb; 701 int id = msm_dsi->id; 702 int ret; 703 704 if (id > DSI_MAX) { 705 pr_err("%s: invalid id %d\n", __func__, id); 706 return -EINVAL; 707 } 708 709 if (msm_dsim->dsi[id]) { 710 pr_err("%s: dsi%d already registered\n", __func__, id); 711 return -EBUSY; 712 } 713 714 msm_dsim->dsi[id] = msm_dsi; 715 716 ret = dsi_mgr_parse_dual_panel(msm_dsi->pdev->dev.of_node, id); 717 if (ret) { 718 pr_err("%s: failed to parse dual panel info\n", __func__); 719 goto fail; 720 } 721 722 ret = dsi_mgr_host_register(id); 723 if (ret) { 724 pr_err("%s: failed to register mipi dsi host for DSI %d\n", 725 __func__, id); 726 goto fail; 727 } 728 729 return 0; 730 731 fail: 732 msm_dsim->dsi[id] = NULL; 733 return ret; 734 } 735 736 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi) 737 { 738 struct msm_dsi_manager *msm_dsim = &msm_dsim_glb; 739 740 if (msm_dsi->host) 741 msm_dsi_host_unregister(msm_dsi->host); 742 msm_dsim->dsi[msm_dsi->id] = NULL; 743 } 744 745