drm/i915: More intel_engine_cs renaming
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_pm.c
index b28c29f20e754ec740e5aacd101bbe07867f65a6..20c8243ef705172a47949dc2d6747ba0a462fe92 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/module.h>
 
 /**
+ * DOC: RC6
+ *
  * RC6 is a special power stage which allows the GPU to enter an very
  * low-voltage mode when idle, using down to 0V while at this stage.  This
  * stage is entered automatically when the GPU is idle when RC6 support is
@@ -485,20 +487,6 @@ static const struct intel_watermark_params g4x_cursor_wm_info = {
        .guard_size = 2,
        .cacheline_size = G4X_FIFO_LINE_SIZE,
 };
-static const struct intel_watermark_params valleyview_wm_info = {
-       .fifo_size = VALLEYVIEW_FIFO_SIZE,
-       .max_wm = VALLEYVIEW_MAX_WM,
-       .default_wm = VALLEYVIEW_MAX_WM,
-       .guard_size = 2,
-       .cacheline_size = G4X_FIFO_LINE_SIZE,
-};
-static const struct intel_watermark_params valleyview_cursor_wm_info = {
-       .fifo_size = I965_CURSOR_FIFO,
-       .max_wm = VALLEYVIEW_CURSOR_MAX_WM,
-       .default_wm = I965_CURSOR_DFT_WM,
-       .guard_size = 2,
-       .cacheline_size = G4X_FIFO_LINE_SIZE,
-};
 static const struct intel_watermark_params i965_cursor_wm_info = {
        .fifo_size = I965_CURSOR_FIFO,
        .max_wm = I965_CURSOR_MAX_WM,
@@ -546,7 +534,7 @@ static const struct intel_watermark_params i845_wm_info = {
  * intel_calculate_wm - calculate watermark level
  * @clock_in_khz: pixel clock
  * @wm: chip FIFO params
- * @pixel_size: display pixel size
+ * @cpp: bytes per pixel
  * @latency_ns: memory latency for the platform
  *
  * Calculate the watermark level (the level at which the display plane will
@@ -562,8 +550,7 @@ static const struct intel_watermark_params i845_wm_info = {
  */
 static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
                                        const struct intel_watermark_params *wm,
-                                       int fifo_size,
-                                       int pixel_size,
+                                       int fifo_size, int cpp,
                                        unsigned long latency_ns)
 {
        long entries_required, wm_size;
@@ -574,7 +561,7 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
         * clocks go from a few thousand to several hundred thousand.
         * latency is usually a few thousand
         */
-       entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) /
+       entries_required = ((clock_in_khz / 1000) * cpp * latency_ns) /
                1000;
        entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size);
 
@@ -638,13 +625,13 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
        crtc = single_enabled_crtc(dev);
        if (crtc) {
                const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
-               int pixel_size = crtc->primary->state->fb->bits_per_pixel / 8;
+               int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
                int clock = adjusted_mode->crtc_clock;
 
                /* Display SR */
                wm = intel_calculate_wm(clock, &pineview_display_wm,
                                        pineview_display_wm.fifo_size,
-                                       pixel_size, latency->display_sr);
+                                       cpp, latency->display_sr);
                reg = I915_READ(DSPFW1);
                reg &= ~DSPFW_SR_MASK;
                reg |= FW_WM(wm, SR);
@@ -654,7 +641,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
                /* cursor SR */
                wm = intel_calculate_wm(clock, &pineview_cursor_wm,
                                        pineview_display_wm.fifo_size,
-                                       pixel_size, latency->cursor_sr);
+                                       cpp, latency->cursor_sr);
                reg = I915_READ(DSPFW3);
                reg &= ~DSPFW_CURSOR_SR_MASK;
                reg |= FW_WM(wm, CURSOR_SR);
@@ -663,7 +650,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
                /* Display HPLL off SR */
                wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm,
                                        pineview_display_hplloff_wm.fifo_size,
-                                       pixel_size, latency->display_hpll_disable);
+                                       cpp, latency->display_hpll_disable);
                reg = I915_READ(DSPFW3);
                reg &= ~DSPFW_HPLL_SR_MASK;
                reg |= FW_WM(wm, HPLL_SR);
@@ -672,7 +659,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc)
                /* cursor HPLL off SR */
                wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm,
                                        pineview_display_hplloff_wm.fifo_size,
-                                       pixel_size, latency->cursor_hpll_disable);
+                                       cpp, latency->cursor_hpll_disable);
                reg = I915_READ(DSPFW3);
                reg &= ~DSPFW_HPLL_CURSOR_MASK;
                reg |= FW_WM(wm, HPLL_CURSOR);
