brintos

brintos / linux-shallow public Read only

0
0
Text · 76.0 KiB · ef2fdbf Raw
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