diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_runtime_pm.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_runtime_pm.c | 947 |
1 files changed, 435 insertions, 512 deletions
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index f630d632a976..b66d8e136aa3 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -50,10 +50,11 @@ */ bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, - int power_well_id); + enum i915_power_well_id power_well_id); static struct i915_power_well * -lookup_power_well(struct drm_i915_private *dev_priv, int power_well_id); +lookup_power_well(struct drm_i915_private *dev_priv, + enum i915_power_well_id power_well_id); const char * intel_display_power_domain_str(enum intel_display_power_domain domain) @@ -168,18 +169,6 @@ static void intel_power_well_put(struct drm_i915_private *dev_priv, intel_power_well_disable(dev_priv, power_well); } -/* - * We should only use the power well if we explicitly asked the hardware to - * enable it, so check if it's enabled and also check if we've requested it to - * be enabled. - */ -static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - return I915_READ(HSW_PWR_WELL_DRIVER) == - (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); -} - /** * __intel_display_power_is_enabled - unlocked check for a power domain * @dev_priv: i915 device instance @@ -278,7 +267,8 @@ void intel_display_set_init_power(struct drm_i915_private *dev_priv, * to be enabled, and it will only be disabled if none of the registers is * requesting it to be enabled. */ -static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) +static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv, + u8 irq_pipe_mask, bool has_vga) { struct pci_dev *pdev = dev_priv->drm.pdev; @@ -292,85 +282,55 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) * sure vgacon can keep working normally without triggering interrupts * and error messages. */ - vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); - outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); - vga_put(pdev, VGA_RSRC_LEGACY_IO); - - if (IS_BROADWELL(dev_priv)) - gen8_irq_power_well_post_enable(dev_priv, - 1 << PIPE_C | 1 << PIPE_B); -} - -static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv) -{ - if (IS_BROADWELL(dev_priv)) - gen8_irq_power_well_pre_disable(dev_priv, - 1 << PIPE_C | 1 << PIPE_B); -} - -static void skl_power_well_post_enable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - struct pci_dev *pdev = dev_priv->drm.pdev; - - /* - * After we re-enable the power well, if we touch VGA register 0x3d5 - * we'll get unclaimed register interrupts. This stops after we write - * anything to the VGA MSR register. The vgacon module uses this - * register all the time, so if we unbind our driver and, as a - * consequence, bind vgacon, we'll get stuck in an infinite loop at - * console_unlock(). So make here we touch the VGA MSR register, making - * sure vgacon can keep working normally without triggering interrupts - * and error messages. - */ - if (power_well->id == SKL_DISP_PW_2) { + if (has_vga) { vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); vga_put(pdev, VGA_RSRC_LEGACY_IO); - - gen8_irq_power_well_post_enable(dev_priv, - 1 << PIPE_C | 1 << PIPE_B); } + + if (irq_pipe_mask) + gen8_irq_power_well_post_enable(dev_priv, irq_pipe_mask); } -static void skl_power_well_pre_disable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) +static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv, + u8 irq_pipe_mask) { - if (power_well->id == SKL_DISP_PW_2) - gen8_irq_power_well_pre_disable(dev_priv, - 1 << PIPE_C | 1 << PIPE_B); + if (irq_pipe_mask) + gen8_irq_power_well_pre_disable(dev_priv, irq_pipe_mask); } -static void gen9_wait_for_power_well_enable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) + +static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) { - int id = power_well->id; + enum i915_power_well_id id = power_well->id; /* Timeout for PW1:10 us, AUX:not specified, other PWs:20 us. */ WARN_ON(intel_wait_for_register(dev_priv, - HSW_PWR_WELL_DRIVER, - SKL_POWER_WELL_STATE(id), - SKL_POWER_WELL_STATE(id), + HSW_PWR_WELL_CTL_DRIVER(id), + HSW_PWR_WELL_CTL_STATE(id), + HSW_PWR_WELL_CTL_STATE(id), 1)); } -static u32 gen9_power_well_requesters(struct drm_i915_private *dev_priv, int id) +static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv, + enum i915_power_well_id id) { - u32 req_mask = SKL_POWER_WELL_REQ(id); + u32 req_mask = HSW_PWR_WELL_CTL_REQ(id); u32 ret; - ret = I915_READ(HSW_PWR_WELL_BIOS) & req_mask ? 1 : 0; - ret |= I915_READ(HSW_PWR_WELL_DRIVER) & req_mask ? 2 : 0; - ret |= I915_READ(HSW_PWR_WELL_KVMR) & req_mask ? 4 : 0; - ret |= I915_READ(HSW_PWR_WELL_DEBUG) & req_mask ? 8 : 0; + ret = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)) & req_mask ? 1 : 0; + ret |= I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & req_mask ? 2 : 0; + ret |= I915_READ(HSW_PWR_WELL_CTL_KVMR) & req_mask ? 4 : 0; + ret |= I915_READ(HSW_PWR_WELL_CTL_DEBUG(id)) & req_mask ? 8 : 0; return ret; } -static void gen9_wait_for_power_well_disable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) +static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) { - int id = power_well->id; + enum i915_power_well_id id = power_well->id; bool disabled; u32 reqs; @@ -383,9 +343,9 @@ static void gen9_wait_for_power_well_disable(struct drm_i915_private *dev_priv, * Skip the wait in case any of the request bits are set and print a * diagnostic message. */ - wait_for((disabled = !(I915_READ(HSW_PWR_WELL_DRIVER) & - SKL_POWER_WELL_STATE(id))) || - (reqs = gen9_power_well_requesters(dev_priv, id)), 1); + wait_for((disabled = !(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & + HSW_PWR_WELL_CTL_STATE(id))) || + (reqs = hsw_power_well_requesters(dev_priv, id)), 1); if (disabled) return; @@ -394,216 +354,85 @@ static void gen9_wait_for_power_well_disable(struct drm_i915_private *dev_priv, !!(reqs & 1), !!(reqs & 2), !!(reqs & 4), !!(reqs & 8)); } -static void hsw_set_power_well(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well, bool enable) +static void gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv, + enum skl_power_gate pg) { - bool is_enabled, enable_requested; - uint32_t tmp; + /* Timeout 5us for PG#0, for other PGs 1us */ + WARN_ON(intel_wait_for_register(dev_priv, SKL_FUSE_STATUS, + SKL_FUSE_PG_DIST_STATUS(pg), + SKL_FUSE_PG_DIST_STATUS(pg), 1)); +} - tmp = I915_READ(HSW_PWR_WELL_DRIVER); - is_enabled = tmp & HSW_PWR_WELL_STATE_ENABLED; - enable_requested = tmp & HSW_PWR_WELL_ENABLE_REQUEST; - - if (enable) { - if (!enable_requested) - I915_WRITE(HSW_PWR_WELL_DRIVER, - HSW_PWR_WELL_ENABLE_REQUEST); - - if (!is_enabled) { - DRM_DEBUG_KMS("Enabling power well\n"); - if (intel_wait_for_register(dev_priv, - HSW_PWR_WELL_DRIVER, - HSW_PWR_WELL_STATE_ENABLED, - HSW_PWR_WELL_STATE_ENABLED, - 20)) - DRM_ERROR("Timeout enabling power well\n"); - hsw_power_well_post_enable(dev_priv); - } +static void hsw_power_well_enable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + enum i915_power_well_id id = power_well->id; + bool wait_fuses = power_well->hsw.has_fuses; + enum skl_power_gate pg; + u32 val; - } else { - if (enable_requested) { - hsw_power_well_pre_disable(dev_priv); - I915_WRITE(HSW_PWR_WELL_DRIVER, 0); - POSTING_READ(HSW_PWR_WELL_DRIVER); - DRM_DEBUG_KMS("Requesting to disable the power well\n"); - } + if (wait_fuses) { + pg = SKL_PW_TO_PG(id); + /* + * For PW1 we have to wait both for the PW0/PG0 fuse state + * before enabling the power well and PW1/PG1's own fuse + * state after the enabling. For all other power wells with + * fuses we only have to wait for that PW/PG's fuse state + * after the enabling. + */ + if (pg == SKL_PG1) + gen9_wait_for_power_well_fuses(dev_priv, SKL_PG0); } + + val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)); + I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), val | HSW_PWR_WELL_CTL_REQ(id)); + hsw_wait_for_power_well_enable(dev_priv, power_well); + + if (wait_fuses) + gen9_wait_for_power_well_fuses(dev_priv, pg); + + hsw_power_well_post_enable(dev_priv, power_well->hsw.irq_pipe_mask, + power_well->hsw.has_vga); } -#define SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) | \ - BIT_ULL(POWER_DOMAIN_AUX_B) | \ - BIT_ULL(POWER_DOMAIN_AUX_C) | \ - BIT_ULL(POWER_DOMAIN_AUX_D) | \ - BIT_ULL(POWER_DOMAIN_AUDIO) | \ - BIT_ULL(POWER_DOMAIN_VGA) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define SKL_DISPLAY_DC_OFF_POWER_DOMAINS ( \ - SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ - BIT_ULL(POWER_DOMAIN_MODESET) | \ - BIT_ULL(POWER_DOMAIN_AUX_A) | \ - BIT_ULL(POWER_DOMAIN_INIT)) +static void hsw_power_well_disable(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + enum i915_power_well_id id = power_well->id; + u32 val; -#define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ - BIT_ULL(POWER_DOMAIN_AUX_B) | \ - BIT_ULL(POWER_DOMAIN_AUX_C) | \ - BIT_ULL(POWER_DOMAIN_AUDIO) | \ - BIT_ULL(POWER_DOMAIN_VGA) | \ - BIT_ULL(POWER_DOMAIN_GMBUS) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define BXT_DISPLAY_DC_OFF_POWER_DOMAINS ( \ - BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ - BIT_ULL(POWER_DOMAIN_MODESET) | \ - BIT_ULL(POWER_DOMAIN_AUX_A) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define BXT_DPIO_CMN_A_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) | \ - BIT_ULL(POWER_DOMAIN_AUX_A) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define BXT_DPIO_CMN_BC_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ - BIT_ULL(POWER_DOMAIN_AUX_B) | \ - BIT_ULL(POWER_DOMAIN_AUX_C) | \ - BIT_ULL(POWER_DOMAIN_INIT)) + hsw_power_well_pre_disable(dev_priv, power_well->hsw.irq_pipe_mask); -#define GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ - BIT_ULL(POWER_DOMAIN_AUX_B) | \ - BIT_ULL(POWER_DOMAIN_AUX_C) | \ - BIT_ULL(POWER_DOMAIN_AUDIO) | \ - BIT_ULL(POWER_DOMAIN_VGA) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO)) -#define GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO)) -#define GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO)) -#define GLK_DPIO_CMN_A_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) | \ - BIT_ULL(POWER_DOMAIN_AUX_A) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DPIO_CMN_B_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ - BIT_ULL(POWER_DOMAIN_AUX_B) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DPIO_CMN_C_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ - BIT_ULL(POWER_DOMAIN_AUX_C) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_AUX_A_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_AUX_A) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_AUX_B_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_AUX_B) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_AUX_C_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_AUX_C) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define GLK_DISPLAY_DC_OFF_POWER_DOMAINS ( \ - GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ - BIT_ULL(POWER_DOMAIN_MODESET) | \ - BIT_ULL(POWER_DOMAIN_AUX_A) | \ - BIT_ULL(POWER_DOMAIN_INIT)) + val = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)); + I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), + val & ~HSW_PWR_WELL_CTL_REQ(id)); + hsw_wait_for_power_well_disable(dev_priv, power_well); +} -#define CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) | \ - BIT_ULL(POWER_DOMAIN_AUX_B) | \ - BIT_ULL(POWER_DOMAIN_AUX_C) | \ - BIT_ULL(POWER_DOMAIN_AUX_D) | \ - BIT_ULL(POWER_DOMAIN_AUDIO) | \ - BIT_ULL(POWER_DOMAIN_VGA) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_AUX_A_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_AUX_A) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_AUX_B_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_AUX_B) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_AUX_C_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_AUX_C) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_AUX_D_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_AUX_D) | \ - BIT_ULL(POWER_DOMAIN_INIT)) -#define CNL_DISPLAY_DC_OFF_POWER_DOMAINS ( \ - CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ - BIT_ULL(POWER_DOMAIN_MODESET) | \ - BIT_ULL(POWER_DOMAIN_AUX_A) | \ - BIT_ULL(POWER_DOMAIN_INIT)) +/* + * We should only use the power well if we explicitly asked the hardware to + * enable it, so check if it's enabled and also check if we've requested it to + * be enabled. + */ +static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv, + struct i915_power_well *power_well) +{ + enum i915_power_well_id id = power_well->id; + u32 mask = HSW_PWR_WELL_CTL_REQ(id) | HSW_PWR_WELL_CTL_STATE(id); + + return (I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & mask) == mask; +} static void assert_can_enable_dc9(struct drm_i915_private *dev_priv) { + enum i915_power_well_id id = SKL_DISP_PW_2; + WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9), "DC9 already programmed to be enabled.\n"); WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5, "DC5 still not disabled to enable DC9.\n"); - WARN_ONCE(I915_READ(HSW_PWR_WELL_DRIVER) & - SKL_POWER_WELL_REQ(SKL_DISP_PW_2), + WARN_ONCE(I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)) & + HSW_PWR_WELL_CTL_REQ(id), "Power well 2 on.\n"); WARN_ONCE(intel_irqs_enabled(dev_priv), "Interrupts not disabled yet.\n"); @@ -799,181 +628,39 @@ void skl_disable_dc6(struct drm_i915_private *dev_priv) gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); } -static void skl_set_power_well(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well, bool enable) -{ - uint32_t tmp, fuse_status; - uint32_t req_mask, state_mask; - bool is_enabled, enable_requested, check_fuse_status = false; - - tmp = I915_READ(HSW_PWR_WELL_DRIVER); - fuse_status = I915_READ(SKL_FUSE_STATUS); - - switch (power_well->id) { - case SKL_DISP_PW_1: - if (intel_wait_for_register(dev_priv, - SKL_FUSE_STATUS, - SKL_FUSE_PG0_DIST_STATUS, - SKL_FUSE_PG0_DIST_STATUS, - 1)) { - DRM_ERROR("PG0 not enabled\n"); - return; - } - break; - case SKL_DISP_PW_2: - if (!(fuse_status & SKL_FUSE_PG1_DIST_STATUS)) { - DRM_ERROR("PG1 in disabled state\n"); - return; - } - break; - case SKL_DISP_PW_MISC_IO: - case SKL_DISP_PW_DDI_A_E: /* GLK_DISP_PW_DDI_A, CNL_DISP_PW_DDI_A */ - case SKL_DISP_PW_DDI_B: - case SKL_DISP_PW_DDI_C: - case SKL_DISP_PW_DDI_D: - case GLK_DISP_PW_AUX_A: /* CNL_DISP_PW_AUX_A */ - case GLK_DISP_PW_AUX_B: /* CNL_DISP_PW_AUX_B */ - case GLK_DISP_PW_AUX_C: /* CNL_DISP_PW_AUX_C */ - case CNL_DISP_PW_AUX_D: - break; - default: - WARN(1, "Unknown power well %lu\n", power_well->id); - return; - } - - req_mask = SKL_POWER_WELL_REQ(power_well->id); - enable_requested = tmp & req_mask; - state_mask = SKL_POWER_WELL_STATE(power_well->id); - is_enabled = tmp & state_mask; - - if (!enable && enable_requested) - skl_power_well_pre_disable(dev_priv, power_well); - - if (enable) { - if (!enable_requested) { - WARN((tmp & state_mask) && - !I915_READ(HSW_PWR_WELL_BIOS), - "Invalid for power well status to be enabled, unless done by the BIOS, \ - when request is to disable!\n"); - I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask); - } - - if (!is_enabled) { - DRM_DEBUG_KMS("Enabling %s\n", power_well->name); - check_fuse_status = true; - } - - gen9_wait_for_power_well_enable(dev_priv, power_well); - } else { - if (enable_requested) { - I915_WRITE(HSW_PWR_WELL_DRIVER, tmp & ~req_mask); - POSTING_READ(HSW_PWR_WELL_DRIVER); - DRM_DEBUG_KMS("Disabling %s\n", power_well->name); - } - - gen9_wait_for_power_well_disable(dev_priv, power_well); - } - - if (check_fuse_status) { - if (power_well->id == SKL_DISP_PW_1) { - if (intel_wait_for_register(dev_priv, - SKL_FUSE_STATUS, - SKL_FUSE_PG1_DIST_STATUS, - SKL_FUSE_PG1_DIST_STATUS, - 1)) - DRM_ERROR("PG1 distributing status timeout\n"); - } else if (power_well->id == SKL_DISP_PW_2) { - if (intel_wait_for_register(dev_priv, - SKL_FUSE_STATUS, - SKL_FUSE_PG2_DIST_STATUS, - SKL_FUSE_PG2_DIST_STATUS, - 1)) - DRM_ERROR("PG2 distributing status timeout\n"); - } - } - - if (enable && !is_enabled) - skl_power_well_post_enable(dev_priv, power_well); -} - static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - /* Take over the request bit if set by BIOS. */ - if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST) { - if (!(I915_READ(HSW_PWR_WELL_DRIVER) & - HSW_PWR_WELL_ENABLE_REQUEST)) - I915_WRITE(HSW_PWR_WELL_DRIVER, - HSW_PWR_WELL_ENABLE_REQUEST); - I915_WRITE(HSW_PWR_WELL_BIOS, 0); - } -} - -static void hsw_power_well_enable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - hsw_set_power_well(dev_priv, power_well, true); -} - -static void hsw_power_well_disable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - hsw_set_power_well(dev_priv, power_well, false); -} - -static bool skl_power_well_enabled(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - uint32_t mask = SKL_POWER_WELL_REQ(power_well->id) | - SKL_POWER_WELL_STATE(power_well->id); - - return (I915_READ(HSW_PWR_WELL_DRIVER) & mask) == mask; -} - -static void skl_power_well_sync_hw(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - uint32_t mask = SKL_POWER_WELL_REQ(power_well->id); - uint32_t bios_req = I915_READ(HSW_PWR_WELL_BIOS); + enum i915_power_well_id id = power_well->id; + u32 mask = HSW_PWR_WELL_CTL_REQ(id); + u32 bios_req = I915_READ(HSW_PWR_WELL_CTL_BIOS(id)); /* Take over the request bit if set by BIOS. */ if (bios_req & mask) { - uint32_t drv_req = I915_READ(HSW_PWR_WELL_DRIVER); + u32 drv_req = I915_READ(HSW_PWR_WELL_CTL_DRIVER(id)); if (!(drv_req & mask)) - I915_WRITE(HSW_PWR_WELL_DRIVER, drv_req | mask); - I915_WRITE(HSW_PWR_WELL_BIOS, bios_req & ~mask); + I915_WRITE(HSW_PWR_WELL_CTL_DRIVER(id), drv_req | mask); + I915_WRITE(HSW_PWR_WELL_CTL_BIOS(id), bios_req & ~mask); } } -static void skl_power_well_enable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - skl_set_power_well(dev_priv, power_well, true); -} - -static void skl_power_well_disable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - skl_set_power_well(dev_priv, power_well, false); -} - static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - bxt_ddi_phy_init(dev_priv, power_well->data); + bxt_ddi_phy_init(dev_priv, power_well->bxt.phy); } static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - bxt_ddi_phy_uninit(dev_priv, power_well->data); + bxt_ddi_phy_uninit(dev_priv, power_well->bxt.phy); } static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - return bxt_ddi_phy_is_enabled(dev_priv, power_well->data); + return bxt_ddi_phy_is_enabled(dev_priv, power_well->bxt.phy); } static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv) @@ -982,16 +669,16 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv) power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A); if (power_well->count > 0) - bxt_ddi_phy_verify_state(dev_priv, power_well->data); + bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy); power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_BC); if (power_well->count > 0) - bxt_ddi_phy_verify_state(dev_priv, power_well->data); + bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy); if (IS_GEMINILAKE(dev_priv)) { power_well = lookup_power_well(dev_priv, GLK_DPIO_CMN_C); if (power_well->count > 0) - bxt_ddi_phy_verify_state(dev_priv, power_well->data); + bxt_ddi_phy_verify_state(dev_priv, power_well->bxt.phy); } } @@ -1089,7 +776,7 @@ static void i830_pipes_power_well_sync_hw(struct drm_i915_private *dev_priv, static void vlv_set_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { - enum punit_power_well power_well_id = power_well->id; + enum i915_power_well_id power_well_id = power_well->id; u32 mask; u32 state; u32 ctrl; @@ -1137,7 +824,7 @@ static void vlv_power_well_disable(struct drm_i915_private *dev_priv, static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - int power_well_id = power_well->id; + enum i915_power_well_id power_well_id = power_well->id; bool enabled = false; u32 mask; u32 state; @@ -1324,8 +1011,9 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, #define POWER_DOMAIN_MASK (GENMASK_ULL(POWER_DOMAIN_NUM - 1, 0)) -static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv, - int power_well_id) +static struct i915_power_well * +lookup_power_well(struct drm_i915_private *dev_priv, + enum i915_power_well_id power_well_id) { struct i915_power_domains *power_domains = &dev_priv->power_domains; int i; @@ -1672,7 +1360,7 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder, static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - enum pipe pipe = power_well->id; + enum pipe pipe = PIPE_A; bool enabled; u32 state, ctrl; @@ -1702,7 +1390,7 @@ static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool enable) { - enum pipe pipe = power_well->id; + enum pipe pipe = PIPE_A; u32 state; u32 ctrl; @@ -1735,7 +1423,7 @@ out: static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - WARN_ON_ONCE(power_well->id != PIPE_A); + WARN_ON_ONCE(power_well->id != CHV_DISP_PW_PIPE_A); chv_set_pipe_power_well(dev_priv, power_well, true); @@ -1745,7 +1433,7 @@ static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv, static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - WARN_ON_ONCE(power_well->id != PIPE_A); + WARN_ON_ONCE(power_well->id != CHV_DISP_PW_PIPE_A); vlv_display_power_well_deinit(dev_priv); @@ -1861,37 +1549,13 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, intel_runtime_pm_put(dev_priv); } -#define HSW_DISPLAY_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PIPE_B) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C) | \ - BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */ \ - BIT_ULL(POWER_DOMAIN_VGA) | \ - BIT_ULL(POWER_DOMAIN_AUDIO) | \ - BIT_ULL(POWER_DOMAIN_INIT)) - -#define BDW_DISPLAY_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PIPE_B) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \ - BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */ \ - BIT_ULL(POWER_DOMAIN_VGA) | \ - BIT_ULL(POWER_DOMAIN_AUDIO) | \ +#define I830_PIPES_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PIPE_A) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B) | \ + BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ BIT_ULL(POWER_DOMAIN_INIT)) #define VLV_DISPLAY_POWER_DOMAINS ( \ @@ -1974,13 +1638,201 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, BIT_ULL(POWER_DOMAIN_AUX_D) | \ BIT_ULL(POWER_DOMAIN_INIT)) -#define I830_PIPES_POWER_DOMAINS ( \ - BIT_ULL(POWER_DOMAIN_PIPE_A) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B) | \ - BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ - BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ +#define HSW_DISPLAY_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PIPE_B) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C) | \ + BIT_ULL(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */ \ + BIT_ULL(POWER_DOMAIN_VGA) | \ + BIT_ULL(POWER_DOMAIN_AUDIO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) + +#define BDW_DISPLAY_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PIPE_B) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_CRT) | /* DDI E */ \ + BIT_ULL(POWER_DOMAIN_VGA) | \ + BIT_ULL(POWER_DOMAIN_AUDIO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) + +#define SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_AUX_C) | \ + BIT_ULL(POWER_DOMAIN_AUX_D) | \ + BIT_ULL(POWER_DOMAIN_AUDIO) | \ + BIT_ULL(POWER_DOMAIN_VGA) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define SKL_DISPLAY_DC_OFF_POWER_DOMAINS ( \ + SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ + BIT_ULL(POWER_DOMAIN_MODESET) | \ + BIT_ULL(POWER_DOMAIN_AUX_A) | \ + BIT_ULL(POWER_DOMAIN_INIT)) + +#define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_AUX_C) | \ + BIT_ULL(POWER_DOMAIN_AUDIO) | \ + BIT_ULL(POWER_DOMAIN_VGA) | \ + BIT_ULL(POWER_DOMAIN_GMBUS) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define BXT_DISPLAY_DC_OFF_POWER_DOMAINS ( \ + BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ + BIT_ULL(POWER_DOMAIN_MODESET) | \ + BIT_ULL(POWER_DOMAIN_AUX_A) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define BXT_DPIO_CMN_A_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_A) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define BXT_DPIO_CMN_BC_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_AUX_C) | \ + BIT_ULL(POWER_DOMAIN_INIT)) + +#define GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_AUX_C) | \ + BIT_ULL(POWER_DOMAIN_AUDIO) | \ + BIT_ULL(POWER_DOMAIN_VGA) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO)) +#define GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO)) +#define GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO)) +#define GLK_DPIO_CMN_A_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_A_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_A) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DPIO_CMN_B_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DPIO_CMN_C_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_C) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_AUX_A_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_AUX_A) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_AUX_B_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_AUX_C_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_AUX_C) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define GLK_DISPLAY_DC_OFF_POWER_DOMAINS ( \ + GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ + BIT_ULL(POWER_DOMAIN_MODESET) | \ + BIT_ULL(POWER_DOMAIN_AUX_A) | \ + BIT_ULL(POWER_DOMAIN_INIT)) + +#define CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_A) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_B) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C) | \ + BIT_ULL(POWER_DOMAIN_TRANSCODER_C) | \ + BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_LANES) | \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) | \ + BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_AUX_C) | \ + BIT_ULL(POWER_DOMAIN_AUX_D) | \ + BIT_ULL(POWER_DOMAIN_AUDIO) | \ + BIT_ULL(POWER_DOMAIN_VGA) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_C_IO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_AUX_A_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_AUX_A) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_AUX_B_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_AUX_B) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_AUX_C_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_AUX_C) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_AUX_D_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_AUX_D) | \ + BIT_ULL(POWER_DOMAIN_INIT)) +#define CNL_DISPLAY_DC_OFF_POWER_DOMAINS ( \ + CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ + BIT_ULL(POWER_DOMAIN_MODESET) | \ + BIT_ULL(POWER_DOMAIN_AUX_A) | \ BIT_ULL(POWER_DOMAIN_INIT)) static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { @@ -2010,6 +1862,7 @@ static struct i915_power_well i9xx_always_on_power_well[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, + .id = I915_DISP_PW_ALWAYS_ON, }, }; @@ -2026,11 +1879,13 @@ static struct i915_power_well i830_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, + .id = I915_DISP_PW_ALWAYS_ON, }, { .name = "pipes", .domains = I830_PIPES_POWER_DOMAINS, .ops = &i830_pipes_power_well_ops, + .id = I830_DISP_PW_PIPES, }, }; @@ -2041,13 +1896,6 @@ static const struct i915_power_well_ops hsw_power_well_ops = { .is_enabled = hsw_power_well_enabled, }; -static const struct i915_power_well_ops skl_power_well_ops = { - .sync_hw = skl_power_well_sync_hw, - .enable = skl_power_well_enable, - .disable = skl_power_well_disable, - .is_enabled = skl_power_well_enabled, -}; - static const struct i915_power_well_ops gen9_dc_off_power_well_ops = { .sync_hw = i9xx_power_well_sync_hw_noop, .enable = gen9_dc_off_power_well_enable, @@ -2068,11 +1916,16 @@ static struct i915_power_well hsw_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, + .id = I915_DISP_PW_ALWAYS_ON, }, { .name = "display", .domains = HSW_DISPLAY_POWER_DOMAINS, .ops = &hsw_power_well_ops, + .id = HSW_DISP_PW_GLOBAL, + { + .hsw.has_vga = true, + }, }, }; @@ -2082,11 +1935,17 @@ static struct i915_power_well bdw_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, + .id = I915_DISP_PW_ALWAYS_ON, }, { .name = "display", .domains = BDW_DISPLAY_POWER_DOMAINS, .ops = &hsw_power_well_ops, + .id = HSW_DISP_PW_GLOBAL, + { + .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), + .hsw.has_vga = true, + }, }, }; @@ -2117,7 +1976,7 @@ static struct i915_power_well vlv_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, - .id = PUNIT_POWER_WELL_ALWAYS_ON, + .id = I915_DISP_PW_ALWAYS_ON, }, { .name = "display", @@ -2175,6 +2034,7 @@ static struct i915_power_well chv_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, + .id = I915_DISP_PW_ALWAYS_ON, }, { .name = "display", @@ -2184,7 +2044,7 @@ static struct i915_power_well chv_power_wells[] = { * required for any pipe to work. */ .domains = CHV_DISPLAY_POWER_DOMAINS, - .id = PIPE_A, + .id = CHV_DISP_PW_PIPE_A, .ops = &chv_pipe_power_well_ops, }, { @@ -2202,7 +2062,7 @@ static struct i915_power_well chv_power_wells[] = { }; bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, - int power_well_id) + enum i915_power_well_id power_well_id) { struct i915_power_well *power_well; bool ret; @@ -2219,20 +2079,23 @@ static struct i915_power_well skl_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, - .id = SKL_DISP_PW_ALWAYS_ON, + .id = I915_DISP_PW_ALWAYS_ON, }, { .name = "power well 1", /* Handled by the DMC firmware */ .domains = 0, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, + { + .hsw.has_fuses = true, + }, }, { .name = "MISC IO power well", /* Handled by the DMC firmware */ .domains = 0, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_MISC_IO, }, { @@ -2244,31 +2107,36 @@ static struct i915_power_well skl_power_wells[] = { { .name = "power well 2", .domains = SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, + { + .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), + .hsw.has_vga = true, + .hsw.has_fuses = true, + }, }, { .name = "DDI A/E IO power well", .domains = SKL_DISPLAY_DDI_IO_A_E_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_A_E, }, { .name = "DDI B IO power well", .domains = SKL_DISPLAY_DDI_IO_B_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_B, }, { .name = "DDI C IO power well", .domains = SKL_DISPLAY_DDI_IO_C_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_C, }, { .name = "DDI D IO power well", .domains = SKL_DISPLAY_DDI_IO_D_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_D, }, }; @@ -2279,12 +2147,16 @@ static struct i915_power_well bxt_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, + .id = I915_DISP_PW_ALWAYS_ON, }, { .name = "power well 1", .domains = 0, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, + { + .hsw.has_fuses = true, + }, }, { .name = "DC off", @@ -2295,22 +2167,31 @@ static struct i915_power_well bxt_power_wells[] = { { .name = "power well 2", .domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, + { + .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), + .hsw.has_vga = true, + .hsw.has_fuses = true, + }, }, { .name = "dpio-common-a", .domains = BXT_DPIO_CMN_A_POWER_DOMAINS, .ops = &bxt_dpio_cmn_power_well_ops, .id = BXT_DPIO_CMN_A, - .data = DPIO_PHY1, + { + .bxt.phy = DPIO_PHY1, + }, }, { .name = "dpio-common-bc", .domains = BXT_DPIO_CMN_BC_POWER_DOMAINS, .ops = &bxt_dpio_cmn_power_well_ops, .id = BXT_DPIO_CMN_BC, - .data = DPIO_PHY0, + { + .bxt.phy = DPIO_PHY0, + }, }, }; @@ -2320,13 +2201,17 @@ static struct i915_power_well glk_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, + .id = I915_DISP_PW_ALWAYS_ON, }, { .name = "power well 1", /* Handled by the DMC firmware */ .domains = 0, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, + { + .hsw.has_fuses = true, + }, }, { .name = "DC off", @@ -2337,64 +2222,75 @@ static struct i915_power_well glk_power_wells[] = { { .name = "power well 2", .domains = GLK_DISPLAY_POWERWELL_2_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, + { + .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), + .hsw.has_vga = true, + .hsw.has_fuses = true, + }, }, { .name = "dpio-common-a", .domains = GLK_DPIO_CMN_A_POWER_DOMAINS, .ops = &bxt_dpio_cmn_power_well_ops, .id = BXT_DPIO_CMN_A, - .data = DPIO_PHY1, + { + .bxt.phy = DPIO_PHY1, + }, }, { .name = "dpio-common-b", .domains = GLK_DPIO_CMN_B_POWER_DOMAINS, .ops = &bxt_dpio_cmn_power_well_ops, .id = BXT_DPIO_CMN_BC, - .data = DPIO_PHY0, + { + .bxt.phy = DPIO_PHY0, + }, }, { .name = "dpio-common-c", .domains = GLK_DPIO_CMN_C_POWER_DOMAINS, .ops = &bxt_dpio_cmn_power_well_ops, .id = GLK_DPIO_CMN_C, - .data = DPIO_PHY2, + { + .bxt.phy = DPIO_PHY2, + }, }, { .name = "AUX A", .domains = GLK_DISPLAY_AUX_A_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = GLK_DISP_PW_AUX_A, }, { .name = "AUX B", .domains = GLK_DISPLAY_AUX_B_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = GLK_DISP_PW_AUX_B, }, { .name = "AUX C", .domains = GLK_DISPLAY_AUX_C_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = GLK_DISP_PW_AUX_C, }, { .name = "DDI A IO power well", .domains = GLK_DISPLAY_DDI_IO_A_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = GLK_DISP_PW_DDI_A, }, { .name = "DDI B IO power well", .domains = GLK_DISPLAY_DDI_IO_B_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_B, }, { .name = "DDI C IO power well", .domains = GLK_DISPLAY_DDI_IO_C_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_C, }, }; @@ -2405,36 +2301,40 @@ static struct i915_power_well cnl_power_wells[] = { .always_on = 1, .domains = POWER_DOMAIN_MASK, .ops = &i9xx_always_on_power_well_ops, + .id = I915_DISP_PW_ALWAYS_ON, }, { .name = "power well 1", /* Handled by the DMC firmware */ .domains = 0, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, + { + .hsw.has_fuses = true, + }, }, { .name = "AUX A", .domains = CNL_DISPLAY_AUX_A_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_AUX_A, }, { .name = "AUX B", .domains = CNL_DISPLAY_AUX_B_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_AUX_B, }, { .name = "AUX C", .domains = CNL_DISPLAY_AUX_C_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_AUX_C, }, { .name = "AUX D", .domains = CNL_DISPLAY_AUX_D_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_AUX_D, }, { @@ -2446,31 +2346,36 @@ static struct i915_power_well cnl_power_wells[] = { { .name = "power well 2", .domains = CNL_DISPLAY_POWERWELL_2_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, + { + .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), + .hsw.has_vga = true, + .hsw.has_fuses = true, + }, }, { .name = "DDI A IO power well", .domains = CNL_DISPLAY_DDI_A_IO_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = CNL_DISP_PW_DDI_A, }, { .name = "DDI B IO power well", .domains = CNL_DISPLAY_DDI_B_IO_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_B, }, { .name = "DDI C IO power well", .domains = CNL_DISPLAY_DDI_C_IO_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_C, }, { .name = "DDI D IO power well", .domains = CNL_DISPLAY_DDI_D_IO_POWER_DOMAINS, - .ops = &skl_power_well_ops, + .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_DDI_D, }, }; @@ -2534,6 +2439,22 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv, return mask; } +static void assert_power_well_ids_unique(struct drm_i915_private *dev_priv) +{ + struct i915_power_domains *power_domains = &dev_priv->power_domains; + u64 power_well_ids; + int i; + + power_well_ids = 0; + for (i = 0; i < power_domains->power_well_count; i++) { + enum i915_power_well_id id = power_domains->power_wells[i].id; + + WARN_ON(id >= sizeof(power_well_ids) * 8); + WARN_ON(power_well_ids & BIT_ULL(id)); + power_well_ids |= BIT_ULL(id); + } +} + #define set_power_wells(power_domains, __power_wells) ({ \ (power_domains)->power_wells = (__power_wells); \ (power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \ @@ -2585,6 +2506,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) set_power_wells(power_domains, i9xx_always_on_power_well); } + assert_power_well_ids_unique(dev_priv); + return 0; } @@ -2820,7 +2743,7 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume /* 2. Enable Comp */ val = I915_READ(CHICKEN_MISC_2); - val &= ~COMP_PWR_DOWN; + val &= ~CNL_COMP_PWR_DOWN; I915_WRITE(CHICKEN_MISC_2, val); val = I915_READ(CNL_PORT_COMP_DW3); @@ -2894,7 +2817,7 @@ static void cnl_display_core_uninit(struct drm_i915_private *dev_priv) /* 5. Disable Comp */ val = I915_READ(CHICKEN_MISC_2); - val |= COMP_PWR_DOWN; + val |= CNL_COMP_PWR_DOWN; I915_WRITE(CHICKEN_MISC_2, val); } |