@@ -696,7 +683,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
 {
        struct drm_crtc *crtc;
        const struct drm_display_mode *adjusted_mode;
-       int htotal, hdisplay, clock, pixel_size;
+       int htotal, hdisplay, clock, cpp;
        int line_time_us, line_count;
        int entries, tlb_miss;
 
@@ -711,10 +698,10 @@ static bool g4x_compute_wm0(struct drm_device *dev,
        clock = adjusted_mode->crtc_clock;
        htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
-       pixel_size = crtc->primary->state->fb->bits_per_pixel / 8;
+       cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
 
        /* Use the small buffer method to calculate plane watermark */
-       entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
+       entries = ((clock * cpp / 1000) * display_latency_ns) / 1000;
        tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8;
        if (tlb_miss > 0)
                entries += tlb_miss;
@@ -726,7 +713,7 @@ static bool g4x_compute_wm0(struct drm_device *dev,
        /* Use the large buffer method to calculate cursor watermark */
        line_time_us = max(htotal * 1000 / clock, 1);
        line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
-       entries = line_count * crtc->cursor->state->crtc_w * pixel_size;
+       entries = line_count * crtc->cursor->state->crtc_w * cpp;
        tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
        if (tlb_miss > 0)
                entries += tlb_miss;
@@ -782,7 +769,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
 {
        struct drm_crtc *crtc;
        const struct drm_display_mode *adjusted_mode;
-       int hdisplay, htotal, pixel_size, clock;
+       int hdisplay, htotal, cpp, clock;
        unsigned long line_time_us;
        int line_count, line_size;
        int small, large;
@@ -798,21 +785,21 @@ static bool g4x_compute_srwm(struct drm_device *dev,
        clock = adjusted_mode->crtc_clock;
        htotal = adjusted_mode->crtc_htotal;
        hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
-       pixel_size = crtc->primary->state->fb->bits_per_pixel / 8;
+       cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
 
        line_time_us = max(htotal * 1000 / clock, 1);
        line_count = (latency_ns / line_time_us + 1000) / 1000;
-       line_size = hdisplay * pixel_size;
+       line_size = hdisplay * cpp;
 
        /* Use the minimum of the small and large buffer method for primary */
-       small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
+       small = ((clock * cpp / 1000) * latency_ns) / 1000;
        large = line_count * line_size;
 
        entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
        *display_wm = entries + display->guard_size;
 
        /* calculate the self-refresh watermark for display cursor */
-       entries = line_count * pixel_size * crtc->cursor->state->crtc_w;
+       entries = line_count * cpp * crtc->cursor->state->crtc_w;
        entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
        *cursor_wm = entries + cursor->guard_size;
 
@@ -904,13 +891,13 @@ enum vlv_wm_level {
 static unsigned int vlv_wm_method2(unsigned int pixel_rate,
                                   unsigned int pipe_htotal,
                                   unsigned int horiz_pixels,
-                                  unsigned int bytes_per_pixel,
+                                  unsigned int cpp,
                                   unsigned int latency)
 {
        unsigned int ret;
 
        ret = (latency * pixel_rate) / (pipe_htotal * 10000);
-       ret = (ret + 1) * horiz_pixels * bytes_per_pixel;
+       ret = (ret + 1) * horiz_pixels * cpp;
        ret = DIV_ROUND_UP(ret, 64);
 
        return ret;
@@ -939,7 +926,7 @@ static uint16_t vlv_compute_wm_level(struct intel_plane *plane,
                                     int level)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-       int clock, htotal, pixel_size, width, wm;
+       int clock, htotal, cpp, width, wm;
 
        if (dev_priv->wm.pri_latency[level] == 0)
                return USHRT_MAX;
@@ -947,7 +934,7 @@ static uint16_t vlv_compute_wm_level(struct intel_plane *plane,
        if (!state->visible)
                return 0;
 
-       pixel_size = drm_format_plane_cpp(state->base.fb->pixel_format, 0);
+       cpp = drm_format_plane_cpp(state->base.fb->pixel_format, 0);
        clock = crtc->config->base.adjusted_mode.crtc_clock;
        htotal = crtc->config->base.adjusted_mode.crtc_htotal;
        width = crtc->config->pipe_src_w;
@@ -963,7 +950,7 @@ static uint16_t vlv_compute_wm_level(struct intel_plane *plane,
                 */
                wm = 63;
        } else {
-               wm = vlv_wm_method2(clock, htotal, width, pixel_size,
+               wm = vlv_wm_method2(clock, htotal, width, cpp,
                                    dev_priv->wm.pri_latency[level] * 10);
        }
 
@@ -1437,7 +1424,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
                int clock = adjusted_mode->crtc_clock;
                int htotal = adjusted_mode->crtc_htotal;
                int hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
-               int pixel_size = crtc->primary->state->fb->bits_per_pixel / 8;
+               int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
                unsigned long line_time_us;
                int entries;
 
@@ -1445,7 +1432,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
 
                /* Use ns/us then divide to preserve precision */
                entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-                       pixel_size * hdisplay;
+                       cpp * hdisplay;
                entries = DIV_ROUND_UP(entries, I915_FIFO_LINE_SIZE);
                srwm = I965_FIFO_SIZE - entries;
                if (srwm < 0)
@@ -1455,7 +1442,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc)
                              entries, srwm);
 
                entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-                       pixel_size * crtc->cursor->state->crtc_w;
+                       cpp * crtc->cursor->state->crtc_w;
                entries = DIV_ROUND_UP(entries,
                                          i965_cursor_wm_info.cacheline_size);
                cursor_sr = i965_cursor_wm_info.fifo_size -
@@ -1516,7 +1503,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
        crtc = intel_get_crtc_for_plane(dev, 0);
        if (intel_crtc_active(crtc)) {
                const struct drm_display_mode *adjusted_mode;
-               int cpp = crtc->primary->state->fb->bits_per_pixel / 8;
+               int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
                if (IS_GEN2(dev))
                        cpp = 4;
 
@@ -1538,7 +1525,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
        crtc = intel_get_crtc_for_plane(dev, 1);
        if (intel_crtc_active(crtc)) {
                const struct drm_display_mode *adjusted_mode;
-               int cpp = crtc->primary->state->fb->bits_per_pixel / 8;
+               int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
                if (IS_GEN2(dev))
                        cpp = 4;
 
@@ -1584,7 +1571,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
                int clock = adjusted_mode->crtc_clock;
                int htotal = adjusted_mode->crtc_htotal;
                int hdisplay = to_intel_crtc(enabled)->config->pipe_src_w;
-               int pixel_size = enabled->primary->state->fb->bits_per_pixel / 8;
+               int cpp = drm_format_plane_cpp(enabled->primary->state->fb->pixel_format, 0);
                unsigned long line_time_us;
                int entries;
 
@@ -1592,7 +1579,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
 
                /* Use ns/us then divide to preserve precision */
                entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-                       pixel_size * hdisplay;
+                       cpp * hdisplay;
                entries = DIV_ROUND_UP(entries, wm_info->cacheline_size);
                DRM_DEBUG_KMS("self-refresh entries: %d\n", entries);
                srwm = wm_info->fifo_size - entries;
@@ -1672,6 +1659,9 @@ uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
                if (pipe_h < pfit_h)
                        pipe_h = pfit_h;
 
+               if (WARN_ON(!pfit_w || !pfit_h))
+                       return pixel_rate;
+
                pixel_rate = div_u64((uint64_t) pixel_rate * pipe_w * pipe_h,
                                     pfit_w * pfit_h);
        }
@@ -1680,15 +1670,14 @@ uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
 }
 
 /* latency must be in 0.1us units. */
-static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
-                              uint32_t latency)
+static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency)
 {
        uint64_t ret;
 
        if (WARN(latency == 0, "Latency value missing\n"))
                return UINT_MAX;
 
-       ret = (uint64_t) pixel_rate * bytes_per_pixel * latency;
+       ret = (uint64_t) pixel_rate * cpp * latency;
        ret = DIV_ROUND_UP_ULL(ret, 64 * 10000) + 2;
 
        return ret;
@@ -1696,24 +1685,37 @@ static uint32_t ilk_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
 
 /* latency must be in 0.1us units. */
 static uint32_t ilk_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
-                              uint32_t horiz_pixels, uint8_t bytes_per_pixel,
+                              uint32_t horiz_pixels, uint8_t cpp,
                               uint32_t latency)
 {
        uint32_t ret;
 
        if (WARN(latency == 0, "Latency value missing\n"))
                return UINT_MAX;
+       if (WARN_ON(!pipe_htotal))
+               return UINT_MAX;
 
        ret = (latency * pixel_rate) / (pipe_htotal * 10000);
-       ret = (ret + 1) * horiz_pixels * bytes_per_pixel;
+       ret = (ret + 1) * horiz_pixels * cpp;
        ret = DIV_ROUND_UP(ret, 64) + 2;
        return ret;
 }
 
 static uint32_t ilk_wm_fbc(uint32_t pri_val, uint32_t horiz_pixels,
-                          uint8_t bytes_per_pixel)
+                          uint8_t cpp)
 {
-       return DIV_ROUND_UP(pri_val * 64, horiz_pixels * bytes_per_pixel) + 2;
+       /*
+        * Neither of these should be possible since this function shouldn't be
+        * called if the CRTC is off or the plane is invisible.  But let's be
+        * extra paranoid to avoid a potential divide-by-zero if we screw up
+        * elsewhere in the driver.
+        */
+       if (WARN_ON(!cpp))
+               return 0;
+       if (WARN_ON(!horiz_pixels))
+               return 0;
+
+       return DIV_ROUND_UP(pri_val * 64, horiz_pixels * cpp) + 2;
 }
 
 struct ilk_wm_maximums {
@@ -1732,13 +1734,14 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
                                   uint32_t mem_value,
                                   bool is_lp)
 {
-       int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
+       int cpp = pstate->base.fb ?
+               drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0;
        uint32_t method1, method2;
 
        if (!cstate->base.active || !pstate->visible)
                return 0;
 
-       method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), bpp, mem_value);
+       method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), cpp, mem_value);
 
        if (!is_lp)
                return method1;
@@ -1746,8 +1749,7 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
        method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
                                 cstate->base.adjusted_mode.crtc_htotal,
                                 drm_rect_width(&pstate->dst),
-                                bpp,
-                                mem_value);
+                                cpp, mem_value);
 
        return min(method1, method2);
 }
