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        struct dsi_connector *dsi_connector = to_dsi_connector(connector);
 202
 203        DBG("");
 204
 205        drm_connector_cleanup(connector);
 206
 207        kfree(dsi_connector);
 208}
 209
 210static void dsi_dual_connector_fix_modes(struct drm_connector *connector)
 211{
 212        struct drm_display_mode *mode, *m;
 213
 214        /* Only support left-right mode */
 215        list_for_each_entry_safe(mode, m, &connector->probed_modes, head) {
 216                mode->clock >>= 1;
 217                mode->hdisplay >>= 1;
 218                mode->hsync_start >>= 1;
 219                mode->hsync_end >>= 1;
 220                mode->htotal >>= 1;
 221                drm_mode_set_name(mode);
 222        }
 223}
 224
 225static int dsi_dual_connector_tile_init(
 226                        struct drm_connector *connector, int id)
 227{
 228        struct drm_display_mode *mode;
 229        /* Fake topology id */
 230        char topo_id[8] = {'M', 'S', 'M', 'D', 'U', 'D', 'S', 'I'};
 231
 232        if (connector->tile_group) {
 233                DBG("Tile property has been initialized");
 234                return 0;
 235        }
 236
 237        /* Use the first mode only for now */
 238        mode = list_first_entry(&connector->probed_modes,
 239                                struct drm_display_mode,
 240                                head);
 241        if (!mode)
 242                return -EINVAL;
 243
 244        connector->tile_group = drm_mode_get_tile_group(
 245                                        connector->dev, topo_id);
 246        if (!connector->tile_group)
 247                connector->tile_group = drm_mode_create_tile_group(
 248                                        connector->dev, topo_id);
 249        if (!connector->tile_group) {
 250                pr_err("%s: failed to create tile group\n", __func__);
 251                return -ENOMEM;
 252        }
 253
 254        connector->has_tile = true;
 255        connector->tile_is_single_monitor = true;
 256
 257        /* mode has been fixed */
 258        connector->tile_h_size = mode->hdisplay;
 259        connector->tile_v_size = mode->vdisplay;
 260
 261        /* Only support left-right mode */
 262        connector->num_h_tile = 2;
 263        connector->num_v_tile = 1;
 264
 265        connector->tile_v_loc = 0;
 266        connector->tile_h_loc = (id == DSI_RIGHT) ? 1 : 0;
 267
 268        return 0;
 269}
 270
 271static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
 272{
 273        int id = dsi_mgr_connector_get_id(connector);
 274        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 275        struct drm_panel *panel = msm_dsi->panel;
 276        int ret, num;
 277
 278        if (!panel)
 279                return 0;
 280
 281        /* Since we have 2 connectors, but only 1 drm_panel in dual DSI mode,
 282         * panel should not attach to any connector.
 283         * Only temporarily attach panel to the current connector here,
 284         * to let panel set mode to this connector.
 285         */
 286        drm_panel_attach(panel, connector);
 287        num = drm_panel_get_modes(panel);
 288        drm_panel_detach(panel);
 289        if (!num)
 290                return 0;
 291
 292        if (IS_DUAL_DSI()) {
 293                /* report half resolution to user */
 294                dsi_dual_connector_fix_modes(connector);
 295                ret = dsi_dual_connector_tile_init(connector, id);
 296                if (ret)
 297                        return ret;
 298                ret = drm_mode_connector_set_tile_property(connector);
 299                if (ret) {
 300                        pr_err("%s: set tile property failed, %d\n",
 301                                        __func__, ret);
 302                        return ret;
 303                }
 304        }
 305
 306        return num;
 307}
 308
 309static int dsi_mgr_connector_mode_valid(struct drm_connector *connector,
 310                                struct drm_display_mode *mode)
 311{
 312        int id = dsi_mgr_connector_get_id(connector);
 313        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 314        struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi);
 315        struct msm_drm_private *priv = connector->dev->dev_private;
 316        struct msm_kms *kms = priv->kms;
 317        long actual, requested;
 318
 319        DBG("");
 320        requested = 1000 * mode->clock;
 321        actual = kms->funcs->round_pixclk(kms, requested, encoder);
 322
 323        DBG("requested=%ld, actual=%ld", requested, actual);
 324        if (actual != requested)
 325                return MODE_CLOCK_RANGE;
 326
 327        return MODE_OK;
 328}
 329
 330static struct drm_encoder *
 331dsi_mgr_connector_best_encoder(struct drm_connector *connector)
 332{
 333        int id = dsi_mgr_connector_get_id(connector);
 334        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 335
 336        DBG("");
 337        return msm_dsi_get_encoder(msm_dsi);
 338}
 339
 340static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 341{
 342        int id = dsi_mgr_bridge_get_id(bridge);
 343        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 344        struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
 345        struct mipi_dsi_host *host = msm_dsi->host;
 346        struct drm_panel *panel = msm_dsi->panel;
 347        bool is_dual_dsi = IS_DUAL_DSI();
 348        int ret;
 349
 350        DBG("id=%d", id);
 351        if (!msm_dsi_device_connected(msm_dsi) ||
 352                        (is_dual_dsi && (DSI_1 == id)))
 353                return;
 354
 355        ret = msm_dsi_host_power_on(host);
 356        if (ret) {
 357                pr_err("%s: power on host %d failed, %d\n", __func__, id, ret);
 358                goto host_on_fail;
 359        }
 360
 361        if (is_dual_dsi && msm_dsi1) {
 362                ret = msm_dsi_host_power_on(msm_dsi1->host);
 363                if (ret) {
 364                        pr_err("%s: power on host1 failed, %d\n",
 365                                                        __func__, ret);
 366                        goto host1_on_fail;
 367                }
 368        }
 369
 370        /* Always call panel functions once, because even for dual panels,
 371         * there is only one drm_panel instance.
 372         */
 373        if (panel) {
 374                ret = drm_panel_prepare(panel);
 375                if (ret) {
 376                        pr_err("%s: prepare panel %d failed, %d\n", __func__,
 377                                                                id, ret);
 378                        goto panel_prep_fail;
 379                }
 380        }
 381
 382        ret = msm_dsi_host_enable(host);
 383        if (ret) {
 384                pr_err("%s: enable host %d failed, %d\n", __func__, id, ret);
 385                goto host_en_fail;
 386        }
 387
 388        if (is_dual_dsi && msm_dsi1) {
 389                ret = msm_dsi_host_enable(msm_dsi1->host);
 390                if (ret) {
 391                        pr_err("%s: enable host1 failed, %d\n", __func__, ret);
 392                        goto host1_en_fail;
 393                }
 394        }
 395
 396        if (panel) {
 397                ret = drm_panel_enable(panel);
 398                if (ret) {
 399                        pr_err("%s: enable panel %d failed, %d\n", __func__, id,
 400                                                                        ret);
 401                        goto panel_en_fail;
 402                }
 403        }
 404
 405        return;
 406
 407panel_en_fail:
 408        if (is_dual_dsi && msm_dsi1)
 409                msm_dsi_host_disable(msm_dsi1->host);
 410host1_en_fail:
 411        msm_dsi_host_disable(host);
 412host_en_fail:
 413        if (panel)
 414                drm_panel_unprepare(panel);
 415panel_prep_fail:
 416        if (is_dual_dsi && msm_dsi1)
 417                msm_dsi_host_power_off(msm_dsi1->host);
 418host1_on_fail:
 419        msm_dsi_host_power_off(host);
 420host_on_fail:
 421        return;
 422}
 423
 424static void dsi_mgr_bridge_enable(struct drm_bridge *bridge)
 425{
 426        DBG("");
 427}
 428
 429static void dsi_mgr_bridge_disable(struct drm_bridge *bridge)
 430{
 431        DBG("");
 432}
 433
 434static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 435{
 436        int id = dsi_mgr_bridge_get_id(bridge);
 437        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 438        struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
 439        struct mipi_dsi_host *host = msm_dsi->host;
 440        struct drm_panel *panel = msm_dsi->panel;
 441        bool is_dual_dsi = IS_DUAL_DSI();
 442        int ret;
 443
 444        DBG("id=%d", id);
 445
 446        if (!msm_dsi_device_connected(msm_dsi) ||
 447                        (is_dual_dsi && (DSI_1 == id)))
 448                return;
 449
 450        if (panel) {
 451                ret = drm_panel_disable(panel);
 452                if (ret)
 453                        pr_err("%s: Panel %d OFF failed, %d\n", __func__, id,
 454                                                                        ret);
 455        }
 456
 457        ret = msm_dsi_host_disable(host);
 458        if (ret)
 459                pr_err("%s: host %d disable failed, %d\n", __func__, id, ret);
 460
 461        if (is_dual_dsi && msm_dsi1) {
 462                ret = msm_dsi_host_disable(msm_dsi1->host);
 463                if (ret)
 464                        pr_err("%s: host1 disable failed, %d\n", __func__, ret);
 465        }
 466
 467        if (panel) {
 468                ret = drm_panel_unprepare(panel);
 469                if (ret)
 470                        pr_err("%s: Panel %d unprepare failed,%d\n", __func__,
 471                                                                id, ret);
 472        }
 473
 474        ret = msm_dsi_host_power_off(host);
 475        if (ret)
 476                pr_err("%s: host %d power off failed,%d\n", __func__, id, ret);
 477
 478        if (is_dual_dsi && msm_dsi1) {
 479                ret = msm_dsi_host_power_off(msm_dsi1->host);
 480                if (ret)
 481                        pr_err("%s: host1 power off failed, %d\n",
 482                                                                __func__, ret);
 483        }
 484}
 485
 486static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
 487                struct drm_display_mode *mode,
 488                struct drm_display_mode *adjusted_mode)
 489{
 490        int id = dsi_mgr_bridge_get_id(bridge);
 491        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 492        struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
 493        struct mipi_dsi_host *host = msm_dsi->host;
 494        bool is_dual_dsi = IS_DUAL_DSI();
 495
 496        DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
 497                        mode->base.id, mode->name,
 498                        mode->vrefresh, mode->clock,
 499                        mode->hdisplay, mode->hsync_start,
 500                        mode->hsync_end, mode->htotal,
 501                        mode->vdisplay, mode->vsync_start,
 502                        mode->vsync_end, mode->vtotal,
 503                        mode->type, mode->flags);
 504
 505        if (is_dual_dsi && (DSI_1 == id))
 506                return;
 507
 508        msm_dsi_host_set_display_mode(host, adjusted_mode);
 509        if (is_dual_dsi && other_dsi)
 510                msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
 511}
 512
 513static const struct drm_connector_funcs dsi_mgr_connector_funcs = {
 514        .dpms = drm_atomic_helper_connector_dpms,
 515        .detect = dsi_mgr_connector_detect,
 516        .fill_modes = drm_helper_probe_single_connector_modes,
 517        .destroy = dsi_mgr_connector_destroy,
 518        .reset = drm_atomic_helper_connector_reset,
 519        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 520        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 521};
 522
 523static const struct drm_connector_helper_funcs dsi_mgr_conn_helper_funcs = {
 524        .get_modes = dsi_mgr_connector_get_modes,
 525        .mode_valid = dsi_mgr_connector_mode_valid,
 526        .best_encoder = dsi_mgr_connector_best_encoder,
 527};
 528
 529static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = {
 530        .pre_enable = dsi_mgr_bridge_pre_enable,
 531        .enable = dsi_mgr_bridge_enable,
 532        .disable = dsi_mgr_bridge_disable,
 533        .post_disable = dsi_mgr_bridge_post_disable,
 534        .mode_set = dsi_mgr_bridge_mode_set,
 535};
 536
 537/* initialize connector when we're connected to a drm_panel */
 538struct drm_connector *msm_dsi_manager_connector_init(u8 id)
 539{
 540        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 541        struct drm_connector *connector = NULL;
 542        struct dsi_connector *dsi_connector;
 543        int ret, i;
 544
 545        dsi_connector = kzalloc(sizeof(*dsi_connector), GFP_KERNEL);
 546        if (!dsi_connector)
 547                return ERR_PTR(-ENOMEM);
 548
 549        dsi_connector->id = id;
 550
 551        connector = &dsi_connector->base;
 552
 553        ret = drm_connector_init(msm_dsi->dev, connector,
 554                        &dsi_mgr_connector_funcs, DRM_MODE_CONNECTOR_DSI);
 555        if (ret)
 556                return ERR_PTR(ret);
 557
 558        drm_connector_helper_add(connector, &dsi_mgr_conn_helper_funcs);
 559
 560        /* Enable HPD to let hpd event is handled
 561         * when panel is attached to the host.
 562         */
 563        connector->polled = DRM_CONNECTOR_POLL_HPD;
 564
 565        /* Display driver doesn't support interlace now. */
 566        connector->interlace_allowed = 0;
 567        connector->doublescan_allowed = 0;
 568
 569        for (i = 0; i < MSM_DSI_ENCODER_NUM; i++)
 570                drm_mode_connector_attach_encoder(connector,
 571                                                msm_dsi->encoders[i]);
 572
 573        return connector;
 574}
 575
 576/* initialize bridge */
 577struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
 578{
 579        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 580        struct drm_bridge *bridge = NULL;
 581        struct dsi_bridge *dsi_bridge;
 582        int ret;
 583
 584        dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
 585                                sizeof(*dsi_bridge), GFP_KERNEL);
 586        if (!dsi_bridge) {
 587                ret = -ENOMEM;
 588                goto fail;
 589        }
 590
 591        dsi_bridge->id = id;
 592
 593        bridge = &dsi_bridge->base;
 594        bridge->funcs = &dsi_mgr_bridge_funcs;
 595
 596        ret = drm_bridge_attach(msm_dsi->dev, bridge);
 597        if (ret)
 598                goto fail;
 599
 600        return bridge;
 601
 602fail:
 603        if (bridge)
 604                msm_dsi_manager_bridge_destroy(bridge);
 605
 606        return ERR_PTR(ret);
 607}
 608
 609struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
 610{
 611        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 612        struct drm_device *dev = msm_dsi->dev;
 613        struct drm_encoder *encoder;
 614        struct drm_bridge *int_bridge, *ext_bridge;
 615        struct drm_connector *connector;
 616        struct list_head *connector_list;
 617
 618        int_bridge = msm_dsi->bridge;
 619        ext_bridge = msm_dsi->external_bridge =
 620                        msm_dsi_host_get_bridge(msm_dsi->host);
 621
 622        /*
 623         * HACK: we may not know the external DSI bridge device's mode
 624         * flags here. We'll get to know them only when the device
 625         * attaches to the dsi host. For now, assume the bridge supports
 626         * DSI video mode
 627         */
 628        encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
 629
 630        /* link the internal dsi bridge to the external bridge */
 631        int_bridge->next = ext_bridge;
 632        /* set the external bridge's encoder as dsi's encoder */
 633        ext_bridge->encoder = encoder;
 634
 635        drm_bridge_attach(dev, ext_bridge);
 636
 637        /*
 638         * we need the drm_connector created by the external bridge
 639         * driver (or someone else) to feed it to our driver's
 640         * priv->connector[] list, mainly for msm_fbdev_init()
 641         */
 642        connector_list = &dev->mode_config.connector_list;
 643
 644        list_for_each_entry(connector, connector_list, head) {
 645                int i;
 646
 647                for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 648                        if (connector->encoder_ids[i] == encoder->base.id)
 649                                return connector;
 650                }
 651        }
 652
 653        return ERR_PTR(-ENODEV);
 654}
 655
 656void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge)
 657{
 658}
 659
 660int msm_dsi_manager_phy_enable(int id,
 661                const unsigned long bit_rate, const unsigned long esc_rate,
 662                u32 *clk_pre, u32 *clk_post)
 663{
 664        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 665        struct msm_dsi_phy *phy = msm_dsi->phy;
 666        int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
 667        struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
 668        int ret;
 669
 670        ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate);
 671        if (ret)
 672                return ret;
 673
 674        /*
 675         * Reset DSI PHY silently changes its PLL registers to reset status,
 676         * which will confuse clock driver and result in wrong output rate of
 677         * link clocks. Restore PLL status if its PLL is being used as clock
 678         * source.
 679         */
 680        if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER)) {
 681                ret = msm_dsi_pll_restore_state(pll);
 682                if (ret) {
 683                        pr_err("%s: failed to restore pll state\n", __func__);
 684                        msm_dsi_phy_disable(phy);
 685                        return ret;
 686                }
 687        }
 688
 689        msm_dsi->phy_enabled = true;
 690        msm_dsi_phy_get_clk_pre_post(phy, clk_pre, clk_post);
 691
 692        return 0;
 693}
 694
 695void msm_dsi_manager_phy_disable(int id)
 696{
 697        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 698        struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
 699        struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
 700        struct msm_dsi_phy *phy = msm_dsi->phy;
 701        struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
 702
 703        /* Save PLL status if it is a clock source */
 704        if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER))
 705                msm_dsi_pll_save_state(pll);
 706
 707        /* disable DSI phy
 708         * In dual-dsi configuration, the phy should be disabled for the
 709         * first controller only when the second controller is disabled.
 710         */
 711        msm_dsi->phy_enabled = false;
 712        if (IS_DUAL_DSI() && mdsi && sdsi) {
 713                if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
 714                        msm_dsi_phy_disable(sdsi->phy);
 715                        msm_dsi_phy_disable(mdsi->phy);
 716                }
 717        } else {
 718                msm_dsi_phy_disable(phy);
 719        }
 720}
 721
 722int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg)
 723{
 724        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 725        struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
 726        struct mipi_dsi_host *host = msm_dsi->host;
 727        bool is_read = (msg->rx_buf && msg->rx_len);
 728        bool need_sync = (IS_SYNC_NEEDED() && !is_read);
 729        int ret;
 730
 731        if (!msg->tx_buf || !msg->tx_len)
 732                return 0;
 733
 734        /* In dual master case, panel requires the same commands sent to
 735         * both DSI links. Host issues the command trigger to both links
 736         * when DSI_1 calls the cmd transfer function, no matter it happens
 737         * before or after DSI_0 cmd transfer.
 738         */
 739        if (need_sync && (id == DSI_0))
 740                return is_read ? msg->rx_len : msg->tx_len;
 741
 742        if (need_sync && msm_dsi0) {
 743                ret = msm_dsi_host_xfer_prepare(msm_dsi0->host, msg);
 744                if (ret) {
 745                        pr_err("%s: failed to prepare non-trigger host, %d\n",
 746                                __func__, ret);
 747                        return ret;
 748                }
 749        }
 750        ret = msm_dsi_host_xfer_prepare(host, msg);
 751        if (ret) {
 752                pr_err("%s: failed to prepare host, %d\n", __func__, ret);
 753                goto restore_host0;
 754        }
 755
 756        ret = is_read ? msm_dsi_host_cmd_rx(host, msg) :
 757                        msm_dsi_host_cmd_tx(host, msg);
 758
 759        msm_dsi_host_xfer_restore(host, msg);
 760
 761restore_host0:
 762        if (need_sync && msm_dsi0)
 763                msm_dsi_host_xfer_restore(msm_dsi0->host, msg);
 764
 765        return ret;
 766}
 767
 768bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
 769{
 770        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 771        struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
 772        struct mipi_dsi_host *host = msm_dsi->host;
 773
 774        if (IS_SYNC_NEEDED() && (id == DSI_0))
 775                return false;
 776
 777        if (IS_SYNC_NEEDED() && msm_dsi0)
 778                msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, dma_base, len);
 779
 780        msm_dsi_host_cmd_xfer_commit(host, dma_base, len);
 781
 782        return true;
 783}
 784
 785int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
 786{
 787        struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
 788        int id = msm_dsi->id;
 789        int ret;
 790
 791        if (id > DSI_MAX) {
 792                pr_err("%s: invalid id %d\n", __func__, id);
 793                return -EINVAL;
 794        }
 795
 796        if (msm_dsim->dsi[id]) {
 797                pr_err("%s: dsi%d already registered\n", __func__, id);
 798                return -EBUSY;
 799        }
 800
 801        msm_dsim->dsi[id] = msm_dsi;
 802
 803        ret = dsi_mgr_parse_dual_dsi(msm_dsi->pdev->dev.of_node, id);
 804        if (ret) {
 805                pr_err("%s: failed to parse dual DSI info\n", __func__);
 806                goto fail;
 807        }
 808
 809        ret = dsi_mgr_host_register(id);
 810        if (ret) {
 811                pr_err("%s: failed to register mipi dsi host for DSI %d\n",
 812                        __func__, id);
 813                goto fail;
 814        }
 815
 816        return 0;
 817
 818fail:
 819        msm_dsim->dsi[id] = NULL;
 820        return ret;
 821}
 822
 823void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi)
 824{
 825        struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
 826
 827        if (msm_dsi->host)
 828                msm_dsi_host_unregister(msm_dsi->host);
 829        msm_dsim->dsi[msm_dsi->id] = NULL;
 830}
 831
 832