1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2019 Intel Corporation 4 */ 5 6 #include "i915_drv.h" 7 #include "i915_reg.h" 8 #include "intel_display.h" 9 #include "intel_display_power_map.h" 10 #include "intel_display_types.h" 11 #include "intel_dkl_phy_regs.h" 12 #include "intel_dp_mst.h" 13 #include "intel_mg_phy_regs.h" 14 #include "intel_tc.h" 15 16 static const char *tc_port_mode_name(enum tc_port_mode mode) 17 { 18 static const char * const names[] = { 19 [TC_PORT_DISCONNECTED] = "disconnected", 20 [TC_PORT_TBT_ALT] = "tbt-alt", 21 [TC_PORT_DP_ALT] = "dp-alt", 22 [TC_PORT_LEGACY] = "legacy", 23 }; 24 25 if (WARN_ON(mode >= ARRAY_SIZE(names))) 26 mode = TC_PORT_DISCONNECTED; 27 28 return names[mode]; 29 } 30 31 static bool intel_tc_port_in_mode(struct intel_digital_port *dig_port, 32 enum tc_port_mode mode) 33 { 34 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 35 enum phy phy = intel_port_to_phy(i915, dig_port->base.port); 36 37 return intel_phy_is_tc(i915, phy) && dig_port->tc_mode == mode; 38 } 39 40 bool intel_tc_port_in_tbt_alt_mode(struct intel_digital_port *dig_port) 41 { 42 return intel_tc_port_in_mode(dig_port, TC_PORT_TBT_ALT); 43 } 44 45 bool intel_tc_port_in_dp_alt_mode(struct intel_digital_port *dig_port) 46 { 47 return intel_tc_port_in_mode(dig_port, TC_PORT_DP_ALT); 48 } 49 50 bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port) 51 { 52 return intel_tc_port_in_mode(dig_port, TC_PORT_LEGACY); 53 } 54 55 bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port) 56 { 57 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 58 59 return (DISPLAY_VER(i915) == 11 && dig_port->tc_legacy_port) || 60 IS_ALDERLAKE_P(i915); 61 } 62 63 static enum intel_display_power_domain 64 tc_cold_get_power_domain(struct intel_digital_port *dig_port, enum tc_port_mode mode) 65 { 66 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 67 68 if (mode == TC_PORT_TBT_ALT || !intel_tc_cold_requires_aux_pw(dig_port)) 69 return POWER_DOMAIN_TC_COLD_OFF; 70 71 return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); 72 } 73 74 static intel_wakeref_t 75 tc_cold_block_in_mode(struct intel_digital_port *dig_port, enum tc_port_mode mode, 76 enum intel_display_power_domain *domain) 77 { 78 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 79 80 *domain = tc_cold_get_power_domain(dig_port, mode); 81 82 return intel_display_power_get(i915, *domain); 83 } 84 85 static intel_wakeref_t 86 tc_cold_block(struct intel_digital_port *dig_port, enum intel_display_power_domain *domain) 87 { 88 return tc_cold_block_in_mode(dig_port, dig_port->tc_mode, domain); 89 } 90 91 static void 92 tc_cold_unblock(struct intel_digital_port *dig_port, enum intel_display_power_domain domain, 93 intel_wakeref_t wakeref) 94 { 95 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 96 97 /* 98 * wakeref == -1, means some error happened saving save_depot_stack but 99 * power should still be put down and 0 is a invalid save_depot_stack 100 * id so can be used to skip it for non TC legacy ports. 101 */ 102 if (wakeref == 0) 103 return; 104 105 intel_display_power_put(i915, domain, wakeref); 106 } 107 108 static void 109 assert_tc_cold_blocked(struct intel_digital_port *dig_port) 110 { 111 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 112 bool enabled; 113 114 enabled = intel_display_power_is_enabled(i915, 115 tc_cold_get_power_domain(dig_port, 116 dig_port->tc_mode)); 117 drm_WARN_ON(&i915->drm, !enabled); 118 } 119 120 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port) 121 { 122 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 123 struct intel_uncore *uncore = &i915->uncore; 124 u32 lane_mask; 125 126 lane_mask = intel_uncore_read(uncore, 127 PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); 128 129 drm_WARN_ON(&i915->drm, lane_mask == 0xffffffff); 130 assert_tc_cold_blocked(dig_port); 131 132 lane_mask &= DP_LANE_ASSIGNMENT_MASK(dig_port->tc_phy_fia_idx); 133 return lane_mask >> DP_LANE_ASSIGNMENT_SHIFT(dig_port->tc_phy_fia_idx); 134 } 135 136 u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port) 137 { 138 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 139 struct intel_uncore *uncore = &i915->uncore; 140 u32 pin_mask; 141 142 pin_mask = intel_uncore_read(uncore, 143 PORT_TX_DFLEXPA1(dig_port->tc_phy_fia)); 144 145 drm_WARN_ON(&i915->drm, pin_mask == 0xffffffff); 146 assert_tc_cold_blocked(dig_port); 147 148 return (pin_mask & DP_PIN_ASSIGNMENT_MASK(dig_port->tc_phy_fia_idx)) >> 149 DP_PIN_ASSIGNMENT_SHIFT(dig_port->tc_phy_fia_idx); 150 } 151 152 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port) 153 { 154 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 155 intel_wakeref_t wakeref; 156 u32 lane_mask; 157 158 if (dig_port->tc_mode != TC_PORT_DP_ALT) 159 return 4; 160 161 assert_tc_cold_blocked(dig_port); 162 163 lane_mask = 0; 164 with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref) 165 lane_mask = intel_tc_port_get_lane_mask(dig_port); 166 167 switch (lane_mask) { 168 default: 169 MISSING_CASE(lane_mask); 170 fallthrough; 171 case 0x1: 172 case 0x2: 173 case 0x4: 174 case 0x8: 175 return 1; 176 case 0x3: 177 case 0xc: 178 return 2; 179 case 0xf: 180 return 4; 181 } 182 } 183 184 void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, 185 int required_lanes) 186 { 187 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 188 bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; 189 struct intel_uncore *uncore = &i915->uncore; 190 u32 val; 191 192 drm_WARN_ON(&i915->drm, 193 lane_reversal && dig_port->tc_mode != TC_PORT_LEGACY); 194 195 assert_tc_cold_blocked(dig_port); 196 197 val = intel_uncore_read(uncore, 198 PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia)); 199 val &= ~DFLEXDPMLE1_DPMLETC_MASK(dig_port->tc_phy_fia_idx); 200 201 switch (required_lanes) { 202 case 1: 203 val |= lane_reversal ? 204 DFLEXDPMLE1_DPMLETC_ML3(dig_port->tc_phy_fia_idx) : 205 DFLEXDPMLE1_DPMLETC_ML0(dig_port->tc_phy_fia_idx); 206 break; 207 case 2: 208 val |= lane_reversal ? 209 DFLEXDPMLE1_DPMLETC_ML3_2(dig_port->tc_phy_fia_idx) : 210 DFLEXDPMLE1_DPMLETC_ML1_0(dig_port->tc_phy_fia_idx); 211 break; 212 case 4: 213 val |= DFLEXDPMLE1_DPMLETC_ML3_0(dig_port->tc_phy_fia_idx); 214 break; 215 default: 216 MISSING_CASE(required_lanes); 217 } 218 219 intel_uncore_write(uncore, 220 PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val); 221 } 222 223 static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port, 224 u32 live_status_mask) 225 { 226 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 227 u32 valid_hpd_mask; 228 229 if (dig_port->tc_legacy_port) 230 valid_hpd_mask = BIT(TC_PORT_LEGACY); 231 else 232 valid_hpd_mask = BIT(TC_PORT_DP_ALT) | 233 BIT(TC_PORT_TBT_ALT); 234 235 if (!(live_status_mask & ~valid_hpd_mask)) 236 return; 237 238 /* If live status mismatches the VBT flag, trust the live status. */ 239 drm_dbg_kms(&i915->drm, 240 "Port %s: live status %08x mismatches the legacy port flag %08x, fixing flag\n", 241 dig_port->tc_port_name, live_status_mask, valid_hpd_mask); 242 243 dig_port->tc_legacy_port = !dig_port->tc_legacy_port; 244 } 245 246 static u32 icl_tc_port_live_status_mask(struct intel_digital_port *dig_port) 247 { 248 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 249 struct intel_uncore *uncore = &i915->uncore; 250 u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; 251 u32 mask = 0; 252 u32 val; 253 254 val = intel_uncore_read(uncore, 255 PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia)); 256 257 if (val == 0xffffffff) { 258 drm_dbg_kms(&i915->drm, 259 "Port %s: PHY in TCCOLD, nothing connected\n", 260 dig_port->tc_port_name); 261 return mask; 262 } 263 264 if (val & TC_LIVE_STATE_TBT(dig_port->tc_phy_fia_idx)) 265 mask |= BIT(TC_PORT_TBT_ALT); 266 if (val & TC_LIVE_STATE_TC(dig_port->tc_phy_fia_idx)) 267 mask |= BIT(TC_PORT_DP_ALT); 268 269 if (intel_uncore_read(uncore, SDEISR) & isr_bit) 270 mask |= BIT(TC_PORT_LEGACY); 271 272 /* The sink can be connected only in a single mode. */ 273 if (!drm_WARN_ON_ONCE(&i915->drm, hweight32(mask) > 1)) 274 tc_port_fixup_legacy_flag(dig_port, mask); 275 276 return mask; 277 } 278 279 static u32 adl_tc_port_live_status_mask(struct intel_digital_port *dig_port) 280 { 281 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 282 enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); 283 u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; 284 struct intel_uncore *uncore = &i915->uncore; 285 u32 val, mask = 0; 286 287 /* 288 * On ADL-P HW/FW will wake from TCCOLD to complete the read access of 289 * registers in IOM. Note that this doesn't apply to PHY and FIA 290 * registers. 291 */ 292 val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port)); 293 if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT) 294 mask |= BIT(TC_PORT_DP_ALT); 295 if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT) 296 mask |= BIT(TC_PORT_TBT_ALT); 297 298 if (intel_uncore_read(uncore, SDEISR) & isr_bit) 299 mask |= BIT(TC_PORT_LEGACY); 300 301 /* The sink can be connected only in a single mode. */ 302 if (!drm_WARN_ON(&i915->drm, hweight32(mask) > 1)) 303 tc_port_fixup_legacy_flag(dig_port, mask); 304 305 return mask; 306 } 307 308 static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port) 309 { 310 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 311 312 if (IS_ALDERLAKE_P(i915)) 313 return adl_tc_port_live_status_mask(dig_port); 314 315 return icl_tc_port_live_status_mask(dig_port); 316 } 317 318 /* 319 * Return the PHY status complete flag indicating that display can acquire the 320 * PHY ownership. The IOM firmware sets this flag when a DP-alt or legacy sink 321 * is connected and it's ready to switch the ownership to display. The flag 322 * will be left cleared when a TBT-alt sink is connected, where the PHY is 323 * owned by the TBT subsystem and so switching the ownership to display is not 324 * required. 325 */ 326 static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port) 327 { 328 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 329 struct intel_uncore *uncore = &i915->uncore; 330 u32 val; 331 332 val = intel_uncore_read(uncore, 333 PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia)); 334 if (val == 0xffffffff) { 335 drm_dbg_kms(&i915->drm, 336 "Port %s: PHY in TCCOLD, assuming not complete\n", 337 dig_port->tc_port_name); 338 return false; 339 } 340 341 return val & DP_PHY_MODE_STATUS_COMPLETED(dig_port->tc_phy_fia_idx); 342 } 343 344 /* 345 * Return the PHY status complete flag indicating that display can acquire the 346 * PHY ownership. The IOM firmware sets this flag when it's ready to switch 347 * the ownership to display, regardless of what sink is connected (TBT-alt, 348 * DP-alt, legacy or nothing). For TBT-alt sinks the PHY is owned by the TBT 349 * subsystem and so switching the ownership to display is not required. 350 */ 351 static bool adl_tc_phy_status_complete(struct intel_digital_port *dig_port) 352 { 353 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 354 enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); 355 struct intel_uncore *uncore = &i915->uncore; 356 u32 val; 357 358 val = intel_uncore_read(uncore, TCSS_DDI_STATUS(tc_port)); 359 if (val == 0xffffffff) { 360 drm_dbg_kms(&i915->drm, 361 "Port %s: PHY in TCCOLD, assuming not complete\n", 362 dig_port->tc_port_name); 363 return false; 364 } 365 366 return val & TCSS_DDI_STATUS_READY; 367 } 368 369 static bool tc_phy_status_complete(struct intel_digital_port *dig_port) 370 { 371 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 372 373 if (IS_ALDERLAKE_P(i915)) 374 return adl_tc_phy_status_complete(dig_port); 375 376 return icl_tc_phy_status_complete(dig_port); 377 } 378 379 static bool icl_tc_phy_take_ownership(struct intel_digital_port *dig_port, 380 bool take) 381 { 382 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 383 struct intel_uncore *uncore = &i915->uncore; 384 u32 val; 385 386 val = intel_uncore_read(uncore, 387 PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); 388 if (val == 0xffffffff) { 389 drm_dbg_kms(&i915->drm, 390 "Port %s: PHY in TCCOLD, can't %s ownership\n", 391 dig_port->tc_port_name, take ? "take" : "release"); 392 393 return false; 394 } 395 396 val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx); 397 if (take) 398 val |= DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx); 399 400 intel_uncore_write(uncore, 401 PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val); 402 403 return true; 404 } 405 406 static bool adl_tc_phy_take_ownership(struct intel_digital_port *dig_port, 407 bool take) 408 { 409 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 410 struct intel_uncore *uncore = &i915->uncore; 411 enum port port = dig_port->base.port; 412 413 intel_uncore_rmw(uncore, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP, 414 take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0); 415 416 return true; 417 } 418 419 static bool tc_phy_take_ownership(struct intel_digital_port *dig_port, bool take) 420 { 421 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 422 423 if (IS_ALDERLAKE_P(i915)) 424 return adl_tc_phy_take_ownership(dig_port, take); 425 426 return icl_tc_phy_take_ownership(dig_port, take); 427 } 428 429 static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port) 430 { 431 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 432 struct intel_uncore *uncore = &i915->uncore; 433 u32 val; 434 435 val = intel_uncore_read(uncore, 436 PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia)); 437 if (val == 0xffffffff) { 438 drm_dbg_kms(&i915->drm, 439 "Port %s: PHY in TCCOLD, assume safe mode\n", 440 dig_port->tc_port_name); 441 return true; 442 } 443 444 return val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx); 445 } 446 447 static bool adl_tc_phy_is_owned(struct intel_digital_port *dig_port) 448 { 449 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 450 struct intel_uncore *uncore = &i915->uncore; 451 enum port port = dig_port->base.port; 452 u32 val; 453 454 val = intel_uncore_read(uncore, DDI_BUF_CTL(port)); 455 return val & DDI_BUF_CTL_TC_PHY_OWNERSHIP; 456 } 457 458 static bool tc_phy_is_owned(struct intel_digital_port *dig_port) 459 { 460 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 461 462 if (IS_ALDERLAKE_P(i915)) 463 return adl_tc_phy_is_owned(dig_port); 464 465 return icl_tc_phy_is_owned(dig_port); 466 } 467 468 /* 469 * This function implements the first part of the Connect Flow described by our 470 * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading 471 * lanes, EDID, etc) is done as needed in the typical places. 472 * 473 * Unlike the other ports, type-C ports are not available to use as soon as we 474 * get a hotplug. The type-C PHYs can be shared between multiple controllers: 475 * display, USB, etc. As a result, handshaking through FIA is required around 476 * connect and disconnect to cleanly transfer ownership with the controller and 477 * set the type-C power state. 478 */ 479 static void icl_tc_phy_connect(struct intel_digital_port *dig_port, 480 int required_lanes) 481 { 482 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 483 u32 live_status_mask; 484 int max_lanes; 485 486 if (!tc_phy_status_complete(dig_port)) { 487 drm_dbg_kms(&i915->drm, "Port %s: PHY not ready\n", 488 dig_port->tc_port_name); 489 goto out_set_tbt_alt_mode; 490 } 491 492 live_status_mask = tc_port_live_status_mask(dig_port); 493 if (!(live_status_mask & (BIT(TC_PORT_DP_ALT) | BIT(TC_PORT_LEGACY))) && 494 !dig_port->tc_legacy_port) { 495 drm_dbg_kms(&i915->drm, "Port %s: PHY ownership not required (live status %02x)\n", 496 dig_port->tc_port_name, live_status_mask); 497 goto out_set_tbt_alt_mode; 498 } 499 500 if (!tc_phy_take_ownership(dig_port, true) && 501 !drm_WARN_ON(&i915->drm, dig_port->tc_legacy_port)) 502 goto out_set_tbt_alt_mode; 503 504 max_lanes = intel_tc_port_fia_max_lane_count(dig_port); 505 if (dig_port->tc_legacy_port) { 506 drm_WARN_ON(&i915->drm, max_lanes != 4); 507 dig_port->tc_mode = TC_PORT_LEGACY; 508 509 return; 510 } 511 512 /* 513 * Now we have to re-check the live state, in case the port recently 514 * became disconnected. Not necessary for legacy mode. 515 */ 516 if (!(tc_port_live_status_mask(dig_port) & BIT(TC_PORT_DP_ALT))) { 517 drm_dbg_kms(&i915->drm, "Port %s: PHY sudden disconnect\n", 518 dig_port->tc_port_name); 519 goto out_release_phy; 520 } 521 522 if (max_lanes < required_lanes) { 523 drm_dbg_kms(&i915->drm, 524 "Port %s: PHY max lanes %d < required lanes %d\n", 525 dig_port->tc_port_name, 526 max_lanes, required_lanes); 527 goto out_release_phy; 528 } 529 530 dig_port->tc_mode = TC_PORT_DP_ALT; 531 532 return; 533 534 out_release_phy: 535 tc_phy_take_ownership(dig_port, false); 536 out_set_tbt_alt_mode: 537 dig_port->tc_mode = TC_PORT_TBT_ALT; 538 } 539 540 /* 541 * See the comment at the connect function. This implements the Disconnect 542 * Flow. 543 */ 544 static void icl_tc_phy_disconnect(struct intel_digital_port *dig_port) 545 { 546 switch (dig_port->tc_mode) { 547 case TC_PORT_LEGACY: 548 case TC_PORT_DP_ALT: 549 tc_phy_take_ownership(dig_port, false); 550 fallthrough; 551 case TC_PORT_TBT_ALT: 552 dig_port->tc_mode = TC_PORT_DISCONNECTED; 553 fallthrough; 554 case TC_PORT_DISCONNECTED: 555 break; 556 default: 557 MISSING_CASE(dig_port->tc_mode); 558 } 559 } 560 561 static bool icl_tc_phy_is_connected(struct intel_digital_port *dig_port) 562 { 563 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 564 565 if (!tc_phy_status_complete(dig_port)) { 566 drm_dbg_kms(&i915->drm, "Port %s: PHY status not complete\n", 567 dig_port->tc_port_name); 568 return dig_port->tc_mode == TC_PORT_TBT_ALT; 569 } 570 571 /* On ADL-P the PHY complete flag is set in TBT mode as well. */ 572 if (IS_ALDERLAKE_P(i915) && dig_port->tc_mode == TC_PORT_TBT_ALT) 573 return true; 574 575 if (!tc_phy_is_owned(dig_port)) { 576 drm_dbg_kms(&i915->drm, "Port %s: PHY not owned\n", 577 dig_port->tc_port_name); 578 579 return false; 580 } 581 582 return dig_port->tc_mode == TC_PORT_DP_ALT || 583 dig_port->tc_mode == TC_PORT_LEGACY; 584 } 585 586 static enum tc_port_mode 587 intel_tc_port_get_current_mode(struct intel_digital_port *dig_port) 588 { 589 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 590 u32 live_status_mask = tc_port_live_status_mask(dig_port); 591 enum tc_port_mode mode; 592 593 if (!tc_phy_is_owned(dig_port) || 594 drm_WARN_ON(&i915->drm, !tc_phy_status_complete(dig_port))) 595 return TC_PORT_TBT_ALT; 596 597 mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY : TC_PORT_DP_ALT; 598 if (live_status_mask) { 599 enum tc_port_mode live_mode = fls(live_status_mask) - 1; 600 601 if (!drm_WARN_ON(&i915->drm, live_mode == TC_PORT_TBT_ALT)) 602 mode = live_mode; 603 } 604 605 return mode; 606 } 607 608 static enum tc_port_mode 609 intel_tc_port_get_target_mode(struct intel_digital_port *dig_port) 610 { 611 u32 live_status_mask = tc_port_live_status_mask(dig_port); 612 613 if (live_status_mask) 614 return fls(live_status_mask) - 1; 615 616 return TC_PORT_TBT_ALT; 617 } 618 619 static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port, 620 int required_lanes, bool force_disconnect) 621 { 622 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 623 enum tc_port_mode old_tc_mode = dig_port->tc_mode; 624 625 intel_display_power_flush_work(i915); 626 if (!intel_tc_cold_requires_aux_pw(dig_port)) { 627 enum intel_display_power_domain aux_domain; 628 bool aux_powered; 629 630 aux_domain = intel_aux_power_domain(dig_port); 631 aux_powered = intel_display_power_is_enabled(i915, aux_domain); 632 drm_WARN_ON(&i915->drm, aux_powered); 633 } 634 635 icl_tc_phy_disconnect(dig_port); 636 if (!force_disconnect) 637 icl_tc_phy_connect(dig_port, required_lanes); 638 639 drm_dbg_kms(&i915->drm, "Port %s: TC port mode reset (%s -> %s)\n", 640 dig_port->tc_port_name, 641 tc_port_mode_name(old_tc_mode), 642 tc_port_mode_name(dig_port->tc_mode)); 643 } 644 645 static bool intel_tc_port_needs_reset(struct intel_digital_port *dig_port) 646 { 647 return intel_tc_port_get_target_mode(dig_port) != dig_port->tc_mode; 648 } 649 650 static void intel_tc_port_update_mode(struct intel_digital_port *dig_port, 651 int required_lanes, bool force_disconnect) 652 { 653 enum intel_display_power_domain domain; 654 intel_wakeref_t wref; 655 bool needs_reset = force_disconnect; 656 657 if (!needs_reset) { 658 /* Get power domain required to check the hotplug live status. */ 659 wref = tc_cold_block(dig_port, &domain); 660 needs_reset = intel_tc_port_needs_reset(dig_port); 661 tc_cold_unblock(dig_port, domain, wref); 662 } 663 664 if (!needs_reset) 665 return; 666 667 /* Get power domain required for resetting the mode. */ 668 wref = tc_cold_block_in_mode(dig_port, TC_PORT_DISCONNECTED, &domain); 669 670 intel_tc_port_reset_mode(dig_port, required_lanes, force_disconnect); 671 672 /* Get power domain matching the new mode after reset. */ 673 tc_cold_unblock(dig_port, dig_port->tc_lock_power_domain, 674 fetch_and_zero(&dig_port->tc_lock_wakeref)); 675 if (dig_port->tc_mode != TC_PORT_DISCONNECTED) 676 dig_port->tc_lock_wakeref = tc_cold_block(dig_port, 677 &dig_port->tc_lock_power_domain); 678 679 tc_cold_unblock(dig_port, domain, wref); 680 } 681 682 static void 683 intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port, 684 int refcount) 685 { 686 dig_port->tc_link_refcount = refcount; 687 } 688 689 /** 690 * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode 691 * @dig_port: digital port 692 * 693 * Read out the HW state and initialize the TypeC mode of @dig_port. The mode 694 * will be locked until intel_tc_port_sanitize_mode() is called. 695 */ 696 void intel_tc_port_init_mode(struct intel_digital_port *dig_port) 697 { 698 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 699 intel_wakeref_t tc_cold_wref; 700 enum intel_display_power_domain domain; 701 702 mutex_lock(&dig_port->tc_lock); 703 704 drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_DISCONNECTED); 705 drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref); 706 drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount); 707 708 tc_cold_wref = tc_cold_block(dig_port, &domain); 709 710 dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port); 711 /* Prevent changing dig_port->tc_mode until intel_tc_port_sanitize_mode() is called. */ 712 intel_tc_port_link_init_refcount(dig_port, 1); 713 dig_port->tc_lock_wakeref = tc_cold_block(dig_port, &dig_port->tc_lock_power_domain); 714 715 tc_cold_unblock(dig_port, domain, tc_cold_wref); 716 717 drm_dbg_kms(&i915->drm, "Port %s: init mode (%s)\n", 718 dig_port->tc_port_name, 719 tc_port_mode_name(dig_port->tc_mode)); 720 721 mutex_unlock(&dig_port->tc_lock); 722 } 723 724 /** 725 * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode 726 * @dig_port: digital port 727 * 728 * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver 729 * loading and system resume: 730 * If the encoder is enabled keep the TypeC mode/PHY connected state locked until 731 * the encoder is disabled. 732 * If the encoder is disabled make sure the PHY is disconnected. 733 */ 734 void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port) 735 { 736 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 737 struct intel_encoder *encoder = &dig_port->base; 738 int active_links = 0; 739 740 mutex_lock(&dig_port->tc_lock); 741 742 if (dig_port->dp.is_mst) 743 active_links = intel_dp_mst_encoder_active_links(dig_port); 744 else if (encoder->base.crtc) 745 active_links = to_intel_crtc(encoder->base.crtc)->active; 746 747 drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount != 1); 748 intel_tc_port_link_init_refcount(dig_port, active_links); 749 750 if (active_links) { 751 if (!icl_tc_phy_is_connected(dig_port)) 752 drm_dbg_kms(&i915->drm, 753 "Port %s: PHY disconnected with %d active link(s)\n", 754 dig_port->tc_port_name, active_links); 755 } else { 756 /* 757 * TBT-alt is the default mode in any case the PHY ownership is not 758 * held (regardless of the sink's connected live state), so 759 * we'll just switch to disconnected mode from it here without 760 * a note. 761 */ 762 if (dig_port->tc_mode != TC_PORT_TBT_ALT) 763 drm_dbg_kms(&i915->drm, 764 "Port %s: PHY left in %s mode on disabled port, disconnecting it\n", 765 dig_port->tc_port_name, 766 tc_port_mode_name(dig_port->tc_mode)); 767 icl_tc_phy_disconnect(dig_port); 768 769 tc_cold_unblock(dig_port, dig_port->tc_lock_power_domain, 770 fetch_and_zero(&dig_port->tc_lock_wakeref)); 771 } 772 773 drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n", 774 dig_port->tc_port_name, 775 tc_port_mode_name(dig_port->tc_mode)); 776 777 mutex_unlock(&dig_port->tc_lock); 778 } 779 780 /* 781 * The type-C ports are different because even when they are connected, they may 782 * not be available/usable by the graphics driver: see the comment on 783 * icl_tc_phy_connect(). So in our driver instead of adding the additional 784 * concept of "usable" and make everything check for "connected and usable" we 785 * define a port as "connected" when it is not only connected, but also when it 786 * is usable by the rest of the driver. That maintains the old assumption that 787 * connected ports are usable, and avoids exposing to the users objects they 788 * can't really use. 789 */ 790 bool intel_tc_port_connected(struct intel_encoder *encoder) 791 { 792 struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 793 bool is_connected; 794 795 intel_tc_port_lock(dig_port); 796 797 is_connected = tc_port_live_status_mask(dig_port) & 798 BIT(dig_port->tc_mode); 799 800 intel_tc_port_unlock(dig_port); 801 802 return is_connected; 803 } 804 805 static void __intel_tc_port_lock(struct intel_digital_port *dig_port, 806 int required_lanes) 807 { 808 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 809 810 mutex_lock(&dig_port->tc_lock); 811 812 cancel_delayed_work(&dig_port->tc_disconnect_phy_work); 813 814 if (!dig_port->tc_link_refcount) 815 intel_tc_port_update_mode(dig_port, required_lanes, 816 false); 817 818 drm_WARN_ON(&i915->drm, dig_port->tc_mode == TC_PORT_DISCONNECTED); 819 drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_TBT_ALT && 820 !tc_phy_is_owned(dig_port)); 821 } 822 823 void intel_tc_port_lock(struct intel_digital_port *dig_port) 824 { 825 __intel_tc_port_lock(dig_port, 1); 826 } 827 828 /** 829 * intel_tc_port_disconnect_phy_work: disconnect TypeC PHY from display port 830 * @dig_port: digital port 831 * 832 * Disconnect the given digital port from its TypeC PHY (handing back the 833 * control of the PHY to the TypeC subsystem). This will happen in a delayed 834 * manner after each aux transactions and modeset disables. 835 */ 836 static void intel_tc_port_disconnect_phy_work(struct work_struct *work) 837 { 838 struct intel_digital_port *dig_port = 839 container_of(work, struct intel_digital_port, tc_disconnect_phy_work.work); 840 841 mutex_lock(&dig_port->tc_lock); 842 843 if (!dig_port->tc_link_refcount) 844 intel_tc_port_update_mode(dig_port, 1, true); 845 846 mutex_unlock(&dig_port->tc_lock); 847 } 848 849 /** 850 * intel_tc_port_flush_work: flush the work disconnecting the PHY 851 * @dig_port: digital port 852 * 853 * Flush the delayed work disconnecting an idle PHY. 854 */ 855 void intel_tc_port_flush_work(struct intel_digital_port *dig_port) 856 { 857 flush_delayed_work(&dig_port->tc_disconnect_phy_work); 858 } 859 860 void intel_tc_port_unlock(struct intel_digital_port *dig_port) 861 { 862 if (!dig_port->tc_link_refcount && dig_port->tc_mode != TC_PORT_DISCONNECTED) 863 queue_delayed_work(system_unbound_wq, &dig_port->tc_disconnect_phy_work, 864 msecs_to_jiffies(1000)); 865 866 mutex_unlock(&dig_port->tc_lock); 867 } 868 869 bool intel_tc_port_ref_held(struct intel_digital_port *dig_port) 870 { 871 return mutex_is_locked(&dig_port->tc_lock) || 872 dig_port->tc_link_refcount; 873 } 874 875 void intel_tc_port_get_link(struct intel_digital_port *dig_port, 876 int required_lanes) 877 { 878 __intel_tc_port_lock(dig_port, required_lanes); 879 dig_port->tc_link_refcount++; 880 intel_tc_port_unlock(dig_port); 881 } 882 883 void intel_tc_port_put_link(struct intel_digital_port *dig_port) 884 { 885 intel_tc_port_lock(dig_port); 886 --dig_port->tc_link_refcount; 887 intel_tc_port_unlock(dig_port); 888 889 /* 890 * Disconnecting the PHY after the PHY's PLL gets disabled may 891 * hang the system on ADL-P, so disconnect the PHY here synchronously. 892 * TODO: remove this once the root cause of the ordering requirement 893 * is found/fixed. 894 */ 895 intel_tc_port_flush_work(dig_port); 896 } 897 898 static bool 899 tc_has_modular_fia(struct drm_i915_private *i915, struct intel_digital_port *dig_port) 900 { 901 enum intel_display_power_domain domain; 902 intel_wakeref_t wakeref; 903 u32 val; 904 905 if (!INTEL_INFO(i915)->display.has_modular_fia) 906 return false; 907 908 mutex_lock(&dig_port->tc_lock); 909 wakeref = tc_cold_block(dig_port, &domain); 910 val = intel_uncore_read(&i915->uncore, PORT_TX_DFLEXDPSP(FIA1)); 911 tc_cold_unblock(dig_port, domain, wakeref); 912 mutex_unlock(&dig_port->tc_lock); 913 914 drm_WARN_ON(&i915->drm, val == 0xffffffff); 915 916 return val & MODULAR_FIA_MASK; 917 } 918 919 static void 920 tc_port_load_fia_params(struct drm_i915_private *i915, struct intel_digital_port *dig_port) 921 { 922 enum port port = dig_port->base.port; 923 enum tc_port tc_port = intel_port_to_tc(i915, port); 924 925 /* 926 * Each Modular FIA instance houses 2 TC ports. In SOC that has more 927 * than two TC ports, there are multiple instances of Modular FIA. 928 */ 929 if (tc_has_modular_fia(i915, dig_port)) { 930 dig_port->tc_phy_fia = tc_port / 2; 931 dig_port->tc_phy_fia_idx = tc_port % 2; 932 } else { 933 dig_port->tc_phy_fia = FIA1; 934 dig_port->tc_phy_fia_idx = tc_port; 935 } 936 } 937 938 void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) 939 { 940 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 941 enum port port = dig_port->base.port; 942 enum tc_port tc_port = intel_port_to_tc(i915, port); 943 944 if (drm_WARN_ON(&i915->drm, tc_port == TC_PORT_NONE)) 945 return; 946 947 snprintf(dig_port->tc_port_name, sizeof(dig_port->tc_port_name), 948 "%c/TC#%d", port_name(port), tc_port + 1); 949 950 mutex_init(&dig_port->tc_lock); 951 INIT_DELAYED_WORK(&dig_port->tc_disconnect_phy_work, intel_tc_port_disconnect_phy_work); 952 dig_port->tc_legacy_port = is_legacy; 953 dig_port->tc_mode = TC_PORT_DISCONNECTED; 954 dig_port->tc_link_refcount = 0; 955 tc_port_load_fia_params(i915, dig_port); 956 957 intel_tc_port_init_mode(dig_port); 958 } 959