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