linux/drivers/gpu/drm/msm/dsi/dsi_manager.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
   4 */
   5
   6#include "msm_kms.h"
   7#include "dsi.h"
   8
   9#define DSI_CLOCK_MASTER        DSI_0
  10#define DSI_CLOCK_SLAVE         DSI_1
  11
  12#define DSI_LEFT                DSI_0
  13#define DSI_RIGHT               DSI_1
  14
  15/* According to the current drm framework sequence, take the encoder of
  16 * DSI_1 as master encoder
  17 */
  18#define DSI_ENCODER_MASTER      DSI_1
  19#define DSI_ENCODER_SLAVE       DSI_0
  20
  21struct msm_dsi_manager {
  22        struct msm_dsi *dsi[DSI_MAX];
  23
  24        bool is_bonded_dsi;
  25        bool is_sync_needed;
  26        int master_dsi_link_id;
  27};
  28
  29static struct msm_dsi_manager msm_dsim_glb;
  30
  31#define IS_BONDED_DSI()         (msm_dsim_glb.is_bonded_dsi)
  32#define IS_SYNC_NEEDED()        (msm_dsim_glb.is_sync_needed)
  33#define IS_MASTER_DSI_LINK(id)  (msm_dsim_glb.master_dsi_link_id == id)
  34
  35static inline struct msm_dsi *dsi_mgr_get_dsi(int id)
  36{
  37        return msm_dsim_glb.dsi[id];
  38}
  39
  40static inline struct msm_dsi *dsi_mgr_get_other_dsi(int id)
  41{
  42        return msm_dsim_glb.dsi[(id + 1) % DSI_MAX];
  43}
  44
  45static int dsi_mgr_parse_of(struct device_node *np, int id)
  46{
  47        struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
  48
  49        /* We assume 2 dsi nodes have the same information of bonded dsi and
  50         * sync-mode, and only one node specifies master in case of bonded mode.
  51         */
  52        if (!msm_dsim->is_bonded_dsi)
  53                msm_dsim->is_bonded_dsi = of_property_read_bool(np, "qcom,dual-dsi-mode");
  54
  55        if (msm_dsim->is_bonded_dsi) {
  56                if (of_property_read_bool(np, "qcom,master-dsi"))
  57                        msm_dsim->master_dsi_link_id = id;
  58                if (!msm_dsim->is_sync_needed)
  59                        msm_dsim->is_sync_needed = of_property_read_bool(
  60                                        np, "qcom,sync-dual-dsi");
  61        }
  62
  63        return 0;
  64}
  65
  66static int dsi_mgr_setup_components(int id)
  67{
  68        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
  69        struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
  70        struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
  71        struct msm_dsi *clk_slave_dsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
  72        int ret;
  73
  74        if (!IS_BONDED_DSI()) {
  75                ret = msm_dsi_host_register(msm_dsi->host, true);
  76                if (ret)
  77                        return ret;
  78
  79                msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE);
  80                ret = msm_dsi_host_set_src_pll(msm_dsi->host, msm_dsi->phy);
  81        } else if (!other_dsi) {
  82                ret = 0;
  83        } else {
  84                struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ?
  85                                                        msm_dsi : other_dsi;
  86                struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ?
  87                                                        other_dsi : msm_dsi;
  88                /* Register slave host first, so that slave DSI device
  89                 * has a chance to probe, and do not block the master
  90                 * DSI device's probe.
  91                 * Also, do not check defer for the slave host,
  92                 * because only master DSI device adds the panel to global
  93                 * panel list. The panel's device is the master DSI device.
  94                 */
  95                ret = msm_dsi_host_register(slave_link_dsi->host, false);
  96                if (ret)
  97                        return ret;
  98                ret = msm_dsi_host_register(master_link_dsi->host, true);
  99                if (ret)
 100                        return ret;
 101
 102                /* PLL0 is to drive both 2 DSI link clocks in bonded DSI mode. */
 103                msm_dsi_phy_set_usecase(clk_master_dsi->phy,
 104                                        MSM_DSI_PHY_MASTER);
 105                msm_dsi_phy_set_usecase(clk_slave_dsi->phy,
 106                                        MSM_DSI_PHY_SLAVE);
 107                ret = msm_dsi_host_set_src_pll(msm_dsi->host, clk_master_dsi->phy);
 108                if (ret)
 109                        return ret;
 110                ret = msm_dsi_host_set_src_pll(other_dsi->host, clk_master_dsi->phy);
 111        }
 112
 113        return ret;
 114}
 115
 116static int enable_phy(struct msm_dsi *msm_dsi,
 117                      struct msm_dsi_phy_shared_timings *shared_timings)
 118{
 119        struct msm_dsi_phy_clk_request clk_req;
 120        int ret;
 121        bool is_bonded_dsi = IS_BONDED_DSI();
 122
 123        msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req, is_bonded_dsi);
 124
 125        ret = msm_dsi_phy_enable(msm_dsi->phy, &clk_req, shared_timings);
 126
 127        return ret;
 128}
 129
 130static int
 131dsi_mgr_phy_enable(int id,
 132                   struct msm_dsi_phy_shared_timings shared_timings[DSI_MAX])
 133{
 134        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 135        struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
 136        struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
 137        int ret;
 138
 139        /* In case of bonded DSI, some registers in PHY1 have been programmed
 140         * during PLL0 clock's set_rate. The PHY1 reset called by host1 here
 141         * will silently reset those PHY1 registers. Therefore we need to reset
 142         * and enable both PHYs before any PLL clock operation.
 143         */
 144        if (IS_BONDED_DSI() && mdsi && sdsi) {
 145                if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
 146                        msm_dsi_host_reset_phy(mdsi->host);
 147                        msm_dsi_host_reset_phy(sdsi->host);
 148
 149                        ret = enable_phy(mdsi,
 150                                         &shared_timings[DSI_CLOCK_MASTER]);
 151                        if (ret)
 152                                return ret;
 153                        ret = enable_phy(sdsi,
 154                                         &shared_timings[DSI_CLOCK_SLAVE]);
 155                        if (ret) {
 156                                msm_dsi_phy_disable(mdsi->phy);
 157                                return ret;
 158                        }
 159                }
 160        } else {
 161                msm_dsi_host_reset_phy(msm_dsi->host);
 162                ret = enable_phy(msm_dsi, &shared_timings[id]);
 163                if (ret)
 164                        return ret;
 165        }
 166
 167        msm_dsi->phy_enabled = true;
 168
 169        return 0;
 170}
 171
 172static void dsi_mgr_phy_disable(int id)
 173{
 174        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 175        struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
 176        struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
 177
 178        /* disable DSI phy
 179         * In bonded dsi configuration, the phy should be disabled for the
 180         * first controller only when the second controller is disabled.
 181         */
 182        msm_dsi->phy_enabled = false;
 183        if (IS_BONDED_DSI() && mdsi && sdsi) {
 184                if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
 185                        msm_dsi_phy_disable(sdsi->phy);
 186                        msm_dsi_phy_disable(mdsi->phy);
 187                }
 188        } else {
 189                msm_dsi_phy_disable(msm_dsi->phy);
 190        }
 191}
 192
 193struct dsi_connector {
 194        struct drm_connector base;
 195        int id;
 196};
 197
 198struct dsi_bridge {
 199        struct drm_bridge base;
 200        int id;
 201};
 202
 203#define to_dsi_connector(x) container_of(x, struct dsi_connector, base)
 204#define to_dsi_bridge(x) container_of(x, struct dsi_bridge, base)
 205
 206static inline int dsi_mgr_connector_get_id(struct drm_connector *connector)
 207{
 208        struct dsi_connector *dsi_connector = to_dsi_connector(connector);
 209        return dsi_connector->id;
 210}
 211
 212static int dsi_mgr_bridge_get_id(struct drm_bridge *bridge)
 213{
 214        struct dsi_bridge *dsi_bridge = to_dsi_bridge(bridge);
 215        return dsi_bridge->id;
 216}
 217
 218static int msm_dsi_manager_panel_init(struct drm_connector *conn, u8 id)
 219{
 220        struct msm_drm_private *priv = conn->dev->dev_private;
 221        struct msm_kms *kms = priv->kms;
 222        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 223        struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
 224        struct msm_dsi *master_dsi, *slave_dsi;
 225        struct drm_panel *panel;
 226
 227        if (IS_BONDED_DSI() && !IS_MASTER_DSI_LINK(id)) {
 228                master_dsi = other_dsi;
 229                slave_dsi = msm_dsi;
 230        } else {
 231                master_dsi = msm_dsi;
 232                slave_dsi = other_dsi;
 233        }
 234
 235        /*
 236         * There is only 1 panel in the global panel list for bonded DSI mode.
 237         * Therefore slave dsi should get the drm_panel instance from master
 238         * dsi.
 239         */
 240        panel = msm_dsi_host_get_panel(master_dsi->host);
 241        if (IS_ERR(panel)) {
 242                DRM_ERROR("Could not find panel for %u (%ld)\n", msm_dsi->id,
 243                          PTR_ERR(panel));
 244                return PTR_ERR(panel);
 245        }
 246
 247        if (!panel || !IS_BONDED_DSI())
 248                goto out;
 249
 250        drm_object_attach_property(&conn->base,
 251                                   conn->dev->mode_config.tile_property, 0);
 252
 253        /*
 254         * Set split display info to kms once bonded DSI panel is connected to
 255         * both hosts.
 256         */
 257        if (other_dsi && other_dsi->panel && kms->funcs->set_split_display) {
 258                kms->funcs->set_split_display(kms, master_dsi->encoder,
 259                                              slave_dsi->encoder,
 260                                              msm_dsi_is_cmd_mode(msm_dsi));
 261        }
 262
 263out:
 264        msm_dsi->panel = panel;
 265        return 0;
 266}
 267
 268static enum drm_connector_status dsi_mgr_connector_detect(
 269                struct drm_connector *connector, bool force)
 270{
 271        int id = dsi_mgr_connector_get_id(connector);
 272        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 273
 274        return msm_dsi->panel ? connector_status_connected :
 275                connector_status_disconnected;
 276}
 277
 278static void dsi_mgr_connector_destroy(struct drm_connector *connector)
 279{
 280        struct dsi_connector *dsi_connector = to_dsi_connector(connector);
 281
 282        DBG("");
 283
 284        drm_connector_cleanup(connector);
 285
 286        kfree(dsi_connector);
 287}
 288
 289static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
 290{
 291        int id = dsi_mgr_connector_get_id(connector);
 292        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 293        struct drm_panel *panel = msm_dsi->panel;
 294        int num;
 295
 296        if (!panel)
 297                return 0;
 298
 299        /*
 300         * In bonded DSI mode, we have one connector that can be
 301         * attached to the drm_panel.
 302         */
 303        num = drm_panel_get_modes(panel, connector);
 304        if (!num)
 305                return 0;
 306
 307        return num;
 308}
 309
 310static enum drm_mode_status dsi_mgr_connector_mode_valid(struct drm_connector *connector,
 311                                struct drm_display_mode *mode)
 312{
 313        int id = dsi_mgr_connector_get_id(connector);
 314        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 315        struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi);
 316        struct msm_drm_private *priv = connector->dev->dev_private;
 317        struct msm_kms *kms = priv->kms;
 318        long actual, requested;
 319
 320        DBG("");
 321        requested = 1000 * mode->clock;
 322        actual = kms->funcs->round_pixclk(kms, requested, encoder);
 323
 324        DBG("requested=%ld, actual=%ld", requested, actual);
 325        if (actual != requested)
 326                return MODE_CLOCK_RANGE;
 327
 328        return MODE_OK;
 329}
 330
 331static struct drm_encoder *
 332dsi_mgr_connector_best_encoder(struct drm_connector *connector)
 333{
 334        int id = dsi_mgr_connector_get_id(connector);
 335        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 336
 337        DBG("");
 338        return msm_dsi_get_encoder(msm_dsi);
 339}
 340
 341static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 342{
 343        int id = dsi_mgr_bridge_get_id(bridge);
 344        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 345        struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
 346        struct mipi_dsi_host *host = msm_dsi->host;
 347        struct drm_panel *panel = msm_dsi->panel;
 348        struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX];
 349        bool is_bonded_dsi = IS_BONDED_DSI();
 350        int ret;
 351
 352        DBG("id=%d", id);
 353        if (!msm_dsi_device_connected(msm_dsi))
 354                return;
 355
 356        /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
 357        if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
 358                return;
 359
 360        ret = dsi_mgr_phy_enable(id, phy_shared_timings);
 361        if (ret)
 362                goto phy_en_fail;
 363
 364        ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_bonded_dsi, msm_dsi->phy);
 365        if (ret) {
 366                pr_err("%s: power on host %d failed, %d\n", __func__, id, ret);
 367                goto host_on_fail;
 368        }
 369
 370        if (is_bonded_dsi && msm_dsi1) {
 371                ret = msm_dsi_host_power_on(msm_dsi1->host,
 372                                &phy_shared_timings[DSI_1], is_bonded_dsi, msm_dsi1->phy);
 373                if (ret) {
 374                        pr_err("%s: power on host1 failed, %d\n",
 375                                                        __func__, ret);
 376                        goto host1_on_fail;
 377                }
 378        }
 379
 380        /* Always call panel functions once, because even for dual panels,
 381         * there is only one drm_panel instance.
 382         */
 383        if (panel) {
 384                ret = drm_panel_prepare(panel);
 385                if (ret) {
 386                        pr_err("%s: prepare panel %d failed, %d\n", __func__,
 387                                                                id, ret);
 388                        goto panel_prep_fail;
 389                }
 390        }
 391
 392        ret = msm_dsi_host_enable(host);
 393        if (ret) {
 394                pr_err("%s: enable host %d failed, %d\n", __func__, id, ret);
 395                goto host_en_fail;
 396        }
 397
 398        if (is_bonded_dsi && msm_dsi1) {
 399                ret = msm_dsi_host_enable(msm_dsi1->host);
 400                if (ret) {
 401                        pr_err("%s: enable host1 failed, %d\n", __func__, ret);
 402                        goto host1_en_fail;
 403                }
 404        }
 405
 406        return;
 407
 408host1_en_fail:
 409        msm_dsi_host_disable(host);
 410host_en_fail:
 411        if (panel)
 412                drm_panel_unprepare(panel);
 413panel_prep_fail:
 414        if (is_bonded_dsi && msm_dsi1)
 415                msm_dsi_host_power_off(msm_dsi1->host);
 416host1_on_fail:
 417        msm_dsi_host_power_off(host);
 418host_on_fail:
 419        dsi_mgr_phy_disable(id);
 420phy_en_fail:
 421        return;
 422}
 423
 424void msm_dsi_manager_tpg_enable(void)
 425{
 426        struct msm_dsi *m_dsi = dsi_mgr_get_dsi(DSI_0);
 427        struct msm_dsi *s_dsi = dsi_mgr_get_dsi(DSI_1);
 428
 429        /* if dual dsi, trigger tpg on master first then slave */
 430        if (m_dsi) {
 431                msm_dsi_host_test_pattern_en(m_dsi->host);
 432                if (IS_BONDED_DSI() && s_dsi)
 433                        msm_dsi_host_test_pattern_en(s_dsi->host);
 434        }
 435}
 436
 437static void dsi_mgr_bridge_enable(struct drm_bridge *bridge)
 438{
 439        int id = dsi_mgr_bridge_get_id(bridge);
 440        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 441        struct drm_panel *panel = msm_dsi->panel;
 442        bool is_bonded_dsi = IS_BONDED_DSI();
 443        int ret;
 444
 445        DBG("id=%d", id);
 446        if (!msm_dsi_device_connected(msm_dsi))
 447                return;
 448
 449        /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
 450        if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
 451                return;
 452
 453        if (panel) {
 454                ret = drm_panel_enable(panel);
 455                if (ret) {
 456                        pr_err("%s: enable panel %d failed, %d\n", __func__, id,
 457                                                                        ret);
 458                }
 459        }
 460}
 461
 462static void dsi_mgr_bridge_disable(struct drm_bridge *bridge)
 463{
 464        int id = dsi_mgr_bridge_get_id(bridge);
 465        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 466        struct drm_panel *panel = msm_dsi->panel;
 467        bool is_bonded_dsi = IS_BONDED_DSI();
 468        int ret;
 469
 470        DBG("id=%d", id);
 471        if (!msm_dsi_device_connected(msm_dsi))
 472                return;
 473
 474        /* Do nothing with the host if it is slave-DSI in case of bonded DSI */
 475        if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
 476                return;
 477
 478        if (panel) {
 479                ret = drm_panel_disable(panel);
 480                if (ret)
 481                        pr_err("%s: Panel %d OFF failed, %d\n", __func__, id,
 482                                                                        ret);
 483        }
 484}
 485
 486static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 487{
 488        int id = dsi_mgr_bridge_get_id(bridge);
 489        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 490        struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
 491        struct mipi_dsi_host *host = msm_dsi->host;
 492        struct drm_panel *panel = msm_dsi->panel;
 493        bool is_bonded_dsi = IS_BONDED_DSI();
 494        int ret;
 495
 496        DBG("id=%d", id);
 497
 498        if (!msm_dsi_device_connected(msm_dsi))
 499                return;
 500
 501        /*
 502         * Do nothing with the host if it is slave-DSI in case of bonded DSI.
 503         * It is safe to call dsi_mgr_phy_disable() here because a single PHY
 504         * won't be diabled until both PHYs request disable.
 505         */
 506        if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
 507                goto disable_phy;
 508
 509        ret = msm_dsi_host_disable(host);
 510        if (ret)
 511                pr_err("%s: host %d disable failed, %d\n", __func__, id, ret);
 512
 513        if (is_bonded_dsi && msm_dsi1) {
 514                ret = msm_dsi_host_disable(msm_dsi1->host);
 515                if (ret)
 516                        pr_err("%s: host1 disable failed, %d\n", __func__, ret);
 517        }
 518
 519        if (panel) {
 520                ret = drm_panel_unprepare(panel);
 521                if (ret)
 522                        pr_err("%s: Panel %d unprepare failed,%d\n", __func__,
 523                                                                id, ret);
 524        }
 525
 526        /* Save PHY status if it is a clock source */
 527        msm_dsi_phy_pll_save_state(msm_dsi->phy);
 528
 529        ret = msm_dsi_host_power_off(host);
 530        if (ret)
 531                pr_err("%s: host %d power off failed,%d\n", __func__, id, ret);
 532
 533        if (is_bonded_dsi && msm_dsi1) {
 534                ret = msm_dsi_host_power_off(msm_dsi1->host);
 535                if (ret)
 536                        pr_err("%s: host1 power off failed, %d\n",
 537                                                                __func__, ret);
 538        }
 539
 540disable_phy:
 541        dsi_mgr_phy_disable(id);
 542}
 543
 544static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
 545                const struct drm_display_mode *mode,
 546                const struct drm_display_mode *adjusted_mode)
 547{
 548        int id = dsi_mgr_bridge_get_id(bridge);
 549        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 550        struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
 551        struct mipi_dsi_host *host = msm_dsi->host;
 552        bool is_bonded_dsi = IS_BONDED_DSI();
 553
 554        DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode));
 555
 556        if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id))
 557                return;
 558
 559        msm_dsi_host_set_display_mode(host, adjusted_mode);
 560        if (is_bonded_dsi && other_dsi)
 561                msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
 562}
 563
 564static const struct drm_connector_funcs dsi_mgr_connector_funcs = {
 565        .detect = dsi_mgr_connector_detect,
 566        .fill_modes = drm_helper_probe_single_connector_modes,
 567        .destroy = dsi_mgr_connector_destroy,
 568        .reset = drm_atomic_helper_connector_reset,
 569        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 570        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 571};
 572
 573static const struct drm_connector_helper_funcs dsi_mgr_conn_helper_funcs = {
 574        .get_modes = dsi_mgr_connector_get_modes,
 575        .mode_valid = dsi_mgr_connector_mode_valid,
 576        .best_encoder = dsi_mgr_connector_best_encoder,
 577};
 578
 579static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = {
 580        .pre_enable = dsi_mgr_bridge_pre_enable,
 581        .enable = dsi_mgr_bridge_enable,
 582        .disable = dsi_mgr_bridge_disable,
 583        .post_disable = dsi_mgr_bridge_post_disable,
 584        .mode_set = dsi_mgr_bridge_mode_set,
 585};
 586
 587/* initialize connector when we're connected to a drm_panel */
 588struct drm_connector *msm_dsi_manager_connector_init(u8 id)
 589{
 590        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 591        struct drm_connector *connector = NULL;
 592        struct dsi_connector *dsi_connector;
 593        int ret;
 594
 595        dsi_connector = kzalloc(sizeof(*dsi_connector), GFP_KERNEL);
 596        if (!dsi_connector)
 597                return ERR_PTR(-ENOMEM);
 598
 599        dsi_connector->id = id;
 600
 601        connector = &dsi_connector->base;
 602
 603        ret = drm_connector_init(msm_dsi->dev, connector,
 604                        &dsi_mgr_connector_funcs, DRM_MODE_CONNECTOR_DSI);
 605        if (ret)
 606                return ERR_PTR(ret);
 607
 608        drm_connector_helper_add(connector, &dsi_mgr_conn_helper_funcs);
 609
 610        /* Enable HPD to let hpd event is handled
 611         * when panel is attached to the host.
 612         */
 613        connector->polled = DRM_CONNECTOR_POLL_HPD;
 614
 615        /* Display driver doesn't support interlace now. */
 616        connector->interlace_allowed = 0;
 617        connector->doublescan_allowed = 0;
 618
 619        drm_connector_attach_encoder(connector, msm_dsi->encoder);
 620
 621        ret = msm_dsi_manager_panel_init(connector, id);
 622        if (ret) {
 623                DRM_DEV_ERROR(msm_dsi->dev->dev, "init panel failed %d\n", ret);
 624                goto fail;
 625        }
 626
 627        return connector;
 628
 629fail:
 630        connector->funcs->destroy(msm_dsi->connector);
 631        return ERR_PTR(ret);
 632}
 633
 634bool msm_dsi_manager_validate_current_config(u8 id)
 635{
 636        bool is_bonded_dsi = IS_BONDED_DSI();
 637
 638        /*
 639         * For bonded DSI, we only have one drm panel. For this
 640         * use case, we register only one bridge/connector.
 641         * Skip bridge/connector initialisation if it is
 642         * slave-DSI for bonded DSI configuration.
 643         */
 644        if (is_bonded_dsi && !IS_MASTER_DSI_LINK(id)) {
 645                DBG("Skip bridge registration for slave DSI->id: %d\n", id);
 646                return false;
 647        }
 648        return true;
 649}
 650
 651/* initialize bridge */
 652struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
 653{
 654        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 655        struct drm_bridge *bridge = NULL;
 656        struct dsi_bridge *dsi_bridge;
 657        struct drm_encoder *encoder;
 658        int ret;
 659
 660        dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
 661                                sizeof(*dsi_bridge), GFP_KERNEL);
 662        if (!dsi_bridge) {
 663                ret = -ENOMEM;
 664                goto fail;
 665        }
 666
 667        dsi_bridge->id = id;
 668
 669        encoder = msm_dsi->encoder;
 670
 671        bridge = &dsi_bridge->base;
 672        bridge->funcs = &dsi_mgr_bridge_funcs;
 673
 674        ret = drm_bridge_attach(encoder, bridge, NULL, 0);
 675        if (ret)
 676                goto fail;
 677
 678        return bridge;
 679
 680fail:
 681        if (bridge)
 682                msm_dsi_manager_bridge_destroy(bridge);
 683
 684        return ERR_PTR(ret);
 685}
 686
 687struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
 688{
 689        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 690        struct drm_device *dev = msm_dsi->dev;
 691        struct drm_encoder *encoder;
 692        struct drm_bridge *int_bridge, *ext_bridge;
 693        struct drm_connector *connector;
 694        struct list_head *connector_list;
 695
 696        int_bridge = msm_dsi->bridge;
 697        ext_bridge = msm_dsi->external_bridge =
 698                        msm_dsi_host_get_bridge(msm_dsi->host);
 699
 700        encoder = msm_dsi->encoder;
 701
 702        /* link the internal dsi bridge to the external bridge */
 703        drm_bridge_attach(encoder, ext_bridge, int_bridge, 0);
 704
 705        /*
 706         * we need the drm_connector created by the external bridge
 707         * driver (or someone else) to feed it to our driver's
 708         * priv->connector[] list, mainly for msm_fbdev_init()
 709         */
 710        connector_list = &dev->mode_config.connector_list;
 711
 712        list_for_each_entry(connector, connector_list, head) {
 713                if (drm_connector_has_possible_encoder(connector, encoder))
 714                        return connector;
 715        }
 716
 717        return ERR_PTR(-ENODEV);
 718}
 719
 720void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge)
 721{
 722}
 723
 724int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg)
 725{
 726        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 727        struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
 728        struct mipi_dsi_host *host = msm_dsi->host;
 729        bool is_read = (msg->rx_buf && msg->rx_len);
 730        bool need_sync = (IS_SYNC_NEEDED() && !is_read);
 731        int ret;
 732
 733        if (!msg->tx_buf || !msg->tx_len)
 734                return 0;
 735
 736        /* In bonded master case, panel requires the same commands sent to
 737         * both DSI links. Host issues the command trigger to both links
 738         * when DSI_1 calls the cmd transfer function, no matter it happens
 739         * before or after DSI_0 cmd transfer.
 740         */
 741        if (need_sync && (id == DSI_0))
 742                return is_read ? msg->rx_len : msg->tx_len;
 743
 744        if (need_sync && msm_dsi0) {
 745                ret = msm_dsi_host_xfer_prepare(msm_dsi0->host, msg);
 746                if (ret) {
 747                        pr_err("%s: failed to prepare non-trigger host, %d\n",
 748                                __func__, ret);
 749                        return ret;
 750                }
 751        }
 752        ret = msm_dsi_host_xfer_prepare(host, msg);
 753        if (ret) {
 754                pr_err("%s: failed to prepare host, %d\n", __func__, ret);
 755                goto restore_host0;
 756        }
 757
 758        ret = is_read ? msm_dsi_host_cmd_rx(host, msg) :
 759                        msm_dsi_host_cmd_tx(host, msg);
 760
 761        msm_dsi_host_xfer_restore(host, msg);
 762
 763restore_host0:
 764        if (need_sync && msm_dsi0)
 765                msm_dsi_host_xfer_restore(msm_dsi0->host, msg);
 766
 767        return ret;
 768}
 769
 770bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
 771{
 772        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 773        struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
 774        struct mipi_dsi_host *host = msm_dsi->host;
 775
 776        if (IS_SYNC_NEEDED() && (id == DSI_0))
 777                return false;
 778
 779        if (IS_SYNC_NEEDED() && msm_dsi0)
 780                msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, dma_base, len);
 781
 782        msm_dsi_host_cmd_xfer_commit(host, dma_base, len);
 783
 784        return true;
 785}
 786
 787int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
 788{
 789        struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
 790        int id = msm_dsi->id;
 791        int ret;
 792
 793        if (id >= DSI_MAX) {
 794                pr_err("%s: invalid id %d\n", __func__, id);
 795                return -EINVAL;
 796        }
 797
 798        if (msm_dsim->dsi[id]) {
 799                pr_err("%s: dsi%d already registered\n", __func__, id);
 800                return -EBUSY;
 801        }
 802
 803        msm_dsim->dsi[id] = msm_dsi;
 804
 805        ret = dsi_mgr_parse_of(msm_dsi->pdev->dev.of_node, id);
 806        if (ret) {
 807                pr_err("%s: failed to parse OF DSI info\n", __func__);
 808                goto fail;
 809        }
 810
 811        ret = dsi_mgr_setup_components(id);
 812        if (ret) {
 813                pr_err("%s: failed to register mipi dsi host for DSI %d: %d\n",
 814                        __func__, id, ret);
 815                goto fail;
 816        }
 817
 818        return 0;
 819
 820fail:
 821        msm_dsim->dsi[id] = NULL;
 822        return ret;
 823}
 824
 825void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi)
 826{
 827        struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
 828
 829        if (msm_dsi->host)
 830                msm_dsi_host_unregister(msm_dsi->host);
 831
 832        if (msm_dsi->id >= 0)
 833                msm_dsim->dsi[msm_dsi->id] = NULL;
 834}
 835
 836bool msm_dsi_is_bonded_dsi(struct msm_dsi *msm_dsi)
 837{
 838        return IS_BONDED_DSI();
 839}
 840
 841bool msm_dsi_is_master_dsi(struct msm_dsi *msm_dsi)
 842{
 843        return IS_MASTER_DSI_LINK(msm_dsi->id);
 844}
 845