]> Git Repo - linux.git/blobdiff - drivers/gpu/drm/i915/intel_runtime_pm.c
iov_iter: use bvec iterator to implement iterate_bvec()
[linux.git] / drivers / gpu / drm / i915 / intel_runtime_pm.c
index 7fe2ba970777dbc3b733256c4de30ceb0df4fee2..7fb1da4e7fc349dfdfe26bb32dd7e97192b2ec04 100644 (file)
@@ -397,11 +397,6 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
        BIT(POWER_DOMAIN_MODESET) |                     \
        BIT(POWER_DOMAIN_AUX_A) |                       \
        BIT(POWER_DOMAIN_INIT))
-#define SKL_DISPLAY_ALWAYS_ON_POWER_DOMAINS (          \
-       (POWER_DOMAIN_MASK & ~(                         \
-       SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS |         \
-       SKL_DISPLAY_DC_OFF_POWER_DOMAINS)) |            \
-       BIT(POWER_DOMAIN_INIT))
 
 #define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS (                \
        BIT(POWER_DOMAIN_TRANSCODER_A) |                \
@@ -419,27 +414,11 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
        BIT(POWER_DOMAIN_VGA) |                         \
        BIT(POWER_DOMAIN_GMBUS) |                       \
        BIT(POWER_DOMAIN_INIT))
-#define BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS (                \
-       BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS |         \
-       BIT(POWER_DOMAIN_PIPE_A) |                      \
-       BIT(POWER_DOMAIN_TRANSCODER_EDP) |              \
-       BIT(POWER_DOMAIN_TRANSCODER_DSI_A) |            \
-       BIT(POWER_DOMAIN_TRANSCODER_DSI_C) |            \
-       BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |         \
-       BIT(POWER_DOMAIN_PORT_DDI_A_LANES) |            \
-       BIT(POWER_DOMAIN_PORT_DSI) |                    \
-       BIT(POWER_DOMAIN_AUX_A) |                       \
-       BIT(POWER_DOMAIN_PLLS) |                        \
-       BIT(POWER_DOMAIN_INIT))
 #define BXT_DISPLAY_DC_OFF_POWER_DOMAINS (             \
        BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS |         \
        BIT(POWER_DOMAIN_MODESET) |                     \
        BIT(POWER_DOMAIN_AUX_A) |                       \
        BIT(POWER_DOMAIN_INIT))
-#define BXT_DISPLAY_ALWAYS_ON_POWER_DOMAINS (          \
-       (POWER_DOMAIN_MASK & ~(BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS |  \
-       BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS)) |       \
-       BIT(POWER_DOMAIN_INIT))
 
 static void assert_can_enable_dc9(struct drm_i915_private *dev_priv)
 {
@@ -513,10 +492,9 @@ static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
                              state, rewrites);
 }
 
-static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
+static u32 gen9_dc_mask(struct drm_i915_private *dev_priv)
 {
-       uint32_t val;
-       uint32_t mask;
+       u32 mask;
 
        mask = DC_STATE_EN_UPTO_DC5;
        if (IS_BROXTON(dev_priv))
@@ -524,10 +502,30 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
        else
                mask |= DC_STATE_EN_UPTO_DC6;
 
+       return mask;
+}
+
+void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv)
+{
+       u32 val;
+
+       val = I915_READ(DC_STATE_EN) & gen9_dc_mask(dev_priv);
+
+       DRM_DEBUG_KMS("Resetting DC state tracking from %02x to %02x\n",
+                     dev_priv->csr.dc_state, val);
+       dev_priv->csr.dc_state = val;
+}
+
+static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
+{
+       uint32_t val;
+       uint32_t mask;
+
        if (WARN_ON_ONCE(state & ~dev_priv->csr.allowed_dc_mask))
                state &= dev_priv->csr.allowed_dc_mask;
 
        val = I915_READ(DC_STATE_EN);
+       mask = gen9_dc_mask(dev_priv);
        DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n",
                      val & mask, state);
 
@@ -584,7 +582,7 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
        assert_csr_loaded(dev_priv);
 }
 
