drm/i915: extract intel_crt.h from intel_drv.h
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / intel_display.c
index 702d284..d601cc9 100644 (file)
 
 #include "i915_drv.h"
 #include "i915_gem_clflush.h"
+#include "i915_reset.h"
 #include "i915_trace.h"
+#include "intel_crt.h"
 #include "intel_drv.h"
 #include "intel_dsi.h"
 #include "intel_frontbuffer.h"
 
-#include "intel_drv.h"
-#include "intel_dsi.h"
-#include "intel_frontbuffer.h"
-
-#include "i915_drv.h"
-#include "i915_gem_clflush.h"
-#include "i915_reset.h"
-#include "i915_trace.h"
-
 /* Primary plane formats for gen <= 3 */
 static const u32 i8xx_primary_formats[] = {
        DRM_FORMAT_C8,
@@ -9754,7 +9747,8 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
 
 static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
                                     struct intel_crtc_state *pipe_config,
-                                    u64 *power_domain_mask)
+                                    u64 *power_domain_mask,
+                                    intel_wakeref_t *wakerefs)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -9762,6 +9756,7 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
        unsigned long panel_transcoder_mask = 0;
        unsigned long enabled_panel_transcoders = 0;
        enum transcoder panel_transcoder;
+       intel_wakeref_t wf;
        u32 tmp;
 
        if (INTEL_GEN(dev_priv) >= 11)
@@ -9827,10 +9822,13 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
                enabled_panel_transcoders != BIT(TRANSCODER_EDP));
 
        power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
+
+       wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wf)
                return false;
 
-       WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
+       wakerefs[power_domain] = wf;
        *power_domain_mask |= BIT_ULL(power_domain);
 
        tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
@@ -9840,13 +9838,15 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
 
 static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
                                         struct intel_crtc_state *pipe_config,
-                                        u64 *power_domain_mask)
+                                        u64 *power_domain_mask,
+                                        intel_wakeref_t *wakerefs)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        enum intel_display_power_domain power_domain;
-       enum port port;
        enum transcoder cpu_transcoder;
