Merge branch 'master' into for-2.6.35
[safe/jmp/linux-2.6] / drivers / gpu / drm / i915 / intel_overlay.c
index f1bf0b0..6d524a1 100644 (file)
@@ -172,7 +172,7 @@ struct overlay_registers {
 #define OFC_UPDATE             0x1
 
 #define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev))
-#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IGDNG(dev))
+#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev))
 
 
 static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
@@ -199,16 +199,11 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over
 
 static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
 {
-       struct drm_device *dev = overlay->dev;
-        drm_i915_private_t *dev_priv = dev->dev_private;
-
        if (OVERLAY_NONPHYSICAL(overlay->dev))
                io_mapping_unmap_atomic(overlay->virt_addr);
 
        overlay->virt_addr = NULL;
 
-       I915_READ(OVADD); /* flush wc cashes */
-
        return;
 }
 
@@ -225,9 +220,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
        overlay->active = 1;
        overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP;
 
-       BEGIN_LP_RING(6);
-       OUT_RING(MI_FLUSH);
-       OUT_RING(MI_NOOP);
+       BEGIN_LP_RING(4);
        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
        OUT_RING(overlay->flip_addr | OFC_UPDATE);
        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -267,9 +260,7 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
        if (tmp & (1 << 17))
                DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
 
-       BEGIN_LP_RING(4);
-       OUT_RING(MI_FLUSH);
-       OUT_RING(MI_NOOP);
+       BEGIN_LP_RING(2);
        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
        OUT_RING(flip_addr);
         ADVANCE_LP_RING();
@@ -338,9 +329,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        /* wait for overlay to go idle */
        overlay->hw_wedged = SWITCH_OFF_STAGE_1;
 
-       BEGIN_LP_RING(6);
-       OUT_RING(MI_FLUSH);
-       OUT_RING(MI_NOOP);
+       BEGIN_LP_RING(4);
        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
        OUT_RING(flip_addr);
         OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -358,9 +347,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        /* turn overlay off */
        overlay->hw_wedged = SWITCH_OFF_STAGE_2;
 
-       BEGIN_LP_RING(6);
-        OUT_RING(MI_FLUSH);
-        OUT_RING(MI_NOOP);
+       BEGIN_LP_RING(4);
         OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
        OUT_RING(flip_addr);
         OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -375,12 +362,28 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        if (ret != 0)
                return ret;
 
-       overlay->active = 0;
        overlay->hw_wedged = 0;
        overlay->last_flip_req = 0;
        return ret;
 }
 
+static void intel_overlay_off_tail(struct intel_overlay *overlay)
+{
+       struct drm_gem_object *obj;
+
+       /* never have the overlay hw on without showing a frame */
+       BUG_ON(!overlay->vid_bo);
+       obj = overlay->vid_bo->obj;
+
+       i915_gem_object_unpin(obj);
+       drm_gem_object_unreference(obj);
+       overlay->vid_bo = NULL;
+
+       overlay->crtc->overlay = NULL;
+       overlay->crtc = NULL;
+       overlay->active = 0;
+}
+
 /* recover from an interruption due to a signal
  * We have to be careful not to repeat work forever an make forward progess. */
 int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
@@ -419,9 +422,7 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
 
                        overlay->hw_wedged = SWITCH_OFF_STAGE_2;
 
-                       BEGIN_LP_RING(6);
-                       OUT_RING(MI_FLUSH);
-                       OUT_RING(MI_NOOP);
+                       BEGIN_LP_RING(4);
                        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
                        OUT_RING(flip_addr);
                        OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
@@ -438,17 +439,7 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
                                return ret;
 
                case SWITCH_OFF_STAGE_2:
-                       BUG_ON(!overlay->vid_bo);
-                       obj = overlay->vid_bo->obj;
-
-                       i915_gem_object_unpin(obj);
-                       drm_gem_object_unreference(obj);
-                       overlay->vid_bo = NULL;
-
-                       overlay->crtc->overlay = NULL;
-                       overlay->crtc = NULL;
-
-                       overlay->active = 0;
+                       intel_overlay_off_tail(overlay);
                        break;
                default:
                        BUG_ON(overlay->hw_wedged != NEEDS_WAIT_FOR_FLIP);
@@ -733,7 +724,7 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay,
        int ret, tmp_width;
        struct overlay_registers *regs;
        bool scale_changed = false;
-       struct drm_i915_gem_object *bo_priv = new_bo->driver_private;
+       struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo);
        struct drm_device *dev = overlay->dev;
 
        BUG_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -818,7 +809,7 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay,
        intel_overlay_continue(overlay, scale_changed);
 
        overlay->old_vid_bo = overlay->vid_bo;
-       overlay->vid_bo = new_bo->driver_private;
+       overlay->vid_bo = to_intel_bo(new_bo);
 
        return 0;
 
@@ -831,18 +822,20 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
 {
        int ret;
        struct overlay_registers *regs;
-       struct drm_gem_object *obj;
        struct drm_device *dev = overlay->dev;
 
        BUG_ON(!mutex_is_locked(&dev->struct_mutex));
        BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
 
+       if (overlay->hw_wedged) {
+               ret = intel_overlay_recover_from_interrupt(overlay, 1);
+               if (ret != 0)
+                       return ret;
+       }
+
        if (!overlay->active)
                return 0;
 
-       if (overlay->hw_wedged)
-               return -EBUSY;
-
        ret = intel_overlay_release_old_vid(overlay);
        if (ret != 0)
                return ret;
@@ -855,16 +848,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
        if (ret != 0)
                return ret;
 
-       /* never have the overlay hw on without showing a frame */
-       BUG_ON(!overlay->vid_bo);
-       obj = overlay->vid_bo->obj;
-
-       i915_gem_object_unpin(obj);
-       drm_gem_object_unreference(obj);
-       overlay->vid_bo = NULL;
-
-       overlay->crtc->overlay = NULL;
-       overlay->crtc = NULL;
+       intel_overlay_off_tail(overlay);
 
        return 0;
 }
@@ -1084,14 +1068,18 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 
        drmmode_obj = drm_mode_object_find(dev, put_image_rec->crtc_id,
                         DRM_MODE_OBJECT_CRTC);
-       if (!drmmode_obj)
-               return -ENOENT;
+       if (!drmmode_obj) {
+               ret = -ENOENT;
+               goto out_free;
+       }
        crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
 
        new_bo = drm_gem_object_lookup(dev, file_priv,
                        put_image_rec->bo_handle);
-       if (!new_bo)
-               return -ENOENT;
+       if (!new_bo) {
+               ret = -ENOENT;
+               goto out_free;
+       }
 
        mutex_lock(&dev->mode_config.mutex);
        mutex_lock(&dev->struct_mutex);
@@ -1180,7 +1168,8 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 out_unlock:
        mutex_unlock(&dev->struct_mutex);
        mutex_unlock(&dev->mode_config.mutex);
-       drm_gem_object_unreference(new_bo);
+       drm_gem_object_unreference_unlocked(new_bo);
+out_free:
        kfree(params);
 
        return ret;
@@ -1355,7 +1344,7 @@ void intel_setup_overlay(struct drm_device *dev)
        reg_bo = drm_gem_object_alloc(dev, PAGE_SIZE);
        if (!reg_bo)
                goto out_free;
-       overlay->reg_bo = reg_bo->driver_private;
+       overlay->reg_bo = to_intel_bo(reg_bo);
 
        if (OVERLAY_NONPHYSICAL(dev)) {
                ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);