]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/i915/intel_overlay.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / gpu / drm / i915 / intel_overlay.c
index 02ff0a481f470cea6e3f4f109805e07fbd84725e..3fbb98b948d6add163d0538bbe56a1cae738abc6 100644 (file)
@@ -221,15 +221,16 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
        int ret;
 
        BUG_ON(overlay->last_flip_req);
-       overlay->last_flip_req =
-               i915_add_request(dev, NULL, request, &dev_priv->render_ring);
-       if (overlay->last_flip_req == 0)
-               return -ENOMEM;
-
+       ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
+       if (ret) {
+           kfree(request);
+           return ret;
+       }
+       overlay->last_flip_req = request->seqno;
        overlay->flip_tail = tail;
        ret = i915_do_wait_request(dev,
                                   overlay->last_flip_req, true,
-                                  &dev_priv->render_ring);
+                                  LP_RING(dev_priv));
        if (ret)
                return ret;
 
@@ -289,6 +290,7 @@ i830_deactivate_pipe_a(struct drm_device *dev)
 static int intel_overlay_on(struct intel_overlay *overlay)
 {
        struct drm_device *dev = overlay->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_request *request;
        int pipe_a_quirk = 0;
        int ret;
@@ -308,7 +310,12 @@ static int intel_overlay_on(struct intel_overlay *overlay)
                goto out;
        }
 
-       BEGIN_LP_RING(4);
+       ret = BEGIN_LP_RING(4);
+       if (ret) {
+               kfree(request);
+               goto out;
+       }
+
        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);
@@ -332,6 +339,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
        struct drm_i915_gem_request *request;
        u32 flip_addr = overlay->flip_addr;
        u32 tmp;
+       int ret;
 
        BUG_ON(!overlay->active);
 
@@ -347,36 +355,44 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
        if (tmp & (1 << 17))
                DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
 
-       BEGIN_LP_RING(2);
+       ret = BEGIN_LP_RING(2);
+       if (ret) {
+               kfree(request);
+               return ret;
+       }
        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
        OUT_RING(flip_addr);
         ADVANCE_LP_RING();
 
-       overlay->last_flip_req =
-               i915_add_request(dev, NULL, request, &dev_priv->render_ring);
+       ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
+       if (ret) {
+               kfree(request);
+               return ret;
+       }
+
+       overlay->last_flip_req = request->seqno;
        return 0;
 }
 
 static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
 {
-       struct drm_gem_object *obj = &overlay->old_vid_bo->base;
+       struct drm_i915_gem_object *obj = overlay->old_vid_bo;
 
        i915_gem_object_unpin(obj);
-       drm_gem_object_unreference(obj);
+       drm_gem_object_unreference(&obj->base);
 
        overlay->old_vid_bo = NULL;
 }
 
 static void intel_overlay_off_tail(struct intel_overlay *overlay)
 {
-       struct drm_gem_object *obj;
+       struct drm_i915_gem_object *obj = overlay->vid_bo;
 
        /* never have the overlay hw on without showing a frame */
        BUG_ON(!overlay->vid_bo);
-       obj = &overlay->vid_bo->base;
 
        i915_gem_object_unpin(obj);
-       drm_gem_object_unreference(obj);
+       drm_gem_object_unreference(&obj->base);
        overlay->vid_bo = NULL;
 
        overlay->crtc->overlay = NULL;
@@ -389,8 +405,10 @@ static int intel_overlay_off(struct intel_overlay *overlay,
                             bool interruptible)
 {
        struct drm_device *dev = overlay->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        u32 flip_addr = overlay->flip_addr;
        struct drm_i915_gem_request *request;
+       int ret;
 
        BUG_ON(!overlay->active);
 
@@ -404,7 +422,11 @@ static int intel_overlay_off(struct intel_overlay *overlay,
         * of the hw. Do it in both cases */
        flip_addr |= OFC_UPDATE;
 
-       BEGIN_LP_RING(6);
+       ret = BEGIN_LP_RING(6);
+       if (ret) {
+               kfree(request);
+               return ret;
+       }
        /* wait for overlay to go idle */
        OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
        OUT_RING(flip_addr);
@@ -432,7 +454,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
                return 0;
 
        ret = i915_do_wait_request(dev, overlay->last_flip_req,
-                                  interruptible, &dev_priv->render_ring);
+                                  interruptible, LP_RING(dev_priv));
        if (ret)
                return ret;
 
@@ -467,7 +489,12 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
                if (request == NULL)
                        return -ENOMEM;
 
-               BEGIN_LP_RING(2);
+               ret = BEGIN_LP_RING(2);
+               if (ret) {
+                       kfree(request);
+                       return ret;
+               }
+
                OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
                OUT_RING(MI_NOOP);
                ADVANCE_LP_RING();
@@ -736,13 +763,12 @@ static u32 overlay_cmd_reg(struct put_image_params *params)
 }
 
 static int intel_overlay_do_put_image(struct intel_overlay *overlay,
-                                     struct drm_gem_object *new_bo,
+                                     struct drm_i915_gem_object *new_bo,
                                      struct put_image_params *params)
 {
        int ret, tmp_width;
        struct overlay_registers *regs;
        bool scale_changed = false;
-       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));
@@ -753,7 +779,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
        if (ret != 0)
                return ret;
 
-       ret = i915_gem_object_pin(new_bo, PAGE_SIZE);
+       ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true);
        if (ret != 0)
                return ret;
 
@@ -761,6 +787,10 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
        if (ret != 0)
                goto out_unpin;
 
