2542 lines · c
1/* SPDX-License-Identifier: MIT */2/*3 * Copyright © 2019 Intel Corporation4 */5 6#include <linux/string_helpers.h>7 8#include "i915_drv.h"9#include "i915_irq.h"10#include "i915_reg.h"11#include "intel_backlight_regs.h"12#include "intel_cdclk.h"13#include "intel_clock_gating.h"14#include "intel_combo_phy.h"15#include "intel_de.h"16#include "intel_display_power.h"17#include "intel_display_power_map.h"18#include "intel_display_power_well.h"19#include "intel_display_types.h"20#include "intel_dmc.h"21#include "intel_mchbar_regs.h"22#include "intel_pch_refclk.h"23#include "intel_pcode.h"24#include "intel_pmdemand.h"25#include "intel_pps_regs.h"26#include "intel_snps_phy.h"27#include "skl_watermark.h"28#include "skl_watermark_regs.h"29#include "vlv_sideband.h"30 31#define for_each_power_domain_well(__dev_priv, __power_well, __domain) \32 for_each_power_well(__dev_priv, __power_well) \33 for_each_if(test_bit((__domain), (__power_well)->domains.bits))34 35#define for_each_power_domain_well_reverse(__dev_priv, __power_well, __domain) \36 for_each_power_well_reverse(__dev_priv, __power_well) \37 for_each_if(test_bit((__domain), (__power_well)->domains.bits))38 39static const char *40intel_display_power_domain_str(enum intel_display_power_domain domain)41{42 switch (domain) {43 case POWER_DOMAIN_DISPLAY_CORE:44 return "DISPLAY_CORE";45 case POWER_DOMAIN_PIPE_A:46 return "PIPE_A";47 case POWER_DOMAIN_PIPE_B:48 return "PIPE_B";49 case POWER_DOMAIN_PIPE_C:50 return "PIPE_C";51 case POWER_DOMAIN_PIPE_D:52 return "PIPE_D";53 case POWER_DOMAIN_PIPE_PANEL_FITTER_A:54 return "PIPE_PANEL_FITTER_A";55 case POWER_DOMAIN_PIPE_PANEL_FITTER_B:56 return "PIPE_PANEL_FITTER_B";57 case POWER_DOMAIN_PIPE_PANEL_FITTER_C:58 return "PIPE_PANEL_FITTER_C";59 case POWER_DOMAIN_PIPE_PANEL_FITTER_D:60 return "PIPE_PANEL_FITTER_D";61 case POWER_DOMAIN_TRANSCODER_A:62 return "TRANSCODER_A";63 case POWER_DOMAIN_TRANSCODER_B:64 return "TRANSCODER_B";65 case POWER_DOMAIN_TRANSCODER_C:66 return "TRANSCODER_C";67 case POWER_DOMAIN_TRANSCODER_D:68 return "TRANSCODER_D";69 case POWER_DOMAIN_TRANSCODER_EDP:70 return "TRANSCODER_EDP";71 case POWER_DOMAIN_TRANSCODER_DSI_A:72 return "TRANSCODER_DSI_A";73 case POWER_DOMAIN_TRANSCODER_DSI_C:74 return "TRANSCODER_DSI_C";75 case POWER_DOMAIN_TRANSCODER_VDSC_PW2:76 return "TRANSCODER_VDSC_PW2";77 case POWER_DOMAIN_PORT_DDI_LANES_A:78 return "PORT_DDI_LANES_A";79 case POWER_DOMAIN_PORT_DDI_LANES_B:80 return "PORT_DDI_LANES_B";81 case POWER_DOMAIN_PORT_DDI_LANES_C:82 return "PORT_DDI_LANES_C";83 case POWER_DOMAIN_PORT_DDI_LANES_D:84 return "PORT_DDI_LANES_D";85 case POWER_DOMAIN_PORT_DDI_LANES_E:86 return "PORT_DDI_LANES_E";87 case POWER_DOMAIN_PORT_DDI_LANES_F:88 return "PORT_DDI_LANES_F";89 case POWER_DOMAIN_PORT_DDI_LANES_TC1:90 return "PORT_DDI_LANES_TC1";91 case POWER_DOMAIN_PORT_DDI_LANES_TC2:92 return "PORT_DDI_LANES_TC2";93 case POWER_DOMAIN_PORT_DDI_LANES_TC3:94 return "PORT_DDI_LANES_TC3";95 case POWER_DOMAIN_PORT_DDI_LANES_TC4:96 return "PORT_DDI_LANES_TC4";97 case POWER_DOMAIN_PORT_DDI_LANES_TC5:98 return "PORT_DDI_LANES_TC5";99 case POWER_DOMAIN_PORT_DDI_LANES_TC6:100 return "PORT_DDI_LANES_TC6";101 case POWER_DOMAIN_PORT_DDI_IO_A:102 return "PORT_DDI_IO_A";103 case POWER_DOMAIN_PORT_DDI_IO_B:104 return "PORT_DDI_IO_B";105 case POWER_DOMAIN_PORT_DDI_IO_C:106 return "PORT_DDI_IO_C";107 case POWER_DOMAIN_PORT_DDI_IO_D:108 return "PORT_DDI_IO_D";109 case POWER_DOMAIN_PORT_DDI_IO_E:110 return "PORT_DDI_IO_E";111 case POWER_DOMAIN_PORT_DDI_IO_F:112 return "PORT_DDI_IO_F";113 case POWER_DOMAIN_PORT_DDI_IO_TC1:114 return "PORT_DDI_IO_TC1";115 case POWER_DOMAIN_PORT_DDI_IO_TC2:116 return "PORT_DDI_IO_TC2";117 case POWER_DOMAIN_PORT_DDI_IO_TC3:118 return "PORT_DDI_IO_TC3";119 case POWER_DOMAIN_PORT_DDI_IO_TC4:120 return "PORT_DDI_IO_TC4";121 case POWER_DOMAIN_PORT_DDI_IO_TC5:122 return "PORT_DDI_IO_TC5";123 case POWER_DOMAIN_PORT_DDI_IO_TC6:124 return "PORT_DDI_IO_TC6";125 case POWER_DOMAIN_PORT_DSI:126 return "PORT_DSI";127 case POWER_DOMAIN_PORT_CRT:128 return "PORT_CRT";129 case POWER_DOMAIN_PORT_OTHER:130 return "PORT_OTHER";131 case POWER_DOMAIN_VGA:132 return "VGA";133 case POWER_DOMAIN_AUDIO_MMIO:134 return "AUDIO_MMIO";135 case POWER_DOMAIN_AUDIO_PLAYBACK:136 return "AUDIO_PLAYBACK";137 case POWER_DOMAIN_AUX_IO_A:138 return "AUX_IO_A";139 case POWER_DOMAIN_AUX_IO_B:140 return "AUX_IO_B";141 case POWER_DOMAIN_AUX_IO_C:142 return "AUX_IO_C";143 case POWER_DOMAIN_AUX_IO_D:144 return "AUX_IO_D";145 case POWER_DOMAIN_AUX_IO_E:146 return "AUX_IO_E";147 case POWER_DOMAIN_AUX_IO_F:148 return "AUX_IO_F";149 case POWER_DOMAIN_AUX_A:150 return "AUX_A";151 case POWER_DOMAIN_AUX_B:152 return "AUX_B";153 case POWER_DOMAIN_AUX_C:154 return "AUX_C";155 case POWER_DOMAIN_AUX_D:156 return "AUX_D";157 case POWER_DOMAIN_AUX_E:158 return "AUX_E";159 case POWER_DOMAIN_AUX_F:160 return "AUX_F";161 case POWER_DOMAIN_AUX_USBC1:162 return "AUX_USBC1";163 case POWER_DOMAIN_AUX_USBC2:164 return "AUX_USBC2";165 case POWER_DOMAIN_AUX_USBC3:166 return "AUX_USBC3";167 case POWER_DOMAIN_AUX_USBC4:168 return "AUX_USBC4";169 case POWER_DOMAIN_AUX_USBC5:170 return "AUX_USBC5";171 case POWER_DOMAIN_AUX_USBC6:172 return "AUX_USBC6";173 case POWER_DOMAIN_AUX_TBT1:174 return "AUX_TBT1";175 case POWER_DOMAIN_AUX_TBT2:176 return "AUX_TBT2";177 case POWER_DOMAIN_AUX_TBT3:178 return "AUX_TBT3";179 case POWER_DOMAIN_AUX_TBT4:180 return "AUX_TBT4";181 case POWER_DOMAIN_AUX_TBT5:182 return "AUX_TBT5";183 case POWER_DOMAIN_AUX_TBT6:184 return "AUX_TBT6";185 case POWER_DOMAIN_GMBUS:186 return "GMBUS";187 case POWER_DOMAIN_INIT:188 return "INIT";189 case POWER_DOMAIN_GT_IRQ:190 return "GT_IRQ";191 case POWER_DOMAIN_DC_OFF:192 return "DC_OFF";193 case POWER_DOMAIN_TC_COLD_OFF:194 return "TC_COLD_OFF";195 default:196 MISSING_CASE(domain);197 return "?";198 }199}200 201static bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,202 enum intel_display_power_domain domain)203{204 struct i915_power_well *power_well;205 bool is_enabled;206 207 if (pm_runtime_suspended(dev_priv->drm.dev))208 return false;209 210 is_enabled = true;211 212 for_each_power_domain_well_reverse(dev_priv, power_well, domain) {213 if (intel_power_well_is_always_on(power_well))214 continue;215 216 if (!intel_power_well_is_enabled_cached(power_well)) {217 is_enabled = false;218 break;219 }220 }221 222 return is_enabled;223}224 225/**226 * intel_display_power_is_enabled - check for a power domain227 * @dev_priv: i915 device instance228 * @domain: power domain to check229 *230 * This function can be used to check the hw power domain state. It is mostly231 * used in hardware state readout functions. Everywhere else code should rely232 * upon explicit power domain reference counting to ensure that the hardware233 * block is powered up before accessing it.234 *235 * Callers must hold the relevant modesetting locks to ensure that concurrent236 * threads can't disable the power well while the caller tries to read a few237 * registers.238 *239 * Returns:240 * True when the power domain is enabled, false otherwise.241 */242bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,243 enum intel_display_power_domain domain)244{245 struct i915_power_domains *power_domains;246 bool ret;247 248 power_domains = &dev_priv->display.power.domains;249 250 mutex_lock(&power_domains->lock);251 ret = __intel_display_power_is_enabled(dev_priv, domain);252 mutex_unlock(&power_domains->lock);253 254 return ret;255}256 257static u32258sanitize_target_dc_state(struct drm_i915_private *i915,259 u32 target_dc_state)260{261 struct i915_power_domains *power_domains = &i915->display.power.domains;262 static const u32 states[] = {263 DC_STATE_EN_UPTO_DC6,264 DC_STATE_EN_UPTO_DC5,265 DC_STATE_EN_DC3CO,266 DC_STATE_DISABLE,267 };268 int i;269 270 for (i = 0; i < ARRAY_SIZE(states) - 1; i++) {271 if (target_dc_state != states[i])272 continue;273 274 if (power_domains->allowed_dc_mask & target_dc_state)275 break;276 277 target_dc_state = states[i + 1];278 }279 280 return target_dc_state;281}282 283/**284 * intel_display_power_set_target_dc_state - Set target dc state.285 * @dev_priv: i915 device286 * @state: state which needs to be set as target_dc_state.287 *288 * This function set the "DC off" power well target_dc_state,289 * based upon this target_dc_stste, "DC off" power well will290 * enable desired DC state.291 */292void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv,293 u32 state)294{295 struct i915_power_well *power_well;296 bool dc_off_enabled;297 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;298 299 mutex_lock(&power_domains->lock);300 power_well = lookup_power_well(dev_priv, SKL_DISP_DC_OFF);301 302 if (drm_WARN_ON(&dev_priv->drm, !power_well))303 goto unlock;304 305 state = sanitize_target_dc_state(dev_priv, state);306 307 if (state == power_domains->target_dc_state)308 goto unlock;309 310 dc_off_enabled = intel_power_well_is_enabled(dev_priv, power_well);311 /*312 * If DC off power well is disabled, need to enable and disable the313 * DC off power well to effect target DC state.314 */315 if (!dc_off_enabled)316 intel_power_well_enable(dev_priv, power_well);317 318 power_domains->target_dc_state = state;319 320 if (!dc_off_enabled)321 intel_power_well_disable(dev_priv, power_well);322 323unlock:324 mutex_unlock(&power_domains->lock);325}326 327static void __async_put_domains_mask(struct i915_power_domains *power_domains,328 struct intel_power_domain_mask *mask)329{330 bitmap_or(mask->bits,331 power_domains->async_put_domains[0].bits,332 power_domains->async_put_domains[1].bits,333 POWER_DOMAIN_NUM);334}335 336#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)337 338static bool339assert_async_put_domain_masks_disjoint(struct i915_power_domains *power_domains)340{341 struct drm_i915_private *i915 = container_of(power_domains,342 struct drm_i915_private,343 display.power.domains);344 345 return !drm_WARN_ON(&i915->drm,346 bitmap_intersects(power_domains->async_put_domains[0].bits,347 power_domains->async_put_domains[1].bits,348 POWER_DOMAIN_NUM));349}350 351static bool352__async_put_domains_state_ok(struct i915_power_domains *power_domains)353{354 struct drm_i915_private *i915 = container_of(power_domains,355 struct drm_i915_private,356 display.power.domains);357 struct intel_power_domain_mask async_put_mask;358 enum intel_display_power_domain domain;359 bool err = false;360 361 err |= !assert_async_put_domain_masks_disjoint(power_domains);362 __async_put_domains_mask(power_domains, &async_put_mask);363 err |= drm_WARN_ON(&i915->drm,364 !!power_domains->async_put_wakeref !=365 !bitmap_empty(async_put_mask.bits, POWER_DOMAIN_NUM));366 367 for_each_power_domain(domain, &async_put_mask)368 err |= drm_WARN_ON(&i915->drm,369 power_domains->domain_use_count[domain] != 1);370 371 return !err;372}373 374static void print_power_domains(struct i915_power_domains *power_domains,375 const char *prefix, struct intel_power_domain_mask *mask)376{377 struct drm_i915_private *i915 = container_of(power_domains,378 struct drm_i915_private,379 display.power.domains);380 enum intel_display_power_domain domain;381 382 drm_dbg(&i915->drm, "%s (%d):\n", prefix, bitmap_weight(mask->bits, POWER_DOMAIN_NUM));383 for_each_power_domain(domain, mask)384 drm_dbg(&i915->drm, "%s use_count %d\n",385 intel_display_power_domain_str(domain),386 power_domains->domain_use_count[domain]);387}388 389static void390print_async_put_domains_state(struct i915_power_domains *power_domains)391{392 struct drm_i915_private *i915 = container_of(power_domains,393 struct drm_i915_private,394 display.power.domains);395 396 drm_dbg(&i915->drm, "async_put_wakeref: %s\n",397 str_yes_no(power_domains->async_put_wakeref));398 399 print_power_domains(power_domains, "async_put_domains[0]",400 &power_domains->async_put_domains[0]);401 print_power_domains(power_domains, "async_put_domains[1]",402 &power_domains->async_put_domains[1]);403}404 405static void406verify_async_put_domains_state(struct i915_power_domains *power_domains)407{408 if (!__async_put_domains_state_ok(power_domains))409 print_async_put_domains_state(power_domains);410}411 412#else413 414static void415assert_async_put_domain_masks_disjoint(struct i915_power_domains *power_domains)416{417}418 419static void420verify_async_put_domains_state(struct i915_power_domains *power_domains)421{422}423 424#endif /* CONFIG_DRM_I915_DEBUG_RUNTIME_PM */425 426static void async_put_domains_mask(struct i915_power_domains *power_domains,427 struct intel_power_domain_mask *mask)428 429{430 assert_async_put_domain_masks_disjoint(power_domains);431 432 __async_put_domains_mask(power_domains, mask);433}434 435static void436async_put_domains_clear_domain(struct i915_power_domains *power_domains,437 enum intel_display_power_domain domain)438{439 assert_async_put_domain_masks_disjoint(power_domains);440 441 clear_bit(domain, power_domains->async_put_domains[0].bits);442 clear_bit(domain, power_domains->async_put_domains[1].bits);443}444 445static void446cancel_async_put_work(struct i915_power_domains *power_domains, bool sync)447{448 if (sync)449 cancel_delayed_work_sync(&power_domains->async_put_work);450 else451 cancel_delayed_work(&power_domains->async_put_work);452 453 power_domains->async_put_next_delay = 0;454}455 456static bool457intel_display_power_grab_async_put_ref(struct drm_i915_private *dev_priv,458 enum intel_display_power_domain domain)459{460 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;461 struct intel_power_domain_mask async_put_mask;462 bool ret = false;463 464 async_put_domains_mask(power_domains, &async_put_mask);465 if (!test_bit(domain, async_put_mask.bits))466 goto out_verify;467 468 async_put_domains_clear_domain(power_domains, domain);469 470 ret = true;471 472 async_put_domains_mask(power_domains, &async_put_mask);473 if (!bitmap_empty(async_put_mask.bits, POWER_DOMAIN_NUM))474 goto out_verify;475 476 cancel_async_put_work(power_domains, false);477 intel_runtime_pm_put_raw(&dev_priv->runtime_pm,478 fetch_and_zero(&power_domains->async_put_wakeref));479out_verify:480 verify_async_put_domains_state(power_domains);481 482 return ret;483}484 485static void486__intel_display_power_get_domain(struct drm_i915_private *dev_priv,487 enum intel_display_power_domain domain)488{489 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;490 struct i915_power_well *power_well;491 492 if (intel_display_power_grab_async_put_ref(dev_priv, domain))493 return;494 495 for_each_power_domain_well(dev_priv, power_well, domain)496 intel_power_well_get(dev_priv, power_well);497 498 power_domains->domain_use_count[domain]++;499}500 501/**502 * intel_display_power_get - grab a power domain reference503 * @dev_priv: i915 device instance504 * @domain: power domain to reference505 *506 * This function grabs a power domain reference for @domain and ensures that the507 * power domain and all its parents are powered up. Therefore users should only508 * grab a reference to the innermost power domain they need.509 *510 * Any power domain reference obtained by this function must have a symmetric511 * call to intel_display_power_put() to release the reference again.512 */513intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,514 enum intel_display_power_domain domain)515{516 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;517 intel_wakeref_t wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);518 519 mutex_lock(&power_domains->lock);520 __intel_display_power_get_domain(dev_priv, domain);521 mutex_unlock(&power_domains->lock);522 523 return wakeref;524}525 526/**527 * intel_display_power_get_if_enabled - grab a reference for an enabled display power domain528 * @dev_priv: i915 device instance529 * @domain: power domain to reference530 *531 * This function grabs a power domain reference for @domain and ensures that the532 * power domain and all its parents are powered up. Therefore users should only533 * grab a reference to the innermost power domain they need.534 *535 * Any power domain reference obtained by this function must have a symmetric536 * call to intel_display_power_put() to release the reference again.537 */538intel_wakeref_t539intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,540 enum intel_display_power_domain domain)541{542 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;543 intel_wakeref_t wakeref;544 bool is_enabled;545 546 wakeref = intel_runtime_pm_get_if_in_use(&dev_priv->runtime_pm);547 if (!wakeref)548 return false;549 550 mutex_lock(&power_domains->lock);551 552 if (__intel_display_power_is_enabled(dev_priv, domain)) {553 __intel_display_power_get_domain(dev_priv, domain);554 is_enabled = true;555 } else {556 is_enabled = false;557 }558 559 mutex_unlock(&power_domains->lock);560 561 if (!is_enabled) {562 intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);563 wakeref = 0;564 }565 566 return wakeref;567}568 569static void570__intel_display_power_put_domain(struct drm_i915_private *dev_priv,571 enum intel_display_power_domain domain)572{573 struct i915_power_domains *power_domains;574 struct i915_power_well *power_well;575 const char *name = intel_display_power_domain_str(domain);576 struct intel_power_domain_mask async_put_mask;577 578 power_domains = &dev_priv->display.power.domains;579 580 drm_WARN(&dev_priv->drm, !power_domains->domain_use_count[domain],581 "Use count on domain %s is already zero\n",582 name);583 async_put_domains_mask(power_domains, &async_put_mask);584 drm_WARN(&dev_priv->drm,585 test_bit(domain, async_put_mask.bits),586 "Async disabling of domain %s is pending\n",587 name);588 589 power_domains->domain_use_count[domain]--;590 591 for_each_power_domain_well_reverse(dev_priv, power_well, domain)592 intel_power_well_put(dev_priv, power_well);593}594 595static void __intel_display_power_put(struct drm_i915_private *dev_priv,596 enum intel_display_power_domain domain)597{598 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;599 600 mutex_lock(&power_domains->lock);601 __intel_display_power_put_domain(dev_priv, domain);602 mutex_unlock(&power_domains->lock);603}604 605static void606queue_async_put_domains_work(struct i915_power_domains *power_domains,607 intel_wakeref_t wakeref,608 int delay_ms)609{610 struct drm_i915_private *i915 = container_of(power_domains,611 struct drm_i915_private,612 display.power.domains);613 drm_WARN_ON(&i915->drm, power_domains->async_put_wakeref);614 power_domains->async_put_wakeref = wakeref;615 drm_WARN_ON(&i915->drm, !queue_delayed_work(system_unbound_wq,616 &power_domains->async_put_work,617 msecs_to_jiffies(delay_ms)));618}619 620static void621release_async_put_domains(struct i915_power_domains *power_domains,622 struct intel_power_domain_mask *mask)623{624 struct drm_i915_private *dev_priv =625 container_of(power_domains, struct drm_i915_private,626 display.power.domains);627 struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;628 enum intel_display_power_domain domain;629 intel_wakeref_t wakeref;630 631 wakeref = intel_runtime_pm_get_noresume(rpm);632 633 for_each_power_domain(domain, mask) {634 /* Clear before put, so put's sanity check is happy. */635 async_put_domains_clear_domain(power_domains, domain);636 __intel_display_power_put_domain(dev_priv, domain);637 }638 639 intel_runtime_pm_put(rpm, wakeref);640}641 642static void643intel_display_power_put_async_work(struct work_struct *work)644{645 struct drm_i915_private *dev_priv =646 container_of(work, struct drm_i915_private,647 display.power.domains.async_put_work.work);648 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;649 struct intel_runtime_pm *rpm = &dev_priv->runtime_pm;650 intel_wakeref_t new_work_wakeref = intel_runtime_pm_get_raw(rpm);651 intel_wakeref_t old_work_wakeref = 0;652 653 mutex_lock(&power_domains->lock);654 655 /*656 * Bail out if all the domain refs pending to be released were grabbed657 * by subsequent gets or a flush_work.658 */659 old_work_wakeref = fetch_and_zero(&power_domains->async_put_wakeref);660 if (!old_work_wakeref)661 goto out_verify;662 663 release_async_put_domains(power_domains,664 &power_domains->async_put_domains[0]);665 666 /*667 * Cancel the work that got queued after this one got dequeued,668 * since here we released the corresponding async-put reference.669 */670 cancel_async_put_work(power_domains, false);671 672 /* Requeue the work if more domains were async put meanwhile. */673 if (!bitmap_empty(power_domains->async_put_domains[1].bits, POWER_DOMAIN_NUM)) {674 bitmap_copy(power_domains->async_put_domains[0].bits,675 power_domains->async_put_domains[1].bits,676 POWER_DOMAIN_NUM);677 bitmap_zero(power_domains->async_put_domains[1].bits,678 POWER_DOMAIN_NUM);679 queue_async_put_domains_work(power_domains,680 fetch_and_zero(&new_work_wakeref),681 power_domains->async_put_next_delay);682 power_domains->async_put_next_delay = 0;683 }684 685out_verify:686 verify_async_put_domains_state(power_domains);687 688 mutex_unlock(&power_domains->lock);689 690 if (old_work_wakeref)691 intel_runtime_pm_put_raw(rpm, old_work_wakeref);692 if (new_work_wakeref)693 intel_runtime_pm_put_raw(rpm, new_work_wakeref);694}695 696/**697 * __intel_display_power_put_async - release a power domain reference asynchronously698 * @i915: i915 device instance699 * @domain: power domain to reference700 * @wakeref: wakeref acquired for the reference that is being released701 * @delay_ms: delay of powering down the power domain702 *703 * This function drops the power domain reference obtained by704 * intel_display_power_get*() and schedules a work to power down the705 * corresponding hardware block if this is the last reference.706 * The power down is delayed by @delay_ms if this is >= 0, or by a default707 * 100 ms otherwise.708 */709void __intel_display_power_put_async(struct drm_i915_private *i915,710 enum intel_display_power_domain domain,711 intel_wakeref_t wakeref,712 int delay_ms)713{714 struct i915_power_domains *power_domains = &i915->display.power.domains;715 struct intel_runtime_pm *rpm = &i915->runtime_pm;716 intel_wakeref_t work_wakeref = intel_runtime_pm_get_raw(rpm);717 718 delay_ms = delay_ms >= 0 ? delay_ms : 100;719 720 mutex_lock(&power_domains->lock);721 722 if (power_domains->domain_use_count[domain] > 1) {723 __intel_display_power_put_domain(i915, domain);724 725 goto out_verify;726 }727 728 drm_WARN_ON(&i915->drm, power_domains->domain_use_count[domain] != 1);729 730 /* Let a pending work requeue itself or queue a new one. */731 if (power_domains->async_put_wakeref) {732 set_bit(domain, power_domains->async_put_domains[1].bits);733 power_domains->async_put_next_delay = max(power_domains->async_put_next_delay,734 delay_ms);735 } else {736 set_bit(domain, power_domains->async_put_domains[0].bits);737 queue_async_put_domains_work(power_domains,738 fetch_and_zero(&work_wakeref),739 delay_ms);740 }741 742out_verify:743 verify_async_put_domains_state(power_domains);744 745 mutex_unlock(&power_domains->lock);746 747 if (work_wakeref)748 intel_runtime_pm_put_raw(rpm, work_wakeref);749 750 intel_runtime_pm_put(rpm, wakeref);751}752 753/**754 * intel_display_power_flush_work - flushes the async display power disabling work755 * @i915: i915 device instance756 *757 * Flushes any pending work that was scheduled by a preceding758 * intel_display_power_put_async() call, completing the disabling of the759 * corresponding power domains.760 *761 * Note that the work handler function may still be running after this762 * function returns; to ensure that the work handler isn't running use763 * intel_display_power_flush_work_sync() instead.764 */765void intel_display_power_flush_work(struct drm_i915_private *i915)766{767 struct i915_power_domains *power_domains = &i915->display.power.domains;768 struct intel_power_domain_mask async_put_mask;769 intel_wakeref_t work_wakeref;770 771 mutex_lock(&power_domains->lock);772 773 work_wakeref = fetch_and_zero(&power_domains->async_put_wakeref);774 if (!work_wakeref)775 goto out_verify;776 777 async_put_domains_mask(power_domains, &async_put_mask);778 release_async_put_domains(power_domains, &async_put_mask);779 cancel_async_put_work(power_domains, false);780 781out_verify:782 verify_async_put_domains_state(power_domains);783 784 mutex_unlock(&power_domains->lock);785 786 if (work_wakeref)787 intel_runtime_pm_put_raw(&i915->runtime_pm, work_wakeref);788}789 790/**791 * intel_display_power_flush_work_sync - flushes and syncs the async display power disabling work792 * @i915: i915 device instance793 *794 * Like intel_display_power_flush_work(), but also ensure that the work795 * handler function is not running any more when this function returns.796 */797static void798intel_display_power_flush_work_sync(struct drm_i915_private *i915)799{800 struct i915_power_domains *power_domains = &i915->display.power.domains;801 802 intel_display_power_flush_work(i915);803 cancel_async_put_work(power_domains, true);804 805 verify_async_put_domains_state(power_domains);806 807 drm_WARN_ON(&i915->drm, power_domains->async_put_wakeref);808}809 810#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)811/**812 * intel_display_power_put - release a power domain reference813 * @dev_priv: i915 device instance814 * @domain: power domain to reference815 * @wakeref: wakeref acquired for the reference that is being released816 *817 * This function drops the power domain reference obtained by818 * intel_display_power_get() and might power down the corresponding hardware819 * block right away if this is the last reference.820 */821void intel_display_power_put(struct drm_i915_private *dev_priv,822 enum intel_display_power_domain domain,823 intel_wakeref_t wakeref)824{825 __intel_display_power_put(dev_priv, domain);826 intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);827}828#else829/**830 * intel_display_power_put_unchecked - release an unchecked power domain reference831 * @dev_priv: i915 device instance832 * @domain: power domain to reference833 *834 * This function drops the power domain reference obtained by835 * intel_display_power_get() and might power down the corresponding hardware836 * block right away if this is the last reference.837 *838 * This function is only for the power domain code's internal use to suppress wakeref839 * tracking when the correspondig debug kconfig option is disabled, should not840 * be used otherwise.841 */842void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,843 enum intel_display_power_domain domain)844{845 __intel_display_power_put(dev_priv, domain);846 intel_runtime_pm_put_unchecked(&dev_priv->runtime_pm);847}848#endif849 850void851intel_display_power_get_in_set(struct drm_i915_private *i915,852 struct intel_display_power_domain_set *power_domain_set,853 enum intel_display_power_domain domain)854{855 intel_wakeref_t __maybe_unused wf;856 857 drm_WARN_ON(&i915->drm, test_bit(domain, power_domain_set->mask.bits));858 859 wf = intel_display_power_get(i915, domain);860#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)861 power_domain_set->wakerefs[domain] = wf;862#endif863 set_bit(domain, power_domain_set->mask.bits);864}865 866bool867intel_display_power_get_in_set_if_enabled(struct drm_i915_private *i915,868 struct intel_display_power_domain_set *power_domain_set,869 enum intel_display_power_domain domain)870{871 intel_wakeref_t wf;872 873 drm_WARN_ON(&i915->drm, test_bit(domain, power_domain_set->mask.bits));874 875 wf = intel_display_power_get_if_enabled(i915, domain);876 if (!wf)877 return false;878 879#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)880 power_domain_set->wakerefs[domain] = wf;881#endif882 set_bit(domain, power_domain_set->mask.bits);883 884 return true;885}886 887void888intel_display_power_put_mask_in_set(struct drm_i915_private *i915,889 struct intel_display_power_domain_set *power_domain_set,890 struct intel_power_domain_mask *mask)891{892 enum intel_display_power_domain domain;893 894 drm_WARN_ON(&i915->drm,895 !bitmap_subset(mask->bits, power_domain_set->mask.bits, POWER_DOMAIN_NUM));896 897 for_each_power_domain(domain, mask) {898 intel_wakeref_t __maybe_unused wf = -1;899 900#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)901 wf = fetch_and_zero(&power_domain_set->wakerefs[domain]);902#endif903 intel_display_power_put(i915, domain, wf);904 clear_bit(domain, power_domain_set->mask.bits);905 }906}907 908static int909sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv,910 int disable_power_well)911{912 if (disable_power_well >= 0)913 return !!disable_power_well;914 915 return 1;916}917 918static u32 get_allowed_dc_mask(const struct drm_i915_private *dev_priv,919 int enable_dc)920{921 u32 mask;922 int requested_dc;923 int max_dc;924 925 if (!HAS_DISPLAY(dev_priv))926 return 0;927 928 if (DISPLAY_VER(dev_priv) >= 20)929 max_dc = 2;930 else if (IS_DG2(dev_priv))931 max_dc = 1;932 else if (IS_DG1(dev_priv))933 max_dc = 3;934 else if (DISPLAY_VER(dev_priv) >= 12)935 max_dc = 4;936 else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))937 max_dc = 1;938 else if (DISPLAY_VER(dev_priv) >= 9)939 max_dc = 2;940 else941 max_dc = 0;942 943 /*944 * DC9 has a separate HW flow from the rest of the DC states,945 * not depending on the DMC firmware. It's needed by system946 * suspend/resume, so allow it unconditionally.947 */948 mask = IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) ||949 DISPLAY_VER(dev_priv) >= 11 ?950 DC_STATE_EN_DC9 : 0;951 952 if (!dev_priv->display.params.disable_power_well)953 max_dc = 0;954 955 if (enable_dc >= 0 && enable_dc <= max_dc) {956 requested_dc = enable_dc;957 } else if (enable_dc == -1) {958 requested_dc = max_dc;959 } else if (enable_dc > max_dc && enable_dc <= 4) {960 drm_dbg_kms(&dev_priv->drm,961 "Adjusting requested max DC state (%d->%d)\n",962 enable_dc, max_dc);963 requested_dc = max_dc;964 } else {965 drm_err(&dev_priv->drm,966 "Unexpected value for enable_dc (%d)\n", enable_dc);967 requested_dc = max_dc;968 }969 970 switch (requested_dc) {971 case 4:972 mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC6;973 break;974 case 3:975 mask |= DC_STATE_EN_DC3CO | DC_STATE_EN_UPTO_DC5;976 break;977 case 2:978 mask |= DC_STATE_EN_UPTO_DC6;979 break;980 case 1:981 mask |= DC_STATE_EN_UPTO_DC5;982 break;983 }984 985 drm_dbg_kms(&dev_priv->drm, "Allowed DC state mask %02x\n", mask);986 987 return mask;988}989 990/**991 * intel_power_domains_init - initializes the power domain structures992 * @dev_priv: i915 device instance993 *994 * Initializes the power domain structures for @dev_priv depending upon the995 * supported platform.996 */997int intel_power_domains_init(struct drm_i915_private *dev_priv)998{999 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;1000 1001 dev_priv->display.params.disable_power_well =1002 sanitize_disable_power_well_option(dev_priv,1003 dev_priv->display.params.disable_power_well);1004 power_domains->allowed_dc_mask =1005 get_allowed_dc_mask(dev_priv, dev_priv->display.params.enable_dc);1006 1007 power_domains->target_dc_state =1008 sanitize_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);1009 1010 mutex_init(&power_domains->lock);1011 1012 INIT_DELAYED_WORK(&power_domains->async_put_work,1013 intel_display_power_put_async_work);1014 1015 return intel_display_power_map_init(power_domains);1016}1017 1018/**1019 * intel_power_domains_cleanup - clean up power domains resources1020 * @dev_priv: i915 device instance1021 *1022 * Release any resources acquired by intel_power_domains_init()1023 */1024void intel_power_domains_cleanup(struct drm_i915_private *dev_priv)1025{1026 intel_display_power_map_cleanup(&dev_priv->display.power.domains);1027}1028 1029static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)1030{1031 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;1032 struct i915_power_well *power_well;1033 1034 mutex_lock(&power_domains->lock);1035 for_each_power_well(dev_priv, power_well)1036 intel_power_well_sync_hw(dev_priv, power_well);1037 mutex_unlock(&power_domains->lock);1038}1039 1040static void gen9_dbuf_slice_set(struct drm_i915_private *dev_priv,1041 enum dbuf_slice slice, bool enable)1042{1043 i915_reg_t reg = DBUF_CTL_S(slice);1044 bool state;1045 1046 intel_de_rmw(dev_priv, reg, DBUF_POWER_REQUEST,1047 enable ? DBUF_POWER_REQUEST : 0);1048 intel_de_posting_read(dev_priv, reg);1049 udelay(10);1050 1051 state = intel_de_read(dev_priv, reg) & DBUF_POWER_STATE;1052 drm_WARN(&dev_priv->drm, enable != state,1053 "DBuf slice %d power %s timeout!\n",1054 slice, str_enable_disable(enable));1055}1056 1057void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv,1058 u8 req_slices)1059{1060 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;1061 u8 slice_mask = DISPLAY_INFO(dev_priv)->dbuf.slice_mask;1062 enum dbuf_slice slice;1063 1064 drm_WARN(&dev_priv->drm, req_slices & ~slice_mask,1065 "Invalid set of dbuf slices (0x%x) requested (total dbuf slices 0x%x)\n",1066 req_slices, slice_mask);1067 1068 drm_dbg_kms(&dev_priv->drm, "Updating dbuf slices to 0x%x\n",1069 req_slices);1070 1071 /*1072 * Might be running this in parallel to gen9_dc_off_power_well_enable1073 * being called from intel_dp_detect for instance,1074 * which causes assertion triggered by race condition,1075 * as gen9_assert_dbuf_enabled might preempt this when registers1076 * were already updated, while dev_priv was not.1077 */1078 mutex_lock(&power_domains->lock);1079 1080 for_each_dbuf_slice(dev_priv, slice)1081 gen9_dbuf_slice_set(dev_priv, slice, req_slices & BIT(slice));1082 1083 dev_priv->display.dbuf.enabled_slices = req_slices;1084 1085 mutex_unlock(&power_domains->lock);1086}1087 1088static void gen9_dbuf_enable(struct drm_i915_private *dev_priv)1089{1090 u8 slices_mask;1091 1092 dev_priv->display.dbuf.enabled_slices =1093 intel_enabled_dbuf_slices_mask(dev_priv);1094 1095 slices_mask = BIT(DBUF_S1) | dev_priv->display.dbuf.enabled_slices;1096 1097 if (DISPLAY_VER(dev_priv) >= 14)1098 intel_pmdemand_program_dbuf(dev_priv, slices_mask);1099 1100 /*1101 * Just power up at least 1 slice, we will1102 * figure out later which slices we have and what we need.1103 */1104 gen9_dbuf_slices_update(dev_priv, slices_mask);1105}1106 1107static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)1108{1109 gen9_dbuf_slices_update(dev_priv, 0);1110 1111 if (DISPLAY_VER(dev_priv) >= 14)1112 intel_pmdemand_program_dbuf(dev_priv, 0);1113}1114 1115static void gen12_dbuf_slices_config(struct drm_i915_private *dev_priv)1116{1117 enum dbuf_slice slice;1118 1119 if (IS_ALDERLAKE_P(dev_priv))1120 return;1121 1122 for_each_dbuf_slice(dev_priv, slice)1123 intel_de_rmw(dev_priv, DBUF_CTL_S(slice),1124 DBUF_TRACKER_STATE_SERVICE_MASK,1125 DBUF_TRACKER_STATE_SERVICE(8));1126}1127 1128static void icl_mbus_init(struct drm_i915_private *dev_priv)1129{1130 unsigned long abox_regs = DISPLAY_INFO(dev_priv)->abox_mask;1131 u32 mask, val, i;1132 1133 if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14)1134 return;1135 1136 mask = MBUS_ABOX_BT_CREDIT_POOL1_MASK |1137 MBUS_ABOX_BT_CREDIT_POOL2_MASK |1138 MBUS_ABOX_B_CREDIT_MASK |1139 MBUS_ABOX_BW_CREDIT_MASK;1140 val = MBUS_ABOX_BT_CREDIT_POOL1(16) |1141 MBUS_ABOX_BT_CREDIT_POOL2(16) |1142 MBUS_ABOX_B_CREDIT(1) |1143 MBUS_ABOX_BW_CREDIT(1);1144 1145 /*1146 * gen12 platforms that use abox1 and abox2 for pixel data reads still1147 * expect us to program the abox_ctl0 register as well, even though1148 * we don't have to program other instance-0 registers like BW_BUDDY.1149 */1150 if (DISPLAY_VER(dev_priv) == 12)1151 abox_regs |= BIT(0);1152 1153 for_each_set_bit(i, &abox_regs, sizeof(abox_regs))1154 intel_de_rmw(dev_priv, MBUS_ABOX_CTL(i), mask, val);1155}1156 1157static void hsw_assert_cdclk(struct drm_i915_private *dev_priv)1158{1159 u32 val = intel_de_read(dev_priv, LCPLL_CTL);1160 1161 /*1162 * The LCPLL register should be turned on by the BIOS. For now1163 * let's just check its state and print errors in case1164 * something is wrong. Don't even try to turn it on.1165 */1166 1167 if (val & LCPLL_CD_SOURCE_FCLK)1168 drm_err(&dev_priv->drm, "CDCLK source is not LCPLL\n");1169 1170 if (val & LCPLL_PLL_DISABLE)1171 drm_err(&dev_priv->drm, "LCPLL is disabled\n");1172 1173 if ((val & LCPLL_REF_MASK) != LCPLL_REF_NON_SSC)1174 drm_err(&dev_priv->drm, "LCPLL not using non-SSC reference\n");1175}1176 1177static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)1178{1179 struct intel_crtc *crtc;1180 1181 for_each_intel_crtc(&dev_priv->drm, crtc)1182 I915_STATE_WARN(dev_priv, crtc->active,1183 "CRTC for pipe %c enabled\n",1184 pipe_name(crtc->pipe));1185 1186 I915_STATE_WARN(dev_priv, intel_de_read(dev_priv, HSW_PWR_WELL_CTL2),1187 "Display power well on\n");1188 I915_STATE_WARN(dev_priv,1189 intel_de_read(dev_priv, SPLL_CTL) & SPLL_PLL_ENABLE,1190 "SPLL enabled\n");1191 I915_STATE_WARN(dev_priv,1192 intel_de_read(dev_priv, WRPLL_CTL(0)) & WRPLL_PLL_ENABLE,1193 "WRPLL1 enabled\n");1194 I915_STATE_WARN(dev_priv,1195 intel_de_read(dev_priv, WRPLL_CTL(1)) & WRPLL_PLL_ENABLE,1196 "WRPLL2 enabled\n");1197 I915_STATE_WARN(dev_priv,1198 intel_de_read(dev_priv, PP_STATUS(dev_priv, 0)) & PP_ON,1199 "Panel power on\n");1200 I915_STATE_WARN(dev_priv,1201 intel_de_read(dev_priv, BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,1202 "CPU PWM1 enabled\n");1203 if (IS_HASWELL(dev_priv))1204 I915_STATE_WARN(dev_priv,1205 intel_de_read(dev_priv, HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,1206 "CPU PWM2 enabled\n");1207 I915_STATE_WARN(dev_priv,1208 intel_de_read(dev_priv, BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,1209 "PCH PWM1 enabled\n");1210 I915_STATE_WARN(dev_priv,1211 (intel_de_read(dev_priv, UTIL_PIN_CTL) & (UTIL_PIN_ENABLE | UTIL_PIN_MODE_MASK)) == (UTIL_PIN_ENABLE | UTIL_PIN_MODE_PWM),1212 "Utility pin enabled in PWM mode\n");1213 I915_STATE_WARN(dev_priv,1214 intel_de_read(dev_priv, PCH_GTC_CTL) & PCH_GTC_ENABLE,1215 "PCH GTC enabled\n");1216 1217 /*1218 * In theory we can still leave IRQs enabled, as long as only the HPD1219 * interrupts remain enabled. We used to check for that, but since it's1220 * gen-specific and since we only disable LCPLL after we fully disable1221 * the interrupts, the check below should be enough.1222 */1223 I915_STATE_WARN(dev_priv, intel_irqs_enabled(dev_priv),1224 "IRQs enabled\n");1225}1226 1227static u32 hsw_read_dcomp(struct drm_i915_private *dev_priv)1228{1229 if (IS_HASWELL(dev_priv))1230 return intel_de_read(dev_priv, D_COMP_HSW);1231 else1232 return intel_de_read(dev_priv, D_COMP_BDW);1233}1234 1235static void hsw_write_dcomp(struct drm_i915_private *dev_priv, u32 val)1236{1237 if (IS_HASWELL(dev_priv)) {1238 if (snb_pcode_write(&dev_priv->uncore, GEN6_PCODE_WRITE_D_COMP, val))1239 drm_dbg_kms(&dev_priv->drm,1240 "Failed to write to D_COMP\n");1241 } else {1242 intel_de_write(dev_priv, D_COMP_BDW, val);1243 intel_de_posting_read(dev_priv, D_COMP_BDW);1244 }1245}1246 1247/*1248 * This function implements pieces of two sequences from BSpec:1249 * - Sequence for display software to disable LCPLL1250 * - Sequence for display software to allow package C8+1251 * The steps implemented here are just the steps that actually touch the LCPLL1252 * register. Callers should take care of disabling all the display engine1253 * functions, doing the mode unset, fixing interrupts, etc.1254 */1255static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,1256 bool switch_to_fclk, bool allow_power_down)1257{1258 u32 val;1259 1260 assert_can_disable_lcpll(dev_priv);1261 1262 val = intel_de_read(dev_priv, LCPLL_CTL);1263 1264 if (switch_to_fclk) {1265 val |= LCPLL_CD_SOURCE_FCLK;1266 intel_de_write(dev_priv, LCPLL_CTL, val);1267 1268 if (wait_for_us(intel_de_read(dev_priv, LCPLL_CTL) &1269 LCPLL_CD_SOURCE_FCLK_DONE, 1))1270 drm_err(&dev_priv->drm, "Switching to FCLK failed\n");1271 1272 val = intel_de_read(dev_priv, LCPLL_CTL);1273 }1274 1275 val |= LCPLL_PLL_DISABLE;1276 intel_de_write(dev_priv, LCPLL_CTL, val);1277 intel_de_posting_read(dev_priv, LCPLL_CTL);1278 1279 if (intel_de_wait_for_clear(dev_priv, LCPLL_CTL, LCPLL_PLL_LOCK, 1))1280 drm_err(&dev_priv->drm, "LCPLL still locked\n");1281 1282 val = hsw_read_dcomp(dev_priv);1283 val |= D_COMP_COMP_DISABLE;1284 hsw_write_dcomp(dev_priv, val);1285 ndelay(100);1286 1287 if (wait_for((hsw_read_dcomp(dev_priv) &1288 D_COMP_RCOMP_IN_PROGRESS) == 0, 1))1289 drm_err(&dev_priv->drm, "D_COMP RCOMP still in progress\n");1290 1291 if (allow_power_down) {1292 intel_de_rmw(dev_priv, LCPLL_CTL, 0, LCPLL_POWER_DOWN_ALLOW);1293 intel_de_posting_read(dev_priv, LCPLL_CTL);1294 }1295}1296 1297/*1298 * Fully restores LCPLL, disallowing power down and switching back to LCPLL1299 * source.1300 */1301static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)1302{1303 u32 val;1304 1305 val = intel_de_read(dev_priv, LCPLL_CTL);1306 1307 if ((val & (LCPLL_PLL_LOCK | LCPLL_PLL_DISABLE | LCPLL_CD_SOURCE_FCLK |1308 LCPLL_POWER_DOWN_ALLOW)) == LCPLL_PLL_LOCK)1309 return;1310 1311 /*1312 * Make sure we're not on PC8 state before disabling PC8, otherwise1313 * we'll hang the machine. To prevent PC8 state, just enable force_wake.1314 */1315 intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL);1316 1317 if (val & LCPLL_POWER_DOWN_ALLOW) {1318 val &= ~LCPLL_POWER_DOWN_ALLOW;1319 intel_de_write(dev_priv, LCPLL_CTL, val);1320 intel_de_posting_read(dev_priv, LCPLL_CTL);1321 }1322 1323 val = hsw_read_dcomp(dev_priv);1324 val |= D_COMP_COMP_FORCE;1325 val &= ~D_COMP_COMP_DISABLE;1326 hsw_write_dcomp(dev_priv, val);1327 1328 val = intel_de_read(dev_priv, LCPLL_CTL);1329 val &= ~LCPLL_PLL_DISABLE;1330 intel_de_write(dev_priv, LCPLL_CTL, val);1331 1332 if (intel_de_wait_for_set(dev_priv, LCPLL_CTL, LCPLL_PLL_LOCK, 5))1333 drm_err(&dev_priv->drm, "LCPLL not locked yet\n");1334 1335 if (val & LCPLL_CD_SOURCE_FCLK) {1336 intel_de_rmw(dev_priv, LCPLL_CTL, LCPLL_CD_SOURCE_FCLK, 0);1337 1338 if (wait_for_us((intel_de_read(dev_priv, LCPLL_CTL) &1339 LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))1340 drm_err(&dev_priv->drm,1341 "Switching back to LCPLL failed\n");1342 }1343 1344 intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);1345 1346 intel_update_cdclk(dev_priv);1347 intel_cdclk_dump_config(dev_priv, &dev_priv->display.cdclk.hw, "Current CDCLK");1348}1349 1350/*1351 * Package states C8 and deeper are really deep PC states that can only be1352 * reached when all the devices on the system allow it, so even if the graphics1353 * device allows PC8+, it doesn't mean the system will actually get to these1354 * states. Our driver only allows PC8+ when going into runtime PM.1355 *1356 * The requirements for PC8+ are that all the outputs are disabled, the power1357 * well is disabled and most interrupts are disabled, and these are also1358 * requirements for runtime PM. When these conditions are met, we manually do1359 * the other conditions: disable the interrupts, clocks and switch LCPLL refclk1360 * to Fclk. If we're in PC8+ and we get an non-hotplug interrupt, we can hard1361 * hang the machine.1362 *1363 * When we really reach PC8 or deeper states (not just when we allow it) we lose1364 * the state of some registers, so when we come back from PC8+ we need to1365 * restore this state. We don't get into PC8+ if we're not in RC6, so we don't1366 * need to take care of the registers kept by RC6. Notice that this happens even1367 * if we don't put the device in PCI D3 state (which is what currently happens1368 * because of the runtime PM support).1369 *1370 * For more, read "Display Sequences for Package C8" on the hardware1371 * documentation.1372 */1373static void hsw_enable_pc8(struct drm_i915_private *dev_priv)1374{1375 drm_dbg_kms(&dev_priv->drm, "Enabling package C8+\n");1376 1377 if (HAS_PCH_LPT_LP(dev_priv))1378 intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D,1379 PCH_LP_PARTITION_LEVEL_DISABLE, 0);1380 1381 lpt_disable_clkout_dp(dev_priv);1382 hsw_disable_lcpll(dev_priv, true, true);1383}1384 1385static void hsw_disable_pc8(struct drm_i915_private *dev_priv)1386{1387 drm_dbg_kms(&dev_priv->drm, "Disabling package C8+\n");1388 1389 hsw_restore_lcpll(dev_priv);1390 intel_init_pch_refclk(dev_priv);1391 1392 /* Many display registers don't survive PC8+ */1393 intel_clock_gating_init(dev_priv);1394}1395 1396static void intel_pch_reset_handshake(struct drm_i915_private *dev_priv,1397 bool enable)1398{1399 i915_reg_t reg;1400 u32 reset_bits;1401 1402 if (IS_IVYBRIDGE(dev_priv)) {1403 reg = GEN7_MSG_CTL;1404 reset_bits = WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK;1405 } else {1406 reg = HSW_NDE_RSTWRN_OPT;1407 reset_bits = RESET_PCH_HANDSHAKE_ENABLE;1408 }1409 1410 if (DISPLAY_VER(dev_priv) >= 14)1411 reset_bits |= MTL_RESET_PICA_HANDSHAKE_EN;1412 1413 intel_de_rmw(dev_priv, reg, reset_bits, enable ? reset_bits : 0);1414}1415 1416static void skl_display_core_init(struct drm_i915_private *dev_priv,1417 bool resume)1418{1419 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;1420 struct i915_power_well *well;1421 1422 gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);1423 1424 /* enable PCH reset handshake */1425 intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));1426 1427 if (!HAS_DISPLAY(dev_priv))1428 return;1429 1430 /* enable PG1 and Misc I/O */1431 mutex_lock(&power_domains->lock);1432 1433 well = lookup_power_well(dev_priv, SKL_DISP_PW_1);1434 intel_power_well_enable(dev_priv, well);1435 1436 well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO);1437 intel_power_well_enable(dev_priv, well);1438 1439 mutex_unlock(&power_domains->lock);1440 1441 intel_cdclk_init_hw(dev_priv);1442 1443 gen9_dbuf_enable(dev_priv);1444 1445 if (resume)1446 intel_dmc_load_program(dev_priv);1447}1448 1449static void skl_display_core_uninit(struct drm_i915_private *dev_priv)1450{1451 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;1452 struct i915_power_well *well;1453 1454 if (!HAS_DISPLAY(dev_priv))1455 return;1456 1457 gen9_disable_dc_states(dev_priv);1458 /* TODO: disable DMC program */1459 1460 gen9_dbuf_disable(dev_priv);1461 1462 intel_cdclk_uninit_hw(dev_priv);1463 1464 /* The spec doesn't call for removing the reset handshake flag */1465 /* disable PG1 and Misc I/O */1466 1467 mutex_lock(&power_domains->lock);1468 1469 /*1470 * BSpec says to keep the MISC IO power well enabled here, only1471 * remove our request for power well 1.1472 * Note that even though the driver's request is removed power well 11473 * may stay enabled after this due to DMC's own request on it.1474 */1475 well = lookup_power_well(dev_priv, SKL_DISP_PW_1);1476 intel_power_well_disable(dev_priv, well);1477 1478 mutex_unlock(&power_domains->lock);1479 1480 usleep_range(10, 30); /* 10 us delay per Bspec */1481}1482 1483static void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume)1484{1485 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;1486 struct i915_power_well *well;1487 1488 gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);1489 1490 /*1491 * NDE_RSTWRN_OPT RST PCH Handshake En must always be 0b on BXT1492 * or else the reset will hang because there is no PCH to respond.1493 * Move the handshake programming to initialization sequence.1494 * Previously was left up to BIOS.1495 */1496 intel_pch_reset_handshake(dev_priv, false);1497 1498 if (!HAS_DISPLAY(dev_priv))1499 return;1500 1501 /* Enable PG1 */1502 mutex_lock(&power_domains->lock);1503 1504 well = lookup_power_well(dev_priv, SKL_DISP_PW_1);1505 intel_power_well_enable(dev_priv, well);1506 1507 mutex_unlock(&power_domains->lock);1508 1509 intel_cdclk_init_hw(dev_priv);1510 1511 gen9_dbuf_enable(dev_priv);1512 1513 if (resume)1514 intel_dmc_load_program(dev_priv);1515}1516 1517static void bxt_display_core_uninit(struct drm_i915_private *dev_priv)1518{1519 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;1520 struct i915_power_well *well;1521 1522 if (!HAS_DISPLAY(dev_priv))1523 return;1524 1525 gen9_disable_dc_states(dev_priv);1526 /* TODO: disable DMC program */1527 1528 gen9_dbuf_disable(dev_priv);1529 1530 intel_cdclk_uninit_hw(dev_priv);1531 1532 /* The spec doesn't call for removing the reset handshake flag */1533 1534 /*1535 * Disable PW1 (PG1).1536 * Note that even though the driver's request is removed power well 11537 * may stay enabled after this due to DMC's own request on it.1538 */1539 mutex_lock(&power_domains->lock);1540 1541 well = lookup_power_well(dev_priv, SKL_DISP_PW_1);1542 intel_power_well_disable(dev_priv, well);1543 1544 mutex_unlock(&power_domains->lock);1545 1546 usleep_range(10, 30); /* 10 us delay per Bspec */1547}1548 1549struct buddy_page_mask {1550 u32 page_mask;1551 u8 type;1552 u8 num_channels;1553};1554 1555static const struct buddy_page_mask tgl_buddy_page_masks[] = {1556 { .num_channels = 1, .type = INTEL_DRAM_DDR4, .page_mask = 0xF },1557 { .num_channels = 1, .type = INTEL_DRAM_DDR5, .page_mask = 0xF },1558 { .num_channels = 2, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x1C },1559 { .num_channels = 2, .type = INTEL_DRAM_LPDDR5, .page_mask = 0x1C },1560 { .num_channels = 2, .type = INTEL_DRAM_DDR4, .page_mask = 0x1F },1561 { .num_channels = 2, .type = INTEL_DRAM_DDR5, .page_mask = 0x1E },1562 { .num_channels = 4, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x38 },1563 { .num_channels = 4, .type = INTEL_DRAM_LPDDR5, .page_mask = 0x38 },1564 {}1565};1566 1567static const struct buddy_page_mask wa_1409767108_buddy_page_masks[] = {1568 { .num_channels = 1, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x1 },1569 { .num_channels = 1, .type = INTEL_DRAM_DDR4, .page_mask = 0x1 },1570 { .num_channels = 1, .type = INTEL_DRAM_DDR5, .page_mask = 0x1 },1571 { .num_channels = 1, .type = INTEL_DRAM_LPDDR5, .page_mask = 0x1 },1572 { .num_channels = 2, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x3 },1573 { .num_channels = 2, .type = INTEL_DRAM_DDR4, .page_mask = 0x3 },1574 { .num_channels = 2, .type = INTEL_DRAM_DDR5, .page_mask = 0x3 },1575 { .num_channels = 2, .type = INTEL_DRAM_LPDDR5, .page_mask = 0x3 },1576 {}1577};1578 1579static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv)1580{1581 enum intel_dram_type type = dev_priv->dram_info.type;1582 u8 num_channels = dev_priv->dram_info.num_channels;1583 const struct buddy_page_mask *table;1584 unsigned long abox_mask = DISPLAY_INFO(dev_priv)->abox_mask;1585 int config, i;1586 1587 /* BW_BUDDY registers are not used on dgpu's beyond DG1 */1588 if (IS_DGFX(dev_priv) && !IS_DG1(dev_priv))1589 return;1590 1591 if (IS_ALDERLAKE_S(dev_priv) ||1592 (IS_ROCKETLAKE(dev_priv) && IS_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0)))1593 /* Wa_1409767108 */1594 table = wa_1409767108_buddy_page_masks;1595 else1596 table = tgl_buddy_page_masks;1597 1598 for (config = 0; table[config].page_mask != 0; config++)1599 if (table[config].num_channels == num_channels &&1600 table[config].type == type)1601 break;1602 1603 if (table[config].page_mask == 0) {1604 drm_dbg(&dev_priv->drm,1605 "Unknown memory configuration; disabling address buddy logic.\n");1606 for_each_set_bit(i, &abox_mask, sizeof(abox_mask))1607 intel_de_write(dev_priv, BW_BUDDY_CTL(i),1608 BW_BUDDY_DISABLE);1609 } else {1610 for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) {1611 intel_de_write(dev_priv, BW_BUDDY_PAGE_MASK(i),1612 table[config].page_mask);1613 1614 /* Wa_22010178259:tgl,dg1,rkl,adl-s */1615 if (DISPLAY_VER(dev_priv) == 12)1616 intel_de_rmw(dev_priv, BW_BUDDY_CTL(i),1617 BW_BUDDY_TLB_REQ_TIMER_MASK,1618 BW_BUDDY_TLB_REQ_TIMER(0x8));1619 }1620 }1621}1622 1623static void icl_display_core_init(struct drm_i915_private *dev_priv,1624 bool resume)1625{1626 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;1627 struct i915_power_well *well;1628 1629 gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);1630 1631 /* Wa_14011294188:ehl,jsl,tgl,rkl,adl-s */1632 if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP &&1633 INTEL_PCH_TYPE(dev_priv) < PCH_DG1)1634 intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D, 0,1635 PCH_DPMGUNIT_CLOCK_GATE_DISABLE);1636 1637 /* 1. Enable PCH reset handshake. */1638 intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));1639 1640 if (!HAS_DISPLAY(dev_priv))1641 return;1642 1643 /* 2. Initialize all combo phys */1644 intel_combo_phy_init(dev_priv);1645 1646 /*1647 * 3. Enable Power Well 1 (PG1).1648 * The AUX IO power wells will be enabled on demand.1649 */1650 mutex_lock(&power_domains->lock);1651 well = lookup_power_well(dev_priv, SKL_DISP_PW_1);1652 intel_power_well_enable(dev_priv, well);1653 mutex_unlock(&power_domains->lock);1654 1655 if (DISPLAY_VER(dev_priv) == 14)1656 intel_de_rmw(dev_priv, DC_STATE_EN,1657 HOLD_PHY_PG1_LATCH | HOLD_PHY_CLKREQ_PG1_LATCH, 0);1658 1659 /* 4. Enable CDCLK. */1660 intel_cdclk_init_hw(dev_priv);1661 1662 if (DISPLAY_VER(dev_priv) >= 12)1663 gen12_dbuf_slices_config(dev_priv);1664 1665 /* 5. Enable DBUF. */1666 gen9_dbuf_enable(dev_priv);1667 1668 /* 6. Setup MBUS. */1669 icl_mbus_init(dev_priv);1670 1671 /* 7. Program arbiter BW_BUDDY registers */1672 if (DISPLAY_VER(dev_priv) >= 12)1673 tgl_bw_buddy_init(dev_priv);1674 1675 /* 8. Ensure PHYs have completed calibration and adaptation */1676 if (IS_DG2(dev_priv))1677 intel_snps_phy_wait_for_calibration(dev_priv);1678 1679 /* 9. XE2_HPD: Program CHICKEN_MISC_2 before any cursor or planes are enabled */1680 if (DISPLAY_VER_FULL(dev_priv) == IP_VER(14, 1))1681 intel_de_rmw(dev_priv, CHICKEN_MISC_2, BMG_DARB_HALF_BLK_END_BURST, 1);1682 1683 if (resume)1684 intel_dmc_load_program(dev_priv);1685 1686 /* Wa_14011508470:tgl,dg1,rkl,adl-s,adl-p,dg2 */1687 if (IS_DISPLAY_VER_FULL(dev_priv, IP_VER(12, 0), IP_VER(13, 0)))1688 intel_de_rmw(dev_priv, GEN11_CHICKEN_DCPR_2, 0,1689 DCPR_CLEAR_MEMSTAT_DIS | DCPR_SEND_RESP_IMM |1690 DCPR_MASK_LPMODE | DCPR_MASK_MAXLATENCY_MEMUP_CLR);1691 1692 /* Wa_14011503030:xelpd */1693 if (DISPLAY_VER(dev_priv) == 13)1694 intel_de_write(dev_priv, XELPD_DISPLAY_ERR_FATAL_MASK, ~0);1695 1696 /* Wa_15013987218 */1697 if (DISPLAY_VER(dev_priv) == 20) {1698 intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D,1699 0, PCH_GMBUSUNIT_CLOCK_GATE_DISABLE);1700 intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D,1701 PCH_GMBUSUNIT_CLOCK_GATE_DISABLE, 0);1702 }1703}1704 1705static void icl_display_core_uninit(struct drm_i915_private *dev_priv)1706{1707 struct i915_power_domains *power_domains = &dev_priv->display.power.domains;1708 struct i915_power_well *well;1709 1710 if (!HAS_DISPLAY(dev_priv))1711 return;1712 1713 gen9_disable_dc_states(dev_priv);1714 intel_dmc_disable_program(dev_priv);1715 1716 /* 1. Disable all display engine functions -> aready done */1717 1718 /* 2. Disable DBUF */1719 gen9_dbuf_disable(dev_priv);1720 1721 /* 3. Disable CD clock */1722 intel_cdclk_uninit_hw(dev_priv);1723 1724 if (DISPLAY_VER(dev_priv) == 14)1725 intel_de_rmw(dev_priv, DC_STATE_EN, 0,1726 HOLD_PHY_PG1_LATCH | HOLD_PHY_CLKREQ_PG1_LATCH);1727 1728 /*1729 * 4. Disable Power Well 1 (PG1).1730 * The AUX IO power wells are toggled on demand, so they are already1731 * disabled at this point.1732 */1733 mutex_lock(&power_domains->lock);1734 well = lookup_power_well(dev_priv, SKL_DISP_PW_1);1735 intel_power_well_disable(dev_priv, well);1736 mutex_unlock(&power_domains->lock);1737 1738 /* 5. */1739 intel_combo_phy_uninit(dev_priv);1740}1741 1742static void chv_phy_control_init(struct drm_i915_private *dev_priv)1743{1744 struct i915_power_well *cmn_bc =1745 lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC);1746 struct i915_power_well *cmn_d =1747 lookup_power_well(dev_priv, CHV_DISP_PW_DPIO_CMN_D);1748 1749 /*1750 * DISPLAY_PHY_CONTROL can get corrupted if read. As a1751 * workaround never ever read DISPLAY_PHY_CONTROL, and1752 * instead maintain a shadow copy ourselves. Use the actual1753 * power well state and lane status to reconstruct the1754 * expected initial value.1755 */1756 dev_priv->display.power.chv_phy_control =1757 PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY0) |1758 PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY1) |1759 PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH0) |1760 PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH1) |1761 PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY1, DPIO_CH0);1762 1763 /*1764 * If all lanes are disabled we leave the override disabled1765 * with all power down bits cleared to match the state we1766 * would use after disabling the port. Otherwise enable the1767 * override and set the lane powerdown bits accding to the1768 * current lane status.1769 */1770 if (intel_power_well_is_enabled(dev_priv, cmn_bc)) {1771 u32 status = intel_de_read(dev_priv, DPLL(dev_priv, PIPE_A));1772 unsigned int mask;1773 1774 mask = status & DPLL_PORTB_READY_MASK;1775 if (mask == 0xf)1776 mask = 0x0;1777 else1778 dev_priv->display.power.chv_phy_control |=1779 PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0);1780 1781 dev_priv->display.power.chv_phy_control |=1782 PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH0);1783 1784 mask = (status & DPLL_PORTC_READY_MASK) >> 4;1785 if (mask == 0xf)1786 mask = 0x0;1787 else1788 dev_priv->display.power.chv_phy_control |=1789 PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1);1790 1791 dev_priv->display.power.chv_phy_control |=1792 PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH1);1793 1794 dev_priv->display.power.chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0);1795 1796 dev_priv->display.power.chv_phy_assert[DPIO_PHY0] = false;1797 } else {1798 dev_priv->display.power.chv_phy_assert[DPIO_PHY0] = true;1799 }1800 1801 if (intel_power_well_is_enabled(dev_priv, cmn_d)) {1802 u32 status = intel_de_read(dev_priv, DPIO_PHY_STATUS);1803 unsigned int mask;1804 1805 mask = status & DPLL_PORTD_READY_MASK;1806 1807 if (mask == 0xf)1808 mask = 0x0;1809 else1810 dev_priv->display.power.chv_phy_control |=1811 PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0);1812 1813 dev_priv->display.power.chv_phy_control |=1814 PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY1, DPIO_CH0);1815 1816 dev_priv->display.power.chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1);1817 1818 dev_priv->display.power.chv_phy_assert[DPIO_PHY1] = false;1819 } else {1820 dev_priv->display.power.chv_phy_assert[DPIO_PHY1] = true;1821 }1822 1823 drm_dbg_kms(&dev_priv->drm, "Initial PHY_CONTROL=0x%08x\n",1824 dev_priv->display.power.chv_phy_control);1825 1826 /* Defer application of initial phy_control to enabling the powerwell */1827}1828 1829static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)1830{1831 struct i915_power_well *cmn =1832 lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC);1833 struct i915_power_well *disp2d =1834 lookup_power_well(dev_priv, VLV_DISP_PW_DISP2D);1835 1836 /* If the display might be already active skip this */1837 if (intel_power_well_is_enabled(dev_priv, cmn) &&1838 intel_power_well_is_enabled(dev_priv, disp2d) &&1839 intel_de_read(dev_priv, DPIO_CTL) & DPIO_CMNRST)1840 return;1841 1842 drm_dbg_kms(&dev_priv->drm, "toggling display PHY side reset\n");1843 1844 /* cmnlane needs DPLL registers */1845 intel_power_well_enable(dev_priv, disp2d);1846 1847 /*1848 * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx:1849 * Need to assert and de-assert PHY SB reset by gating the1850 * common lane power, then un-gating it.1851 * Simply ungating isn't enough to reset the PHY enough to get1852 * ports and lanes running.1853 */1854 intel_power_well_disable(dev_priv, cmn);1855}1856 1857static bool vlv_punit_is_power_gated(struct drm_i915_private *dev_priv, u32 reg0)1858{1859 bool ret;1860 1861 vlv_punit_get(dev_priv);1862 ret = (vlv_punit_read(dev_priv, reg0) & SSPM0_SSC_MASK) == SSPM0_SSC_PWR_GATE;1863 vlv_punit_put(dev_priv);1864 1865 return ret;1866}1867 1868static void assert_ved_power_gated(struct drm_i915_private *dev_priv)1869{1870 drm_WARN(&dev_priv->drm,1871 !vlv_punit_is_power_gated(dev_priv, PUNIT_REG_VEDSSPM0),1872 "VED not power gated\n");1873}1874 1875static void assert_isp_power_gated(struct drm_i915_private *dev_priv)1876{1877 static const struct pci_device_id isp_ids[] = {1878 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0f38)},1879 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x22b8)},1880 {}1881 };1882 1883 drm_WARN(&dev_priv->drm, !pci_dev_present(isp_ids) &&1884 !vlv_punit_is_power_gated(dev_priv, PUNIT_REG_ISPSSPM0),1885 "ISP not power gated\n");1886}1887 1888static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);1889 1890/**1891 * intel_power_domains_init_hw - initialize hardware power domain state1892 * @i915: i915 device instance1893 * @resume: Called from resume code paths or not1894 *1895 * This function initializes the hardware power domain state and enables all1896 * power wells belonging to the INIT power domain. Power wells in other1897 * domains (and not in the INIT domain) are referenced or disabled by1898 * intel_modeset_readout_hw_state(). After that the reference count of each1899 * power well must match its HW enabled state, see1900 * intel_power_domains_verify_state().1901 *1902 * It will return with power domains disabled (to be enabled later by1903 * intel_power_domains_enable()) and must be paired with1904 * intel_power_domains_driver_remove().1905 */1906void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)1907{1908 struct i915_power_domains *power_domains = &i915->display.power.domains;1909 1910 power_domains->initializing = true;1911 1912 if (DISPLAY_VER(i915) >= 11) {1913 icl_display_core_init(i915, resume);1914 } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {1915 bxt_display_core_init(i915, resume);1916 } else if (DISPLAY_VER(i915) == 9) {1917 skl_display_core_init(i915, resume);1918 } else if (IS_CHERRYVIEW(i915)) {1919 mutex_lock(&power_domains->lock);1920 chv_phy_control_init(i915);1921 mutex_unlock(&power_domains->lock);1922 assert_isp_power_gated(i915);1923 } else if (IS_VALLEYVIEW(i915)) {1924 mutex_lock(&power_domains->lock);1925 vlv_cmnlane_wa(i915);1926 mutex_unlock(&power_domains->lock);1927 assert_ved_power_gated(i915);1928 assert_isp_power_gated(i915);1929 } else if (IS_BROADWELL(i915) || IS_HASWELL(i915)) {1930 hsw_assert_cdclk(i915);1931 intel_pch_reset_handshake(i915, !HAS_PCH_NOP(i915));1932 } else if (IS_IVYBRIDGE(i915)) {1933 intel_pch_reset_handshake(i915, !HAS_PCH_NOP(i915));1934 }1935 1936 /*1937 * Keep all power wells enabled for any dependent HW access during1938 * initialization and to make sure we keep BIOS enabled display HW1939 * resources powered until display HW readout is complete. We drop1940 * this reference in intel_power_domains_enable().1941 */1942 drm_WARN_ON(&i915->drm, power_domains->init_wakeref);1943 power_domains->init_wakeref =1944 intel_display_power_get(i915, POWER_DOMAIN_INIT);1945 1946 /* Disable power support if the user asked so. */1947 if (!i915->display.params.disable_power_well) {1948 drm_WARN_ON(&i915->drm, power_domains->disable_wakeref);1949 i915->display.power.domains.disable_wakeref = intel_display_power_get(i915,1950 POWER_DOMAIN_INIT);1951 }1952 intel_power_domains_sync_hw(i915);1953 1954 power_domains->initializing = false;1955}1956 1957/**1958 * intel_power_domains_driver_remove - deinitialize hw power domain state1959 * @i915: i915 device instance1960 *1961 * De-initializes the display power domain HW state. It also ensures that the1962 * device stays powered up so that the driver can be reloaded.1963 *1964 * It must be called with power domains already disabled (after a call to1965 * intel_power_domains_disable()) and must be paired with1966 * intel_power_domains_init_hw().1967 */1968void intel_power_domains_driver_remove(struct drm_i915_private *i915)1969{1970 intel_wakeref_t wakeref __maybe_unused =1971 fetch_and_zero(&i915->display.power.domains.init_wakeref);1972 1973 /* Remove the refcount we took to keep power well support disabled. */1974 if (!i915->display.params.disable_power_well)1975 intel_display_power_put(i915, POWER_DOMAIN_INIT,1976 fetch_and_zero(&i915->display.power.domains.disable_wakeref));1977 1978 intel_display_power_flush_work_sync(i915);1979 1980 intel_power_domains_verify_state(i915);1981 1982 /* Keep the power well enabled, but cancel its rpm wakeref. */1983 intel_runtime_pm_put(&i915->runtime_pm, wakeref);1984}1985 1986/**1987 * intel_power_domains_sanitize_state - sanitize power domains state1988 * @i915: i915 device instance1989 *1990 * Sanitize the power domains state during driver loading and system resume.1991 * The function will disable all display power wells that BIOS has enabled1992 * without a user for it (any user for a power well has taken a reference1993 * on it by the time this function is called, after the state of all the1994 * pipe, encoder, etc. HW resources have been sanitized).1995 */1996void intel_power_domains_sanitize_state(struct drm_i915_private *i915)1997{1998 struct i915_power_domains *power_domains = &i915->display.power.domains;1999 struct i915_power_well *power_well;2000 2001 mutex_lock(&power_domains->lock);2002 2003 for_each_power_well_reverse(i915, power_well) {2004 if (power_well->desc->always_on || power_well->count ||2005 !intel_power_well_is_enabled(i915, power_well))2006 continue;2007 2008 drm_dbg_kms(&i915->drm,2009 "BIOS left unused %s power well enabled, disabling it\n",2010 intel_power_well_name(power_well));2011 intel_power_well_disable(i915, power_well);2012 }2013 2014 mutex_unlock(&power_domains->lock);2015}2016 2017/**2018 * intel_power_domains_enable - enable toggling of display power wells2019 * @i915: i915 device instance2020 *2021 * Enable the ondemand enabling/disabling of the display power wells. Note that2022 * power wells not belonging to POWER_DOMAIN_INIT are allowed to be toggled2023 * only at specific points of the display modeset sequence, thus they are not2024 * affected by the intel_power_domains_enable()/disable() calls. The purpose2025 * of these function is to keep the rest of power wells enabled until the end2026 * of display HW readout (which will acquire the power references reflecting2027 * the current HW state).2028 */2029void intel_power_domains_enable(struct drm_i915_private *i915)2030{2031 intel_wakeref_t wakeref __maybe_unused =2032 fetch_and_zero(&i915->display.power.domains.init_wakeref);2033 2034 intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);2035 intel_power_domains_verify_state(i915);2036}2037 2038/**2039 * intel_power_domains_disable - disable toggling of display power wells2040 * @i915: i915 device instance2041 *2042 * Disable the ondemand enabling/disabling of the display power wells. See2043 * intel_power_domains_enable() for which power wells this call controls.2044 */2045void intel_power_domains_disable(struct drm_i915_private *i915)2046{2047 struct i915_power_domains *power_domains = &i915->display.power.domains;2048 2049 drm_WARN_ON(&i915->drm, power_domains->init_wakeref);2050 power_domains->init_wakeref =2051 intel_display_power_get(i915, POWER_DOMAIN_INIT);2052 2053 intel_power_domains_verify_state(i915);2054}2055 2056/**2057 * intel_power_domains_suspend - suspend power domain state2058 * @i915: i915 device instance2059 * @s2idle: specifies whether we go to idle, or deeper sleep2060 *2061 * This function prepares the hardware power domain state before entering2062 * system suspend.2063 *2064 * It must be called with power domains already disabled (after a call to2065 * intel_power_domains_disable()) and paired with intel_power_domains_resume().2066 */2067void intel_power_domains_suspend(struct drm_i915_private *i915, bool s2idle)2068{2069 struct i915_power_domains *power_domains = &i915->display.power.domains;2070 intel_wakeref_t wakeref __maybe_unused =2071 fetch_and_zero(&power_domains->init_wakeref);2072 2073 intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);2074 2075 /*2076 * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC92077 * support don't manually deinit the power domains. This also means the2078 * DMC firmware will stay active, it will power down any HW2079 * resources as required and also enable deeper system power states2080 * that would be blocked if the firmware was inactive.2081 */2082 if (!(power_domains->allowed_dc_mask & DC_STATE_EN_DC9) && s2idle &&2083 intel_dmc_has_payload(i915)) {2084 intel_display_power_flush_work(i915);2085 intel_power_domains_verify_state(i915);2086 return;2087 }2088 2089 /*2090 * Even if power well support was disabled we still want to disable2091 * power wells if power domains must be deinitialized for suspend.2092 */2093 if (!i915->display.params.disable_power_well)2094 intel_display_power_put(i915, POWER_DOMAIN_INIT,2095 fetch_and_zero(&i915->display.power.domains.disable_wakeref));2096 2097 intel_display_power_flush_work(i915);2098 intel_power_domains_verify_state(i915);2099 2100 if (DISPLAY_VER(i915) >= 11)2101 icl_display_core_uninit(i915);2102 else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915))2103 bxt_display_core_uninit(i915);2104 else if (DISPLAY_VER(i915) == 9)2105 skl_display_core_uninit(i915);2106 2107 power_domains->display_core_suspended = true;2108}2109 2110/**2111 * intel_power_domains_resume - resume power domain state2112 * @i915: i915 device instance2113 *2114 * This function resume the hardware power domain state during system resume.2115 *2116 * It will return with power domain support disabled (to be enabled later by2117 * intel_power_domains_enable()) and must be paired with2118 * intel_power_domains_suspend().2119 */2120void intel_power_domains_resume(struct drm_i915_private *i915)2121{2122 struct i915_power_domains *power_domains = &i915->display.power.domains;2123 2124 if (power_domains->display_core_suspended) {2125 intel_power_domains_init_hw(i915, true);2126 power_domains->display_core_suspended = false;2127 } else {2128 drm_WARN_ON(&i915->drm, power_domains->init_wakeref);2129 power_domains->init_wakeref =2130 intel_display_power_get(i915, POWER_DOMAIN_INIT);2131 }2132 2133 intel_power_domains_verify_state(i915);2134}2135 2136#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)2137 2138static void intel_power_domains_dump_info(struct drm_i915_private *i915)2139{2140 struct i915_power_domains *power_domains = &i915->display.power.domains;2141 struct i915_power_well *power_well;2142 2143 for_each_power_well(i915, power_well) {2144 enum intel_display_power_domain domain;2145 2146 drm_dbg(&i915->drm, "%-25s %d\n",2147 intel_power_well_name(power_well), intel_power_well_refcount(power_well));2148 2149 for_each_power_domain(domain, intel_power_well_domains(power_well))2150 drm_dbg(&i915->drm, " %-23s %d\n",2151 intel_display_power_domain_str(domain),2152 power_domains->domain_use_count[domain]);2153 }2154}2155 2156/**2157 * intel_power_domains_verify_state - verify the HW/SW state for all power wells2158 * @i915: i915 device instance2159 *2160 * Verify if the reference count of each power well matches its HW enabled2161 * state and the total refcount of the domains it belongs to. This must be2162 * called after modeset HW state sanitization, which is responsible for2163 * acquiring reference counts for any power wells in use and disabling the2164 * ones left on by BIOS but not required by any active output.2165 */2166static void intel_power_domains_verify_state(struct drm_i915_private *i915)2167{2168 struct i915_power_domains *power_domains = &i915->display.power.domains;2169 struct i915_power_well *power_well;2170 bool dump_domain_info;2171 2172 mutex_lock(&power_domains->lock);2173 2174 verify_async_put_domains_state(power_domains);2175 2176 dump_domain_info = false;2177 for_each_power_well(i915, power_well) {2178 enum intel_display_power_domain domain;2179 int domains_count;2180 bool enabled;2181 2182 enabled = intel_power_well_is_enabled(i915, power_well);2183 if ((intel_power_well_refcount(power_well) ||2184 intel_power_well_is_always_on(power_well)) !=2185 enabled)2186 drm_err(&i915->drm,2187 "power well %s state mismatch (refcount %d/enabled %d)",2188 intel_power_well_name(power_well),2189 intel_power_well_refcount(power_well), enabled);2190 2191 domains_count = 0;2192 for_each_power_domain(domain, intel_power_well_domains(power_well))2193 domains_count += power_domains->domain_use_count[domain];2194 2195 if (intel_power_well_refcount(power_well) != domains_count) {2196 drm_err(&i915->drm,2197 "power well %s refcount/domain refcount mismatch "2198 "(refcount %d/domains refcount %d)\n",2199 intel_power_well_name(power_well),2200 intel_power_well_refcount(power_well),2201 domains_count);2202 dump_domain_info = true;2203 }2204 }2205 2206 if (dump_domain_info) {2207 static bool dumped;2208 2209 if (!dumped) {2210 intel_power_domains_dump_info(i915);2211 dumped = true;2212 }2213 }2214 2215 mutex_unlock(&power_domains->lock);2216}2217 2218#else2219 2220static void intel_power_domains_verify_state(struct drm_i915_private *i915)2221{2222}2223 2224#endif2225 2226void intel_display_power_suspend_late(struct drm_i915_private *i915)2227{2228 if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||2229 IS_BROXTON(i915)) {2230 bxt_enable_dc9(i915);2231 } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {2232 hsw_enable_pc8(i915);2233 }2234 2235 /* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */2236 if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1)2237 intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS);2238}2239 2240void intel_display_power_resume_early(struct drm_i915_private *i915)2241{2242 if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||2243 IS_BROXTON(i915)) {2244 gen9_sanitize_dc_state(i915);2245 bxt_disable_dc9(i915);2246 } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {2247 hsw_disable_pc8(i915);2248 }2249 2250 /* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */2251 if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1)2252 intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);2253}2254 2255void intel_display_power_suspend(struct drm_i915_private *i915)2256{2257 if (DISPLAY_VER(i915) >= 11) {2258 icl_display_core_uninit(i915);2259 bxt_enable_dc9(i915);2260 } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {2261 bxt_display_core_uninit(i915);2262 bxt_enable_dc9(i915);2263 } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {2264 hsw_enable_pc8(i915);2265 }2266}2267 2268void intel_display_power_resume(struct drm_i915_private *i915)2269{2270 struct i915_power_domains *power_domains = &i915->display.power.domains;2271 2272 if (DISPLAY_VER(i915) >= 11) {2273 bxt_disable_dc9(i915);2274 icl_display_core_init(i915, true);2275 if (intel_dmc_has_payload(i915)) {2276 if (power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC6)2277 skl_enable_dc6(i915);2278 else if (power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC5)2279 gen9_enable_dc5(i915);2280 }2281 } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) {2282 bxt_disable_dc9(i915);2283 bxt_display_core_init(i915, true);2284 if (intel_dmc_has_payload(i915) &&2285 (power_domains->allowed_dc_mask & DC_STATE_EN_UPTO_DC5))2286 gen9_enable_dc5(i915);2287 } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {2288 hsw_disable_pc8(i915);2289 }2290}2291 2292void intel_display_power_debug(struct drm_i915_private *i915, struct seq_file *m)2293{2294 struct i915_power_domains *power_domains = &i915->display.power.domains;2295 int i;2296 2297 mutex_lock(&power_domains->lock);2298 2299 seq_printf(m, "%-25s %s\n", "Power well/domain", "Use count");2300 for (i = 0; i < power_domains->power_well_count; i++) {2301 struct i915_power_well *power_well;2302 enum intel_display_power_domain power_domain;2303 2304 power_well = &power_domains->power_wells[i];2305 seq_printf(m, "%-25s %d\n", intel_power_well_name(power_well),2306 intel_power_well_refcount(power_well));2307 2308 for_each_power_domain(power_domain, intel_power_well_domains(power_well))2309 seq_printf(m, " %-23s %d\n",2310 intel_display_power_domain_str(power_domain),2311 power_domains->domain_use_count[power_domain]);2312 }2313 2314 mutex_unlock(&power_domains->lock);2315}2316 2317struct intel_ddi_port_domains {2318 enum port port_start;2319 enum port port_end;2320 enum aux_ch aux_ch_start;2321 enum aux_ch aux_ch_end;2322 2323 enum intel_display_power_domain ddi_lanes;2324 enum intel_display_power_domain ddi_io;2325 enum intel_display_power_domain aux_io;2326 enum intel_display_power_domain aux_legacy_usbc;2327 enum intel_display_power_domain aux_tbt;2328};2329 2330static const struct intel_ddi_port_domains2331i9xx_port_domains[] = {2332 {2333 .port_start = PORT_A,2334 .port_end = PORT_F,2335 .aux_ch_start = AUX_CH_A,2336 .aux_ch_end = AUX_CH_F,2337 2338 .ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_A,2339 .ddi_io = POWER_DOMAIN_PORT_DDI_IO_A,2340 .aux_io = POWER_DOMAIN_AUX_IO_A,2341 .aux_legacy_usbc = POWER_DOMAIN_AUX_A,2342 .aux_tbt = POWER_DOMAIN_INVALID,2343 },2344};2345 2346static const struct intel_ddi_port_domains2347d11_port_domains[] = {2348 {2349 .port_start = PORT_A,2350 .port_end = PORT_B,2351 .aux_ch_start = AUX_CH_A,2352 .aux_ch_end = AUX_CH_B,2353 2354 .ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_A,2355 .ddi_io = POWER_DOMAIN_PORT_DDI_IO_A,2356 .aux_io = POWER_DOMAIN_AUX_IO_A,2357 .aux_legacy_usbc = POWER_DOMAIN_AUX_A,2358 .aux_tbt = POWER_DOMAIN_INVALID,2359 }, {2360 .port_start = PORT_C,2361 .port_end = PORT_F,2362 .aux_ch_start = AUX_CH_C,2363 .aux_ch_end = AUX_CH_F,2364 2365 .ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_C,2366 .ddi_io = POWER_DOMAIN_PORT_DDI_IO_C,2367 .aux_io = POWER_DOMAIN_AUX_IO_C,2368 .aux_legacy_usbc = POWER_DOMAIN_AUX_C,2369 .aux_tbt = POWER_DOMAIN_AUX_TBT1,2370 },2371};2372 2373static const struct intel_ddi_port_domains2374d12_port_domains[] = {2375 {2376 .port_start = PORT_A,2377 .port_end = PORT_C,2378 .aux_ch_start = AUX_CH_A,2379 .aux_ch_end = AUX_CH_C,2380 2381 .ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_A,2382 .ddi_io = POWER_DOMAIN_PORT_DDI_IO_A,2383 .aux_io = POWER_DOMAIN_AUX_IO_A,2384 .aux_legacy_usbc = POWER_DOMAIN_AUX_A,2385 .aux_tbt = POWER_DOMAIN_INVALID,2386 }, {2387 .port_start = PORT_TC1,2388 .port_end = PORT_TC6,2389 .aux_ch_start = AUX_CH_USBC1,2390 .aux_ch_end = AUX_CH_USBC6,2391 2392 .ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_TC1,2393 .ddi_io = POWER_DOMAIN_PORT_DDI_IO_TC1,2394 .aux_io = POWER_DOMAIN_INVALID,2395 .aux_legacy_usbc = POWER_DOMAIN_AUX_USBC1,2396 .aux_tbt = POWER_DOMAIN_AUX_TBT1,2397 },2398};2399 2400static const struct intel_ddi_port_domains2401d13_port_domains[] = {2402 {2403 .port_start = PORT_A,2404 .port_end = PORT_C,2405 .aux_ch_start = AUX_CH_A,2406 .aux_ch_end = AUX_CH_C,2407 2408 .ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_A,2409 .ddi_io = POWER_DOMAIN_PORT_DDI_IO_A,2410 .aux_io = POWER_DOMAIN_AUX_IO_A,2411 .aux_legacy_usbc = POWER_DOMAIN_AUX_A,2412 .aux_tbt = POWER_DOMAIN_INVALID,2413 }, {2414 .port_start = PORT_TC1,2415 .port_end = PORT_TC4,2416 .aux_ch_start = AUX_CH_USBC1,2417 .aux_ch_end = AUX_CH_USBC4,2418 2419 .ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_TC1,2420 .ddi_io = POWER_DOMAIN_PORT_DDI_IO_TC1,2421 .aux_io = POWER_DOMAIN_INVALID,2422 .aux_legacy_usbc = POWER_DOMAIN_AUX_USBC1,2423 .aux_tbt = POWER_DOMAIN_AUX_TBT1,2424 }, {2425 .port_start = PORT_D_XELPD,2426 .port_end = PORT_E_XELPD,2427 .aux_ch_start = AUX_CH_D_XELPD,2428 .aux_ch_end = AUX_CH_E_XELPD,2429 2430 .ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_D,2431 .ddi_io = POWER_DOMAIN_PORT_DDI_IO_D,2432 .aux_io = POWER_DOMAIN_AUX_IO_D,2433 .aux_legacy_usbc = POWER_DOMAIN_AUX_D,2434 .aux_tbt = POWER_DOMAIN_INVALID,2435 },2436};2437 2438static void2439intel_port_domains_for_platform(struct drm_i915_private *i915,2440 const struct intel_ddi_port_domains **domains,2441 int *domains_size)2442{2443 if (DISPLAY_VER(i915) >= 13) {2444 *domains = d13_port_domains;2445 *domains_size = ARRAY_SIZE(d13_port_domains);2446 } else if (DISPLAY_VER(i915) >= 12) {2447 *domains = d12_port_domains;2448 *domains_size = ARRAY_SIZE(d12_port_domains);2449 } else if (DISPLAY_VER(i915) >= 11) {2450 *domains = d11_port_domains;2451 *domains_size = ARRAY_SIZE(d11_port_domains);2452 } else {2453 *domains = i9xx_port_domains;2454 *domains_size = ARRAY_SIZE(i9xx_port_domains);2455 }2456}2457 2458static const struct intel_ddi_port_domains *2459intel_port_domains_for_port(struct drm_i915_private *i915, enum port port)2460{2461 const struct intel_ddi_port_domains *domains;2462 int domains_size;2463 int i;2464 2465 intel_port_domains_for_platform(i915, &domains, &domains_size);2466 for (i = 0; i < domains_size; i++)2467 if (port >= domains[i].port_start && port <= domains[i].port_end)2468 return &domains[i];2469 2470 return NULL;2471}2472 2473enum intel_display_power_domain2474intel_display_power_ddi_io_domain(struct drm_i915_private *i915, enum port port)2475{2476 const struct intel_ddi_port_domains *domains = intel_port_domains_for_port(i915, port);2477 2478 if (drm_WARN_ON(&i915->drm, !domains || domains->ddi_io == POWER_DOMAIN_INVALID))2479 return POWER_DOMAIN_PORT_DDI_IO_A;2480 2481 return domains->ddi_io + (int)(port - domains->port_start);2482}2483 2484enum intel_display_power_domain2485intel_display_power_ddi_lanes_domain(struct drm_i915_private *i915, enum port port)2486{2487 const struct intel_ddi_port_domains *domains = intel_port_domains_for_port(i915, port);2488 2489 if (drm_WARN_ON(&i915->drm, !domains || domains->ddi_lanes == POWER_DOMAIN_INVALID))2490 return POWER_DOMAIN_PORT_DDI_LANES_A;2491 2492 return domains->ddi_lanes + (int)(port - domains->port_start);2493}2494 2495static const struct intel_ddi_port_domains *2496intel_port_domains_for_aux_ch(struct drm_i915_private *i915, enum aux_ch aux_ch)2497{2498 const struct intel_ddi_port_domains *domains;2499 int domains_size;2500 int i;2501 2502 intel_port_domains_for_platform(i915, &domains, &domains_size);2503 for (i = 0; i < domains_size; i++)2504 if (aux_ch >= domains[i].aux_ch_start && aux_ch <= domains[i].aux_ch_end)2505 return &domains[i];2506 2507 return NULL;2508}2509 2510enum intel_display_power_domain2511intel_display_power_aux_io_domain(struct drm_i915_private *i915, enum aux_ch aux_ch)2512{2513 const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(i915, aux_ch);2514 2515 if (drm_WARN_ON(&i915->drm, !domains || domains->aux_io == POWER_DOMAIN_INVALID))2516 return POWER_DOMAIN_AUX_IO_A;2517 2518 return domains->aux_io + (int)(aux_ch - domains->aux_ch_start);2519}2520 2521enum intel_display_power_domain2522intel_display_power_legacy_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch)2523{2524 const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(i915, aux_ch);2525 2526 if (drm_WARN_ON(&i915->drm, !domains || domains->aux_legacy_usbc == POWER_DOMAIN_INVALID))2527 return POWER_DOMAIN_AUX_A;2528 2529 return domains->aux_legacy_usbc + (int)(aux_ch - domains->aux_ch_start);2530}2531 2532enum intel_display_power_domain2533intel_display_power_tbt_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch)2534{2535 const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(i915, aux_ch);2536 2537 if (drm_WARN_ON(&i915->drm, !domains || domains->aux_tbt == POWER_DOMAIN_INVALID))2538 return POWER_DOMAIN_AUX_TBT1;2539 2540 return domains->aux_tbt + (int)(aux_ch - domains->aux_ch_start);2541}2542