|
@@ -2970,11 +2970,13 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
|
|
if (srwm < 0)
|
|
if (srwm < 0)
|
|
srwm = 1;
|
|
srwm = 1;
|
|
srwm &= 0x3f;
|
|
srwm &= 0x3f;
|
|
- I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
|
|
|
|
|
|
+ if (IS_I965GM(dev))
|
|
|
|
+ I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
|
|
} else {
|
|
} else {
|
|
/* Turn off self refresh if both pipes are enabled */
|
|
/* Turn off self refresh if both pipes are enabled */
|
|
- I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
|
|
|
|
- & ~FW_BLC_SELF_EN);
|
|
|
|
|
|
+ if (IS_I965GM(dev))
|
|
|
|
+ I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
|
|
|
|
+ & ~FW_BLC_SELF_EN);
|
|
}
|
|
}
|
|
|
|
|
|
DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
|
|
DRM_DEBUG_KMS("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR %d\n",
|
|
@@ -4483,6 +4485,7 @@ static void intel_idle_update(struct work_struct *work)
|
|
struct drm_device *dev = dev_priv->dev;
|
|
struct drm_device *dev = dev_priv->dev;
|
|
struct drm_crtc *crtc;
|
|
struct drm_crtc *crtc;
|
|
struct intel_crtc *intel_crtc;
|
|
struct intel_crtc *intel_crtc;
|
|
|
|
+ int enabled = 0;
|
|
|
|
|
|
if (!i915_powersave)
|
|
if (!i915_powersave)
|
|
return;
|
|
return;
|
|
@@ -4491,21 +4494,22 @@ static void intel_idle_update(struct work_struct *work)
|
|
|
|
|
|
i915_update_gfx_val(dev_priv);
|
|
i915_update_gfx_val(dev_priv);
|
|
|
|
|
|
- if (IS_I945G(dev) || IS_I945GM(dev)) {
|
|
|
|
- DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
|
|
|
|
- I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
/* Skip inactive CRTCs */
|
|
/* Skip inactive CRTCs */
|
|
if (!crtc->fb)
|
|
if (!crtc->fb)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
+ enabled++;
|
|
intel_crtc = to_intel_crtc(crtc);
|
|
intel_crtc = to_intel_crtc(crtc);
|
|
if (!intel_crtc->busy)
|
|
if (!intel_crtc->busy)
|
|
intel_decrease_pllclock(crtc);
|
|
intel_decrease_pllclock(crtc);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) {
|
|
|
|
+ DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
|
|
|
|
+ I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
|
|
|
|
+ }
|
|
|
|
+
|
|
mutex_unlock(&dev->struct_mutex);
|
|
mutex_unlock(&dev->struct_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4601,10 +4605,10 @@ static void intel_unpin_work_fn(struct work_struct *__work)
|
|
kfree(work);
|
|
kfree(work);
|
|
}
|
|
}
|
|
|
|
|
|
-void intel_finish_page_flip(struct drm_device *dev, int pipe)
|
|
|
|
|
|
+static void do_intel_finish_page_flip(struct drm_device *dev,
|
|
|
|
+ struct drm_crtc *crtc)
|
|
{
|
|
{
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
|
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
struct intel_unpin_work *work;
|
|
struct intel_unpin_work *work;
|
|
struct drm_i915_gem_object *obj_priv;
|
|
struct drm_i915_gem_object *obj_priv;
|
|
@@ -4648,6 +4652,22 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
|
|
schedule_work(&work->work);
|
|
schedule_work(&work->work);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void intel_finish_page_flip(struct drm_device *dev, int pipe)
|
|
|
|
+{
|
|
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
+ struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
|
|
|
+
|
|
|
|
+ do_intel_finish_page_flip(dev, crtc);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
|
|
|
|
+{
|
|
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
+ struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane];
|
|
|
|
+
|
|
|
|
+ do_intel_finish_page_flip(dev, crtc);
|
|
|
|
+}
|
|
|
|
+
|
|
void intel_prepare_page_flip(struct drm_device *dev, int plane)
|
|
void intel_prepare_page_flip(struct drm_device *dev, int plane)
|
|
{
|
|
{
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
@@ -4678,6 +4698,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
|
|
int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
|
|
int ret, pipesrc;
|
|
int ret, pipesrc;
|
|
|
|
+ u32 flip_mask;
|
|
|
|
|
|
work = kzalloc(sizeof *work, GFP_KERNEL);
|
|
work = kzalloc(sizeof *work, GFP_KERNEL);
|
|
if (work == NULL)
|
|
if (work == NULL)
|
|
@@ -4731,15 +4752,28 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
atomic_inc(&obj_priv->pending_flip);
|
|
atomic_inc(&obj_priv->pending_flip);
|
|
work->pending_flip_obj = obj;
|
|
work->pending_flip_obj = obj;
|
|
|
|
|
|
|
|
+ if (intel_crtc->plane)
|
|
|
|
+ flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
|
|
|
|
+ else
|
|
|
|
+ flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
|
|
|
|
+
|
|
|
|
+ /* Wait for any previous flip to finish */
|
|
|
|
+ if (IS_GEN3(dev))
|
|
|
|
+ while (I915_READ(ISR) & flip_mask)
|
|
|
|
+ ;
|
|
|
|
+
|
|
BEGIN_LP_RING(4);
|
|
BEGIN_LP_RING(4);
|
|
- OUT_RING(MI_DISPLAY_FLIP |
|
|
|
|
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
|
- OUT_RING(fb->pitch);
|
|
|
|
if (IS_I965G(dev)) {
|
|
if (IS_I965G(dev)) {
|
|
|
|
+ OUT_RING(MI_DISPLAY_FLIP |
|
|
|
|
+ MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
|
+ OUT_RING(fb->pitch);
|
|
OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
|
|
OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode);
|
|
pipesrc = I915_READ(pipesrc_reg);
|
|
pipesrc = I915_READ(pipesrc_reg);
|
|
OUT_RING(pipesrc & 0x0fff0fff);
|
|
OUT_RING(pipesrc & 0x0fff0fff);
|
|
} else {
|
|
} else {
|
|
|
|
+ OUT_RING(MI_DISPLAY_FLIP_I915 |
|
|
|
|
+ MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
|
|
|
|
+ OUT_RING(fb->pitch);
|
|
OUT_RING(obj_priv->gtt_offset);
|
|
OUT_RING(obj_priv->gtt_offset);
|
|
OUT_RING(MI_NOOP);
|
|
OUT_RING(MI_NOOP);
|
|
}
|
|
}
|