|
@@ -3242,6 +3242,42 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
|
|
|
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
|
|
}
|
|
|
|
|
|
+/* IPS only exists on ULT machines and is tied to pipe A. */
|
|
|
+static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
|
|
|
+{
|
|
|
+ return IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A;
|
|
|
+}
|
|
|
+
|
|
|
+static void hsw_enable_ips(struct intel_crtc *crtc)
|
|
|
+{
|
|
|
+ struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
|
|
|
+
|
|
|
+ if (!crtc->config.ips_enabled)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* We can only enable IPS after we enable a plane and wait for a vblank.
|
|
|
+ * We guarantee that the plane is enabled by calling intel_enable_ips
|
|
|
+ * only after intel_enable_plane. And intel_enable_plane already waits
|
|
|
+ * for a vblank, so all we need to do here is to enable the IPS bit. */
|
|
|
+ assert_plane_enabled(dev_priv, crtc->plane);
|
|
|
+ I915_WRITE(IPS_CTL, IPS_ENABLE);
|
|
|
+}
|
|
|
+
|
|
|
+static void hsw_disable_ips(struct intel_crtc *crtc)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->base.dev;
|
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
+
|
|
|
+ if (!crtc->config.ips_enabled)
|
|
|
+ return;
|
|
|
+
|
|
|
+ assert_plane_enabled(dev_priv, crtc->plane);
|
|
|
+ I915_WRITE(IPS_CTL, 0);
|
|
|
+
|
|
|
+ /* We need to wait for a vblank before we can disable the plane. */
|
|
|
+ intel_wait_for_vblank(dev, crtc->pipe);
|
|
|
+}
|
|
|
+
|
|
|
static void haswell_crtc_enable(struct drm_crtc *crtc)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
@@ -3289,6 +3325,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
|
|
|
intel_crtc->config.has_pch_encoder);
|
|
|
intel_enable_plane(dev_priv, plane, pipe);
|
|
|
|
|
|
+ hsw_enable_ips(intel_crtc);
|
|
|
+
|
|
|
if (intel_crtc->config.has_pch_encoder)
|
|
|
lpt_pch_enable(crtc);
|
|
|
|
|
@@ -3431,6 +3469,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
|
|
|
if (dev_priv->cfb_plane == plane)
|
|
|
intel_disable_fbc(dev);
|
|
|
|
|
|
+ hsw_disable_ips(intel_crtc);
|
|
|
+
|
|
|
intel_disable_plane(dev_priv, plane, pipe);
|
|
|
|
|
|
if (intel_crtc->config.has_pch_encoder)
|
|
@@ -3991,11 +4031,19 @@ retry:
|
|
|
return setup_ok ? 0 : -EINVAL;
|
|
|
}
|
|
|
|
|
|
+static void hsw_compute_ips_config(struct intel_crtc *crtc,
|
|
|
+ struct intel_crtc_config *pipe_config)
|
|
|
+{
|
|
|
+ pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
|
|
|
+ pipe_config->pipe_bpp == 24;
|
|
|
+}
|
|
|
+
|
|
|
static int intel_crtc_compute_config(struct drm_crtc *crtc,
|
|
|
struct intel_crtc_config *pipe_config)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
|
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
|
|
if (HAS_PCH_SPLIT(dev)) {
|
|
|
/* FDI link clock is fixed at 2.7G */
|
|
@@ -4025,8 +4073,11 @@ static int intel_crtc_compute_config(struct drm_crtc *crtc,
|
|
|
pipe_config->pipe_bpp = 8*3;
|
|
|
}
|
|
|
|
|
|
+ if (IS_HASWELL(dev))
|
|
|
+ hsw_compute_ips_config(intel_crtc, pipe_config);
|
|
|
+
|
|
|
if (pipe_config->has_pch_encoder)
|
|
|
- return ironlake_fdi_compute_config(to_intel_crtc(crtc), pipe_config);
|
|
|
+ return ironlake_fdi_compute_config(intel_crtc, pipe_config);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -5932,6 +5983,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
|
|
|
if (intel_display_power_enabled(dev, pfit_domain))
|
|
|
ironlake_get_pfit_config(crtc, pipe_config);
|
|
|
|
|
|
+ pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
|
|
|
+ (I915_READ(IPS_CTL) & IPS_ENABLE);
|
|
|
+
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -6236,8 +6290,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
- int palreg = PALETTE(intel_crtc->pipe);
|
|
|
+ enum pipe pipe = intel_crtc->pipe;
|
|
|
+ int palreg = PALETTE(pipe);
|
|
|
int i;
|
|
|
+ bool reenable_ips = false;
|
|
|
|
|
|
/* The clocks have to be on to load the palette. */
|
|
|
if (!crtc->enabled || !intel_crtc->active)
|
|
@@ -6245,7 +6301,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
|
|
|
|
|
|
/* use legacy palette for Ironlake */
|
|
|
if (HAS_PCH_SPLIT(dev))
|
|
|
- palreg = LGC_PALETTE(intel_crtc->pipe);
|
|
|
+ palreg = LGC_PALETTE(pipe);
|
|
|
+
|
|
|
+ /* Workaround : Do not read or write the pipe palette/gamma data while
|
|
|
+ * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
|
|
|
+ */
|
|
|
+ if (intel_crtc->config.ips_enabled &&
|
|
|
+ ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
|
|
|
+ GAMMA_MODE_MODE_SPLIT)) {
|
|
|
+ hsw_disable_ips(intel_crtc);
|
|
|
+ reenable_ips = true;
|
|
|
+ }
|
|
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
|
I915_WRITE(palreg + 4 * i,
|
|
@@ -6253,6 +6319,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
|
|
|
(intel_crtc->lut_g[i] << 8) |
|
|
|
intel_crtc->lut_b[i]);
|
|
|
}
|
|
|
+
|
|
|
+ if (reenable_ips)
|
|
|
+ hsw_enable_ips(intel_crtc);
|
|
|
}
|
|
|
|
|
|
static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
|
|
@@ -7680,6 +7749,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
|
|
|
DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n",
|
|
|
pipe_config->pch_pfit.pos,
|
|
|
pipe_config->pch_pfit.size);
|
|
|
+ DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
|
|
|
}
|
|
|
|
|
|
static struct intel_crtc_config *
|
|
@@ -7996,6 +8066,8 @@ intel_pipe_config_compare(struct drm_device *dev,
|
|
|
PIPE_CONF_CHECK_I(pch_pfit.pos);
|
|
|
PIPE_CONF_CHECK_I(pch_pfit.size);
|
|
|
|
|
|
+ PIPE_CONF_CHECK_I(ips_enabled);
|
|
|
+
|
|
|
#undef PIPE_CONF_CHECK_I
|
|
|
#undef PIPE_CONF_CHECK_FLAGS
|
|
|
|