root/drivers/gpu/drm/i915/display/intel_tc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tc_port_mode_name
  2. has_modular_fia
  3. tc_port_to_fia
  4. intel_tc_port_get_lane_mask
  5. intel_tc_port_fia_max_lane_count
  6. intel_tc_port_set_fia_lane_count
  7. tc_port_fixup_legacy_flag
  8. tc_port_live_status_mask
  9. icl_tc_phy_status_complete
  10. icl_tc_phy_set_safe_mode
  11. icl_tc_phy_is_in_safe_mode
  12. icl_tc_phy_connect
  13. icl_tc_phy_disconnect
  14. icl_tc_phy_is_connected
  15. intel_tc_port_get_current_mode
  16. intel_tc_port_get_target_mode
  17. intel_tc_port_reset_mode
  18. intel_tc_port_link_init_refcount
  19. intel_tc_port_sanitize
  20. intel_tc_port_needs_reset
  21. intel_tc_port_connected
  22. __intel_tc_port_lock
  23. intel_tc_port_lock
  24. intel_tc_port_unlock
  25. intel_tc_port_ref_held
  26. intel_tc_port_get_link
  27. intel_tc_port_put_link
  28. intel_tc_port_init

   1 // SPDX-License-Identifier: MIT
   2 /*
   3  * Copyright © 2019 Intel Corporation
   4  */
   5 
   6 #include "i915_drv.h"
   7 #include "intel_display.h"
   8 #include "intel_display_types.h"
   9 #include "intel_dp_mst.h"
  10 #include "intel_tc.h"
  11 
  12 static const char *tc_port_mode_name(enum tc_port_mode mode)
  13 {
  14         static const char * const names[] = {
  15                 [TC_PORT_TBT_ALT] = "tbt-alt",
  16                 [TC_PORT_DP_ALT] = "dp-alt",
  17                 [TC_PORT_LEGACY] = "legacy",
  18         };
  19 
  20         if (WARN_ON(mode >= ARRAY_SIZE(names)))
  21                 mode = TC_PORT_TBT_ALT;
  22 
  23         return names[mode];
  24 }
  25 
  26 static bool has_modular_fia(struct drm_i915_private *i915)
  27 {
  28         if (!INTEL_INFO(i915)->display.has_modular_fia)
  29                 return false;
  30 
  31         return intel_uncore_read(&i915->uncore,
  32                                  PORT_TX_DFLEXDPSP(FIA1)) & MODULAR_FIA_MASK;
  33 }
  34 
  35 static enum phy_fia tc_port_to_fia(struct drm_i915_private *i915,
  36                                    enum tc_port tc_port)
  37 {
  38         if (!has_modular_fia(i915))
  39                 return FIA1;
  40 
  41         /*
  42          * Each Modular FIA instance houses 2 TC ports. In SOC that has more
  43          * than two TC ports, there are multiple instances of Modular FIA.
  44          */
  45         return tc_port / 2;
  46 }
  47 
  48 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
  49 {
  50         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
  51         enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
  52         struct intel_uncore *uncore = &i915->uncore;
  53         u32 lane_mask;
  54 
  55         lane_mask = intel_uncore_read(uncore,
  56                                       PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
  57 
  58         WARN_ON(lane_mask == 0xffffffff);
  59 
  60         return (lane_mask & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
  61                DP_LANE_ASSIGNMENT_SHIFT(tc_port);
  62 }
  63 
  64 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
  65 {
  66         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
  67         intel_wakeref_t wakeref;
  68         u32 lane_mask;
  69 
  70         if (dig_port->tc_mode != TC_PORT_DP_ALT)
  71                 return 4;
  72 
  73         lane_mask = 0;
  74         with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
  75                 lane_mask = intel_tc_port_get_lane_mask(dig_port);
  76 
  77         switch (lane_mask) {
  78         default:
  79                 MISSING_CASE(lane_mask);
  80                 /* fall-through */
  81         case 0x1:
  82         case 0x2:
  83         case 0x4:
  84         case 0x8:
  85                 return 1;
  86         case 0x3:
  87         case 0xc:
  88                 return 2;
  89         case 0xf:
  90                 return 4;
  91         }
  92 }
  93 
  94 void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
  95                                       int required_lanes)
  96 {
  97         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
  98         enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
  99         bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
 100         struct intel_uncore *uncore = &i915->uncore;
 101         u32 val;
 102 
 103         WARN_ON(lane_reversal && dig_port->tc_mode != TC_PORT_LEGACY);
 104 
 105         val = intel_uncore_read(uncore,
 106                                 PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia));
 107         val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc_port);
 108 
 109         switch (required_lanes) {
 110         case 1:
 111                 val |= lane_reversal ? DFLEXDPMLE1_DPMLETC_ML3(tc_port) :
 112                         DFLEXDPMLE1_DPMLETC_ML0(tc_port);
 113                 break;
 114         case 2:
 115                 val |= lane_reversal ? DFLEXDPMLE1_DPMLETC_ML3_2(tc_port) :
 116                         DFLEXDPMLE1_DPMLETC_ML1_0(tc_port);
 117                 break;
 118         case 4:
 119                 val |= DFLEXDPMLE1_DPMLETC_ML3_0(tc_port);
 120                 break;
 121         default:
 122                 MISSING_CASE(required_lanes);
 123         }
 124 
 125         intel_uncore_write(uncore,
 126                            PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val);
 127 }
 128 
 129 static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
 130                                       u32 live_status_mask)
 131 {
 132         u32 valid_hpd_mask;
 133 
 134         if (dig_port->tc_legacy_port)
 135                 valid_hpd_mask = BIT(TC_PORT_LEGACY);
 136         else
 137                 valid_hpd_mask = BIT(TC_PORT_DP_ALT) |
 138                                  BIT(TC_PORT_TBT_ALT);
 139 
 140         if (!(live_status_mask & ~valid_hpd_mask))
 141                 return;
 142 
 143         /* If live status mismatches the VBT flag, trust the live status. */
 144         DRM_ERROR("Port %s: live status %08x mismatches the legacy port flag, fix flag\n",
 145                   dig_port->tc_port_name, live_status_mask);
 146 
 147         dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
 148 }
 149 
 150 static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
 151 {
 152         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 153         enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
 154         struct intel_uncore *uncore = &i915->uncore;
 155         u32 mask = 0;
 156         u32 val;
 157 
 158         val = intel_uncore_read(uncore,
 159                                 PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
 160 
 161         if (val == 0xffffffff) {
 162                 DRM_DEBUG_KMS("Port %s: PHY in TCCOLD, nothing connected\n",
 163                               dig_port->tc_port_name);
 164                 return mask;
 165         }
 166 
 167         if (val & TC_LIVE_STATE_TBT(tc_port))
 168                 mask |= BIT(TC_PORT_TBT_ALT);
 169         if (val & TC_LIVE_STATE_TC(tc_port))
 170                 mask |= BIT(TC_PORT_DP_ALT);
 171 
 172         if (intel_uncore_read(uncore, SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))
 173                 mask |= BIT(TC_PORT_LEGACY);
 174 
 175         /* The sink can be connected only in a single mode. */
 176         if (!WARN_ON(hweight32(mask) > 1))
 177                 tc_port_fixup_legacy_flag(dig_port, mask);
 178 
 179         return mask;
 180 }
 181 
 182 static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
 183 {
 184         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 185         enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
 186         struct intel_uncore *uncore = &i915->uncore;
 187         u32 val;
 188 
 189         val = intel_uncore_read(uncore,
 190                                 PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia));
 191         if (val == 0xffffffff) {
 192                 DRM_DEBUG_KMS("Port %s: PHY in TCCOLD, assuming not complete\n",
 193                               dig_port->tc_port_name);
 194                 return false;
 195         }
 196 
 197         return val & DP_PHY_MODE_STATUS_COMPLETED(tc_port);
 198 }
 199 
 200 static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
 201                                      bool enable)
 202 {
 203         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 204         enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
 205         struct intel_uncore *uncore = &i915->uncore;
 206         u32 val;
 207 
 208         val = intel_uncore_read(uncore,
 209                                 PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
 210         if (val == 0xffffffff) {
 211                 DRM_DEBUG_KMS("Port %s: PHY in TCCOLD, can't set safe-mode to %s\n",
 212                               dig_port->tc_port_name,
 213                               enableddisabled(enable));
 214 
 215                 return false;
 216         }
 217 
 218         val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
 219         if (!enable)
 220                 val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc_port);
 221 
 222         intel_uncore_write(uncore,
 223                            PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val);
 224 
 225         if (enable && wait_for(!icl_tc_phy_status_complete(dig_port), 10))
 226                 DRM_DEBUG_KMS("Port %s: PHY complete clear timed out\n",
 227                               dig_port->tc_port_name);
 228 
 229         return true;
 230 }
 231 
 232 static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
 233 {
 234         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 235         enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
 236         struct intel_uncore *uncore = &i915->uncore;
 237         u32 val;
 238 
 239         val = intel_uncore_read(uncore,
 240                                 PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
 241         if (val == 0xffffffff) {
 242                 DRM_DEBUG_KMS("Port %s: PHY in TCCOLD, assume safe mode\n",
 243                               dig_port->tc_port_name);
 244                 return true;
 245         }
 246 
 247         return !(val & DP_PHY_MODE_STATUS_NOT_SAFE(tc_port));
 248 }
 249 
 250 /*
 251  * This function implements the first part of the Connect Flow described by our
 252  * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
 253  * lanes, EDID, etc) is done as needed in the typical places.
 254  *
 255  * Unlike the other ports, type-C ports are not available to use as soon as we
 256  * get a hotplug. The type-C PHYs can be shared between multiple controllers:
 257  * display, USB, etc. As a result, handshaking through FIA is required around
 258  * connect and disconnect to cleanly transfer ownership with the controller and
 259  * set the type-C power state.
 260  */
 261 static void icl_tc_phy_connect(struct intel_digital_port *dig_port,
 262                                int required_lanes)
 263 {
 264         int max_lanes;
 265 
 266         if (!icl_tc_phy_status_complete(dig_port)) {
 267                 DRM_DEBUG_KMS("Port %s: PHY not ready\n",
 268                               dig_port->tc_port_name);
 269                 goto out_set_tbt_alt_mode;
 270         }
 271 
 272         if (!icl_tc_phy_set_safe_mode(dig_port, false) &&
 273             !WARN_ON(dig_port->tc_legacy_port))
 274                 goto out_set_tbt_alt_mode;
 275 
 276         max_lanes = intel_tc_port_fia_max_lane_count(dig_port);
 277         if (dig_port->tc_legacy_port) {
 278                 WARN_ON(max_lanes != 4);
 279                 dig_port->tc_mode = TC_PORT_LEGACY;
 280 
 281                 return;
 282         }
 283 
 284         /*
 285          * Now we have to re-check the live state, in case the port recently
 286          * became disconnected. Not necessary for legacy mode.
 287          */
 288         if (!(tc_port_live_status_mask(dig_port) & BIT(TC_PORT_DP_ALT))) {
 289                 DRM_DEBUG_KMS("Port %s: PHY sudden disconnect\n",
 290                               dig_port->tc_port_name);
 291                 goto out_set_safe_mode;
 292         }
 293 
 294         if (max_lanes < required_lanes) {
 295                 DRM_DEBUG_KMS("Port %s: PHY max lanes %d < required lanes %d\n",
 296                               dig_port->tc_port_name,
 297                               max_lanes, required_lanes);
 298                 goto out_set_safe_mode;
 299         }
 300 
 301         dig_port->tc_mode = TC_PORT_DP_ALT;
 302 
 303         return;
 304 
 305 out_set_safe_mode:
 306         icl_tc_phy_set_safe_mode(dig_port, true);
 307 out_set_tbt_alt_mode:
 308         dig_port->tc_mode = TC_PORT_TBT_ALT;
 309 }
 310 
 311 /*
 312  * See the comment at the connect function. This implements the Disconnect
 313  * Flow.
 314  */
 315 static void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
 316 {
 317         switch (dig_port->tc_mode) {
 318         case TC_PORT_LEGACY:
 319                 /* Nothing to do, we never disconnect from legacy mode */
 320                 break;
 321         case TC_PORT_DP_ALT:
 322                 icl_tc_phy_set_safe_mode(dig_port, true);
 323                 dig_port->tc_mode = TC_PORT_TBT_ALT;
 324                 break;
 325         case TC_PORT_TBT_ALT:
 326                 /* Nothing to do, we stay in TBT-alt mode */
 327                 break;
 328         default:
 329                 MISSING_CASE(dig_port->tc_mode);
 330         }
 331 }
 332 
 333 static bool icl_tc_phy_is_connected(struct intel_digital_port *dig_port)
 334 {
 335         if (!icl_tc_phy_status_complete(dig_port)) {
 336                 DRM_DEBUG_KMS("Port %s: PHY status not complete\n",
 337                               dig_port->tc_port_name);
 338                 return dig_port->tc_mode == TC_PORT_TBT_ALT;
 339         }
 340 
 341         if (icl_tc_phy_is_in_safe_mode(dig_port)) {
 342                 DRM_DEBUG_KMS("Port %s: PHY still in safe mode\n",
 343                               dig_port->tc_port_name);
 344 
 345                 return false;
 346         }
 347 
 348         return dig_port->tc_mode == TC_PORT_DP_ALT ||
 349                dig_port->tc_mode == TC_PORT_LEGACY;
 350 }
 351 
 352 static enum tc_port_mode
 353 intel_tc_port_get_current_mode(struct intel_digital_port *dig_port)
 354 {
 355         u32 live_status_mask = tc_port_live_status_mask(dig_port);
 356         bool in_safe_mode = icl_tc_phy_is_in_safe_mode(dig_port);
 357         enum tc_port_mode mode;
 358 
 359         if (in_safe_mode || WARN_ON(!icl_tc_phy_status_complete(dig_port)))
 360                 return TC_PORT_TBT_ALT;
 361 
 362         mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY : TC_PORT_DP_ALT;
 363         if (live_status_mask) {
 364                 enum tc_port_mode live_mode = fls(live_status_mask) - 1;
 365 
 366                 if (!WARN_ON(live_mode == TC_PORT_TBT_ALT))
 367                         mode = live_mode;
 368         }
 369 
 370         return mode;
 371 }
 372 
 373 static enum tc_port_mode
 374 intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
 375 {
 376         u32 live_status_mask = tc_port_live_status_mask(dig_port);
 377 
 378         if (live_status_mask)
 379                 return fls(live_status_mask) - 1;
 380 
 381         return icl_tc_phy_status_complete(dig_port) &&
 382                dig_port->tc_legacy_port ? TC_PORT_LEGACY :
 383                                           TC_PORT_TBT_ALT;
 384 }
 385 
 386 static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
 387                                      int required_lanes)
 388 {
 389         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 390         enum tc_port_mode old_tc_mode = dig_port->tc_mode;
 391 
 392         intel_display_power_flush_work(i915);
 393         WARN_ON(intel_display_power_is_enabled(i915,
 394                                                intel_aux_power_domain(dig_port)));
 395 
 396         icl_tc_phy_disconnect(dig_port);
 397         icl_tc_phy_connect(dig_port, required_lanes);
 398 
 399         DRM_DEBUG_KMS("Port %s: TC port mode reset (%s -> %s)\n",
 400                       dig_port->tc_port_name,
 401                       tc_port_mode_name(old_tc_mode),
 402                       tc_port_mode_name(dig_port->tc_mode));
 403 }
 404 
 405 static void
 406 intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port,
 407                                  int refcount)
 408 {
 409         WARN_ON(dig_port->tc_link_refcount);
 410         dig_port->tc_link_refcount = refcount;
 411 }
 412 
 413 void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
 414 {
 415         struct intel_encoder *encoder = &dig_port->base;
 416         int active_links = 0;
 417 
 418         mutex_lock(&dig_port->tc_lock);
 419 
 420         dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
 421         if (dig_port->dp.is_mst)
 422                 active_links = intel_dp_mst_encoder_active_links(dig_port);
 423         else if (encoder->base.crtc)
 424                 active_links = to_intel_crtc(encoder->base.crtc)->active;
 425 
 426         if (active_links) {
 427                 if (!icl_tc_phy_is_connected(dig_port))
 428                         DRM_DEBUG_KMS("Port %s: PHY disconnected with %d active link(s)\n",
 429                                       dig_port->tc_port_name, active_links);
 430                 intel_tc_port_link_init_refcount(dig_port, active_links);
 431 
 432                 goto out;
 433         }
 434 
 435         if (dig_port->tc_legacy_port)
 436                 icl_tc_phy_connect(dig_port, 1);
 437 
 438 out:
 439         DRM_DEBUG_KMS("Port %s: sanitize mode (%s)\n",
 440                       dig_port->tc_port_name,
 441                       tc_port_mode_name(dig_port->tc_mode));
 442 
 443         mutex_unlock(&dig_port->tc_lock);
 444 }
 445 
 446 static bool intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
 447 {
 448         return intel_tc_port_get_target_mode(dig_port) != dig_port->tc_mode;
 449 }
 450 
 451 /*
 452  * The type-C ports are different because even when they are connected, they may
 453  * not be available/usable by the graphics driver: see the comment on
 454  * icl_tc_phy_connect(). So in our driver instead of adding the additional
 455  * concept of "usable" and make everything check for "connected and usable" we
 456  * define a port as "connected" when it is not only connected, but also when it
 457  * is usable by the rest of the driver. That maintains the old assumption that
 458  * connected ports are usable, and avoids exposing to the users objects they
 459  * can't really use.
 460  */
 461 bool intel_tc_port_connected(struct intel_digital_port *dig_port)
 462 {
 463         bool is_connected;
 464 
 465         intel_tc_port_lock(dig_port);
 466         is_connected = tc_port_live_status_mask(dig_port) &
 467                        BIT(dig_port->tc_mode);
 468         intel_tc_port_unlock(dig_port);
 469 
 470         return is_connected;
 471 }
 472 
 473 static void __intel_tc_port_lock(struct intel_digital_port *dig_port,
 474                                  int required_lanes)
 475 {
 476         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 477         intel_wakeref_t wakeref;
 478 
 479         wakeref = intel_display_power_get(i915, POWER_DOMAIN_DISPLAY_CORE);
 480 
 481         mutex_lock(&dig_port->tc_lock);
 482 
 483         if (!dig_port->tc_link_refcount &&
 484             intel_tc_port_needs_reset(dig_port))
 485                 intel_tc_port_reset_mode(dig_port, required_lanes);
 486 
 487         WARN_ON(dig_port->tc_lock_wakeref);
 488         dig_port->tc_lock_wakeref = wakeref;
 489 }
 490 
 491 void intel_tc_port_lock(struct intel_digital_port *dig_port)
 492 {
 493         __intel_tc_port_lock(dig_port, 1);
 494 }
 495 
 496 void intel_tc_port_unlock(struct intel_digital_port *dig_port)
 497 {
 498         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 499         intel_wakeref_t wakeref = fetch_and_zero(&dig_port->tc_lock_wakeref);
 500 
 501         mutex_unlock(&dig_port->tc_lock);
 502 
 503         intel_display_power_put_async(i915, POWER_DOMAIN_DISPLAY_CORE,
 504                                       wakeref);
 505 }
 506 
 507 bool intel_tc_port_ref_held(struct intel_digital_port *dig_port)
 508 {
 509         return mutex_is_locked(&dig_port->tc_lock) ||
 510                dig_port->tc_link_refcount;
 511 }
 512 
 513 void intel_tc_port_get_link(struct intel_digital_port *dig_port,
 514                             int required_lanes)
 515 {
 516         __intel_tc_port_lock(dig_port, required_lanes);
 517         dig_port->tc_link_refcount++;
 518         intel_tc_port_unlock(dig_port);
 519 }
 520 
 521 void intel_tc_port_put_link(struct intel_digital_port *dig_port)
 522 {
 523         mutex_lock(&dig_port->tc_lock);
 524         dig_port->tc_link_refcount--;
 525         mutex_unlock(&dig_port->tc_lock);
 526 }
 527 
 528 void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
 529 {
 530         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
 531         enum port port = dig_port->base.port;
 532         enum tc_port tc_port = intel_port_to_tc(i915, port);
 533 
 534         if (WARN_ON(tc_port == PORT_TC_NONE))
 535                 return;
 536 
 537         snprintf(dig_port->tc_port_name, sizeof(dig_port->tc_port_name),
 538                  "%c/TC#%d", port_name(port), tc_port + 1);
 539 
 540         mutex_init(&dig_port->tc_lock);
 541         dig_port->tc_legacy_port = is_legacy;
 542         dig_port->tc_link_refcount = 0;
 543         dig_port->tc_phy_fia = tc_port_to_fia(i915, tc_port);
 544 }

/* [<][>][^][v][top][bottom][index][help] */