+       intel_wakeref_t wf;
+       enum port port;
        u32 tmp;
 
        for_each_port_masked(port, BIT(PORT_A) | BIT(PORT_C)) {
@@ -9856,10 +9856,13 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
                        cpu_transcoder = TRANSCODER_DSI_C;
 
                power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
-               if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
+
+               wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
+               if (!wf)
                        continue;
 
-               WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
+               wakerefs[power_domain] = wf;
                *power_domain_mask |= BIT_ULL(power_domain);
 
                /*
@@ -9938,6 +9941,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                                    struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       intel_wakeref_t wakerefs[POWER_DOMAIN_NUM], wf;
        enum intel_display_power_domain power_domain;
        u64 power_domain_mask;
        bool active;
@@ -9945,16 +9949,21 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        intel_crtc_init_scalers(crtc, pipe_config);
 
        power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wf)
                return false;
+
+       wakerefs[power_domain] = wf;
        power_domain_mask = BIT_ULL(power_domain);
 
        pipe_config->shared_dpll = NULL;
 
-       active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_mask);
+       active = hsw_get_transcoder_state(crtc, pipe_config,
+                                         &power_domain_mask, wakerefs);
 
        if (IS_GEN9_LP(dev_priv) &&
-           bxt_get_dsi_transcoder_state(crtc, pipe_config, &power_domain_mask)) {
+           bxt_get_dsi_transcoder_state(crtc, pipe_config,
+                                        &power_domain_mask, wakerefs)) {
                WARN_ON(active);
                active = true;
        }
@@ -9988,8 +9997,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        }
 
        power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
-       if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
-               WARN_ON(power_domain_mask & BIT_ULL(power_domain));
+       WARN_ON(power_domain_mask & BIT_ULL(power_domain));
+
+       wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (wf) {
+               wakerefs[power_domain] = wf;
                power_domain_mask |= BIT_ULL(power_domain);
 
                if (INTEL_GEN(dev_priv) >= 9)
@@ -10021,7 +10033,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 
 out:
        for_each_power_domain(power_domain, power_domain_mask)
-               intel_display_power_put_unchecked(dev_priv, power_domain);
+               intel_display_power_put(dev_priv,
+                                       power_domain, wakerefs[power_domain]);
 
        return active;
 }
@@ -13002,6 +13015,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
        intel_state->active_crtcs = dev_priv->active_crtcs;
        intel_state->cdclk.logical = dev_priv->cdclk.logical;
        intel_state->cdclk.actual = dev_priv->cdclk.actual;
+       intel_state->cdclk.pipe = INVALID_PIPE;
 
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                if (new_crtc_state->active)
@@ -13021,6 +13035,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
         * adjusted_mode bits in the crtc directly.
         */
        if (dev_priv->display.modeset_calc_cdclk) {
+               enum pipe pipe;
+
                ret = dev_priv->display.modeset_calc_cdclk(state);
                if (ret < 0)
                        return ret;
@@ -13037,12 +13053,36 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
                                return ret;
                }
 
+               if (is_power_of_2(intel_state->active_crtcs)) {
+                       struct drm_crtc *crtc;
+                       struct drm_crtc_state *crtc_state;
+
+                       pipe = ilog2(intel_state->active_crtcs);
+                       crtc = &intel_get_crtc_for_pipe(dev_priv, pipe)->base;
+                       crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+                       if (crtc_state && needs_modeset(crtc_state))
+                               pipe = INVALID_PIPE;
+               } else {
+                       pipe = INVALID_PIPE;
+               }
+
                /* All pipes must be switched off while we change the cdclk. */
-               if (intel_cdclk_needs_modeset(&dev_priv->cdclk.actual,
-                                             &intel_state->cdclk.actual)) {
+               if (pipe != INVALID_PIPE &&
+                   intel_cdclk_needs_cd2x_update(dev_priv,
+                                                 &dev_priv->cdclk.actual,
+                                                 &intel_state->cdclk.actual)) {
+                       ret = intel_lock_all_pipes(state);
+                       if (ret < 0)
+                               return ret;
+
+                       intel_state->cdclk.pipe = pipe;
+               } else if (intel_cdclk_needs_modeset(&dev_priv->cdclk.actual,
+                                                    &intel_state->cdclk.actual)) {
                        ret = intel_modeset_all_pipes(state);
                        if (ret < 0)
                                return ret;
+
+                       intel_state->cdclk.pipe = INVALID_PIPE;
                }
 
                DRM_DEBUG_KMS("New cdclk calculated to be logical %u kHz, actual %u kHz\n",
@@ -13051,8 +13091,6 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
                DRM_DEBUG_KMS("New voltage level calculated to be logical %u, actual %u\n",
                              intel_state->cdclk.logical.voltage_level,
                              intel_state->cdclk.actual.voltage_level);
-       } else {
-               to_intel_atomic_state(state)->cdclk.logical = dev_priv->cdclk.logical;
        }
 
        intel_modeset_clear_plls(state);
@@ -13453,7 +13491,10 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
        if (intel_state->modeset) {
                drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
 
-               intel_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
+               intel_set_cdclk_pre_plane_update(dev_priv,
+                                                &intel_state->cdclk.actual,
+                                                &dev_priv->cdclk.actual,
+                                                intel_state->cdclk.pipe);
 
                /*
                 * SKL workaround: bspec recommends we disable the SAGV when we
@@ -13482,6 +13523,12 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
        dev_priv->display.update_crtcs(state);
 
+       if (intel_state->modeset)
+               intel_set_cdclk_post_plane_update(dev_priv,
+                                                 &intel_state->cdclk.actual,
+                                                 &dev_priv->cdclk.actual,
+                                                 intel_state->cdclk.pipe);
+
        /* FIXME: We should call drm_atomic_helper_commit_hw_done() here
         * already, but still need the state for the delayed optimization. To
         * fix this: