diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e03a4f80c5c99479cf212badceaeab6c79d900aa..83a557c7bcc585d6b27719f26a4715dd904e057c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -243,6 +243,8 @@ struct drm_i915_display_funcs { void (*update_sprite_wm)(struct drm_device *dev, int pipe, uint32_t sprite_width, int pixel_size); void (*sanitize_pm)(struct drm_device *dev); + void (*update_linetime_wm)(struct drm_device *dev, int pipe, + struct drm_display_mode *mode); int (*crtc_mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 39f122b3ce70f0a663d75ee82310bde8b02dfc3f..fb3f4aaca2c430bb5c610a73af00c734ad382b94 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4609,6 +4609,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, intel_update_watermarks(dev); + intel_update_linetime_watermarks(dev, pipe, adjusted_mode); + return ret; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a5bb5b6ebb4f71f8d62eb4468ffc39475cd29eb4..0ad1bb3839769b4570812337189aabbd0e1500cc 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -454,6 +454,8 @@ extern void intel_update_watermarks(struct drm_device *dev); extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, uint32_t sprite_width, int pixel_size); +extern void intel_update_linetime_watermarks(struct drm_device *dev, int pipe, + struct drm_display_mode *mode); extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 452a9bce81627768b05ce81ccf36fbe6225a9553..8f8d1daf1cac1e277c884aa579fa191180c21b13 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1883,6 +1883,33 @@ static void sandybridge_update_wm(struct drm_device *dev) cursor_wm); } +static void +haswell_update_linetime_wm(struct drm_device *dev, int pipe, + struct drm_display_mode *mode) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 temp; + + temp = I915_READ(PIPE_WM_LINETIME(pipe)); + temp &= ~PIPE_WM_LINETIME_MASK; + + /* The WM are computed with base on how long it takes to fill a single + * row at the given clock rate, multiplied by 8. + * */ + temp |= PIPE_WM_LINETIME_TIME( + ((mode->crtc_hdisplay * 1000) / mode->clock) * 8); + + /* IPS watermarks are only used by pipe A, and are ignored by + * pipes B and C. They are calculated similarly to the common + * linetime values, except that we are using CD clock frequency + * in MHz instead of pixel rate for the division. + * + * This is a placeholder for the IPS watermark calculation code. + */ + + I915_WRITE(PIPE_WM_LINETIME(pipe), temp); +} + static bool sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, uint32_t sprite_width, int pixel_size, @@ -2078,6 +2105,15 @@ void intel_update_watermarks(struct drm_device *dev) dev_priv->display.update_wm(dev); } +void intel_update_linetime_watermarks(struct drm_device *dev, + int pipe, struct drm_display_mode *mode) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->display.update_linetime_wm) + dev_priv->display.update_linetime_wm(dev, pipe, mode); +} + void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, uint32_t sprite_width, int pixel_size) { @@ -3689,6 +3725,7 @@ void intel_init_pm(struct drm_device *dev) if (SNB_READ_WM0_LATENCY()) { dev_priv->display.update_wm = sandybridge_update_wm; dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; + dev_priv->display.update_linetime_wm = haswell_update_linetime_wm; } else { DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n");