-static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
+void gen9_enable_dc5(struct drm_i915_private *dev_priv)
 {
        assert_can_enable_dc5(dev_priv);
 
@@ -647,7 +645,8 @@ gen9_sanitize_power_well_requests(struct drm_i915_private *dev_priv,
         * other request bits to be set, so WARN for those.
         */
        if (power_well_id == SKL_DISP_PW_1 ||
-           (IS_SKYLAKE(dev_priv) && power_well_id == SKL_DISP_PW_MISC_IO))
+           ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
+            power_well_id == SKL_DISP_PW_MISC_IO))
                DRM_DEBUG_DRIVER("Clearing auxiliary requests for %s forced on "
                                 "by DMC\n", power_well->name);
        else
@@ -721,7 +720,7 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
                        DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
                }
 
-               if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
+               if (IS_GEN9(dev_priv))
                        gen9_sanitize_power_well_requests(dev_priv, power_well);
        }
 
@@ -811,11 +810,19 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
                                          struct i915_power_well *power_well)
 {
        gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+       if (IS_BROXTON(dev_priv)) {
+               broxton_cdclk_verify_state(dev_priv);
+               broxton_ddi_phy_verify_state(dev_priv);
+       }
 }
 
 static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv,
                                           struct i915_power_well *power_well)
 {
+       if (!dev_priv->csr.dmc_payload)
+               return;
+
        if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6)
                skl_enable_dc6(dev_priv);
        else if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5)
@@ -1605,34 +1612,56 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
        intel_runtime_pm_put(dev_priv);
 }
 
-#define HSW_ALWAYS_ON_POWER_DOMAINS (                  \
-       BIT(POWER_DOMAIN_PIPE_A) |                      \
-       BIT(POWER_DOMAIN_TRANSCODER_EDP) |              \
-       BIT(POWER_DOMAIN_PORT_DDI_A_LANES) |            \
+#define HSW_DISPLAY_POWER_DOMAINS (                    \
+       BIT(POWER_DOMAIN_PIPE_B) |                      \
+       BIT(POWER_DOMAIN_PIPE_C) |                      \
+       BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |         \
+       BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |         \
+       BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |         \
+       BIT(POWER_DOMAIN_TRANSCODER_A) |                \
+       BIT(POWER_DOMAIN_TRANSCODER_B) |                \
+       BIT(POWER_DOMAIN_TRANSCODER_C) |                \
        BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |            \
        BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |            \
        BIT(POWER_DOMAIN_PORT_DDI_D_LANES) |            \
-       BIT(POWER_DOMAIN_PORT_CRT) |                    \
-       BIT(POWER_DOMAIN_PLLS) |                        \
-       BIT(POWER_DOMAIN_AUX_A) |                       \
-       BIT(POWER_DOMAIN_AUX_B) |                       \
-       BIT(POWER_DOMAIN_AUX_C) |                       \
-       BIT(POWER_DOMAIN_AUX_D) |                       \
-       BIT(POWER_DOMAIN_GMBUS) |                       \
-       BIT(POWER_DOMAIN_INIT))
-#define HSW_DISPLAY_POWER_DOMAINS (                            \
-       (POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |    \
+       BIT(POWER_DOMAIN_PORT_CRT) | /* DDI E */        \
+       BIT(POWER_DOMAIN_VGA) |                         \
+       BIT(POWER_DOMAIN_AUDIO) |                       \
        BIT(POWER_DOMAIN_INIT))
 
-#define BDW_ALWAYS_ON_POWER_DOMAINS (                  \
-       HSW_ALWAYS_ON_POWER_DOMAINS |                   \
-       BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
-#define BDW_DISPLAY_POWER_DOMAINS (                            \
-       (POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |    \
+#define BDW_DISPLAY_POWER_DOMAINS (                    \
+       BIT(POWER_DOMAIN_PIPE_B) |                      \
+       BIT(POWER_DOMAIN_PIPE_C) |                      \
+       BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |         \
+       BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |         \
+       BIT(POWER_DOMAIN_TRANSCODER_A) |                \
+       BIT(POWER_DOMAIN_TRANSCODER_B) |                \
+       BIT(POWER_DOMAIN_TRANSCODER_C) |                \
+       BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |            \
+       BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |            \
+       BIT(POWER_DOMAIN_PORT_DDI_D_LANES) |            \
+       BIT(POWER_DOMAIN_PORT_CRT) | /* DDI E */        \
+       BIT(POWER_DOMAIN_VGA) |                         \
+       BIT(POWER_DOMAIN_AUDIO) |                       \
        BIT(POWER_DOMAIN_INIT))
 