@@ -1760,18 +1762,18 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
                                   const struct intel_plane_state *pstate,
                                   uint32_t mem_value)
 {
-       int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
+       int cpp = pstate->base.fb ?
+               drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0;
        uint32_t method1, method2;
 
        if (!cstate->base.active || !pstate->visible)
                return 0;
 
-       method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), bpp, mem_value);
+       method1 = ilk_wm_method1(ilk_pipe_pixel_rate(cstate), cpp, mem_value);
        method2 = ilk_wm_method2(ilk_pipe_pixel_rate(cstate),
                                 cstate->base.adjusted_mode.crtc_htotal,
                                 drm_rect_width(&pstate->dst),
-                                bpp,
-                                mem_value);
+                                cpp, mem_value);
        return min(method1, method2);
 }
 
@@ -1804,12 +1806,13 @@ static uint32_t ilk_compute_fbc_wm(const struct intel_crtc_state *cstate,
                                   const struct intel_plane_state *pstate,
                                   uint32_t pri_val)
 {
-       int bpp = pstate->base.fb ? pstate->base.fb->bits_per_pixel / 8 : 0;
+       int cpp = pstate->base.fb ?
+               drm_format_plane_cpp(pstate->base.fb->pixel_format, 0) : 0;
 
        if (!cstate->base.active || !pstate->visible)
                return 0;
 
-       return ilk_wm_fbc(pri_val, drm_rect_width(&pstate->dst), bpp);
+       return ilk_wm_fbc(pri_val, drm_rect_width(&pstate->dst), cpp);
 }
 
 static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
@@ -1993,23 +1996,35 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv,
                cur_latency *= 5;
        }
 
-       result->pri_val = ilk_compute_pri_wm(cstate, pristate,
-                                            pri_latency, level);
-       result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
-       result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
-       result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
+       if (pristate) {
+               result->pri_val = ilk_compute_pri_wm(cstate, pristate,
+                                                    pri_latency, level);
+               result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
+       }
+
+       if (sprstate)
+               result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
+
+       if (curstate)
+               result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
+
        result->enable = true;
 }
 
 static uint32_t
-hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc)
+hsw_compute_linetime_wm(struct drm_device *dev,
+                       struct intel_crtc_state *cstate)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
+       const struct drm_display_mode *adjusted_mode =
+               &cstate->base.adjusted_mode;
        u32 linetime, ips_linetime;
 
-       if (!intel_crtc->active)
+       if (!cstate->base.active)
+               return 0;
+       if (WARN_ON(adjusted_mode->crtc_clock == 0))
+               return 0;
+       if (WARN_ON(dev_priv->cdclk_freq == 0))
                return 0;
 
        /* The WM are computed with base on how long it takes to fill a single
@@ -2256,96 +2271,167 @@ static void skl_setup_wm_latency(struct drm_device *dev)
        intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
 }
 
+static bool ilk_validate_pipe_wm(struct drm_device *dev,
+                                struct intel_pipe_wm *pipe_wm)
+{
+       /* LP0 watermark maximums depend on this pipe alone */
+       const struct intel_wm_config config = {
+               .num_pipes_active = 1,
+               .sprites_enabled = pipe_wm->sprites_enabled,
+               .sprites_scaled = pipe_wm->sprites_scaled,
+       };
+       struct ilk_wm_maximums max;
+
+       /* LP0 watermarks always use 1/2 DDB partitioning */
+       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+
+       /* At least LP0 must be valid */
+       if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) {
+               DRM_DEBUG_KMS("LP0 watermark invalid\n");
+               return false;
+       }
+
+       return true;
+}
+
 /* Compute new watermarks for the pipe */
-static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc,
-                              struct drm_atomic_state *state)
+static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate)
 {
+       struct drm_atomic_state *state = cstate->base.state;
+       struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
        struct intel_pipe_wm *pipe_wm;
-       struct drm_device *dev = intel_crtc->base.dev;
+       struct drm_device *dev = state->dev;
        const struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc_state *cstate = NULL;
        struct intel_plane *intel_plane;
-       struct drm_plane_state *ps;
        struct intel_plane_state *pristate = NULL;
        struct intel_plane_state *sprstate = NULL;
        struct intel_plane_state *curstate = NULL;
-       int level, max_level = ilk_wm_max_level(dev);
-       /* LP0 watermark maximums depend on this pipe alone */
-       struct intel_wm_config config = {
-               .num_pipes_active = 1,
-       };
+       int level, max_level = ilk_wm_max_level(dev), usable_level;
        struct ilk_wm_maximums max;
 
-       cstate = intel_atomic_get_crtc_state(state, intel_crtc);
-       if (IS_ERR(cstate))
-               return PTR_ERR(cstate);
-
        pipe_wm = &cstate->wm.optimal.ilk;
 
        for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
-               ps = drm_atomic_get_plane_state(state,
-                                               &intel_plane->base);
-               if (IS_ERR(ps))
-                       return PTR_ERR(ps);
+               struct intel_plane_state *ps;
+
+               ps = intel_atomic_get_existing_plane_state(state,
+                                                          intel_plane);
+               if (!ps)
+                       continue;
 
                if (intel_plane->base.type == DRM_PLANE_TYPE_PRIMARY)
-                       pristate = to_intel_plane_state(ps);
+                       pristate = ps;
                else if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY)
-                       sprstate = to_intel_plane_state(ps);
+                       sprstate = ps;
                else if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
-                       curstate = to_intel_plane_state(ps);
+                       curstate = ps;
        }
 
-       config.sprites_enabled = sprstate->visible;
-       config.sprites_scaled = sprstate->visible &&
-               (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 ||
-               drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16);
-
        pipe_wm->pipe_enabled = cstate->base.active;
-       pipe_wm->sprites_enabled = config.sprites_enabled;
-       pipe_wm->sprites_scaled = config.sprites_scaled;
+       if (sprstate) {
+               pipe_wm->sprites_enabled = sprstate->visible;
+               pipe_wm->sprites_scaled = sprstate->visible &&
+                       (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 ||
+                        drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16);
+       }
+
+       usable_level = max_level;
 
        /* ILK/SNB: LP2+ watermarks only w/o sprites */
-       if (INTEL_INFO(dev)->gen <= 6 && sprstate->visible)
-               max_level = 1;
+       if (INTEL_INFO(dev)->gen <= 6 && pipe_wm->sprites_enabled)
+               usable_level = 1;
 
        /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
-       if (config.sprites_scaled)
-               max_level = 0;
+       if (pipe_wm->sprites_scaled)
+               usable_level = 0;
 
        ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate,
-                            pristate, sprstate, curstate, &pipe_wm->wm[0]);
+                            pristate, sprstate, curstate, &pipe_wm->raw_wm[0]);
 
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               pipe_wm->linetime = hsw_compute_linetime_wm(dev,
-                                                           &intel_crtc->base);
+       memset(&pipe_wm->wm, 0, sizeof(pipe_wm->wm));
+       pipe_wm->wm[0] = pipe_wm->raw_wm[0];
 
-       /* LP0 watermarks always use 1/2 DDB partitioning */
-       ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+               pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate);
 
-       /* At least LP0 must be valid */
-       if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
+       if (!ilk_validate_pipe_wm(dev, pipe_wm))
                return -EINVAL;
 
        ilk_compute_wm_reg_maximums(dev, 1, &max);
 
        for (level = 1; level <= max_level; level++) {
-               struct intel_wm_level wm = {};
+               struct intel_wm_level *wm = &pipe_wm->raw_wm[level];
 
                ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate,
-                                    pristate, sprstate, curstate, &wm);
+                                    pristate, sprstate, curstate, wm);
 
                /*
                 * Disable any watermark level that exceeds the
                 * register maximums since such watermarks are
                 * always invalid.
                 */
