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