-#define VLV_ALWAYS_ON_POWER_DOMAINS    BIT(POWER_DOMAIN_INIT)
-#define VLV_DISPLAY_POWER_DOMAINS      POWER_DOMAIN_MASK
+#define VLV_DISPLAY_POWER_DOMAINS (            \
+       BIT(POWER_DOMAIN_PIPE_A) |              \
+       BIT(POWER_DOMAIN_PIPE_B) |              \
+       BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \
+       BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \
+       BIT(POWER_DOMAIN_TRANSCODER_A) |        \
+       BIT(POWER_DOMAIN_TRANSCODER_B) |        \
+       BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |    \
+       BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |    \
+       BIT(POWER_DOMAIN_PORT_DSI) |            \
+       BIT(POWER_DOMAIN_PORT_CRT) |            \
+       BIT(POWER_DOMAIN_VGA) |                 \
+       BIT(POWER_DOMAIN_AUDIO) |               \
+       BIT(POWER_DOMAIN_AUX_B) |               \
+       BIT(POWER_DOMAIN_AUX_C) |               \
+       BIT(POWER_DOMAIN_GMBUS) |               \
+       BIT(POWER_DOMAIN_INIT))
 
 #define VLV_DPIO_CMN_BC_POWER_DOMAINS (                \
        BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |    \
@@ -1662,6 +1691,28 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
        BIT(POWER_DOMAIN_AUX_C) |               \
        BIT(POWER_DOMAIN_INIT))
 
+#define CHV_DISPLAY_POWER_DOMAINS (            \
+       BIT(POWER_DOMAIN_PIPE_A) |              \
+       BIT(POWER_DOMAIN_PIPE_B) |              \
+       BIT(POWER_DOMAIN_PIPE_C) |              \
+       BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \
+       BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) | \
+       BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) | \
+       BIT(POWER_DOMAIN_TRANSCODER_A) |        \
+       BIT(POWER_DOMAIN_TRANSCODER_B) |        \
+       BIT(POWER_DOMAIN_TRANSCODER_C) |        \
+       BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |    \
+       BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |    \
+       BIT(POWER_DOMAIN_PORT_DDI_D_LANES) |    \
+       BIT(POWER_DOMAIN_PORT_DSI) |            \
+       BIT(POWER_DOMAIN_VGA) |                 \
+       BIT(POWER_DOMAIN_AUDIO) |               \
+       BIT(POWER_DOMAIN_AUX_B) |               \
+       BIT(POWER_DOMAIN_AUX_C) |               \
+       BIT(POWER_DOMAIN_AUX_D) |               \
+       BIT(POWER_DOMAIN_GMBUS) |               \
+       BIT(POWER_DOMAIN_INIT))
+
 #define CHV_DPIO_CMN_BC_POWER_DOMAINS (                \
        BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |    \
        BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |    \