-               if (!ilk_validate_wm_level(level, &max, &wm))
-                       break;
+               if (level > usable_level)
+                       continue;
+
+               if (ilk_validate_wm_level(level, &max, wm))
+                       pipe_wm->wm[level] = *wm;
+               else
+                       usable_level = level;
+       }
+
+       return 0;
+}
+
+/*
+ * Build a set of 'intermediate' watermark values that satisfy both the old
+ * state and the new state.  These can be programmed to the hardware
+ * immediately.
+ */
+static int ilk_compute_intermediate_wm(struct drm_device *dev,
+                                      struct intel_crtc *intel_crtc,
+                                      struct intel_crtc_state *newstate)
+{
+       struct intel_pipe_wm *a = &newstate->wm.intermediate;
+       struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk;
+       int level, max_level = ilk_wm_max_level(dev);
 
-               pipe_wm->wm[level] = wm;
+       /*
+        * Start with the final, target watermarks, then combine with the
+        * currently active watermarks to get values that are safe both before
+        * and after the vblank.
+        */
+       *a = newstate->wm.optimal.ilk;
+       a->pipe_enabled |= b->pipe_enabled;
+       a->sprites_enabled |= b->sprites_enabled;
+       a->sprites_scaled |= b->sprites_scaled;
+
+       for (level = 0; level <= max_level; level++) {
+               struct intel_wm_level *a_wm = &a->wm[level];
+               const struct intel_wm_level *b_wm = &b->wm[level];
+
+               a_wm->enable &= b_wm->enable;
+               a_wm->pri_val = max(a_wm->pri_val, b_wm->pri_val);
+               a_wm->spr_val = max(a_wm->spr_val, b_wm->spr_val);
+               a_wm->cur_val = max(a_wm->cur_val, b_wm->cur_val);
+               a_wm->fbc_val = max(a_wm->fbc_val, b_wm->fbc_val);
        }
 
+       /*
+        * We need to make sure that these merged watermark values are
+        * actually a valid configuration themselves.  If they're not,
+        * there's no safe way to transition from the old state to
+        * the new state, so we need to fail the atomic transaction.
+        */
+       if (!ilk_validate_pipe_wm(dev, a))
+               return -EINVAL;
+
+       /*
+        * If our intermediate WM are identical to the final WM, then we can
+        * omit the post-vblank programming; only update if it's different.
+        */
+       if (memcmp(a, &newstate->wm.optimal.ilk, sizeof(*a)) == 0)
+               newstate->wm.need_postvbl_update = false;
+
        return 0;
 }
 
@@ -2361,9 +2447,7 @@ static void ilk_merge_wm_level(struct drm_device *dev,
        ret_wm->enable = true;
 
        for_each_intel_crtc(dev, intel_crtc) {
-               const struct intel_crtc_state *cstate =
-                       to_intel_crtc_state(intel_crtc->base.state);
-               const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
+               const struct intel_pipe_wm *active = &intel_crtc->wm.active.ilk;
                const struct intel_wm_level *wm = &active->wm[level];
 
                if (!active->pipe_enabled)
@@ -2511,15 +2595,14 @@ static void ilk_compute_wm_results(struct drm_device *dev,
 
        /* LP0 register values */
        for_each_intel_crtc(dev, intel_crtc) {
-               const struct intel_crtc_state *cstate =
-                       to_intel_crtc_state(intel_crtc->base.state);
                enum pipe pipe = intel_crtc->pipe;
-               const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0];
+               const struct intel_wm_level *r =
+                       &intel_crtc->wm.active.ilk.wm[0];
 
                if (WARN_ON(!r->enable))
                        continue;
 
-               results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime;
+               results->wm_linetime[pipe] = intel_crtc->wm.active.ilk.linetime;
 
                results->wm_pipe[pipe] =
                        (r->pri_val << WM0_PIPE_PLANE_SHIFT) |
@@ -2726,7 +2809,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
        dev_priv->wm.hw = *results;
 }
 
-static bool ilk_disable_lp_wm(struct drm_device *dev)
+bool ilk_disable_lp_wm(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -3028,26 +3111,25 @@ static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config)
 
 /*
  * The max latency should be 257 (max the punit can code is 255 and we add 2us
- * for the read latency) and bytes_per_pixel should always be <= 8, so that
+ * for the read latency) and cpp should always be <= 8, so that
  * should allow pixel_rate up to ~2 GHz which seems sufficient since max
  * 2xcdclk is 1350 MHz and the pixel rate should never exceed that.
 */
-static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t bytes_per_pixel,
-                              uint32_t latency)
+static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latency)
 {
        uint32_t wm_intermediate_val, ret;
 
        if (latency == 0)
                return UINT_MAX;
 
-       wm_intermediate_val = latency * pixel_rate * bytes_per_pixel / 512;
+       wm_intermediate_val = latency * pixel_rate * cpp / 512;
        ret = DIV_ROUND_UP(wm_intermediate_val, 1000);
 
        return ret;
 }
 
 static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
-                              uint32_t horiz_pixels, uint8_t bytes_per_pixel,
+                              uint32_t horiz_pixels, uint8_t cpp,
                               uint64_t tiling, uint32_t latency)
 {
        uint32_t ret;
@@ -3057,7 +3139,7 @@ static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
        if (latency == 0)
                return UINT_MAX;
 
-       plane_bytes_per_line = horiz_pixels * bytes_per_pixel;
+       plane_bytes_per_line = horiz_pixels * cpp;
 
        if (tiling == I915_FORMAT_MOD_Y_TILED ||
            tiling == I915_FORMAT_MOD_Yf_TILED) {
@@ -3107,23 +3189,21 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
        uint32_t plane_bytes_per_line, plane_blocks_per_line;
        uint32_t res_blocks, res_lines;
        uint32_t selected_result;
-       uint8_t bytes_per_pixel;
+       uint8_t cpp;
 
        if (latency == 0 || !cstate->base.active || !fb)
                return false;
 
-       bytes_per_pixel = drm_format_plane_cpp(fb->pixel_format, 0);
+       cpp = drm_format_plane_cpp(fb->pixel_format, 0);
        method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
-                                bytes_per_pixel,
-                                latency);
+                                cpp, latency);
        method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate),
                                 cstate->base.adjusted_mode.crtc_htotal,
                                 cstate->pipe_src_w,