+       ret = i915_gem_object_put_fence(new_bo);
+       if (ret)
+               goto out_unpin;
+
        if (!overlay->active) {
                regs = intel_overlay_map_regs(overlay);
                if (!regs) {
@@ -797,7 +827,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
        regs->SWIDTHSW = calc_swidthsw(overlay->dev,
                                       params->offset_Y, tmp_width);
        regs->SHEIGHT = params->src_h;
-       regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y;
+       regs->OBUF_0Y = new_bo->gtt_offset + params-> offset_Y;
        regs->OSTRIDE = params->stride_Y;
 
        if (params->format & I915_OVERLAY_YUV_PLANAR) {
@@ -811,8 +841,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
                                      params->src_w/uv_hscale);
                regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16;
                regs->SHEIGHT |= (params->src_h/uv_vscale) << 16;
-               regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U;
-               regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V;
+               regs->OBUF_0U = new_bo->gtt_offset + params->offset_U;
+               regs->OBUF_0V = new_bo->gtt_offset + params->offset_V;
                regs->OSTRIDE |= params->stride_UV << 16;
        }
 
@@ -829,7 +859,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
                goto out_unpin;
 
        overlay->old_vid_bo = overlay->vid_bo;
-       overlay->vid_bo = to_intel_bo(new_bo);
+       overlay->vid_bo = new_bo;
 
        return 0;
 
@@ -942,7 +972,7 @@ static int check_overlay_scaling(struct put_image_params *rec)
 
 static int check_overlay_src(struct drm_device *dev,
                             struct drm_intel_overlay_put_image *rec,
-                            struct drm_gem_object *new_bo)
+                            struct drm_i915_gem_object *new_bo)
 {
        int uv_hscale = uv_hsubsampling(rec->flags);
        int uv_vscale = uv_vsubsampling(rec->flags);
@@ -1027,7 +1057,7 @@ static int check_overlay_src(struct drm_device *dev,
                        return -EINVAL;
 
                tmp = rec->stride_Y*rec->src_height;
-               if (rec->offset_Y + tmp > new_bo->size)
+               if (rec->offset_Y + tmp > new_bo->base.size)
                        return -EINVAL;
                break;
 
@@ -1038,12 +1068,12 @@ static int check_overlay_src(struct drm_device *dev,
                        return -EINVAL;
 
                tmp = rec->stride_Y * rec->src_height;
-               if (rec->offset_Y + tmp > new_bo->size)
+               if (rec->offset_Y + tmp > new_bo->base.size)
                        return -EINVAL;
 
                tmp = rec->stride_UV * (rec->src_height / uv_vscale);
-               if (rec->offset_U + tmp > new_bo->size ||
-                   rec->offset_V + tmp > new_bo->size)
+               if (rec->offset_U + tmp > new_bo->base.size ||
+                   rec->offset_V + tmp > new_bo->base.size)
                        return -EINVAL;
                break;
        }
@@ -1086,7 +1116,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
        struct intel_overlay *overlay;
        struct drm_mode_object *drmmode_obj;
        struct intel_crtc *crtc;
-       struct drm_gem_object *new_bo;
+       struct drm_i915_gem_object *new_bo;
        struct put_image_params *params;
        int ret;
 
@@ -1125,8 +1155,8 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
        }
        crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
 
-       new_bo = drm_gem_object_lookup(dev, file_priv,
-                                      put_image_rec->bo_handle);
+       new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
+                                                  put_image_rec->bo_handle));
        if (!new_bo) {
                ret = -ENOENT;
                goto out_free;
@@ -1135,6 +1165,12 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
        mutex_lock(&dev->mode_config.mutex);
        mutex_lock(&dev->struct_mutex);
 
+       if (new_bo->tiling_mode) {
+               DRM_ERROR("buffer used for overlay image can not be tiled\n");
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+
        ret = intel_overlay_recover_from_interrupt(overlay, true);
        if (ret != 0)
                goto out_unlock;
@@ -1217,7 +1253,7 @@ 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_unlocked(new_bo);
+       drm_gem_object_unreference_unlocked(&new_bo->base);
 out_free:
        kfree(params);
 
@@ -1370,7 +1406,7 @@ void intel_setup_overlay(struct drm_device *dev)
 {
         drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_overlay *overlay;
-       struct drm_gem_object *reg_bo;
+       struct drm_i915_gem_object *reg_bo;
        struct overlay_registers *regs;
        int ret;
 
@@ -1385,7 +1421,7 @@ void intel_setup_overlay(struct drm_device *dev)
        reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
        if (!reg_bo)
                goto out_free;
-       overlay->reg_bo = to_intel_bo(reg_bo);
+       overlay->reg_bo = reg_bo;
 
        if (OVERLAY_NEEDS_PHYSICAL(dev)) {
                ret = i915_gem_attach_phys_object(dev, reg_bo,
@@ -1395,14 +1431,14 @@ void intel_setup_overlay(struct drm_device *dev)
                         DRM_ERROR("failed to attach phys overlay regs\n");
                         goto out_free_bo;
                 }
-               overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr;
+               overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
        } else {
-               ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
+               ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
                if (ret) {
                         DRM_ERROR("failed to pin overlay register bo\n");
                         goto out_free_bo;
                 }
-               overlay->flip_addr = overlay->reg_bo->gtt_offset;
+               overlay->flip_addr = reg_bo->gtt_offset;
 
                ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
                if (ret) {
@@ -1434,7 +1470,7 @@ void intel_setup_overlay(struct drm_device *dev)
 out_unpin_bo:
        i915_gem_object_unpin(reg_bo);
 out_free_bo:
-       drm_gem_object_unreference(reg_bo);
+       drm_gem_object_unreference(&reg_bo->base);
 out_free:
        kfree(overlay);
        return;