@@ -1729,7 +1780,7 @@ static struct i915_power_well hsw_power_wells[] = {
        {
                .name = "always-on",
                .always_on = 1,
-               .domains = HSW_ALWAYS_ON_POWER_DOMAINS,
+               .domains = POWER_DOMAIN_MASK,
                .ops = &i9xx_always_on_power_well_ops,
        },
        {
@@ -1743,7 +1794,7 @@ static struct i915_power_well bdw_power_wells[] = {
        {
                .name = "always-on",
                .always_on = 1,
-               .domains = BDW_ALWAYS_ON_POWER_DOMAINS,
+               .domains = POWER_DOMAIN_MASK,
                .ops = &i9xx_always_on_power_well_ops,
        },
        {
@@ -1778,7 +1829,7 @@ static struct i915_power_well vlv_power_wells[] = {
        {
                .name = "always-on",
                .always_on = 1,
-               .domains = VLV_ALWAYS_ON_POWER_DOMAINS,
+               .domains = POWER_DOMAIN_MASK,
                .ops = &i9xx_always_on_power_well_ops,
                .data = PUNIT_POWER_WELL_ALWAYS_ON,
        },
@@ -1836,7 +1887,7 @@ static struct i915_power_well chv_power_wells[] = {
        {
                .name = "always-on",
                .always_on = 1,
-               .domains = VLV_ALWAYS_ON_POWER_DOMAINS,
+               .domains = POWER_DOMAIN_MASK,
                .ops = &i9xx_always_on_power_well_ops,
        },
        {
@@ -1846,7 +1897,7 @@ static struct i915_power_well chv_power_wells[] = {
                 * power wells don't actually exist. Pipe A power well is
                 * required for any pipe to work.
                 */
-               .domains = VLV_DISPLAY_POWER_DOMAINS,
+               .domains = CHV_DISPLAY_POWER_DOMAINS,
                .data = PIPE_A,
                .ops = &chv_pipe_power_well_ops,
        },
@@ -1880,7 +1931,7 @@ static struct i915_power_well skl_power_wells[] = {
        {
                .name = "always-on",
                .always_on = 1,
-               .domains = SKL_DISPLAY_ALWAYS_ON_POWER_DOMAINS,
+               .domains = POWER_DOMAIN_MASK,
                .ops = &i9xx_always_on_power_well_ops,
                .data = SKL_DISP_PW_ALWAYS_ON,
        },
@@ -1940,12 +1991,12 @@ static struct i915_power_well bxt_power_wells[] = {
        {
                .name = "always-on",
                .always_on = 1,
-               .domains = BXT_DISPLAY_ALWAYS_ON_POWER_DOMAINS,
+               .domains = POWER_DOMAIN_MASK,
                .ops = &i9xx_always_on_power_well_ops,
        },
        {
                .name = "power well 1",
-               .domains = BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS,
+               .domains = 0,
                .ops = &skl_power_well_ops,
                .data = SKL_DISP_PW_1,
        },
@@ -1970,11 +2021,6 @@ sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv,
        if (disable_power_well >= 0)
                return !!disable_power_well;
 
-       if (IS_BROXTON(dev_priv)) {
-               DRM_DEBUG_KMS("Disabling display power well support\n");
-               return 0;
-       }
-
        return 1;
 }
 
@@ -2181,6 +2227,64 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
        mutex_unlock(&power_domains->lock);
 }
 
+void bxt_display_core_init(struct drm_i915_private *dev_priv,
+                          bool resume)
+{
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_well *well;
+       uint32_t val;
+
+       gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+       /*
+        * NDE_RSTWRN_OPT RST PCH Handshake En must always be 0b on BXT
+        * or else the reset will hang because there is no PCH to respond.
+        * Move the handshake programming to initialization sequence.
+        * Previously was left up to BIOS.
+        */
+       val = I915_READ(HSW_NDE_RSTWRN_OPT);
+       val &= ~RESET_PCH_HANDSHAKE_ENABLE;
+       I915_WRITE(HSW_NDE_RSTWRN_OPT, val);
+
+       /* Enable PG1 */
+       mutex_lock(&power_domains->lock);
+
+       well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
+       intel_power_well_enable(dev_priv, well);
+
+       mutex_unlock(&power_domains->lock);
+
+       broxton_init_cdclk(dev_priv);
+       broxton_ddi_phy_init(dev_priv);
+
+       broxton_cdclk_verify_state(dev_priv);
+       broxton_ddi_phy_verify_state(dev_priv);
+
+       if (resume && dev_priv->csr.dmc_payload)
+               intel_csr_load_program(dev_priv);
+}
+
+void bxt_display_core_uninit(struct drm_i915_private *dev_priv)
+{
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_well *well;
+
+       gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+       broxton_ddi_phy_uninit(dev_priv);
+       broxton_uninit_cdclk(dev_priv);
+
+       /* The spec doesn't call for removing the reset handshake flag */
+
+       /* Disable PG1 */
+       mutex_lock(&power_domains->lock);
+
+       well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
+       intel_power_well_disable(dev_priv, well);
+
+       mutex_unlock(&power_domains->lock);
+}
+
 static void chv_phy_control_init(struct drm_i915_private *dev_priv)
 {
        struct i915_power_well *cmn_bc =
@@ -2312,6 +2416,8 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
 
        if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                skl_display_core_init(dev_priv, resume);
+       } else if (IS_BROXTON(dev)) {
+               bxt_display_core_init(dev_priv, resume);
        } else if (IS_CHERRYVIEW(dev)) {
                mutex_lock(&power_domains->lock);
                chv_phy_control_init(dev_priv);
@@ -2349,6 +2455,8 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
 
        if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
                skl_display_core_uninit(dev_priv);
+       else if (IS_BROXTON(dev_priv))
+               bxt_display_core_uninit(dev_priv);
 }
 
 /**
This page took 0.048611 seconds and 4 git commands to generate.