-                                bytes_per_pixel,
-                                fb->modifier[0],
+                                cpp, fb->modifier[0],
                                 latency);
 
-       plane_bytes_per_line = cstate->pipe_src_w * bytes_per_pixel;
+       plane_bytes_per_line = cstate->pipe_src_w * cpp;
        plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512);
 
        if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
@@ -3131,11 +3211,11 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
                uint32_t min_scanlines = 4;
                uint32_t y_tile_minimum;
                if (intel_rotation_90_or_270(plane->state->rotation)) {
-                       int bpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
+                       int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
                                drm_format_plane_cpp(fb->pixel_format, 1) :
                                drm_format_plane_cpp(fb->pixel_format, 0);
 
-                       switch (bpp) {
+                       switch (cpp) {
                        case 1:
                                min_scanlines = 16;
                                break;
@@ -3606,23 +3686,43 @@ static void skl_update_wm(struct drm_crtc *crtc)
        dev_priv->wm.skl_hw = *results;
 }
 
+static void ilk_compute_wm_config(struct drm_device *dev,
+                                 struct intel_wm_config *config)
+{
+       struct intel_crtc *crtc;
+
+       /* Compute the currently _active_ config */
+       for_each_intel_crtc(dev, crtc) {
+               const struct intel_pipe_wm *wm = &crtc->wm.active.ilk;
+
+               if (!wm->pipe_enabled)
+                       continue;
+
+               config->sprites_enabled |= wm->sprites_enabled;
+               config->sprites_scaled |= wm->sprites_scaled;
+               config->num_pipes_active++;
+       }
+}
+
 static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
        struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
        struct ilk_wm_maximums max;
-       struct intel_wm_config *config = &dev_priv->wm.config;
+       struct intel_wm_config config = {};
        struct ilk_wm_values results = {};
        enum intel_ddb_partitioning partitioning;
 
-       ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_1_2, &max);
-       ilk_wm_merge(dev, config, &max, &lp_wm_1_2);
+       ilk_compute_wm_config(dev, &config);
+
+       ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max);
+       ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
 
        /* 5/6 split only in single pipe config on IVB+ */
        if (INTEL_INFO(dev)->gen >= 7 &&
-           config->num_pipes_active == 1 && config->sprites_enabled) {
-               ilk_compute_wm_maximums(dev, 1, config, INTEL_DDB_PART_5_6, &max);
-               ilk_wm_merge(dev, config, &max, &lp_wm_5_6);
+           config.num_pipes_active == 1 && config.sprites_enabled) {
+               ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
+               ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
 
                best_lp_wm = ilk_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6);
        } else {
@@ -3637,29 +3737,28 @@ static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
        ilk_write_wm_values(dev_priv, &results);
 }
 
-static void ilk_update_wm(struct drm_crtc *crtc)
+static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
-
-       WARN_ON(cstate->base.active != intel_crtc->active);
+       struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+       struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
 
-       /*
-        * IVB workaround: must disable low power watermarks for at least
-        * one frame before enabling scaling.  LP watermarks can be re-enabled
-        * when scaling is disabled.
-        *
-        * WaCxSRDisabledForSpriteScaling:ivb
-        */
-       if (cstate->disable_lp_wm) {
-               ilk_disable_lp_wm(crtc->dev);
-               intel_wait_for_vblank(crtc->dev, intel_crtc->pipe);
-       }
+       mutex_lock(&dev_priv->wm.wm_mutex);
+       intel_crtc->wm.active.ilk = cstate->wm.intermediate;
+       ilk_program_watermarks(dev_priv);
+       mutex_unlock(&dev_priv->wm.wm_mutex);
+}
 
-       intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
+static void ilk_optimize_watermarks(struct intel_crtc_state *cstate)
+{
+       struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+       struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
 
-       ilk_program_watermarks(dev_priv);
+       mutex_lock(&dev_priv->wm.wm_mutex);
+       if (cstate->wm.need_postvbl_update) {
+               intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
+               ilk_program_watermarks(dev_priv);
+       }
+       mutex_unlock(&dev_priv->wm.wm_mutex);
 }
 
 static void skl_pipe_wm_active_state(uint32_t val,
@@ -4045,7 +4144,7 @@ void intel_update_watermarks(struct drm_crtc *crtc)
                dev_priv->display.update_wm(crtc);
 }
 
-/**
+/*
  * Lock protecting IPS related data structures
  */
 DEFINE_SPINLOCK(mchdev_lock);
@@ -4081,11 +4180,13 @@ bool ironlake_set_drps(struct drm_device *dev, u8 val)
 static void ironlake_enable_drps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 rgvmodectl = I915_READ(MEMMODECTL);
+       u32 rgvmodectl;
        u8 fmax, fmin, fstart, vstart;
 
        spin_lock_irq(&mchdev_lock);
 
+       rgvmodectl = I915_READ(MEMMODECTL);
+
        /* Enable temp reporting */
        I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN);
        I915_WRITE16(TSC1, I915_READ(TSC1) | TSE);
@@ -4518,21 +4619,71 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
        }
        if (HAS_RC6p(dev))
                DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s RC6p %s RC6pp %s\n",
