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