-                             (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
-                             (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
-                             (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
+                             onoff(mode & GEN6_RC_CTL_RC6_ENABLE),
+                             onoff(mode & GEN6_RC_CTL_RC6p_ENABLE),
+                             onoff(mode & GEN6_RC_CTL_RC6pp_ENABLE));
 
        else
                DRM_DEBUG_KMS("Enabling RC6 states: RC6 %s\n",
-                             (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off");
+                             onoff(mode & GEN6_RC_CTL_RC6_ENABLE));
 }
 
-static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
+static bool bxt_check_bios_rc6_setup(const struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       bool enable_rc6 = true;
+       unsigned long rc6_ctx_base;
+
+       if (!(I915_READ(RC6_LOCATION) & RC6_CTX_IN_DRAM)) {
+               DRM_DEBUG_KMS("RC6 Base location not set properly.\n");
+               enable_rc6 = false;
+       }
+
+       /*
+        * The exact context size is not known for BXT, so assume a page size
+        * for this check.
+        */
+       rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK;
+       if (!((rc6_ctx_base >= dev_priv->gtt.stolen_reserved_base) &&
+             (rc6_ctx_base + PAGE_SIZE <= dev_priv->gtt.stolen_reserved_base +
+                                       dev_priv->gtt.stolen_reserved_size))) {
+               DRM_DEBUG_KMS("RC6 Base address not as expected.\n");
+               enable_rc6 = false;
+       }
+
+       if (!(((I915_READ(PWRCTX_MAXCNT_RCSUNIT) & IDLE_TIME_MASK) > 1) &&
+             ((I915_READ(PWRCTX_MAXCNT_VCSUNIT0) & IDLE_TIME_MASK) > 1) &&
+             ((I915_READ(PWRCTX_MAXCNT_BCSUNIT) & IDLE_TIME_MASK) > 1) &&
+             ((I915_READ(PWRCTX_MAXCNT_VECSUNIT) & IDLE_TIME_MASK) > 1))) {
+               DRM_DEBUG_KMS("Engine Idle wait time not set properly.\n");
+               enable_rc6 = false;
+       }
+
+       if (!(I915_READ(GEN6_RC_CONTROL) & (GEN6_RC_CTL_RC6_ENABLE |
+                                           GEN6_RC_CTL_HW_ENABLE)) &&
+           ((I915_READ(GEN6_RC_CONTROL) & GEN6_RC_CTL_HW_ENABLE) ||
+            !(I915_READ(GEN6_RC_STATE) & RC6_STATE))) {
+               DRM_DEBUG_KMS("HW/SW RC6 is not enabled by BIOS.\n");
+               enable_rc6 = false;
+       }
+
+       return enable_rc6;
+}
+
+int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
 {
        /* No RC6 before Ironlake and code is gone for ilk. */
        if (INTEL_INFO(dev)->gen < 6)
                return 0;
 
+       if (!enable_rc6)
+               return 0;
+
+       if (IS_BROXTON(dev) && !bxt_check_bios_rc6_setup(dev)) {
+               DRM_INFO("RC6 disabled by BIOS\n");
+               return 0;
+       }
+
        /* Respect the kernel parameter if it is set */
        if (enable_rc6 >= 0) {
                int mask;
@@ -4664,7 +4815,7 @@ static void gen9_enable_rps(struct drm_device *dev)
 static void gen9_enable_rc6(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        uint32_t rc6_mask = 0;
        int unused;
 
@@ -4687,8 +4838,8 @@ static void gen9_enable_rc6(struct drm_device *dev)
                I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
-       for_each_ring(ring, dev_priv, unused)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv, unused)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
        if (HAS_GUC_UCODE(dev))
                I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA);
@@ -4702,8 +4853,7 @@ static void gen9_enable_rc6(struct drm_device *dev)
        /* 3a: Enable RC6 */
        if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
                rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
-       DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
-                       "on" : "off");
+       DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE));
        /* WaRsUseTimeoutMode */
        if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) ||
            IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
@@ -4722,8 +4872,7 @@ static void gen9_enable_rc6(struct drm_device *dev)
         * 3b: Enable Coarse Power Gating only when RC6 is enabled.
         * WaRsDisableCoarsePowerGating:skl,bxt - Render/Media PG need to be disabled with RC6.
         */
-       if ((IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) ||
-           ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && (INTEL_REVID(dev) <= SKL_REVID_F0)))
+       if (NEEDS_WaRsDisableCoarsePowerGating(dev))
                I915_WRITE(GEN9_PG_ENABLE, 0);
        else
                I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
@@ -4736,7 +4885,7 @@ static void gen9_enable_rc6(struct drm_device *dev)
 static void gen8_enable_rps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        uint32_t rc6_mask = 0;
        int unused;
 
@@ -4757,8 +4906,8 @@ static void gen8_enable_rps(struct drm_device *dev)
        I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
-       for_each_ring(ring, dev_priv, unused)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv, unused)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
        I915_WRITE(GEN6_RC_SLEEP, 0);
        if (IS_BROADWELL(dev))
                I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */
@@ -4818,7 +4967,7 @@ static void gen8_enable_rps(struct drm_device *dev)
 static void gen6_enable_rps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        u32 rc6vids, pcu_mbox = 0, rc6_mask = 0;
        u32 gtfifodbg;
        int rc6_mode;
@@ -4854,8 +5003,8 @@ static void gen6_enable_rps(struct drm_device *dev)
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 
-       for_each_ring(ring, dev_priv, i)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv, i)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
        I915_WRITE(GEN6_RC_SLEEP, 0);
        I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
@@ -5146,8 +5295,6 @@ static void cherryview_setup_pctx(struct drm_device *dev)
        u32 pcbr;
        int pctx_size = 32*1024;
 
-       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
        pcbr = I915_READ(VLV_PCBR);
        if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
                DRM_DEBUG_DRIVER("BIOS didn't set up PCBR, fixing up\n");
@@ -5169,7 +5316,7 @@ static void valleyview_setup_pctx(struct drm_device *dev)
        u32 pcbr;
        int pctx_size = 24*1024;
 
-       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+       mutex_lock(&dev->struct_mutex);
 
        pcbr = I915_READ(VLV_PCBR);
        if (pcbr) {
@@ -5197,7 +5344,7 @@ static void valleyview_setup_pctx(struct drm_device *dev)
        pctx = i915_gem_object_create_stolen(dev, pctx_size);
        if (!pctx) {
                DRM_DEBUG("not enough stolen space for PCTX, disabling\n");
-               return;
+               goto out;
        }
 
        pctx_paddr = dev_priv->mm.stolen_base + pctx->stolen->start;
@@ -5206,6 +5353,7 @@ static void valleyview_setup_pctx(struct drm_device *dev)
 out:
        DRM_DEBUG_DRIVER("PCBR: 0x%08x\n", I915_READ(VLV_PCBR));
        dev_priv->vlv_pctx = pctx;
+       mutex_unlock(&dev->struct_mutex);
 }
 
 static void valleyview_cleanup_pctx(struct drm_device *dev)
@@ -5215,7 +5363,7 @@ static void valleyview_cleanup_pctx(struct drm_device *dev)
        if (WARN_ON(!dev_priv->vlv_pctx))
                return;
 
-       drm_gem_object_unreference(&dev_priv->vlv_pctx->base);
+       drm_gem_object_unreference_unlocked(&dev_priv->vlv_pctx->base);
        dev_priv->vlv_pctx = NULL;
 }
 
@@ -5347,7 +5495,7 @@ static void valleyview_cleanup_gt_powersave(struct drm_device *dev)
 static void cherryview_enable_rps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        u32 gtfifodbg, val, rc6_mode = 0, pcbr;
        int i;
 
@@ -5374,8 +5522,8 @@ static void cherryview_enable_rps(struct drm_device *dev)
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
 
-       for_each_ring(ring, dev_priv, i)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv, i)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
        I915_WRITE(GEN6_RC_SLEEP, 0);
 
        /* TO threshold set to 500 us ( 0x186 * 1.28 us) */
@@ -5445,7 +5593,7 @@ static void cherryview_enable_rps(struct drm_device *dev)
 static void valleyview_enable_rps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        u32 gtfifodbg, val, rc6_mode = 0;
        int i;
 
@@ -5485,8 +5633,8 @@ static void valleyview_enable_rps(struct drm_device *dev)
        I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
        I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 
-       for_each_ring(ring, dev_priv, i)
-               I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+       for_each_engine(engine, dev_priv, i)
+               I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
        I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
 
@@ -5862,7 +6010,7 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
 bool i915_gpu_busy(void)
 {
        struct drm_i915_private *dev_priv;
-       struct intel_engine_cs *ring;
+       struct intel_engine_cs *engine;
        bool ret = false;
        int i;
 
@@ -5871,8 +6019,8 @@ bool i915_gpu_busy(void)
                goto out_unlock;
        dev_priv = i915_mch_dev;
 
-       for_each_ring(ring, dev_priv, i)
-               ret |= !list_empty(&ring->request_list);
+       for_each_engine(engine, dev_priv, i)
+               ret |= !list_empty(&engine->request_list);
 
 out_unlock:
        spin_unlock_irq(&mchdev_lock);
@@ -6024,7 +6172,6 @@ void intel_init_gt_powersave(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
        /*
         * RPM depends on RC6 to save restore the GT HW context, so make RC6 a
         * requirement.
@@ -6159,8 +6306,8 @@ void intel_enable_gt_powersave(struct drm_device *dev)
                return;
 
        if (IS_IRONLAKE_M(dev)) {
-               mutex_lock(&dev->struct_mutex);
                ironlake_enable_drps(dev);
+               mutex_lock(&dev->struct_mutex);
                intel_init_emon(dev);
                mutex_unlock(&dev->struct_mutex);
        } else if (INTEL_INFO(dev)->gen >= 6) {
@@ -6988,8 +7135,13 @@ void intel_init_pm(struct drm_device *dev)
                     dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
                    (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
                     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
-                       dev_priv->display.update_wm = ilk_update_wm;
                        dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
+                       dev_priv->display.compute_intermediate_wm =
+                               ilk_compute_intermediate_wm;
+                       dev_priv->display.initial_watermarks =
+                               ilk_initial_watermarks;
+                       dev_priv->display.optimize_watermarks =
+                               ilk_optimize_watermarks;
                } else {
                        DRM_DEBUG_KMS("Failed to read display plane latency. "
                                      "Disable CxSR\n");
@@ -7155,9 +7307,10 @@ static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
        int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
 
-       div = vlv_gpu_freq_div(czclk_freq) / 2;
+       div = vlv_gpu_freq_div(czclk_freq);
        if (div < 0)
                return div;
+       div /= 2;
 
        return DIV_ROUND_CLOSEST(czclk_freq * val, 2 * div) / 2;
 }
@@ -7166,9 +7319,10 @@ static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val)
 {
        int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
 
-       mul = vlv_gpu_freq_div(czclk_freq) / 2;
+       mul = vlv_gpu_freq_div(czclk_freq);
        if (mul < 0)
                return mul;
+       mul /= 2;
 
        /* CHV needs even values */
        return DIV_ROUND_CLOSEST(val * 2 * mul, czclk_freq) * 2;
@@ -7211,7 +7365,7 @@ static void __intel_rps_boost_work(struct work_struct *work)
        struct drm_i915_gem_request *req = boost->req;
 
        if (!i915_gem_request_completed(req, true))
-               gen6_rps_boost(to_i915(req->ring->dev), NULL,
+               gen6_rps_boost(to_i915(req->engine->dev), NULL,
                               req->emitted_jiffies);
 
        i915_gem_request_unreference__unlocked(req);
This page took 0.043792 seconds and 5 git commands to generate.